[Flutter] 누구나 시작하는 앱 개발 튜토리얼

이 글은 [Must Have] 코드팩토리의 플러터 프로그래밍 2판에서 발췌했습니다.
골든래빗 출판사
코드팩토리(최지호) 지음

[Flutter] 앱 개발 튜토리얼입니다. 모바일 앱 개발자로서 알고 있으면 좋은 지식들을 살펴본 후 플러터 프레임워크를 사용하여 간단한 연습용 프로젝트를 진행해보겠습니다. 모바일 앱 개발자로 성장하려면 알고 있으면 좋은 지식을 담고 있으니 가볍게 습득한 후 이해가 되지 않는다면 필요할 때마다 되돌아와서 확인해보세요. 총 2편입니다.

 

[Flutter] 누구나 시작하는 앱 개발 튜토리얼

1. 앱 만들기 프로세스

현업에서는 기획 → UI 구상하기 → 구현하기 → 테스트 순서로 만듭니다. <[MustHave 코드팩토리의 플러터 프로그래밍(2판)>에서는 다양한 앱을 만들며 플러터를 학습하게 됩니다. 앱을 개발하는 흐름은 협업의 순서와 비슷한 순서로 진행하므로 차례대로 설명하겠습니다.

 

▼ 이 책의 앱 만들기 프로세스

 

현업에서 UI로 레이아웃을 구성할 때는 프로토타입을 만들어볼 수 있는 피그마(Figma), 어도비 XD(Adobe XD), 플러터 플로우(Flutter Flow) 프로그램을 주로 사용합니다. UI 프로토타입 도구 사용은 주제를 벗어나므로 간단히 소개만 하고 넘어가겠습니다.

 

▼ 프로토타입용 프로그램

 

구현할 때는 폴더 구조를 잘 잡아야 협업이 편하고 유지보수가 용이합니다. <[MustHave 코드팩토리의 플러터 프로그래밍(2판)>에서는 다음과 같이 폴더 구조를 잡았습니다. 구조에 정답은 없습니다. 여러분도 다음 폴더 구조를 참고하여 용도에 따라 폴더를 나누는 습관을 가지기 바랍니다.

 

▼ 폴더 구조

 

2. 플러그인 추가 방법

오픈 소스 프로젝트들은 불러와서 원하는 프로젝트에 추가하면 개발 속도를 비약적으로 높일 수 있습니다. 예를 들어 웹 브라우저 기능을 추가하려면 WebView가 필요한데, 직접 구현하려면 몇 달이 넘게 걸릴 겁니다. 다행히 webview_flutter 플러그인이 플러터 오픈 소스 저장소인 pub.dev에 공개돼 있어서 우리는 직접 구현하지 않고 가져다 쓰면 그만입니다. 그 외 카메라, 블루투스, GPS 등 다양한 플러그인이 제공됩니다. 플러그인을 불러와 사용하는 방법을 알아보겠습니다.

플러터 프로젝트를 생성하면 자동으로 생성되는 pubspec.yaml 파일에 원하는 플러그인을 추가하고 [pub get] 버튼을 눌러주면 등록한 플러그인을 바로 프로젝트에서 사용할 수 있습니다. WebView 플러그인을 추가하는 예를 들어보겠습니다.

 

// ❶ 플러그인을 여기에 등록하면 됩니다.
dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^1.0.2
  webview_flutter: 2.3.1 // ❷ 웹뷰 플러그인 추가

 

❶ dependencies에 사용할 플러그인을 등록하면 됩니다. ❷ 웹뷰 플러그인을 적었습니다. 콜론 : 오른쪽에 해당 플러그인 버전을 작성하면 플러그인을 프로젝트에 추가할 수 있습니다.

플러그인을 pubspec.yaml에 추가하고 나면 플러그인들을 내려받고 프로젝트에 적용시켜야 합니다. 안드로이드 스튜디오에서 pubspec.yaml 파일을 열면 파일 화면의 오른쪽 위에 [pub get] 버튼이 생깁니다. 이 버튼을 눌러주면 플러그인뿐만 아니라 pubspec.yaml에서 설정한 모든 요소를 현재 프로젝트에 적용시킬 수 있습니다.

 

3. 주변 장치 종류

플러터 프레임워크는 다양한 하드웨어 기능을 제공해줍니다. 그래서 스마트폰에서 장치를 손쉽게 사용할 수 있습니다. 대표적으로 움직임을 측정하는 센서 및 GPS 기능, 카메라 그리고 블루투스나 와이파이 같은 네트워크 기능이 있습니다. 이 책에서는 센서, GPS, 카메라 기능을 활용해 앱을 만들어봅니다. 그 외 기능에 대해서도 간단히 표로 정리해두었으니 참고하기 바랍니다.

 

▼ 플러터에서 지원하는 대표적인 주변 장치

 

4. 연습용 앱 만들기 : 스플래시 스크린 앱

조각조각 이론만 배워서는 앱을 만드는 방법을 체득할 수 없습니다. 아직 아는 내용이 많지 않지만 간단한 앱을 만들며 전반적인 과정을 체험하면 앱 만들기 과정에 대한 감을 잡을 수 있을 겁니다. 새로 다루는 개념은 그때그때 설명하겠습니다. 그래서 이번에는 앱이 로딩되는 동안 보이는 스플래시 스크린을 간단하게 구현하면서 위젯을 화면에 배치하는 Row 위젯과 Column 위젯을 사용해보겠습니다.

 

▼ Splash Screen 구현 최종 목표

 

4.1 사용자 정의 위젯 만들기 : 스테이트리스 위젯

To Do

01 안드로이드 스튜디오에서 실습에 사용할 프로젝트를 생성해주세요.

  • 프로젝트 이름 : splash_screen
  • 네이티브 언어 : 코틀린, 스위프트

안드로이드 스튜디오에서 프로젝트를 생성하는 방법은 2가지입니다. GUI와 CLI에서 각각 생성할 수 있습니다. 두 방법을 알아보겠습니다.

 

GUI 환경에서 생성하기

(1) 안드로이드 스튜디오 전용 플러터 플러그인 덕분에 플러터 프로젝트 생성은 상당히 쉽습니다. 처음 안드로이드 스튜디오를 실행하면 다음과 같은 화면을 볼 수 있습니다. 안드로이드 스튜디오 및 플러그인 설치 절차를 잘 따라오셨다면 ❶ [New Flutter Project] 버튼이 보일 겁니다. 이 버튼을 클릭해주세요.

 

💡Note: 기존에 안드로이드 스튜디오를 사용해서 프로젝트를 생성한 적이 있다면 ‘Welcome to Android Studio’ 화면 대신 프로젝트 화면 화면이 실행됩니다. [New Flutter Project] 버튼이나 [File] → [New] → [New Flutter Project] 메뉴를 찾아 실행해주세요.

 

(2) ❶ [Flutter] 탭을 선택하고 ❷ [Flutter SDK Path]에 플러터를 다운받은 폴더 위치를 찾아주세요. 일반적으로 자동으로 인식됩니다. 완료 후 ❸ [Next]를 눌러주세요.

 

(3) ❶ 프로젝트 이름으로 hello_world를 입력하고, ❻ 안드로이드는 Kotlin, iOS는 Swift를 선택합니다. ❼ 각자의 환경에 맞게 Android 또는 iOS를 선택해주세요. 그 후 ❽ [Finish] 버튼을 눌러 진행합니다. 원한다면 ❷ 프로젝트 위치를 바꿔도 됩니다.

 

참고로 ❸ 은 프로젝트 설명 ❹ 는 프로젝트 종류 (Application이 일반 플러터 프로젝트고 이 책에서는 매번 Application만 선택합니다), ❺ 는 프로젝트의 번들 아이디bundle id입니다. 앱을 마켓에 출시할 때 식별하는 값입니다(일반적으로 도메인을 거꾸로 작성합니다. 예 : codefactory.ai → ai.codefactory.[앱 이름]).

 

(4) 생성이 마무리되면 다음과 같이 프로젝트가 생성됩니다. 만약 ❶ 왼쪽에 폴더 구조가 보이지 않으면 [Project] 탭을 눌러주세요(윈도우에선 Alt +1 , macOS에선 Cmd + 1 을 눌러도 됩니다). 그리고 ❷ [Project] 탭이 활성화되었는지 확인해주세요. 만약에 다른 탭이 활성화돼 있다면 (5)과정을 진행하고 아니면 건너뛰어도 됩니다.

 

(5) 프로젝트를 생성하고 ❶ 탭이 [Project]로 설정돼 있지 않으면 ❶ 탭을 누르고 ❷ [Project]를 눌러주세요(안드로이드 스튜디오는 일반적으로 안드로이드 개발을 할 때 사용하기 때문에 [Android]가 선택되어 있을 수 있습니다).

 

CLI 환경에서 프로젝트 생성하기

앞에서는 안드로이드 스튜디오에서 프로젝트를 생성했습니다. 사실 안드로이드 스튜디오는 플러터 프로젝트 생성을 위한 UI만 제공해줄 뿐입니다. CLI로도 플러터 프로젝트를 생성할 수 있습니다.

(1) 윈도우나 macOS 터미널을 하나 열어서 원하는 폴더로 이동한 후 ‘flutter create <DIRECTORY>’ 명령으로 프로젝트를 생성합시다. <DIRECTORY>에 프로젝트 이름을 넣으면 됩니다(저는 hello_world2를 입력했습니다). 플러터 프로젝트 이름은 소문자나 언더스코어로 시작해야 합니다.

flutter create hello_world2

 

위와 같은 명령어를 실행하면 프로젝트가 생성됩니다. 생성된 프로젝트를 안드로이드 스튜디오로 실행하면 됩니다.

 

02 위젯의 형태는 2가지로 나뉩니다. 위젯의 내부에서 값이 변경되었을 때 위젯 자체에서 다시 렌더링을 실행시킬 수 있는 스테이트풀(Stateful) 위젯과 위젯 내부에서 값이 변경되어도 위젯 자체적으로는 다시 렌더링할 수 없는 스테이트리스(Stateless) 위젯입니다. 여기서는 플러터의 가장 기본이 되는 스테이트리스 위젯을 직접 구현하겠습니다. SplashScreen라는 이름의 스테이트리스 위젯 클래스를 main.dart 파일에 추가합니다.

 

import 'package:flutter/material.dart';

void main() {
 runApp(SplashScreen()); // 1 SplashScreen 위젯을 첫 화면으로 지정
}

class SplashScreen extends StatelessWidget { // 2 StatelessWidget 선언
 @override
 Widget build(BuildContext context) { // 3 위젯의 UI 구현
 }
}

 

플러터에서 기본으로 제공하는 ❷ StatelessWidget이라는 클래스를 사용자 정의 위젯(SplashScreen 클래스)이 상속받으면 됩니다. 그러면 ❸ build(   ) 함수를 필수적으로 오버라이드하게 되는데 화면에 그려주고 싶은 위젯을 입력하면 됩니다. 사용자 정의해서 만든 SplashScreen 위젯을 앱 전체 화면으로 사용할 겁니다. 그러므로 ❶ runApp(   ) 함수의 매개변수로 제공하겠습니다.

 

03 아직 SplashScreen의 build(   ) 함수에서 아무것도 반환을 해주지 않습니다. ❶ MaterialApp 위젯과 ❷ Scaffold 위젯을 기본 제공한 뒤 ❸ 화면 중앙에 ❹ Splash Screen이라는 글자를 넣어주겠습니다. MaterialApp 위젯과 Scaffold 위젯이 어떤 역할을 하는지는 나중에 프로젝트를 진행하면서 차차 알게 됩니다. 지금은 MaterialApp이 항상 최상단에 입력되고 그다음으로 Scaffold 앱이 입력된다는 정도로만 알고 있으면 됩니다.

 

import 'package:flutter/material.dart';

void main() {
 runApp(SplashScreen());
}

class SplashScreen extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return MaterialApp(// ❶ 항상 최상단에 입력되는 위젯
     home: Scaffold(  // ❷ 항상 두 번째로 입력되는 위젯
       body: Center(  // ❸ 중앙 정렬 위젯
         // ❹ 글자를 화면에 보여주는 위젯
         child: Text('Splash Screen'),
       ),
     ),
   );
 }
}

 

