Skip to content

feat: #42 알림 설정 화면 + 도리 등록 알림 권한 안내#46

Merged
kangddong merged 20 commits into
developfrom
feat/42-we-need-notification
May 14, 2026
Merged

feat: #42 알림 설정 화면 + 도리 등록 알림 권한 안내#46
kangddong merged 20 commits into
developfrom
feat/42-we-need-notification

Conversation

@kangddong

Copy link
Copy Markdown
Collaborator

About this PR

⚓ Related Issue


🥥 Contents

1. 알림 설정 API 엔드포인트/응답 모델 추가

  • 알림 설정 조회/변경에 필요한 Endpoint(FetchNotificationSettings, UpdateNotificationSetting) 및 Response 모델을 정의

2. 알림 설정 화면 서버 연동 및 기기 알림 배너 추가

  • 알림 설정 조회/토글 액션을 서버 API와 연결하고, 실패 시 토글 롤백
  • 시스템 알림 권한이 꺼져 있을 때 안내 배너 노출, 탭 시 시스템 설정 진입
  • scenePhase 활성화 시 권한 상태를 재조회해 자동 갱신

3. 도리 등록 후 시스템 알림 권한 안내 알럿

  • 도리 등록 성공 후 알림 권한이 꺼져 있으면 설정 유도 알럿 노출
  • 알럿 타이틀 멀티라인 정렬 적용 (DoriCommonAlert)

4. 마이페이지 FCM 푸시 테스트 진입점 연결

  • 기존 FCMPushTestFeature를 마이페이지 네비게이션에 연결
  • MyPage 모듈에 Core 의존성 추가

5. 릴리스 빌드 앱 표시명 한국어 처리

  • CFBundleDisplayNameAPP_DISPLAY_NAME 변수로 분리
  • Debug: Dori-Debug, Release: 도리로 홈 화면 표시
  • PRODUCT_NAME은 ASCII 유지로 .app 번들 파일명 보존

📸 Screenshot

알림 설정 화면 기기 알림 OFF 배너 등록 후 안내 알럿

Other information 🔥

  • 시스템 알림 권한 체크는 UNUserNotificationCenter를 사용. AddDori는 UserNotificationSettingsClient로 분리되어 있고, MyPage에서는 모듈 간 의존을 피하기 위해 인라인 호출. 추후 Core로 끌어올려 공유하는 게 깔끔할 것 같습니다.
  • 시뮬레이터 빌드 검증 완료 (DoriApp 스킴, Debug).

🤖 Generated with Claude Code

kangddong and others added 11 commits March 27, 2026 16:16
Debug/Release 환경 변수 분리, BuildEnvironment 도입, APS entitlements 추가.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
앱 진입점에서 FCM 토큰 등록 및 APNs 위임 연결.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
QA용 FCMPushTestEndpoint 추가.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
QA용 FCM 푸시 테스트 화면과 UITests 타겟 자산 추가.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
알림 설정 조회/변경에 필요한 Endpoint 및 Response 모델을 정의한다.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 알림 설정 조회/토글 액션을 서버 API와 연결하고 실패 시 토글을 롤백한다.
- 시스템 알림 권한이 꺼져 있을 때 안내 배너를 노출하고, 탭 시 시스템 설정으로 진입한다.
- scenePhase 활성화 시 권한 상태를 재조회해 자동 갱신한다.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
도리 등록 성공 후 시스템 알림 권한이 꺼져 있으면 설정 유도 알럿을 노출하고,
탭 시 시스템 설정으로 진입한다. 알럿 타이틀 멀티라인 정렬을 위해
DoriCommonAlert의 title 정렬도 함께 조정했다.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
기존 FCMPushTestFeature를 마이페이지 네비게이션에 연결하고,
필요한 Core 의존성을 MyPage 모듈에 추가한다.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
CFBundleDisplayName을 APP_DISPLAY_NAME 변수로 분리하여
Debug는 'Dori-Debug', Release는 '도리'로 표시되도록 한다.
PRODUCT_NAME은 ASCII로 유지해 .app 번들 파일명을 보존한다.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@kangddong kangddong linked an issue Apr 28, 2026 that may be closed by this pull request
18 tasks
kangddong and others added 3 commits April 29, 2026 11:35
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

@kangddong kangddong left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리뷰 남겼습니다. 푸시/알림 설정 쪽은 실제 사용자에게 바로 영향이 갈 수 있는 부분이라 머지 전에 수정이 필요해 보입니다. 추가로 git diff --check origin/develop...HEAD에서 trailing whitespace와 EOF blank line 경고가 확인됐습니다. tuist generate --no-open은 clean worktree 기준으로는 설정/의존성 주입 상태를 별도로 맞춰야 하므로, CI/신규 체크아웃 기준의 설정 파일 주입 방식도 같이 확인해주세요.

_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool {
FCMService.shared.configure()

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FirebaseApp.configure()가 런치 시 무조건 실행되는데, GoogleService-Info.plist는 PR 트리에 없고 .gitignore에 추가되어 있습니다. 로컬에는 ignored 파일이 있어서 통과해도 fresh clone/CI/TestFlight 환경에서는 번들에 설정 파일이 없을 수 있고, 그 경우 앱 시작 단계에서 Firebase 초기화가 실패합니다. 환경별 plist를 빌드 단계에서 명시적으로 주입하거나, 누락 시 fail-fast 되는 스크립트/설정을 같이 넣는 게 필요합니다.

FCMService.shared.tokenRefreshHandler = { token in
try? tokenStore.saveFCMToken(token)
let endpoint = RegisterFCMTokenEndpoint(token: token)
_ = try? await networkService.request(

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FCM 토큰 등록 실패를 try?로 버리고 있어서 로그인 전 토큰이 먼저 발급되면 서버 등록 실패 후 재시도 경로가 없습니다. 실제로 권한 요청은 앱 시작 .task에서 실행되고, 인증 토큰 저장은 로그인 성공 후라 순서가 쉽게 어긋날 수 있습니다. 저장된 FCM 토큰을 로그인 성공/앱 인증 완료 시점에 다시 업로드하거나, 인증 실패 케이스를 재시도 큐로 남겨야 푸시 미수신 사용자가 생기지 않습니다.

state.isLoading = false
for setting in settings {
applySetting(typeCode: setting.typeCode, enabled: setting.enabled, state: &state)
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

서버에서 받아온 개별 알림 설정은 반영하지만 isAllPushEnabled는 갱신하지 않아 기본값 false로 남습니다. 그러면 서버상 알림이 켜져 있어도 화면은 '알림이 꺼져 있어요' 상태로 보이고, 하위 설정 영역이 overlay로 비활성처럼 덮입니다. settingsLoaded에서 전체 스위치를 서버 응답 기반으로 계산하거나, 서버가 전체 push type을 내려주도록 모델링해야 합니다.


case .allPushToggled(let value):
// TODO: OS 시스템 알림 설정과 연동 (UNUserNotificationCenter / 시스템 설정 화면 이동)
state.isAllPushEnabled = value

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전체 푸시 토글은 로컬 상태만 바꾸고 서버 업데이트를 하지 않습니다. 사용자가 '앱 알림 받기'를 켜거나 꺼도 다음 진입 시 서버 값으로 돌아가거나, 현재 화면의 하위 토글 상태와 서버 상태가 불일치할 수 있습니다. 전체 토글이 제품 요구사항이라면 관련 typeCode들을 일괄 업데이트하고 실패 시 롤백해야 하고, 단순 UI 잠금용이면 서버 상태에서 파생되는 read-only 값으로 두는 편이 안전합니다.

DoriModules.core.module.projectDependency,
.external(.composableArchitecture)
],
entitlements: .file(path: "Resources/DoriApp.entitlements")

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

앱 타겟이 항상 Resources/DoriApp.entitlements를 사용하고, 해당 파일의 aps-environmentdevelopment로 고정되어 있습니다. Release/App Store 배포에서는 production APNs entitlement가 필요하므로 배포 서명 실패나 푸시 환경 불일치가 날 수 있습니다. Debug/Release 별 entitlements를 분리하거나 빌드 설정으로 aps-environment를 맞춰주세요.

kangddong and others added 6 commits April 30, 2026 00:24
CI(Xcode 26.3 / Swift 6.2.4)에서 commonDictionary 리터럴 초기화 중
Dictionary literal contains duplicate keys 트랩이 발생하여,
빈 딕셔너리에 항목을 하나씩 할당하는 방식으로 우회한다.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
c5c4a6a 머지 결과 파일이 구문상 깨져 CI가 실패했음.
develop가 도입한 iPhone 세로 고정 의도를 유지하되, commonDictionary 리터럴은
fb86203 시점의 형태로 복원해 Swift 6 dictionary literal 트랩을 회피하고,
orientation 키는 baseInfoPlist에서 mutation으로 추가한다.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- InfoPlist commonDictionary 리터럴에 UISupportedInterfaceOrientations 복원
  (Xcode 26.3에서 dictionary literal 중복 키 트랩이 발생하던 형태)
- build.yml Xcode 버전을 latest-stable → 26.2 로 명시 고정

Xcode 버전 차이가 원인이었는지 CI에서 확인하기 위한 임시 커밋이며,
검증 후 롤백/재정리 예정.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
가설 검증 결과 Xcode 26.2 고정 시 CI 통과 확인됨.
운영 정책상 Xcode latest-stable을 유지하되, dictionary literal 트랩을 회피하기 위한
baseInfoPlist mutation 방식 코드는 유지한다.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
dictionary literal 트랩 가설 재검증을 위해 CI가 실패하던 시점의
InfoPlist 형태(commonDictionary literal에 UISupportedInterfaceOrientations
포함)로 되돌린다. build.yml은 latest-stable 유지.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@kangddong kangddong merged commit bf67d65 into develop May 14, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

알림 기능 개발

1 participant