Flutter는 구글이 개발한 오픈소스 UI 소프트웨어 개발 키트로, 단일 코드베이스를 통해 Android, iOS, 웹, 데스크톱 등 다양한 플랫폼에서 네이티브 수준의 성능을 내는 아름다운 애플리케이션을 제작할 수 있게 해줍니다. 개발자들은 Flutter의 빠른 개발 속도, 풍부한 위젯 라이브러리, 그리고 뛰어난 성능에 매료되어 빠르게 Flutter 생태계로 유입되고 있습니다. 하지만 Flutter 프로젝트의 여정을 시작하는 가장 첫 단계, 바로 flutter create
명령어 뒤에 숨겨진 중요한 선택지를 놓치는 경우가 많습니다.
대부분의 Flutter 입문 가이드는 단순히 flutter create my_app
이라는 명령어를 알려주는 데 그칩니다. 이 명령어를 실행하면 프로젝트는 문제없이 생성되지만, 한 가지 중요한 사실을 간과하게 됩니다. 바로 네이티브 플랫폼의 기본 언어가 Android는 Java, iOS는 Objective-C로 설정된다는 점입니다. Java와 Objective-C는 오랫동안 각 플랫폼의 표준 언어였지만, 이제는 새로운 시대의 주역인 Kotlin과 Swift에게 자리를 내어주고 있습니다. 이 글에서는 왜 새로운 Flutter 프로젝트를 시작할 때 Kotlin과 Swift를 선택해야 하는지, 그리고 어떻게 설정하는지, 더 나아가 flutter create
명령어의 다양한 옵션을 활용하여 프로젝트를 완벽하게 제어하는 방법을 심도 있게 다룰 것입니다.
1. 왜 Kotlin과 Swift인가? 구시대의 언어를 넘어서야 하는 이유
Flutter는 Dart 언어로 UI와 비즈니스 로직을 작성하지만, 최종적으로 앱이 사용자 기기에서 실행되기 위해서는 각 플랫폼의 네이티브 코드로 컴파일되고 패키징되는 과정을 거칩니다. 카메라, GPS, 블루투스 등 기기의 고유 기능을 사용하거나, 특정 플랫폼에만 존재하는 SDK를 연동해야 할 때 Flutter는 '플랫폼 채널(Platform Channels)'을 통해 네이ティブ 코드와 통신합니다. 이때 우리가 마주하게 되는 코드가 바로 Android의 Kotlin/Java, iOS의 Swift/Objective-C 코드입니다.
Kotlin: 구글이 선택한 안드로이드의 미래
2019년, 구글은 안드로이드 앱 개발의 공식 언어(First-class language)로 Kotlin을 지정했습니다. 이는 안드로이드 생태계의 패러다임이 Java에서 Kotlin으로 완전히 전환되었음을 의미합니다. 새로운 Flutter 프로젝트에서 Kotlin을 사용해야 하는 이유는 명확합니다.
- 간결하고 표현력 있는 문법: Kotlin은 Java의 장황한 상용구(boilerplate) 코드를 대폭 줄여줍니다. 같은 기능을 구현하더라도 훨씬 적은 양의 코드로 작성할 수 있어 가독성과 생산성이 향상됩니다.
- Null 안정성(Null Safety): Kotlin의 타입 시스템은 Null Pointer Exception(NPE)을 근본적으로 방지하도록 설계되었습니다. 이는 '10억 달러의 실수'라고 불리는 NPE로부터 앱의 안정성을 획기적으로 높여줍니다.
- 코루틴(Coroutines)을 통한 비동기 처리: 복잡한 콜백 지옥(Callback Hell) 없이 비동기 코드를 동기 코드처럼 간결하게 작성할 수 있게 해주는 코루틴은 현대적인 앱 개발의 필수 요소입니다.
- 100% Java 호환성: 기존의 방대한 Java 라이브러리와 프레임워크를 아무런 문제 없이 Kotlin 프로젝트에서 그대로 사용할 수 있습니다.
- 활발한 커뮤니티와 공식 지원: 구글의 전폭적인 지원 아래 최신 안드로이드 기능과 Jetpack 라이브러리들은 Kotlin을 우선적으로 지원하며, 관련 자료와 커뮤니티 역시 빠르게 성장하고 있습니다.
Swift: 애플이 만든 안전하고 빠른 언어
애플은 2014년에 Swift를 공개하며 iOS 및 macOS 개발의 새로운 시대를 열었습니다. Swift는 Objective-C를 대체하기 위해 만들어졌으며, 현대적인 프로그래밍 언어의 장점을 집약했습니다.
- 안전성(Safety): Swift는 옵셔널(Optionals) 개념을 통해 변수가 값을 가지지 않는 경우(nil)를 명시적으로 처리하도록 강제하여, 예기치 않은 런타임 오류를 컴파일 시점에 발견할 수 있도록 돕습니다.
- 속도(Speed): 이름에서 알 수 있듯이, Swift는 C++에 버금가는 높은 성능을 목표로 설계되었습니다. 강력한 컴파일러 최적화를 통해 Objective-C보다 월등한 실행 속도를 보여줍니다.
- 현대적인 문법: Swift는 다른 현대 언어들처럼 읽고 쓰기 쉬운 깔끔한 문법을 제공합니다. 이는 코드의 유지보수성을 높이고 새로운 개발자의 진입 장벽을 낮춥니다.
- ARC (Automatic Reference Counting): 메모리 관리를 자동화하여 개발자가 메모리 누수 걱정 없이 비즈니스 로직에 집중할 수 있도록 해줍니다.
- 애플의 지속적인 투자: 애플은 매년 Swift 언어를 업데이트하며 새로운 기능과 성능 개선을 선보이고 있습니다. SwiftUI와 같은 차세대 프레임워크는 Swift 언어를 기반으로만 동작합니다.
결론적으로, 새로운 Flutter 프로젝트를 Java와 Objective-C로 시작하는 것은 마치 최신형 전기차를 구매하면서 구형 가솔린 엔진을 장착하는 것과 같습니다. 당장은 작동하겠지만, 미래의 기술 발전, 성능, 유지보수, 그리고 개발자 경험 측면에서 큰 손해를 보게 됩니다. 따라서 현대적인 앱 개발의 표준인 Kotlin과 Swift를 선택하는 것은 선택이 아닌 필수입니다.
2. 실전! Kotlin/Swift 기반 Flutter 프로젝트 생성하기
그렇다면 어떻게 Kotlin과 Swift를 기본 언어로 사용하는 Flutter 프로젝트를 생성할 수 있을까요? 답은 flutter create
명령어에 몇 가지 옵션을 추가하는 것만으로 충분합니다.
기본 명령어와 옵션
터미널 또는 명령 프롬프트를 열고 다음 명령어를 입력해 보세요. app_name
부분은 원하는 프로젝트 이름으로 변경하면 됩니다.
flutter create -i swift -a kotlin your_awesome_app
이 명령어에 포함된 각 옵션의 의미는 다음과 같습니다.
-i swift
: iOS 플랫폼의 기본 언어를 Swift로 지정합니다.-i
는--ios-language
의 축약형입니다.-a kotlin
: Android 플랫폼의 기본 언어를 Kotlin으로 지정합니다.-a
는--android-language
의 축약형입니다.

