Flutter iOS Launch Screen & App Icons
Flutter 앱을 위한 전투 검증된 패턴: 첫 프레임에 네이티브 런치 로고와 iOS 사용자 설정 → Default / Dark / Clear / Tinted를 따르는 홈 화면 아이콘.
사용 시점
- 콜드 스타트 시 Flutter가 로드되기 전에 빈 흰색/아이보리 화면이 표시됨
- 시스템 모양(앱 내 ThemeCubit이 아님)을 따르는 라이트 + 다크 런치 로고 필요
- iOS 18+에서 앱 아이콘 Dark / Tinted / Clear 변형 필요
사용하지 말아야 할 때
- Android 스플래시 / Flutter 앱 내 SplashScreen만 필요한 경우
- 앱 내 테마 전환(HydratedBloc) — LaunchScreen 또는 SpringBoard 아이콘에 영향을 주지 않음
중요 규칙 (절대 건너뛰지 마세요)
- 런치 로고는 Assets.car의 이미지셋이 아닌, 앱 번들에 느슨한 PNG 파일이어야 합니다. SplashBoard는 첫 스냅샷에서
UIImage imageNamed로 Assets.car를 로드하는 데 실패하는 경우가 많으며, 그러면 2~3초 동안 빈 화면이 나타납니다. - 같은 기본 이름의 느슨한 파일이 있다면 BrandLogo를 Assets.xcassets에 넣지 마세요. 카탈로그가 우선시되어 로드가 실패합니다.
- LaunchScreen의 배경색은 스토리보드에서 명시적인 sRGB여야 합니다. 명명된 색상(예:
LaunchBackground)은 런치 스냅샷에서 전환에 실패하는 경우가 많습니다. - 트레이트 변형 키는
userInterfaceStyle=dark입니다(interfaceStyle또는luminosity=dark가 아님). - 이미 빌드된
.app에 독립적인ibtoolstoryboardc를 복사하여 런치를 확인하지 마세요. 이렇게 하면 검은색 플래시가 발생합니다. 항상flutter build ios --simulator(또는 기기)로 빌드한 후 삭제 후 재설치하세요. - Dark/Tinted를 추가한 후
flutter_launcher_icons를 실행하지 마세요. 이 도구는Contents.json을 덮어쓰고 모양을 삭제합니다. - 홈 아이콘은 iPhone 모양 / 사용자 설정을 따르며 Flutter 테마를 따르지 않습니다. Clear는 Tinted에서 파생됩니다. 별도의 Clear 슬롯은 없습니다.
워크플로 체크리스트
Progress:
- [ ] 1. 라이트 + 나이트 런치 PNG 생성 (@1x/@2x/@3x)
- [ ] 2. ios/Runner/에 복사하고 Copy Bundle Resources에 추가 (pbxproj)
- [ ] 3. Assets.xcassets에서 BrandLogo*.imageset 제거 (있는 경우)
- [ ] 4. LaunchScreen.storyboard 업데이트 (느슨한 이미지 이름 + 명시적 색상)
- [ ] 5. 선택 사항: Main.storyboard / SceneDelegate handoff 전용 LaunchBackground.colorset
- [ ] 6. 앱 아이콘 dark + tinted 1024 생성 (레거시 항목 유지 시 홈 크기 포함)
- [ ] 7. AppIcon.appiconset/Contents.json에 luminosity dark + tinted 추가
- [ ] 8. flutter build ios --simulator --debug
- [ ] 9. simctl uninstall + install; 런치 <0.5초 및 Assets.car에서 아이콘 모양 확인
1단계 — 런치 로고 생성
scripts/generate_launch_logos.py 사용.
입력:
- 어두운 스튜디오 배경의 소스 로고 (일반적
assets/logo/logo.png) - Light: 검은색 제거 → 2톤 브랜드 색상 유지
- Dark: 동일한 알파 마스크, 단색 골드
#E0B45D(또는 프로젝트 기본 색상) - 크기: 400×363 @1x, 800×727 @2x, 1200×1090 @3x (로고 비율에 맞게 조정)
제거 공식 (Flutter SplashLogo가 있을 경우 일치):
alpha_out = min(255, 4 * (R + G + B), source_alpha)
출력 파일을 ios/Runner/에 저장:
BrandLogo.png,[email protected],[email protected]BrandLogoNight.png,[email protected],[email protected]
2단계 — 번들 리소스
ios/Runner.xcodeproj/project.pbxproj에서:
- 여섯 개의 PNG에 대해
PBXFileReference+PBXBuildFile추가 - Runner 그룹 및 Copy Bundle Resources에 나열
lastKnownFileType = image.png;@2x/@3x경로는 따옴표로 묶음
ios/Runner/Assets.xcassets/BrandLogo.imageset 및 BrandLogoNight.imageset이 있으면 삭제합니다.
빌드 후 확인:
# BrandLogo는 Assets.car에 있으면 안 됨; PNG는 Runner.app에 있어야 함
find build/ios/iphonesimulator/Runner.app -name 'BrandLogo*.png'
xcrun assetutil --info build/ios/iphonesimulator/Runner.app/Assets.car | grep -i BrandLogo || true
3단계 — LaunchScreen.storyboard
최신 IB 형식 사용 (toolsVersion ≥ 21701, useTraitCollections, "documents saved in the Xcode 8 format" 기능).
패턴 (전체 템플릿: references/launch-storyboard.md):
UIImageViewcontentMode="scaleAspectFit", imageBrandLogo- 변형:
key="userInterfaceStyle=dark" image="BrandLogoNight" - 너비 ≈ 슈퍼뷰의
0.28–0.40(약 0.32부터 시작); 높이 = 너비 × 로고 비율 - Center X/Y 제약 조건
- 라이트 배경 명시적 sRGB (예: 아이보리
#FFFCF7) - 다크 배경 변형 명시적 sRGB (예:
#17120E) <resources>는 두 이미지 이름을 내재적 크기와 함께 선언해야 함
Info.plist: UILaunchStoryboardName = LaunchScreen.
4단계 — Flutter 핸드오프 (선택 사항이지만 권장)
Flutter가 인계받을 때 흰 화면 플래시 방지:
- 라이트 + 다크 광도를 가진
LaunchBackground.colorset(비런치 UI에 적합) - Main.storyboard VC 배경 → 명명된
LaunchBackground - SceneDelegate / 사용자 정의
FlutterViewController:viewDidLoad/viewDidLayoutSubviews에서UIColor(named: "LaunchBackground")로view.backgroundColor및window.backgroundColor설정
5단계 — 앱 아이콘 모양 (iOS 18+)
scripts/generate_app_icon_variants.py로 1024 마케팅 아이콘(크림 배경 + 로고)에서 생성.
| 모양 | 아트워크 |
|---|---|
| Default (Any) | 기존 라이트 아이콘 |
| Dark | 다크 플레이트(#17120E)의 골드 로고 또는 Apple HIG에 따른 투명 배경 |
| Tinted | 회색조: 검정 배경에 흰색/회색 로고 (시스템이 틴트 적용) |
| Clear | Tinted에서 자동 파생 — Contents.json에 항목 없음 |
AppIcon.appiconset/Contents.json 업데이트 — references/appicon-contents.md 참조.
다음과 같은 단일 크기 범용 1024 항목 선호:
"appearances": [{ "appearance": "luminosity", "value": "dark" }]
"appearances": [{ "appearance": "luminosity", "value": "tinted" }]
프로젝트에서 여전히 사용 중이라면 레거시 화면 크기별 iPhone 항목 유지; 최소한 60pt @2x/@3x + 마케팅 1024에 대해 dark/tinted 추가.
검증:
xcrun actool ios/Runner/Assets.xcassets --compile /tmp/icons \
--platform iphonesimulator --minimum-deployment-target 15.0 \
--app-icon AppIcon --output-partial-info-plist /tmp/icon-partial.plist
xcrun assetutil --info /tmp/icons/Assets.car | grep -E 'UIAppearanceDark|ISAppearanceTintable'
빌드된 앱은 AppIcon에 UIAppearanceDark 및 ISAppearanceTintable이 표시되어야 합니다.
6단계 — 시뮬레이터에서 확인
flutter build ios --simulator --debug
xcrun simctl uninstall booted <bundle.id>
xcrun simctl install booted build/ios/iphonesimulator/Runner.app
# 실행: ~0.4–0.5초 안에 로고가 나타나야 함 (여러 초의 빈 화면 없음)
# 아이콘: 사용자 설정 → Dark / Tinted; SpringBoard 캐시를 위해 삭제 후 재설치 필요할 수 있음
simctl은 샌드박스 에이전트 환경에서 전체 권한이 필요합니다.
SplashBoard 캐시를 rm -rf로 지우지 마세요. 삭제 후 재설치가 런치 스냅샷을 지웁니다.
브랜드 기본값 (프로젝트에 따라 재정의)
| 토큰 | 기본값 |
|---|---|
| 라이트 런치 배경 | #FFFCF7 |
| 다크 런치 배경 | #17120E |
| 다크 로고 골드 | #E0B45D |
| 런치 로고 너비 | 화면의 32% |
| 다크 아이콘 플레이트 | #17120E |
프로젝트가 다를 경우 사용자에게 브랜드 16진수 값을 요청하세요.
추가 리소스
- 스토리보드 XML 템플릿: references/launch-storyboard.md
- AppIcon Contents.json 모양: references/appicon-contents.md
- 런치 로고 스크립트: scripts/generate_launch_logos.py
- 아이콘 변형 스크립트: scripts/generate_app_icon_variants.py