Skip to content

chore: release/1.1.1 → develop 역머지 - #162

Merged
ParkMazorika merged 4 commits into
developfrom
release/1.1.1
Sep 9, 2026
Merged

ParkMazorika merged 4 commits into
developfrom
release/1.1.1

Conversation

@ParkMazorika

@ParkMazorika ParkMazorika commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

관련 이슈

  • 없음 (릴리스 역머지)

변경 요약

release/1.1.1 을 develop 으로 되돌려 머지한다. 릴리스 브랜치에서만 올린 버전 문자열(1.1.0 → 1.1.1)과 changelog 가 develop 에 없어, 다음 릴리스를 이 상태에서 자르면 버전이 뒤로 간다.

변경 내용

지금 어긋나 있는 것

develop release/1.1.1
CFBundleShortVersionString (App·WatchApp·TimerWidget·WatchComplication) 1.1.0 1.1.1
fastlane/changelog_external.txt 1.1 기준 1.1.1 기준

3c6657b 하나가 전부다 — 1.1 라이브 빌드가 beta_internal 레인 산출물이라 실사용자 트래픽이 dev 로 가던 것을 prod 구성으로 다시 빌드해 내보낸 핫픽스다. 코드 수정은 없고 배포 구성·버전만 정정했다.

왜 역머지가 필요한가

버전 문자열이 릴리스 브랜치에만 있으면 다음 릴리스 브랜치를 develop 에서 자를 때 1.1.0 으로 되돌아간다. App Store 는 버전이 뒤로 가는 빌드를 받지 않으므로, 그때 가서 다시 올려야 하는 값이다.

전례

release/1.0.3 도 develop 으로 역머지되지 않은 채 남아 있다(git merge-base --is-ancestor NO). 그 브랜치 고유 커밋 4건 중 909e586 fix: 아이패드를 배포 대상에서 제외 는 develop 에 별도로 반영돼 있어 코드는 어긋나지 않았지만, 버전·changelog 는 그대로 갈라진 채다. 같은 누락을 이번에 반복하지 않으려는 PR 이다.

충돌 없음

release/1.1.1 은 develop 위에 커밋 하나를 얹은 상태(develop..release/1.1.1 = 1 commit)라 fast-forward 로 붙는다. #161 이 먼저 머지돼도 마찬가지다 — 그 브랜치도 release/1.1.1 위로 리베이스해 뒀다.

테스트

  • 로컬 빌드/실행 확인 — 해당 없음. 코드 변경이 없는 역머지다(버전 문자열 · changelog 텍스트)
  • 정상·에러 케이스 확인 — 해당 없음

체크리스트

  • PR 제목이 [NM-XXX] 요약 형식 — 해당 없음. 이슈에 대응하지 않는 브랜치 정리 PR 이라 chore: 로 달았다
  • 브랜치명 <type>/NM-XXX-요약 형식 — 해당 없음 (기존 release/1.1.1)
  • 커밋 메시지 [NM-XXX] type: 요약 형식 — 새 커밋 없음, 기존 커밋만 나른다
  • 셀프 리뷰 완료

ParkMazorika and others added 4 commits September 3, 2026 00:04
App Store 라이브 1.1 이 `beta_internal` 레인 산출물이라 실사용자 트래픽이
dev 로 가고 있다. 그 레인만 xcargs 로 BASE_URL=dev·FIREBASE_ENV=Debug·INTERNAL 을
덮어쓰는데, 1.1.0 버전대 빌드는 전부 그 레인에서 나왔다 —
cd-release 실행 이력 0건, cd-beta-external 마지막 실행 2026-08-13(1.0.4),
로컬 아카이브도 그 이후 없음. ASC 빌드 목록에 고를 수 있는 정상 빌드가 없었다.

코드 수정은 없다. 같은 커밋을 prod 구성 레인(beta_external)으로 다시 빌드해
내보내는 것이 이 릴리스의 전부다.

- MARKETING_VERSION(CFBundleShortVersionString) 1.1.0 → 1.1.1
  App·WatchApp·TimerWidget·WatchComplication 전 타깃 일치(Apple 검증).
- changelog_external.txt 갱신 — 1.1 에서 만든 데이터가 dev DB 에 남아
  보이지 않는다는 점을 테스터에게 명시.

배포 후 확인할 것:
- prod Firebase(nursemate-96159) Remote Config 에 min_supported_version·
  app_store_url 이 채워져 있는지. 1.1 사용자는 dev 프로젝트를 보므로 긴급 제어는
  당분간 dev·prod 양쪽에 걸어야 한다.
- dev DB 에 쌓인 실사용자 계정 처리(백엔드).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VL6AihNosReBSERxCV3qZZ
서버가 카카오 액세스 토큰으로 사용자 정보를 조회해 이메일을 Firebase 레코드에
채우기 시작했다(backend NM-413). 그 조회는 토큰에 이메일 권한이 실려 있어야만
값을 돌려준다 — 빠지면 서버는 조용히 이메일 없이 넘어간다.