터미널에서 Kotlin/Swift 옵션을 사용하여 Flutter 프로젝트를 생성하는 모습
생성 결과 확인하기
명령어를 실행한 후, 생성된 프로젝트 폴더의 구조를 살펴보면 기본 설정과의 차이점을 명확하게 확인할 수 있습니다.
Android 플랫폼 확인
VS Code, Android Studio 또는 다른 파일 탐색기에서 프로젝트 폴더를 열고 다음 경로로 이동해 보세요.
your_awesome_app/android/app/src/main/
기본값(Java)으로 생성된 프로젝트는 이 경로 아래에 java
폴더가 있지만, Kotlin으로 생성한 프로젝트는 kotlin
폴더가 생성된 것을 볼 수 있습니다. 메인 액티비티 파일의 위치와 확장자도 다릅니다.
- Java (기본값):
android/app/src/main/java/com/example/app_name/MainActivity.java
- Kotlin (옵션 적용):
android/app/src/main/kotlin/com/example/app_name/MainActivity.kt
MainActivity.kt
파일을 열어보면 간결한 Kotlin 코드로 작성된 것을 확인할 수 있습니다.
package com.example.your_awesome_app
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
}
iOS 플랫폼 확인
iOS의 경우, your_awesome_app/ios/Runner/
폴더 내부를 살펴보면 차이를 알 수 있습니다.
- Objective-C (기본값):
AppDelegate.h
와AppDelegate.m
파일이 생성됩니다. - Swift (옵션 적용):
AppDelegate.swift
파일 하나만 생성됩니다.
AppDelegate.swift
파일의 내용은 다음과 같습니다.
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
이처럼 간단한 옵션 추가만으로 프로젝트의 네이티브 기반을 최신 기술 스택으로 설정할 수 있습니다. 이는 향후 네이티브 기능 연동이나 유지보수 시점에서 엄청난 생산성 차이를 만들어낼 것입니다.
3. 앱의 고유 식별자 설정: --org 옵션 활용법
앱을 개발하여 구글 플레이 스토어나 애플 앱스토어에 출시하기 위해서는 앱마다 고유한 식별자가 필요합니다. 안드로이드에서는 이를 '패키지 이름(Package Name)' 또는 'Application ID'라고 부르고, iOS에서는 '번들 식별자(Bundle Identifier)'라고 합니다. 이 식별자는 보통 '역순 도메인(reverse domain name)' 형식을 따릅니다. 예를 들어, 여러분의 회사 도메인이 mycompany.com
이고 앱 이름이 my_app
이라면, 식별자는 com.mycompany.my_app
이 됩니다.
flutter create
명령어 실행 시 이 식별자를 미리 지정하지 않으면 기본값인 com.example.app_name
으로 설정됩니다. 'example' 도메인은 실제 출시용으로 사용할 수 없으므로 나중에 반드시 수정해야 하는 번거로움이 발생합니다. 이 과정을 처음부터 간단하게 처리할 수 있는 옵션이 바로 --org
입니다.
Kotlin/Swift 옵션과 --org
옵션을 함께 사용하여 완벽한 프로젝트를 생성하는 명령어는 다음과 같습니다.
flutter create --org com.mycompany -i swift -a kotlin my_app_name

