[플러터 개발] Flutter 업그레이드하다가 빌드 터진 이야기 — 패키지 버전 지옥 탈출기

2026. 3. 4. 18:48·모바일 개발/플러터
반응형

flutter pub upgrade --major-versions 함부로 치면 안 되는 이유


발단: "패키지 업데이트나 해볼까"

리팩토링 작업을 하고 있었는데, pubspec.lock이 손상되는 바람에 flutter pub get을 다시 돌려야 했습니다.

Error on line 1054, column 7 of pubspec.lock:
The name should be shared_preferences

간단하게 lock 파일 삭제하고 재생성하면 되는 거였습니다.

rm pubspec.lock
flutter pub get

여기까진 좋았어요. 그런데 이김에 패키지도 좀 정리하자는 생각이 들었습니다.

flutter pub upgrade --major-versions

이걸 치는 순간부터 지옥이 시작됐습니다.


1차 폭발: Dart SDK 버전 충돌

The current Dart SDK version is 3.7.2.
Because shared_preferences 2.5.4 requires SDK version ^3.9.0,
shared_preferences ^2.5.4 is forbidden.

shared_preferences 최신 버전이 Dart 3.9.0을 요구하는데, 제 환경은 Dart 3.7.2였습니다.

이때 선택지가 두 개였거든요.

A) Flutter SDK를 3.41.1로 올린다 — Dart 3.9.0+ 포함 B) shared_preferences를 3.7.2에 맞는 버전으로 내린다

프로덕션 앱이니까 안전하게 B를 선택했습니다.

flutter pub add shared_preferences:^2.5.3

근데 하나 내리니까 다른 데서 또 터집니다.


2차 폭발: flutter_lints도 호환 안 됨

The current Dart SDK version is 3.7.2.
Because flutter_lints 6.0.0 requires SDK version ^3.8.0,
flutter_lints ^6.0.0 is forbidden.

flutter_lints도 최신 버전이 Dart 3.8.0을 요구합니다. --major-versions가 모든 패키지를 최신으로 올려버렸으니 당연한 결과죠.

flutter pub add flutter_lints:^5.0.0

이것도 내리고 나서야 겨우 flutter pub get이 성공했습니다.


교훈: --major-versions가 하는 일을 정확히 알아야 한다

flutter pub upgrade                 # 현재 제약 범위 내에서 업데이트 (안전)
flutter pub upgrade --major-versions  # 메이저 버전까지 전부 올림 (위험!)

--major-versions는 pubspec.yaml의 버전 제약 자체를 바꿔버립니다.

# before
shared_preferences: 2.5.3

# after (--major-versions 실행 후)
shared_preferences: ^2.5.4   # Dart 3.9.0 필요!
flutter_lints: ^6.0.0        # Dart 3.8.0 필요!

현재 Dart SDK와 호환되는지 확인하지 않고 무조건 최신으로 올리기 때문에, SDK 버전이 낮으면 빌드가 바로 깨집니다.


안전한 업데이트 순서

제가 겪고 나서 정리한 순서입니다.

# 1. 먼저 뭐가 오래됐는지 확인만 한다
flutter pub outdated

# 2. 현재 SDK 범위 내에서만 업데이트
flutter pub upgrade

# 3. 메이저 업데이트가 필요하면 패키지 하나씩 확인
#    pub.dev에서 Dart SDK 요구 버전 체크 후 수동으로
flutter pub add shared_preferences:^2.5.3

# 4. 절대 먼저 치지 말 것
# flutter pub upgrade --major-versions  ← 이거 함부로 ㄴㄴ

핵심은 flutter pub outdated로 먼저 확인하고, 하나씩 올리는 것입니다. 한 번에 다 올리면 어디서 터졌는지 찾기가 어렵습니다.


번외: Flutter SDK 자체를 올릴 때 주의할 것

만약 "그냥 Flutter를 최신으로 올리자"고 결정했다면, 그것도 만만치 않습니다.

저는 아직 3.7.x에 머물러 있는데, 최신이 3.41.x이라 점프가 너무 큽니다. 검색해보니 주요 Breaking Changes가 이렇게 쌓여 있었습니다.

iOS — UIScene 마이그레이션 (필수)

iOS 27부터 UIScene을 사용하지 않는 앱은 아예 실행이 안 됩니다. Flutter 3.38부터 UIScene 라이프사이클을 지원하며, 3.41에서는 기본값입니다.

마이그레이션이 필요한 부분:

  • AppDelegate에서 플러그인 등록을 didInitializeImplicitFlutterEngine으로 이동
  • Info.plist에 UIApplicationSceneManifest 추가
  • applicationDidBecomeActive 같은 앱 라이프사이클 코드가 있다면 SceneDelegate로 이동