iOS SDK 의 loginWithKakaoTalk · loginWithKakaoAccount 는 scope 인자를 받지 않는다.
동의항목을 정하는 건 카카오 콘솔이고, 앱이 개입할 수 있는 지점은 이미 받은 토큰에
추가 동의를 붙이는 loginWithKakaoAccount(scopes:) 하나뿐이다. 그래서 로그인 직후
scopes 조회로 권한을 확인하고, 빠져 있을 때만 추가 동의를 한 번 받는다.

콘솔에 필수 동의로 걸려 있어 보통은 이 창이 뜨지 않는다. 그럼에도 확인을 두는 건
콘솔 설정이 코드 밖에 있어 눈에 띄지 않게 바뀔 수 있고, 그때 이메일이 조용히
비어 버리기 때문이다.

실패는 전부 삼킨다. 이메일은 로그인의 성립 조건이 아니라는 것이 계약이라
(spec api/domains/auth.md 인증 §카카오), 조회가 실패하거나 사용자가 추가 동의를
취소하면 원래 토큰 그대로 교환을 진행한다.

using 이 false 면 추가 동의를 요청하지 않는다. 앱이 쓰지 않는 항목이라 요청해도
오류만 나고, 판단이 서지 않을 때 창을 띄우는 쪽이 이메일을 못 받는 것보다 나쁘다.

spec 서브모듈도 0.25.1 반영본으로 올린다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WkkHofXT2ZqnGQ6bhjGJYX
`GET /users/me` 의 공급자 불일치가 401 에서 500 으로 바뀌었다(spec 0.24.3).
401 로 주면 클라이언트가 세션 만료로 보고 로그아웃시키는데, 재로그인해도 같은
응답이 와 사용자가 빠져나갈 방법이 없어서다.

그런데 앱은 그 전환의 다른 쪽 절반을 안 하고 있었다. restoreSession 이 fetchMe
실패를 원인 구분 없이 전부 `.login` 으로 접어, 500 이 오면 결국 로그인 화면으로
튕긴다. 서버가 401 을 피한 이유가 앱에서 그대로 재현된다.

503 도 같은 자리에 있었다. 로그아웃 사유가 아니라고 spec 에 못박혀 있고
AuthErrorMapper 는 이미 `.serviceUnavailable` 로 가르고 있었지만, 진입 경로에서만
그 구분이 버려졌다.

그래서 두 상태를 세션을 버리지 않는 실패로 묶고, restoreSession 이 화면을 정하는
대신 throw 하게 했다. 라우트 enum 에 `.retry` 같은 걸 더하지 않는다 — 진입 라우팅은
세션 유무와 onboardingRequired 만으로 정해지는 세 갈래라는 게 spec 이고,
"판정이 서지 않음" 은 그 표의 네 번째 행이 아니라 표를 못 채운 상태다.

AppCoordinator 는 그때 스플래시에 머물러 다시 시도만 받는다. 500 이 공급자 불일치면
재시도해도 계속 실패하지만, 그렇다고 로그인 화면으로 보내면 사용자가 할 수 있는
유일한 행동(로그인)이 같은 500 을 부른다. 머무는 편이 덜 나쁘다.

400·401·네트워크 실패는 그대로 `.login` 이다. spec 이 이름 붙인 건 500·503 둘뿐이고,
나머지까지 스플래시에 묶으면 진짜 세션 만료가 빠져나갈 곳을 잃는다.

같이: 서버에서 삭제된 `GET /health` 를 공개 엔드포인트 목록에서 뺀다(spec 0.25.0).
목록은 서버 permitAll 과 1:1 이어야 의미가 있어, 없는 경로가 남아 있으면 대조가
어긋난다. 테스트에서는 인증 필요 경로 쪽으로 옮겨 다시 열리지 않게 잠근다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WkkHofXT2ZqnGQ6bhjGJYX
…count-email

[NM-413] 카카오 로그인 이메일 수집 · 진입 조회 500·503 로그아웃 금지
@ParkMazorika ParkMazorika self-assigned this Sep 2, 2026
@ParkMazorika
ParkMazorika merged commit ae299de into develop Sep 9, 2026
1 of 2 checks passed
@ParkMazorika
ParkMazorika deleted the release/1.1.1 branch September 9, 2026 09:22
ParkMazorika added a commit that referenced this pull request Sep 9, 2026
App Store Connect 는 같은 버전 트레인(CFBundleShortVersionString)당 심사 중인
빌드를 하나만 허용한다. beta_external 레인은 release/** push 마다 도는데
increment_build_number 가 올리는 건 빌드 번호뿐이라 트레인은 그대로다 —
앞 빌드가 심사 중이면 다음 push 가 구조적으로 Beta App Review 제출에서 걸린다.
(#162 의 외부 배포 실패가 이것)

그때도 바이너리는 이미 올라가 처리까지 끝나 있고, 앞 빌드가 심사를 통과하면
같은 트레인의 이후 빌드는 재심사 없이 배포된다. 큐 사정으로 job 을 빨갛게
만들 이유가 없어 이 에러만 삼키고 안내를 남긴다.

나머지 에러는 그대로 올린다 — 서명·프로파일·네트워크 같은 진짜 실패는 삼키면 안 된다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ch9vPGGKfeTUWMKEsZ3NWM
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant