-
[Flutter] Main View(메인 화면) 만들기 (feat. Dart 설명)공부 2026. 10. 4. 02:50
오늘의 목표는 Flutter의 구조를 이해하는 것이다.
그래서 토이프로젝트로 진행 중인 앱을 실행하면 나오는
로딩화면과 메인화면 두 개를 만들어서 자연스럽게 이어서 실행되도록 만드는 것이 목표이다.
화면을 만들기 전에 Flutter의 기능에 대해서 간략히 정리하자면,
Flutter는 Dart라는 언어로 개발하게 된다.Dart는 기본적으로 C언어의 문법과 비슷하며 Java나 C#과 같이 객체지향 프로그래밍을 지원하는 언어이다.
Flutter에는 "Widget(위젯)"이라는 개념이 있다.
Widget은 Flutter에서 화면을 구성하거나 화면의 구조와 배치를 정의하는 기본 단위를 말한다.
이렇게 말하면 뭔가 이해가 팍 안 되는데, "Widget(위젯)"을 단순하게 설명하면 레고 블록이라 생각하면 쉽다.
그래서 Widget이라는 것은 글자(Text)가 있기도 하고, 사진(Image)이 있기도 하고, 버튼(Button)과 같이 우리가 애플리케이션을 실행하면 보이는 화면을 구성하는 여러 블록들을 의미한다.
그리고 Text, Image, Button처럼 화면에 실제로 표시되는 Widget도 있지만, Column, Row처럼 다른 Widget들을 어떻게 배치할지를 정하는 Widget도 있다.
즉, Widget을 조합해서 하나의 화면을 만들어가는 구조라고 생각하면 된다.
그리고 Flutter는 Dart라는 프로그래밍 언어로 작성되는데, Dart는 Java와 같은 객체지향 프로그래밍 언어이고 Object(객체)를 만들기 위한 설계도 역할을 하는 Class를 사용한다.
Dart에서는 이러한 Class를 이용해서 Widget을 정의한다.
예를 들어 MainScreen이라는 Class를 만들고 그 안에 Column, Text, Image, Button 등의 Widget을 어떻게 배치할지 정의할 수 있다.
그리고 이렇게 만들어진 Widget들이 서로 연결되면서 Widget Tree(위젯 트리)라는 구조를 만든다.
Class로 Widget을 정의하고 ↓ Widget들을 레고처럼 조합하여 ↓ Widget Tree(설계도)를 만들고 ↓ Flutter가 이것을 화면에 표시한다.
라고 이해하면 된다.
객체 지향 프로그래밍 그래서 위 사진과 같은 객채 지향 언어의 특징인 Class를 정의하면 그 Class를 재활용해 여러 Instance(Object)를 만들어 쓸 수 있다.
Flutter에서 사용되는 Dart언어에서는 다음과 같은 형태로 이용한다.// 1. 설계도 재활용: 클래스 하나로 서로 다른 자동차 인스턴스 여러 개 생성 Car model3 = Car('모델3', 'white'); Car modelS = Car('모델S', 'Red'); // 2. 결과물(인스턴스) 재활용: 만들어둔 인스턴스를 여러 곳에서 다시 사용 void driveToWork() { model3.drive(); // 출근할 때 모델3 인스턴스 사용 } void driveToMarket() { model3.drive(); // 장보러 갈 때도 같은 모델3 인스턴스 재사용 }
내용이 좀 샜는데 플러터의 특징은 이러하다.
따라서 오늘 만들 로딩화면과 메인화면도 결국 각각 하나의 Widget들로 조립하고, 앱이 실행됐을 때Loding Screen → Main Screen 순서로 연결되도록 만드는 것이다.
1. Flutter 앱의 시작점 — main()Flutter 앱은 Dart의 main() 함수에서 시작한다.
Dart 프로그램이 실행되면 가장 먼저 main()이 실행된다.
void main() { runApp(const AidaApp()); }runApp()은 특정 화면을 직접 실행하는 함수라기보다는 Flutter에게 앱의 Root Widget을 전달하여 앱을 시작하도록 하는 역할을 한다.
Widget을 레고라고 말했는데, Root Widget은 특별한 기능을 가진 Widget이라기보다는 Widget의 구조를 트리 형태로 표현했을 때 그 구조의 최상위에 있는 Widget이다.

플러터의 실행 구조
runApp()을 통해 Flutter에게 내가 만든 Root Widget을 전달하면, Flutter는 그 Widget을 시작점으로 해서 그 아래에 연결된 Widget들을 포함한 전체 Widget 구조를 구성한다.그래서 전체적인 실행 흐름을 정리하면 다음과 같다.
앱 실행 ↓ main() ↓ runApp() ← AidaApp을 Root Widget으로 지정 ↓ AidaApp ← 우리 앱의 전체 구조를 구성하는 Root Widget ↓ MaterialApp ← 이 앱에서 사용할 기본적인 Flutter 앱 환경과 설정 ↓ 첫 번째 화면 ← 실제로 우리가 의도한 화면그래서 단순한 앱을 만든다면 main에 모든 코드를 정의해도 괜찮지만, 이번에는 하나의 서비스를 완성하는게 목표이니간
관리의 편의성을 위해 Class를 따로 생성해서 main에 import 해서 실행하는 형식으로 분리해서 만들 계획으로
오늘 생성할 파일의 전체 구조도는 다음과 같다.
이런 형태 2. 앱에서 사용할 이미지 추가하기
플러터에서 이미지는 assets/ 에 추가한다.
그리고 이미지를 불러오기 위해서는 pubspec.yaml에 Asset 경로를 등록한다.
pubspec.yaml 친절하게 전부 설명되어있음
그리고 Darf 코드에서는 다음과 같이 이미지를 불러온다.Image.asset( 'assets/main_image/aida_choice.png', )3. Native Splash 설정
Flutter의 외부 패키지 중에는 Splash Screen라는게 있다.
Splash Screen은 앱이 실행될때 메인 화면으로 들어가기 전에 준비(로딩)화면으로 사용되는 화면이라 생각하면된다.설치:
flutter pub add flutter_native_splash
명령어를 실행하면 Flutter가 해당 패키지를 프로젝트에 추가하고, pubspec.yaml 파일의 dependencies에 자동으로 등록해준다.하지만 패키지를 설치했다고 바로 원하는 Splash 화면이 만들어지는 것은 아니다.
내가 원하는 배경, 이미지를 설정하려면 추가로 pubspec.yaml의 flutter_native_splash 항목에서 설정을 추가로 해줘야한다.flutter_native_splash: color: "#FFFFFF" image: assets/images/splash.png여기 까지 설정을 완료했다면, 아래 명령어를 실행하면 설정은 끝난다.
dart run flutter_native_splash:create이 명령어을 통해 작성해 놓은 설정을 실제 Android/iOS 앱 프로젝트에 적용하는 역할을 한다.
이것으로 앱이 실행될 때 로딩화면으로 사용할 Native Splash를 설정은 전부 끝났다.4. 로그인/회원가입 선택 화면 만들기
AuthChoice에는 사용자가 처음 서비스를 이용한다면 보통 로그인 또는 회원 등록을 처음에 선택할 거라 생각하여
화면에는 로그인 버튼, 회원가입 버튼 두 개로 구성해 작성하여 제일 초기화면에 나오도록 설정했다.import 'package:flutter/material.dart'; //2. AuthChoice View class AuthChoice extends StatelessWidget { const AuthChoice({super.key}); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFFF15C58), body: Stack( fit: StackFit.expand, children: [ Center( child: Image.asset( 'assets/main_image/aida_choice.png', fit: BoxFit.contain, ), ), Positioned( left: 24, right: 24, bottom: 40, child: Column( children: [ // 1. Sign Up Button SizedBox( width: double.infinity, height: 55, child: ElevatedButton( onPressed: () {}, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF1D232A), ), child: const Text( 'アカウントを作成する', style: TextStyle(fontSize: 16, color: Colors.white), ), ), ), const SizedBox(height: 12), // 두 버튼 사이 간격 추가 // 2. Login Button SizedBox( width: double.infinity, height: 55, child: ElevatedButton( onPressed: () {}, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF1D232A), ), child: const Text( 'ログイン', style: TextStyle(fontSize: 16, color: Colors.white), ), ), ), ], ), ), ], ), ); } }그리고 생성한 AuthChoice를 main.Dart에 import 하여 다음과 같이 정의해서 이동되도록 설정했다.
import 'package:flutter/material.dart'; import 'appviews/AuthChoice.dart'; // sign_up or login choice View void main() { runApp(const AidaApp()); } // 0. 랜딩 페이지 class AidaApp extends StatelessWidget { const AidaApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: const AuthChoice(), ); } }flutter run 명령어로 실행했더니 다음과 같이 성공적으로 원하는 디자인과 화면이 출력됨.

메인화면 5. 정리
오늘의 목표였던
Flutter의 구조를 이해하고, AIDA 앱을 실행했을 때 로딩 화면과 메인 화면이 자연스럽게 이어지도록 만들기
까지 완료했다.
현재 AIDA의 초기 진입 구조는:
Native Splash ↓ Flutter 실행 ↓ AidaApp ↓ AuthChoice이 구조를 기반으로 다음에는 AuthChoice에서 회원가입 화면과 로그인 화면으로 이동하는 부분을 연결할 수 있다.
'공부' 카테고리의 다른 글
[Flutter] Flutter 프로젝트 생성 및 테스트 코드 실행해보기 (0) 2026.09.28 [Flutter] Mac flutter 개발 환경 설치 (Mac OS 13 Ventura) (0) 2026.09.28 [SOAR] stackstorm Rule 작성해보기 (0) 2026.01.09 [SOAR] stackstorm 정리 및 설치 (0) 2026.01.08 [Mac] 맥으로 터미널로 ssh 접속하기 (0) 2025.11.11