Flutter CLI가 자동 마이그레이션을 시도해주긴 합니다.

flutter build ios  # 자동 마이그레이션 시도
# 성공하면: "Finished migration to UIScene lifecycle"

Android — AGP 9 업데이트 금지

Flutter 3.41 기준으로 AGP(Android Gradle Plugin) 9는 아직 지원 안 됩니다. Android Studio가 AGP 업데이트를 권유해도 무시해야 합니다.

또한 Flutter 3.38부터 Android 15 타겟 시 16KB 페이지 사이즈 지원이 필요하며, NDK r28이 기본값으로 변경되었습니다.

Material 3 마이그레이션

useMaterial3: true가 기본값이 되면서, 기존 Material 2 기반 UI가 미묘하게 달라질 수 있습니다. 특히 ElevatedButton, Card, Dialog 같은 위젯의 기본 스타일이 바뀝니다.


한국 개발자 특별 주의: flutter_naver_map

네이버 맵처럼 한국 패키지는 업데이트가 느린 경우가 많습니다.

flutter_naver_map: 1.3.1  # 최신 Dart SDK와 호환되는지 꼭 확인

Flutter SDK를 올렸는데 네이버 맵이 호환 안 되면, 지도 기능 전체가 빌드 실패합니다. pub.dev에서 패키지의 Dart SDK 요구 버전을 꼭 확인하세요.

같은 이유로 location, geolocator, permission_handler 같은 네이티브 의존성이 강한 패키지도 주의가 필요합니다.


제가 정리한 업그레이드 체크리스트

□ flutter pub outdated로 현황 파악
□ 패키지별 Dart SDK 요구 버전 확인 (pub.dev)
□ flutter_naver_map 등 한국 패키지 호환 여부 확인
□ flutter pub upgrade (범위 내만)
□ 필요한 패키지만 수동으로 버전 지정
□ iOS: UIScene 마이그레이션 여부 확인
□ Android: AGP 버전 유지, NDK r28 확인
□ flutter build ios --debug 테스트
□ flutter build apk --debug 테스트
□ 실기기에서 주요 기능 동작 확인

정리

상황 해야 할 것 하면 안 되는 것

패키지 업데이트 flutter pub outdated 먼저 확인 --major-versions 바로 실행
SDK 충돌 패키지를 현재 SDK에 맞게 다운그레이드 검증 없이 Flutter SDK 올리기
pubspec.lock 손상 삭제 후 flutter pub get lock 파일 수동 편집
Flutter SDK 업그레이드 별도 브랜치에서 충분한 시간 확보 프로덕션 직전에 업그레이드
iOS 빌드 실패 UIScene 마이그레이션 확인 AppDelegate 코드 그대로 방치

결국 핵심은 **"한 번에 다 바꾸지 말고, 하나씩 바꾸면서 빌드 확인"**입니다. --major-versions 한 줄이 반나절을 날릴 수 있다는 걸 몸으로 배웠습니다.


이 글은 에어컨 서비스 플랫폼 "코너 파트너스" 앱 개발 과정에서 작성되었습니다.

반응형
저작자표시 비영리 변경금지 (새창열림)
'모바일 개발/플러터' 카테고리의 다른 글
  • [플러터 개발] Flutter 날짜 파싱 방어 코딩 — 어떤 형식이 와도 터지지 않게
  • [플러터 개발] Riverpod AsyncNotifier에서 다른 Provider 참조해서 필터링하기
  • [플러터 리팩토링 기록] static final vs static const
  • [플러터 기초] Dart 비동기 프로그래밍
서진형(Harvie)
서진형(Harvie)
🚀 1인 개발과 1인 창업의 모든 것! 실전 경험을 바탕으로 기술, 비즈니스, 그리고 성장의 과정까지 담아내는 블로그. 배운 것, 부딪힌 것, 그리고 그 속에서 얻은 인사이트를 공유합니다.
  • 서진형(Harvie)
    Harvie의 개발로 창업하기
    서진형(Harvie)
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 하비의 창업 이야기
      • 개발 공통
        • 개념 정리
        • 문제 해결
        • 깃허브
      • 모바일 개발
        • 플러터
        • 컴포즈
      • 백엔드 관련 개발
        • 클라우드 서비스
        • 파이썬
      • 정보 공유
        • 꿀팁 공유
  • 블로그 메뉴

    • Harive's Portfolio
    • 에어컨 서비스 예약하기
  • 링크

    • 코너 - 냉난방기 종합 서비스
    • 주인장 인스타그램
  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
서진형(Harvie)
[플러터 개발] Flutter 업그레이드하다가 빌드 터진 이야기 — 패키지 버전 지옥 탈출기
상단으로

티스토리툴바