조직(org) 옵션까지 포함하여 프로젝트를 생성하는 전체 명령어
패키지 이름/번들 식별자 확인하기
--org
옵션이 잘 적용되었는지 확인하는 방법은 다음과 같습니다.
Android (Application ID)
my_app_name/android/app/build.gradle
파일을 열어 defaultConfig
블록을 찾아보세요. applicationId
가 우리가 지정한 값으로 설정된 것을 확인할 수 있습니다.
android {
...
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.mycompany.my_app_name" // 이 부분 확인!
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
...
}
iOS (Bundle Identifier)
iOS의 번들 식별자는 Xcode에서 확인하는 것이 가장 직관적입니다. 터미널에서 다음 명령어를 실행하여 Xcode로 iOS 프로젝트를 여세요.
open my_app_name/ios/Runner.xcworkspace
Xcode가 열리면 왼쪽 네비게이터에서 최상단에 있는 Runner 프로젝트를 클릭한 후, 중앙 화면에서 TARGETS 아래의 Runner를 선택하고 General 탭을 확인하세요. Identity 섹션에 있는 Bundle Identifier가 com.mycompany.myAppName
과 같이 올바르게 설정된 것을 볼 수 있습니다.
이처럼 프로젝트 생성 단계에서 단 몇 개의 옵션을 추가하는 것만으로, 나중에 발생할 수 있는 수많은 설정 변경 작업을 예방하고 처음부터 깔끔하고 전문적인 프로젝트 구조를 갖출 수 있습니다.
4. `flutter create` 명령어, 더 깊이 파헤치기
flutter create
명령어는 우리가 살펴본 언어 및 조직 설정 외에도 수많은 유용한 옵션을 제공합니다. 이 옵션들을 알아두면 다양한 상황에 맞춰 최적화된 프로젝트를 생성할 수 있습니다. 터미널에서 flutter create --help
를 입력하면 전체 옵션 목록을 볼 수 있습니다. 여기서는 특히 유용한 몇 가지 옵션을 더 소개합니다.
옵션 | 설명 | 사용 예시 |
---|---|---|
--description |
프로젝트의 pubspec.yaml 파일에 들어갈 설명을 지정합니다. |
flutter create --description "My awesome new app" my_app |
--template |
생성할 프로젝트의 템플릿을 지정합니다. (app, package, plugin, skeleton 등) | flutter create --template=package my_package |
--platforms |
프로젝트가 지원할 플랫폼을 지정합니다. 지정하지 않으면 사용 가능한 모든 플랫폼이 포함됩니다. | flutter create --platforms=android,ios,web my_app |
--[no-]pub |
프로젝트 생성 후 자동으로 flutter pub get 을 실행할지 여부를 결정합니다. (기본값: 실행) |
flutter create --no-pub my_app |
--[no-]overwrite |
이미 존재하는 폴더에 프로젝트를 생성할 때 파일을 덮어쓸지 여부를 결정합니다. | flutter create --overwrite . |
특히 --template
옵션은 매우 강력합니다. 일반적인 앱을 만들 때는 app
(기본값)을 사용하지만, 다른 프로젝트에서 재사용할 Dart 코드를 작성할 때는 package
를, 네이티브 코드와 연동되는 기능을 모듈화할 때는 plugin
을 선택하여 처음부터 목적에 맞는 구조로 프로젝트를 시작할 수 있습니다. --template=skeleton
은 간단한 리스트-상세 화면 구조를 가진 샘플 앱을 생성해주어, 앱 구조 설계에 대한 좋은 참고 자료가 될 수 있습니다.
5. 이미 늦었나요? 기존 Java/Objective-C 프로젝트를 마이그레이션하는 방법
"이 글을 너무 늦게 봤습니다. 이미 Java와 Objective-C로 프로젝트를 한참 진행했는데 어떡하죠?"
걱정하지 마세요. 다소 번거롭지만 기존 프로젝트의 네이티브 언어를 Kotlin과 Swift로 전환할 수 있는 방법이 있습니다. 아쉽게도 Flutter는 이를 위한 자동화된 명령어를 제공하지 않으므로, 각 플랫폼의 개발 도구를 사용하여 수동으로 마이그레이션해야 합니다.
Android: Java에서 Kotlin으로 마이그레이션하기
안드로이드의 경우, Android Studio의 강력한 변환 기능 덕분에 비교적 쉽게 마이그레이션을 진행할 수 있습니다.
- Android Studio로 프로젝트 열기: Flutter 프로젝트의
/android
폴더를 Android Studio로 엽니다. (Flutter 프로젝트 전체를 열지 말고,android
폴더만 여는 것이 중요합니다.) - 자바 파일을 코틀린으로 변환: 왼쪽 Project 창에서
app/src/main/java/your/package/name/MainActivity.java
파일을 찾습니다. - 해당 파일을 우클릭하거나, 파일을 연 상태에서 상단 메뉴의 Code -> Convert Java File to Kotlin File을 선택합니다. (단축키:
Ctrl+Alt+Shift+K
또는Cmd+Option+Shift+K
) - Kotlin 플러그인 설정: 변환을 시도하면 Android Studio가 프로젝트에 Kotlin이 설정되어 있지 않다며 설정을 제안하는 창을 띄울 수 있습니다. 모든 모듈에 대해 Kotlin을 설정하도록 허용합니다. 이 과정에서
build.gradle
파일이 자동으로 수정됩니다. - 동기화 및 확인: Gradle 동기화가 완료되면
MainActivity.java
가MainActivity.kt
로 변경되고, 코드도 Kotlin으로 변환된 것을 확인할 수 있습니다.
이 과정을 통해 프로젝트의 주요 액티비티를 Kotlin으로 전환할 수 있습니다. 프로젝트에 다른 자바 파일이 있다면 동일한 방법으로 모두 변환해주는 것이 좋습니다.
iOS: Objective-C에서 Swift로 마이그레이션하기
iOS의 마이그레이션은 안드로이드보다 조금 더 복잡하며 신중한 접근이 필요합니다. 핵심은 Objective-C와 Swift 코드가 공존할 수 있도록 해주는 '브리징 헤더(Bridging Header)'를 생성하는 것입니다.
- Xcode로 프로젝트 열기: 터미널에서
open your_app/ios/Runner.xcworkspace
를 실행하여 프로젝트를 엽니다. - 새 Swift 파일 추가: Xcode의 Project Navigator에서 Runner 폴더를 우클릭하고 New File...을 선택합니다. 템플릿 선택 창에서 Swift File을 선택하고 다음을 클릭합니다. 파일 이름은
AppDelegate.swift
로 지정합니다. - 브리징 헤더 생성: Swift 파일을 추가하는 순간, Xcode는 "Would you like to configure an Objective-C bridging header?"라는 메시지를 표시합니다. 여기서 Create Bridging Header 버튼을 반드시 클릭해야 합니다. 그러면
Runner-Bridging-Header.h
라는 파일이 생성됩니다. 이 파일은 Swift 코드에서 기존 Objective-C 코드를, Objective-C 코드에서 새로운 Swift 코드를 참조할 수 있게 해주는 다리 역할을 합니다. - 코드 이전: 기존
AppDelegate.m
파일의 내용을 새로운AppDelegate.swift
파일로 옮겨옵니다. 문법이 다르므로 단순히 복사-붙여넣기가 아니라, Swift 문법에 맞게 코드를 다시 작성해야 합니다. 보통 Flutter 기본 템플릿의 내용은 위에서 보여드린 Swift 코드 예시와 거의 동일합니다. - 기존 파일 삭제:
AppDelegate.swift
작성이 완료되었다면, 더 이상 필요 없는AppDelegate.h
,AppDelegate.m
, 그리고main.m
파일을 프로젝트에서 삭제합니다. - (중요) Info.plist 수정:
main.m
을 삭제했다면,Info.plist
파일에서 "Main storyboard file base name" (UIMainStoryboardFile
) 항목을 찾아 삭제해야 할 수 있습니다. Swift 기반 앱에서는 스토리보드를 사용하지 않기 때문입니다.
이 과정은 프로젝트의 복잡성에 따라 난이도가 달라질 수 있습니다. 중요한 네이티브 코드가 많다면 마이그레이션 전에 반드시 프로젝트 전체를 백업하고, 단계별로 신중하게 진행해야 합니다.
결론: 현명한 첫걸음이 성공적인 프로젝트를 만든다
Flutter 개발의 여정은 flutter create
명령어 한 줄로 시작됩니다. 이때 무심코 엔터 키를 누르는 대신, -i swift
, -a kotlin
, --org
옵션을 추가하는 작은 습관이 여러분의 프로젝트를 더욱 견고하고, 현대적이며, 미래지향적으로 만들어 줄 것입니다.
Kotlin과 Swift는 단순히 최신 유행이 아닙니다. 각 플랫폼의 제조사인 구글과 애플이 직접 이끌어가는 개발의 표준이자 미래입니다. 이 언어들이 제공하는 안정성, 생산성, 그리고 성능의 이점을 적극적으로 활용함으로써, 우리는 Flutter의 장점을 극대화하고 더 나은 품질의 애플리케이션을 더 효율적으로 만들어낼 수 있습니다. 오늘부터 시작하는 모든 Flutter 프로젝트는 반드시 Kotlin과 Swift 기반 위에서 첫 삽을 뜨시기를 강력히 권장합니다.
0 개의 댓글:
Post a Comment