본문 바로가기
취미노트/코딩공부

[flutter] 09 효율적인 구조의 코드 작성, 함수 활용

by 복습쟁이 2024. 8. 18.
반응형

- 이번에 해 볼 것 -

ExpandedWidget의 활용

심화 단계의 [dart]함수 학습

Refactoring을 통한 효율적 코드 작성

 

 

 

1. ExpandedWidget을 활용한 버튼 제작

이번에는, 지난번 플레이버튼 제작의 연장선으로, 5개의 버튼과 5개의 사운드 파일 재생 기능을 만들어보자.

 

먼저, ElevatedButton을 Column으로 Wrap하자. 세로로 버튼을 배열하기 위함이다.

그 뒤 ElevatedButton 4개를 복붙하면 총 5개의 버튼이 만들어진다.

텍스트와 mp3파일명도 5개 각각 조절을 해주자.

 

Column(
  children: [
    ElevatedButton(
      onPressed: (){
        player.play(AssetSource("audios/sound1.mp3"),);
      },
      child: Text('Play1'),
    ),
    ElevatedButton(
      onPressed: (){
        player.play(AssetSource("audios/sound2.mp3"),);
      },
      child: Text('Play2'),
    ),
    ElevatedButton(
      onPressed: (){
        player.play(AssetSource("audios/sound3.mp3"),);
      },
      child: Text('Play3'),
    ),
    ElevatedButton(
      onPressed: (){
        player.play(AssetSource("audios/sound4.mp3"),);
      },
      child: Text('Play4'),
    ),
    ElevatedButton(
      onPressed: (){
        player.play(AssetSource("audios/sound5.mp3"),);
      },
      child: Text('Play5'),
    ),
  ],
),

 

 

 

 

 

 

다음은, 이 버튼들을 적절히 배열하여 화면 전체에 가득 차도록 조절해 보자.

버튼을 먼저 가로로 길게 배치하기 위해 crossAxisAlignment 속성을 활용해보았다.

컬럼 바로 아래 해당속성을 주면, 버튼들이 쭉 길어진다.

하는 김에, 버튼 색상도 새로 바꿔보자.

버튼 색상은 ElevatedButton 각각에 style을 적용함으로써 변경 가능하다.

child: Column(
  crossAxisAlignment: CrossAxisAlignment.stretch,
  children: [
    ElevatedButton(
      style: ElevatedButton.styleFrom(backgroundColor: Colors.white38),
      onPressed: (){
        player.play(AssetSource("audios/sound1.mp3"),);
      },

 

 

 

 

 

텍스트 사이즈도 스타일 적용을 통해서 조금 더 키웠다.

ElevatedButton(
  style: ElevatedButton.styleFrom(backgroundColor: Colors.white38),
  onPressed: (){
    player.play(AssetSource("audios/sound1.mp3"),);
  },
  child: Text('Play1', style: TextStyle(fontSize: 30),),
),

 

 

 

 

 

버튼 간격을 주기 위해서 ElevatedButton을 Padding위젯으로 Wrap해주었고, 그 Padding위젯을 Expandid위젯을 이용해서 Wrap해 줌으로써 버튼을 화면에 가득차도록 확장시켜 주었다.

body: Center(
  child: Column(
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: [
      Expanded(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: ElevatedButton(
            style: ElevatedButton.styleFrom(backgroundColor: Colors.white38),
            onPressed: (){
              player.play(AssetSource("audios/sound1.mp3"),);
            },
            child: Text('Play1', style: TextStyle(fontSize: 30),),
          ),
        ),
      ),

 

 

 

 

 

 

2. [dart]함수의 심화학습 및 활용

이상으로 스타일적용과 패딩, 익스팬디드 적용 등으로 버튼을 꾸며보았다. 이 때, 다섯 개의 버튼을 꾸밀 때 마다 각각 작업을 해 주어야 했다. 함수를 활용하면 이러한 작업을 보다 수월하게 할 수 있다.

 

(1) 함수활용의 예시 1

위 코드처럼 스쿼트 운동을 권장하는 프로그램을 하나 만들었다고 생각해보자.

좌측 코드에 대한 출력이 우측 콘솔에 발생했다.

 

이번에는 덤벨프레스 권장을 추가하고 싶다.

그래서 이렇게 덤벨프레스가 있는 문장을 추가해 주었다.

여기에 또 다른 운동을 추가하고 싶다면? 또 노가다를 해줘야 한다. 번거롭다.

 

함수를 이용하면 이러한 번거로움이 한결 덜어진다.

첫 줄에 운동명을 변수로 잡아준 뒤, 각 문장에 있는 운동명을 변수로 바꾸어 주면

변수 값만 바뀌면 문장 전체가 바뀌는 편리함을 가져갈 수 있다.  *참고 : 변수는 중괄호 내의 범위에서만 동작한다.

하지만, 이것도 운동이 바뀔 때 마다 들어갈 문장 세 줄씩을 계속 만들어줘야 한다.

이 3문장 작업들을 계속 추가하기 번거로우니, 하나로 묶어버리면 더 편해질 수 있다.

 

메인함수 아래에 doWorkout이라는 이름의 함수를 선언했다.

그 함수의 파라메터는 workoutName이라는 변수로 갖는다.

그 함수의 바디는 workoutName이 들어간 문장 3줄을 출력한다.

 

이 코딩 대로라면 앞으로 메인함수에서 doWorkout이라는 함수의 파라메터만 원하는 운동 이름으로 추가하면

문장 3줄 프린트는 함수가 알아서 작업을 해 준다.

 

 

(2) 함수활용의 예시2

이번에는 return을 다루는 법을 연습해보자. 위 예시를 이어서, 이번에는 운동 숫자를 랜덤하게 출력하도록 만들어보자.

직전 포스팅에서 패키지 추가한 random_string을 활용하기로 한다.

 

void main() {
  doWorkout('스쿼트');
  doWorkout('덤벨프레스');
  doWorkout('런지');
}

doWorkout(String workoutName) {
  String workoutGoal=randomNumeric(2);
  print('오늘은 $workoutName 하는 날 입니다.');
  print('$workoutName를 $workoutGoal회 수행해 주세요.');
  print('$workoutName는 매우 효율적인 운동입니다.');
  print('');

}

 

이 코드의 결과물은 콘솔에 다음과 같이 출력된다.

 

 

이번에는 각 운동의 횟수를 더한 값을 가장 마지막 줄에 추가하여 출력하고 싶다.

 

랜덤 값은 doWorkout 함수에서 만들지만, 마지막 줄 문장은 main함수에서만 나오면 된다.

그렇기 때문에 doWorkout함수에서 생성된 변수값을 main으로 보내줘야 한다.

 

1. 함수에서 리턴이 나와야 하기 때문에, 함수명 앞에 타입을 줘야 한다. 숫자이므로 int를 주도록 하자.

2. 리턴 키워드로 아웃풋 값을 빼야 한다. 이 때, workoutGoal은 String이었으므로, int로 강제변환 해줘야 한다.

3. doWorkout함수에서 return으로 나온 아웃풋을 새로운 변수를 만들어 그 값을 저장한다(resultWorkoutCount1, 2, 3)

4. 총 합은 이 아웃풋들을 저장한 변수들의 합이 될 것이다.

 

위 코드를 실행한 결과이다. 

 

 

 

(3) 함수활용의 예시2

함수에는 인풋(파라메터)와 아웃풋(리턴)이 있었다. 파라미터를 정의하는 방법이 꽤나 다양하게 있다.

구분 내용 예시
Positional 소괄호로 표현( )
순서 중요.
필수값. 정의가 되면 NULL이라도 무조건 아규먼트를 넘겨야함.
void doWorkout (String day, String? workoutName}){
print('$day에는 $workoutName');
}
doWorkout('월요일',null);  // 함수 동작 O
doWorkout('월요일'); // 함수동작 X (아규먼트 수가 다름)
Optional
positional
대괄호로 표현[ ]
순서 중요.
옵셔널하다(필수아님)
디폴트밸류 또는 Nullable 가능하다
 
Named 중괄호로 표현{ }
순서 없음.
옵셔널(required 키워드 삽입 시,  필수동작함)
key:value 형태로 파라메터 입력
void doWorkout ({required String day, String? workoutName}){
print('$day에는 $workoutName');
}
doWorkout(day: '월요일',workoutName:'스쿼트'); 
doWorkout(workoutName:'스쿼트' ,day: '월요일');

 

Named는 1, 2번을 모두 사용할 수 있으므로 3번은 우선적으로 익히고, 1,2번도 남의 코드 해석할 수 있을 정도로는 익혀야 한다.

3번 Named 예시를 해석하자면, Day는 required 키워드가 붙어있으므로 필수동작이다. 빠지면 에러가 발생한다. Named는 순서가 없으므로, 1번째 호출과 2번째 호출 모두 동작하며 호출 시 앞에 키 이름 : 뒤에 키 값을 넣어서 처리한다.

 

 

3. Refactoring을 통한 코드 효율화

다섯 번 반복되는 Expanded를 함수로 만들어서 효율적으로 처리해보자.

코드를 효율화시키는 작업을 Refactoring이라고 한다.

Expanded 코드 앞에 커서를 두고 우클릭을 한 뒤,

Refactor -> Extract Method를 클릭하면 Expanded를 함수로 만들 수 있다.

 

Expanded playSound() {
  return Expanded(
          child: Padding(
            padding: const EdgeInsets.all(16.0),
            child: ElevatedButton(
              style: ElevatedButton.styleFrom(backgroundColor: Colors.white38),
              onPressed: (){
                player.play(AssetSource("audios/sound1.mp3"),);
              },
              child: Text('Play1', style: TextStyle(fontSize: 30),),
            ),
          ),
        );
}

 

안드로이드 스튜디오가 함수로 만들어 준 코드이다.

이제 익스팬디드 함수들을 다 날리고 칠드런에 함수만 호출하면 코드가 간결해진다

 

body: Center(
  child: Column(
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: [
      playSound(),
      playSound(),
      playSound(),
      playSound(),
      playSound(),

하지만, 이대로 핫 리로드를 하면 버튼이 모두 play1이 되어버린다.

파라메터에 인풋을 줌으로써 인풋과 리턴을 변화시킬 수 있다.

 

안드로이드스튜디오가 만든 코드로 다시 돌아가 파라메터를 설정해 준다.

Expanded playSound({required String name, required String audioNumber}) {
  return Expanded(
          child: Padding(
            padding: const EdgeInsets.all(16.0),
            child: ElevatedButton(
              style: ElevatedButton.styleFrom(backgroundColor: Colors.white38),
              onPressed: (){
                player.play(AssetSource("audios/$audioNumber.mp3"),);
              },
              child: Text('$name', style: TextStyle(fontSize: 30),),
            ),

 

Named를 사용했지만, 둘 다 모두 필수값으로 들어가야 하기에 required 키워드를 넣어줬다.

name은 버튼에 나오는 텍스트에, audioNumber는 mp3 파일명에 넣었다.

 

body: Center(
  child: Column(
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: [
      playSound(name: 'Play1',audioNumber: "sound1"),
      playSound(name: 'Play2',audioNumber: "sound2"),
      playSound(name: 'Play3',audioNumber: "sound3"),
      playSound(name: 'Play4',audioNumber: "sound4"),
      playSound(name: 'Play5',audioNumber: "sound5"),
    ],
  ),
),

이제 익스팬디드는 코드 가장 하단에 한 번만 있으면 된다.

함수를 통해 호출만 다섯번 해 주면 되니까.

 

728x90
반응형

댓글