▼ 실행 화면

 

04 코드를 실행하면 화면 중앙에서 Splash Screen이라는 글자를 확인할 수 있습니다. runApp(   )에 SplashScreen 위젯을 매개변수로 제공해주었더니 앱 화면에서 SplashScreen의 build(   ) 함수에 있는 코드의 실행 결과가 보입니다. 이로써 사용자 정의 위젯을 정의해 사용했습니다. 아울러 build(   ) 함수가 위젯의 UI를 결정한다는 걸 알 수 있습니다.

 

4.2 배경색 바꾸기 : Container와 BoxDecoration 위젯

이번에는 배경색을 바꿔보겠습니다. 배경 관련 UI를 변경할 때 Container 위젯을 가장 많이 사용합니다.

 

To Do

01 배경색을 화면 전체에 적용할 계획이니 Scaffold 위젯 바로 아래에 Container 위젯을 적용해 배경화면을 오렌지색으로 변경하겠습니다.

 

import 'package:flutter/material.dart';

void main() {
 runApp(SplashScreen());
}

class SplashScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Container( // ❶ 컨테이너 위젯
          // ❷ 컨테이너를 디자인하는 클래스
          decoration: BoxDecoration(
            color: Colors.orange, // ❸ 색상
          ),
          child: Center(
            child: Text('Splash Screen'),
          ),
        ),
      ),
    );
  }
}

 

