모바일IOS
5

Flutter + Spring Boot Docker 배포 트러블슈팅 기록

앱 Duo를 개발하면서 겪은 배포 트러블슈팅을 기록한다.

Flutter + Spring Boot Docker 배포 트러블슈팅 기록

들어가며

Duo를 개발하면서 겪은 배포 트러블슈팅을 기록한다.

Flutter로 iOS/Android 앱을 만들고, Spring Boot 백엔드를 Docker로 VPS에 올리는 구조였다. 윈도우 환경이라 Xcode 없이 Codemagic으로 iOS 빌드를 처리했고, 소셜 로그인은 카카오 · 구글 · 애플 세 가지를 지원했다.

Android는 멀쩡히 잘 됐는데 iOS만 소셜 로그인이 전부 막혀있었다. 원인을 파고들다 보니 서버 .env 변수 누락, 각 플랫폼 콘솔 미설정, Firebase 미등록까지 한꺼번에 터져있는 상황이었다. 하나씩 잡은 과정을 아래에 정리한다.


목차

  1. 서버 기동 실패 - 환경변수 누락
  2. iOS 소셜 로그인 전체 실패
  3. 카카오 로그인 수정
  4. 구글 로그인 수정
  5. 애플 로그인 수정
  6. Firebase iOS 앱 등록
  7. .env 파싱 오류
  8. 최종 체크리스트

1. 서버 기동 실패 - 환경변수 누락

증상

BeanCreationException: Error creating bean with name 'webhookController'
Caused by: PlaceholderResolutionException: 
Could not resolve placeholder 'revenuecat.webhook.secret'

Spring Boot 앱이 시작조차 되지 않음.

원인

.env 파일에 REVENUECAT_WEBHOOK_SECRET 변수가 누락된 상태로 배포됨.
Spring Boot는 @Value("${revenuecat.webhook.secret}") 주입 실패 시 컨텍스트 초기화를 중단함.

해결

# .env에 추가
REVENUECAT_WEBHOOK_SECRET=your_secret_here
docker compose down
docker compose up -d
docker logs -f duo-api

교훈

배포 전 .env.example 파일을 관리해서 필요한 환경변수 목록을 문서화해둘 것.


2. iOS 소셜 로그인 전체 실패

증상

{error: invalid_request, error_description: IOS bundleId validation failed.}
  • iOS: 카카오 / 구글 / 애플 로그인 모두 실패
  • Android: 정상 동작

원인 분석

항목상태
.env iOS Bundle ID 변수누락
카카오 개발자 콘솔 iOS 등록미등록
Google Cloud Console iOS 클라이언트미생성
Apple Sign In with Apple 키미생성

Bundle ID 확인

Codemagic → 앱 선택 → iOS code signing → Bundle identifier에서 확인.

com.misnawk.duo

.env에 추가

KAKAO_IOS_BUNDLE_ID=com.misnawk.duo
APPLE_BUNDLE_ID=com.misnawk.duo

3. 카카오 로그인 수정

원인

카카오 개발자 콘솔의 네이티브 앱 키에 iOS 정보가 등록되지 않음.
Android 패키지/키 해시만 등록된 상태였음.

해결

developers.kakao.com
→ 앱 설정 → 앱 → 플랫폼 키
→ 네이티브 앱 키 "duo" → ⋮ → 수정
→ iOS Bundle ID: com.misnawk.duo 입력 → 저장

4. 구글 로그인 수정

원인

Google Cloud Console에 iOS용 OAuth 2.0 클라이언트가 생성되지 않음.
기존 Info.plist의 URL Scheme 값이 잘못된 상태였음.

해결 1 - Google Cloud Console iOS 클라이언트 생성

console.cloud.google.com
→ APIs & Services → Credentials
→ + CREATE CREDENTIALS → OAuth client ID
→ Application type: iOS
→ Bundle ID: com.misnawk.duo
→ 생성

해결 2 - Firebase에서 GoogleService-Info.plist 다운로드

Google Cloud Console이 아닌 Firebase Console에서 받아야 전체 항목이 포함됨.

console.firebase.google.com
→ 프로젝트 설정 → 내 앱
→ iOS 앱 추가 (com.misnawk.duo)
→ GoogleService-Info.plist 다운로드
→ ios/Runner/ 에 교체