▼ 실행 화면

 

❶ Container는 ❷ decoration이라는 네임드 파라미터를 제공합니다. ❷ decoration이라는 매개변수에는 BoxDecoration 클래스를 사용하게 되는데 BoxDecoration의 매개변수를 통해서 배경색, 테두리 색상, 테두리 두께 등 컨테이너의 여러 가지 UI 요소를 지정할 수 있습니다.

❷ BoxDecoration의 ❸ color 매개변수에 Colors.orange값을 적용했습니다. 일반적으로 프로그래밍할 때 색상은 헥스 코드(Hex Code)(예 : #FEFEFE)를 사용해서 지정합니다. 플러터에서도 헥스 코드를 사용해서 정확한 색상을 지정하는 방법도 있지만 Colors 클래스를 이용하면 헥스 코드 없이 쉽게 기본 색상 중에 원하는 색상을 골라낼 수 있습니다.

02 코드를 작성하고 나면 메뉴에서 [File] → [Save All]을 눌러서 파일을 저장합니다(단축키 : 윈도우 Ctrl + S , macOS Cmd + S ). 저장을 하고 나면 마법같은 일이 일어납니다. 따로 실행 버튼을 누르지 않았는데 앱의 화면이 변경한 코드대로 반영됩니다. 핫 리로드(Hot Reload)라는 편리한 기능 덕분입니다.

 

4.3 이미지 출력하기 : Image 위젯

‘Splash Screen’이라는 글자 대신 코드팩토리 로고를 출력하겠습니다. Text 위젯 대신에 이미지를 보여줄 Image 위젯을 사용하면 됩니다. Image 위젯은 다음과 같이 다섯 가지 생성자가 있습니다.

 

  1. 기본 Image 생성자는 ImageProvider라는 또 다른 위젯에서 이미지를 그립니다.
  2. Image.asset 생성자는 앱에 저장된 asset 파일로 이미지를 그립니다.
  3. Image.network 생성자는 URL을 통해서 이미지를 그립니다.
  4. Image.file 생성자는 파일을 통해서 이미지를 그립니다.
  5. Image.memory 생성자는 메모리에서 직접 이미지를 그립니다.

우선 앱에 저장해둔 asset 파일로 이미지를 그려낼 수 있는 Image.asset 생성자를 사용하겠습니다.

 

To Do

01 깃허브에서 내려받은 예제 프로젝트에서 코드팩토리 로고 이미지를 옮겨오겠습니다. ❶ 프로젝트 폴더 위에서 마우스 오른쪽 클릭한 후 [New] → [Directory]를 선택하겠습니다. 팝업창에 assets를 입력해 ❷ [assets] 폴더를 생성합니다. 그리고 [assets] 폴더에 내려받은 코드팩토리 이미지를 드래그 앤 드롭해서 ❸ logo.png라는 이름으로 저장합니다.

 

02 [assets] 폴더에 로고 파일을 추가했지만 아직은 화면에 불러올 수 없습니다. 프로젝트 구조를 보면 맨 아랫부분에 pubspec.yaml 파일이 있습니다. 플러터 프로젝트가 처음 생성되면서 자동으로 생성되는 파일인데 프로젝트에서 사용할 폰트, 이미지, 외부 플러그인 등을 지정하는데 사용합니다. 따라서 이미지를 담을 [asset] 폴더를 pubspec.yaml 파일에 지정해야 합니다. pubspec.yaml 파일을 더블 클릭해서 열어보겠습니다.

 

💡Note: yaml 파일은 현대 프로그래밍에서 설정값을 지정할 때 흔히 사용되는 구조입니다. YAML은 JSON과 비슷하게 키/값이 쌍입니다. : 기호를 기준으로 왼쪽이 키, 오른쪽이 값이 됩니다. 추가적으로 탭 개수로 키/값의 깊이를 정합니다. YAML의 구조에 대해 더 자세히 알고 싶으면 코드팩토리의 2분만에 배우는 YAML 영상 https://youtu.be/1GRKklx4xeo을 참조하시길 바랍니다.

 

03 flutter.assets라는 키에 ❶ [assets] 폴더를 지정합니다.

flutter:

 # The following line ensures that the Material Icons font is
 # included with your application, so that you can use the icons in
 # the material Icons class.
 uses-material-design: true
 assets: # 주석 처리를 풀어주세요.
   - assets/ # ❶ 이미지를 담을 폴더 이름을 적어주세요

 

assets:가 주석 처리되어 있습니다. 주석 처리를 해제하고 그 아래에 원하는 폴더를 지정하면 됩니다. YAML에서 – 기호는 리스트값을 의미하기 때문에 원하는 만큼 -로 시작하는 값들을 계속 추가할 수 있습니다.

 

04 pubspec.yaml은 플러터 프로젝트의 모든 설정이 담긴 파일입니다. 설정을 변경했으므로 asset 파일을 프로젝트에 추가하고, 새로운 플러그인을 내려받는 등 추가 작업이 필요합니다. 플러터에서는 [pub get] 기능을 제공해 이 작업을 자동으로 처리해줍니다. 파일이 수정되었을 때 에디터 위에 자동으로 나타나는 ❶ [pub get] 기능을 클릭해 실행합니다.

 

💡TIP: CLI에서도 pub get 기능할 수 있습니다. 편집기 아래에 있는 ❶ [Terminal] 탭을 클릭해 터미널로 이동해서 ❷ ‘flutter pub get’ 명령어를 실행하면 됩니다.

 

05 [pub get] 기능을 실행하고 나면 앱을 다시 실행을 해야 새로 바뀐 설정이 적용됩니다. 앱을 종료한 후 다시 실행 버튼을 눌러서 새로운 설정을 적용한 채로 앱을 실행하겠습니다.

 

06 코드를 변경한 게 없기 때문에 앱을 재실행해도 화면은 바뀌지 않습니다. 하지만 이제 assets/logo.png 파일을 플러터 코드에서 불러올 수 있게 되었습니다. 글자를 보여주는 Text 위젯을 그림을 보여주는 Image.asset 위젯으로 대체하겠습니다.

 

import 'package:flutter/material.dart';

void main() {
 runApp(SplashScreen());
}

class SplashScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Container(
          decoration: BoxDecoration(
            color: Colors.orange, 
          ),
          child: Center(
            // ❶ Text 위젯을 Image 위젯으로 변경
            child: Image.asset(
              'assets/logo.png',
            ),  
          ),
        ),
      ),
    );
  }
}

 

▼ 실행 화면

❶ Image.asset은 매개변수 하나를 받게 됩니다. 파일의 위치(여기서는 assets/logo.png)를 적어주면 됩니다.

 

07 이미지를 화면에 보여주는 건 성공했지만 로고 이미지의 배경 색상이 앱 전체의 배경 색상과 맞지가 않습니다. Colors.orange 대신에 배경색의 정확한 헥스 코드를 사용해서 이미지 배경색과 앱의 배경색을 똑같이 맞춰보겠습니다. 코드팩토리 로고의 정확한 헥스 코드는 #F99231입니다. 헥스 코드를 색상으로 사용하려면 Colors 대신 Color라는 클래스를 사용해야 합니다. 다음과 같 이 해당 코드를 수정해주세요.

 

▼ 수정 전

color: Colors.orange,

 

▼ 수정 후

olor: Color(0xFFF99231),

 

Colors 클래스를 단순히 Color로 변경하고 첫 번째 위치 매개변수에 헥스 코드를 제공해 색상을 표현했습니다. 6자리 헥스 코드의 앞에 16진수를 의미하는 0x와, 불투명도 100%를 의미하는 ‘FF’를 추가한 다음에 헥스 코드를 ‘#’ 없이 입력하면 됩니다. 결과적으로 F99231이라는 색상은 0xFFF99231로 입력하면 됩니다. 이를 반영하고 저장하면 앱의 배경색과 로고의 배경 색상이 같은 결과 화면을 얻을 수 있습니다.

어느 정도 원하는 목표와 가까워졌습니다. 마지막으로 로고 아래에 로딩 애니메이션을 추가하고 로고 크기를 조절해주면 됩니다.

 

 

4.4 위젯 정렬하기 : Row & Column 위젯

로딩 애니메이션 위젯을 직접 구현할 수도 있지만 이미 플러터팀이 만들어 제공하는 애니메이션 위젯을 사용하겠습니다. 애니메이션 위젯으로는 LinearProgressIndicator와 CircularProgressIndicator가 있습니다. LinearProgressIndicator는 일자 형태로, CircularProgressIndicator는 동그라미 형태로 로딩 애니메이션이 실행되는 위젯입니다.

로고 아래에 동그라미 형태의 로딩 애니메이션을 사용하겠습니다. 그러려면 세로로 가운데 정렬이 필요합니다. Center 위젯은 child에 위젯을 하나만 받을 수 있습니다. 어떻게 Image 위젯과 CircularProgressIndicator 위젯을 모두 가운데 정렬할 수 있을까요?

답은 Row와 Column 위젯에 있습니다. 한글로 Row는 행, 즉 가로를 의미하고 Column은 열, 즉 세로를 의미합니다. Center 위젯은 child에 하나의 위젯만 받을 수 있지만 Row와 Column 위젯은 children 매개변수에 리스트로 원하는 만큼 위젯을 추가할 수 있습니다.

 