해결 3 - Info.plist URL Scheme 교체

<key>CFBundleURLSchemes</key>
<array>
    <!-- Firebase plist의 REVERSED_CLIENT_ID 값으로 교체 -->
    <string>com.googleusercontent.apps.903473547061-7q4iqnldv35ktmsql2ri8i7pv8b9qvuv</string>
    <!-- 카카오 그대로 유지 -->
    <string>kakao9c38d5f22cd49e39d0511d0b0da8cf2d</string>
</array>

⚠️ Google Cloud Console에서 별도로 만든 클라이언트 ID와 Firebase의 REVERSED_CLIENT_ID는 다를 수 있음. Firebase 기준으로 통일할 것.


5. 애플 로그인 수정

원인

Apple Developer Console에 Sign In with Apple 키가 생성되지 않음.
서버 .env에 Apple 관련 변수 전체 누락.

해결 1 - Apple Developer Console 키 생성

developer.apple.com
→ Certificates, Identifiers & Profiles → Keys
→ + 버튼
→ Key Name: DuoSignInKey
→ Sign In with Apple ✅ 체크
→ Configure → Primary App ID: com.misnawk.duo
→ Continue → Register
→ .p8 파일 다운로드 (1회만 가능, 즉시 저장)
→ Key ID 메모

해결 2 - Team ID 확인

developer.apple.com
→ 우측 상단 계정 클릭
→ Membership details → Team ID (10자리)

해결 3 - .env에 추가

APPLE_BUNDLE_ID=com.misnawk.duo
APPLE_TEAM_ID=XXXXXXXXXX
APPLE_KEY_ID=XXXXXXXXXX
APPLE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n내용\n-----END PRIVATE KEY-----"

6. Firebase iOS 앱 등록

문제

Firebase 프로젝트에 Android 앱(com.company.duo)만 등록되어 있고 iOS 앱이 없었음.

해결

console.firebase.google.com → 프로젝트 설정
→ 내 앱 → 앱 추가 → iOS 아이콘
→ Bundle ID: com.misnawk.duo 입력
→ GoogleService-Info.plist 다운로드
→ ios/Runner/GoogleService-Info.plist 교체
→ git push → Codemagic 빌드

7. .env 파싱 오류

증상

failed to read /opt/duo-api/.env: line 35: 
unexpected character "/" in variable name "MIGTAgEAMBMGByqGSM49..."

원인

.p8 Private Key를 .env에 멀티라인으로 그대로 붙여넣으면 Docker Compose가 파싱 실패함.

해결

줄바꿈을 \n으로 교체하고 전체를 큰따옴표로 감쌀 것.

# 잘못된 방법
APPLE_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----
MIGTAgEA...
-----END PRIVATE KEY-----

# 올바른 방법
APPLE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIGTAgEA...\n-----END PRIVATE KEY-----"

PowerShell로 변환:

(Get-Content "AuthKey_XXXXXXXXXX.p8" -Raw).Replace("`r`n", "\n").Replace("`n", "\n")

8. 최종 체크리스트

.env 필수 변수 목록

# DB
DB_USERNAME=
DB_PASSWORD=
DB_NAME=duo

# 카카오
KAKAO_IOS_BUNDLE_ID=com.misnawk.duo

# 구글
GOOGLE_WEB_CLIENT_ID=

# 애플
APPLE_BUNDLE_ID=com.misnawk.duo
APPLE_TEAM_ID=
APPLE_KEY_ID=
APPLE_PRIVATE_KEY=""

# RevenueCat
REVENUECAT_WEBHOOK_SECRET=

# 기타
JWT_SECRET=
PORT=7070

플랫폼별 설정 파일 위치

파일위치용도
GoogleService-Info.plistios/Runner/iOS 구글 로그인
google-services.jsonandroid/app/Android 구글 로그인
Info.plistios/Runner/URL Scheme 등록
.env서버 루트서버 환경변수

docker-compose.yml 권장 설정 (healthcheck 포함)

db:
  healthcheck:
    test: ["CMD-SHELL", "pg_isready -U ${DB_USERNAME} -d ${DB_NAME:-duo}"]
    interval: 10s
    timeout: 5s
    retries: 5

api:
  depends_on:
    db:
      condition: service_healthy

댓글

(0)