To Do

01 로고와 로딩 애니메이션을 정렬하겠습니다. 세로로 가운데 정렬을 할 계획이니 Center 위젯을 Column 위젯으로 변경하고 children 매개변수에 Image 위젯과 CircularProgress Indicator를 모두 넣으면 됩니다.

import 'package:flutter/material.dart';

void main() {
 runApp(SplashScreen());
}

class SplashScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Container(
          decoration: BoxDecoration(
            color: Colors.0xFFF99231,
          ),
          child: Center(
            child: [
              Image.asset(
                'assets/logo.png',
              ),
              CircularProgressIndicator(),
            ],  
          ),
        ),
      ),
    );
  }
}

 

▼ 실행 화면

 

❶ 서브에 위젯들을 입력할 때 대표적으로 child와 children 매개변수가 있습니다. child는 단일 위젯을 입력할 때 사용되고 children 매개변수는 여러 위젯을 입력할 수 있습니다. Column은 children 매개변수를 사용하니 리스트 안에 위젯들을 보여주고 싶은 순서대로 입력해야 합니다. 코딩한 위젯 순서대로 로고가 먼저 나오고 로딩 위젯이 아래에서 빙글빙글 도는 걸 볼 수 있습니다. 하지만 Center 위젯과 다르게 Column 위젯을 사용하니 화면 맨 위에 로고가 위치합니다.

 

02 mainAxisAlignment 매개변수를 이용해서 children에 포함된 위젯들을 재배치할 수 있습니다. mainAxisAlignment 매개변수에는 MainAxisAlignment라는 enum값이 들어가는데 먼저 가운데를 의미하는 MainAxisAlignment.center를 적용합니다. 기존 코드에 ❶ mainAxisAlignment: MainAxisAlignment.center;를 추가해주세요. 그러면 Image 위젯과 CircularProgressIndicator 위젯이 가운데 정렬됩니다.

 

import 'package:flutter/material.dart';

void main() {
 runApp(SplashScreen());
}

class SplashScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Container(
          //
          decoration: BoxDecoration(
            color: Colors.0xFFF99231,
          ),
          child: Column(
            // ❶ 가운데 정렬 추가
            mainAxisAlignment: MainAxisAlignment.center,
            child: [
              Image.asset(
                'assets/logo.png',
              ),
              CircularProgressIndicator(),
            ],  
          ),
        ),
      ),
    );
  }
}

 

▼ 실행 화면

 

03 이제 로고 이미지 크기를 조금 줄여보겠습니다. 이미지 크기 조절에는 Image 위젯의 width(너비) 또는 height(높이) 매개변수를 사용합니다. ❶ width 매개변수에 200 픽셀을 입력해서 코드팩토리 로고 너비를 줄여보겠습니다.

 

import 'package:flutter/material.dart';

void main() {
 runApp(SplashScreen());
}

class SplashScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Container(
          //
          decoration: BoxDecoration(
            color: Colors.0xFFF99231,
          ),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            child: [
              Image.asset(
                'assets/logo.png',
                width: 200,    // ❶ 너비 추가
              ),
              CircularProgressIndicator(),
            ],  
          ),
        ),
      ),
    );
  }
}

 

▼ 실행 화면

 

주황색 배경도 통째로 작아졌습니다. 의도와 다른 결과입니다. Column의 경우 세로로 최대한 크기를 차지하는 특성이 있습니다. 하지만 가로로는 최소한 크기만 차지합니다. 현재 Column 위젯 안에 Image 위젯과 CircularProgressIndicator 위젯만 존재하고 둘 중 더 큰 위젯인 Image 위젯이 가로로 200 픽셀만큼 차지하고 있기 때문에 Column 위젯 또한 가로로 200 픽셀만 차지합니다.

 

04 Row 위젯은 Column 위젯과 정확히 반대로 작동합니다. 가로로는 최대 크기를 차지하고 세로로는 최소 크기를 차지합니다. Row 위젯으로 Column 위젯을 감싸면 Column 위젯과 마찬가지로 Row 위젯도 기본적으로 왼쪽부터 위젯들을 정렬합니다. 하지만 가로, 세로 모두 가운데 정렬을 할 계획이기 때문에 Row의 mainAxisAlignment 매개변수에도 MainAxisAlignment.center를 입력하겠습니다. child: Column 블록을 다음과 같이 수정합니다.

 

import 'package:flutter/material.dart';

void main() {
 runApp(SplashScreen());
}

class SplashScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Container(
          //
          decoration: BoxDecoration(
            color: Colors.0xFFF99231,
          ),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Column(
              mainAxisAlignment: MainAxisAlignment.center,
              child: [
                Image.asset(
                  'assets/logo.png',
                  width: 200,  
                ),
                CircularProgressIndicator(),
              ],  
            ),
          ],
        ),
      ),
    );
  }
}

 

05 드디어 정렬에 성공했습니다. 마지막으로 로딩 위젯(CircularProgressIndicator)을 흰색으로 바꿔보겠습니다.

CircularProgressIndicator와 LinearProgressIndicator는 모두 backgroundColor와 valueColor라는 색상 매개변수를 제공합니다. backgroundColor는 말 그대로 위젯의 배경 색상을 의미하고 valueColor는 실제로 애니메이션으로 움직이는 부분의 색상을 의미합니다. 애니메이션으로 돌아가는 색상을 흰색으로 변경하기 위해 valueColor 매개변수를 활용하겠습니다. 플러터의 대부분의 색상 매개변수는 직접 Color 또는 Colors를 사용해서 색상을 입력하면 됩니다. 하지만 valueColor의 경우 색상이 애니메이션되어야 하기 때문에 Colors.white를 직접 넣을 수 없습니다. 대신에 AlwaysStoppedAnimation이라는 클래스에 감싸서 색상을 제공하겠습니다.

... 생략 ...
CircularProgressIndicator(
 valueColor: AlwaysStoppedAnimation(
   Colors.white,
 ),
),
... 생략 ...

 

드디어 원하는 결과를 얻었습니다. 축하드립니다.

 

 

앱 개발 튜토리얼 마무리

핵심 요약

  1. 플러터는 머티리얼 디자인을 사용하기 때문에 프로젝트의 위젯 트리 가장 상단에 Material App 위젯과 Scaffold 위젯을 사용합니다.
  2. Container 위젯에는 배경색을 적용할 수 있습니다.
  3. Image 위젯은 화면에 이미지를 보여줄 수 있습니다.
  4. flutter pub get을 실행하면 pubspec.yaml의 변경 사항을 프로젝트에 적용할 수 있습니다.
  5. Column 위젯을 이용하면 다수의 위젯을 세로로 배치할 수 있습니다.
  6. Row 위젯을 이용하면 다수의 위젯을 가로로 배치할 수 있습니다.

업그레이드 아이디어

  1. 앱 중앙의 로고를 변경해보세요.
  2. 로고의 너비와 높이를 변경해보세요. 높이는 height 매개변수를 사용하면 됩니다.
  3. 로딩애니메이션의 색상을 빨간색으로 변경해보세요.

 

이것으로 본격적으로 앱을 만들 준비를 마쳤습니다. 하나에 모든 플러터 개발 내용을 다 담을 수는 없지만, 이번 내용은 앱을 만들면 반복적으로 활용하게 되므로 자연스럽게 체화될 겁니다.

최지호(코드팩토리) 
임페리얼 칼리지 런던을 졸업하고 계리 컨설팅 회사 밀리만(Milliman) 한국 지사에서 소프트웨어 엔지니어로 일했습니다. 현재 주식회사 코드팩토리를 창업하여 개발을 하면서 초보자뿐만 아니라 현직 개발자에게도 유용한 개발 강의를 제작합니다. 밀리의서재 플러터 전환 차세대 프로젝트를 리드했습니다.

Leave a Reply

©2020 GoldenRabbit. All rights reserved.
상호명 : 골든래빗 주식회사
(04051) 서울특별시 마포구 양화로 186, 5층 512호, 514호 (동교동, LC타워)
TEL : 0505-398-0505 / FAX : 0505-537-0505
대표이사 : 최현우
사업자등록번호 : 475-87-01581
통신판매업신고 : 2023-서울마포-2391호
master@goldenrabbit.co.kr
개인정보처리방침
배송/반품/환불/교환 안내