Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
6a4c564
refactor: #437 기존 파일명 및 API, 레포지토리, 인터페이스 네이밍 수정
dev-domo Jun 5, 2026
23d3ef2
feat: #437 알림 전체 조회 API 연동
dev-domo Jun 5, 2026
41ab7ec
feat: #437 홈 뷰모델에서 알림 전체 조회하도록 구현
dev-domo Jun 5, 2026
ab1284d
refactor: #437 홈 뷰모델 viewWillAppear 트리거 시 구조적 동시성 반영
dev-domo Jun 5, 2026
863544a
chore: #437 프로비저닝 파일 설정
dev-domo Jun 6, 2026
a59529b
chore: #437 파라미터명 오타 수정
dev-domo Jun 6, 2026
944801b
refactor: #437 NoticesViewController 생성자에서 알람 유무 주입 삭제
dev-domo Jun 6, 2026
7907672
refactor: #437 프로토콜에 정의되지 않은 메서드들 추가
dev-domo Jun 7, 2026
1a6a86c
feat: #437 시간 차이를 계산하여 문자열 정보로 매핑하는 유스케이스 구현
dev-domo Jun 7, 2026
a21e497
refactor: #437 뷰컨트롤러 네이밍 수정 및 NotificationsViewModel 구현
dev-domo Jun 7, 2026
10e7d9c
feat: #437 NotificationType 열거형 구현
dev-domo Jun 7, 2026
8e1277e
feat: #437 NotificationListEntity stub 구현
dev-domo Jun 7, 2026
2e29eb1
refactor: #437 bind 함수 분리 및 알림 정보 구독
dev-domo Jun 7, 2026
f1b6327
chore: #437 줄바꿈 추가
dev-domo Jun 7, 2026
10207ea
refactor: #437 알림 셀 선택 시 회색으로 변하지 않도록 방지
dev-domo Jun 7, 2026
5f40a43
chore: #437 주석 오타 수정
dev-domo Jun 8, 2026
78be1cd
Merge branch 'develop' into feat/#437-fetchAllNotice
dev-domo Jun 8, 2026
4cf0b31
refactor: #437 TaskGroup -> async let 방식으로 변경
dev-domo Jun 8, 2026
cf9eb09
chore: #437 오타 수정
dev-domo Jun 8, 2026
7c82b60
chore: #437 오타 수정
dev-domo Jun 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions ByeBoo-iOS/ByeBoo-iOS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.heartz.ByeBoo-iOS";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development com.heartz.ByeBoo-iOS";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development com.heartz.ByeBoo-iOS 1780581426";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
Expand All @@ -349,7 +349,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = "ByeBoo-iOS/ByeBoo-Prod.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
Comment on lines 350 to 353

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Release 서명이 Development 프로필로 설정되어 배포 아카이브가 실패할 수 있습니다.

Line 352와 Line 375이 Release(iPhoneOS)에서 iPhone Developer + match Development ...를 사용하고 있어, Line 350의 Prod entitlements와 함께 배포용 서명 체인이 깨질 가능성이 큽니다. Release는 배포용 인증서/프로필로 분리해 주세요.

수정 예시
-				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution";
...
-				"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development com.heartz.ByeBoo-iOS 1780581426";
+				"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.heartz.ByeBoo-iOS";

Also applies to: 375-375

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ByeBoo-iOS/ByeBoo-iOS.xcodeproj/project.pbxproj` around lines 350 - 353, The
Release (iphoneos) build settings currently use development signing values:
CODE_SIGN_IDENTITY = "iPhone Developer" and a development provisioning profile
(match Development...), while CODE_SIGN_ENTITLEMENTS references Prod
entitlements; update the Release configuration so the signing chain uses
distribution credentials—set CODE_SIGN_IDENTITY to the distribution identity
(e.g., "iPhone Distribution"), replace the development provisioning profile
entries (match Development...) with the appropriate App Store/Ad Hoc
distribution profile (match AppStore or match AdHoc as applicable), and ensure
CODE_SIGN_ENTITLEMENTS remains the Prod entitlements file and CODE_SIGN_STYLE
stays correct (Manual if using match). Apply the same fixes for the other
Release entry that currently references the development profile.

CURRENT_PROJECT_VERSION = 10;
DEVELOPMENT_TEAM = "";
Expand All @@ -372,7 +372,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.heartz.ByeBoo-iOS";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.heartz.ByeBoo-iOS";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development com.heartz.ByeBoo-iOS 1780581426";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
Expand Down
2 changes: 1 addition & 1 deletion ByeBoo-iOS/ByeBoo-iOS/App/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
guard let notificationRepository = DIContainer.shared.resolve(type: DefaultNotificationRepository.self) else {
guard let notificationRepository = DIContainer.shared.resolve(type: DefaultNotificationTokenRepository.self) else {
return
}

Expand Down
4 changes: 4 additions & 0 deletions ByeBoo-iOS/ByeBoo-iOS/Data/DataDependencyAssembler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ struct DataDependencyAssembler: DependencyAssembler {
DIContainer.shared.register(type: ReportsInterface.self) { _ in
return DefaultReportsRepository(networkService: networkService)
}

DIContainer.shared.register(type: NotificationInterface.self) { _ in
return DefaultNotificationRepository(networkService: networkService)
}
}
}

Expand Down
24 changes: 24 additions & 0 deletions ByeBoo-iOS/ByeBoo-iOS/Data/Enum/NotificationType+Data.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// NotificationType+Data.swift
// ByeBoo-iOS
//
// Created by 더스틴 on 6/7/26.
//

extension NotificationType {

var responseKey: String {
switch self {
case .questOpen:
"QUEST_OPEN"
case .comment:
"COMMENT"
case .like:
"LIKE"
}
}

static func keyToEnum(_ key: String) -> Self? {
allCases.first { $0.responseKey == key }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// NotificationListResponseDTO.swift
// ByeBoo-iOS
//
// Created by 더스틴 on 6/5/26.
//

struct NotificationListResponseDTO: Decodable {
let notifications: [NotificationResponseDTO]
}

struct NotificationResponseDTO: Decodable {
let notificationID: Int
let notificationType: String
let title: String
let content: String
let isRead: Bool
let createdAt: String
let landingURL: String
}
Comment on lines +12 to +20

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# NetworkService의 JSONDecoder 설정 확인
rg -n "keyDecodingStrategy|convertFromSnakeCase" --type swift

Repository: 36-APPJAM-HEARTZ/BYEBOO-iOS

Length of output: 53


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Inspect the targeted DTO file around the reported lines
FILE="ByeBoo-iOS/ByeBoo-iOS/Data/Model/NotificationListReponseDTO.swift"
echo "---- ${FILE} ----"
nl -ba "$FILE" | sed -n '1,200p'

# 2) Check whether CodingKeys exists for NotificationResponseDTO (and nearby)
echo "---- CodingKeys in file ----"
rg -n "CodingKeys|notificationID|landingURL|NotificationResponseDTO" "$FILE"

# 3) Find JSONDecoder usage/config anywhere else
echo "---- JSONDecoder initialization/usages ----"
rg -n "JSONDecoder\(" --type swift

# 4) Look for any decode patterns that set decoder.keyDecodingStrategy explicitly
echo "---- keyDecodingStrategy assignments ----"
rg -n "keyDecodingStrategy" --type swift

# 5) Also search for CodingKeys implementations anywhere (to gauge existing approach)
echo "---- Any CodingKeys usage ----"
rg -n "enum CodingKeys" --type swift

Repository: 36-APPJAM-HEARTZ/BYEBOO-iOS

Length of output: 208


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="ByeBoo-iOS/ByeBoo-iOS/Data/Model/NotificationListReponseDTO.swift"
echo "== File exists? =="
ls -la "$FILE" || true

echo "== First 200 lines with numbers (using cat -n) =="
cat -n "$FILE" | sed -n '1,200p'

echo "== CodingKeys / NotificationResponseDTO in this file =="
rg -n "CodingKeys|enum CodingKeys|NotificationResponseDTO|notificationID|landingURL" "$FILE" || true

echo "== JSONDecoder initialization/usages across repo =="
rg -n "JSONDecoder\(" --type swift . || true

echo "== keyDecodingStrategy usage across repo =="
rg -n "keyDecodingStrategy|convertFromSnakeCase" --type swift . || true

echo "== Any enum CodingKeys usage across repo (spot check) =="
rg -n "enum CodingKeys" --type swift . | head -n 50 || true

Repository: 36-APPJAM-HEARTZ/BYEBOO-iOS

Length of output: 2643


JSON 키 매핑(CodingKeys / snake_case 변환) 설정이 없어 디코딩 실패 가능

  • NotificationResponseDTO에 CodingKeys가 없고, NetworkService/기타 코드에서 JSONDecoder()를 기본 설정으로 사용하므로 백엔드가 snake_case(notification_id, landing_url)로 내려오면 notificationID/landingURL 등이 매핑되지 않을 수 있습니다.
  • JSONDecoder.keyDecodingStrategy = .convertFromSnakeCase 설정 또는 NotificationResponseDTO에 CodingKeys 추가 필요.

[resolve_review_comment in comment context not applicable]

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ByeBoo-iOS/ByeBoo-iOS/Data/Model/NotificationListReponseDTO.swift` around
lines 12 - 20, The DTO lacks JSON key mapping so snake_case keys from the
backend (e.g., notification_id, landing_url) won't decode into camelCase
properties; update NotificationResponseDTO by either adding a CodingKeys enum
mapping notificationID -> "notification_id" and landingURL -> "landing_url" (and
any other snake_case fields), or ensure the decoder is configured with
JSONDecoder.keyDecodingStrategy = .convertFromSnakeCase wherever
NotificationResponseDTO is decoded (e.g., in your NetworkService) so
notificationID, landingURL, etc. map correctly.


extension NotificationListResponseDTO {
func toEntity() -> NotificationListEntity {
let notifications = notifications.map { $0.toEntity() }
return .init(notifications: notifications)
}
}

extension NotificationResponseDTO {
func toEntity() -> NotificationEntity {
.init(
notificationID: notificationID,
notificationType: NotificationType.keyToEnum(notificationType),
title: title,
content: content,
isRead: isRead,
createdAt: createdAt,
landingURL: landingURL
)
}
}
38 changes: 16 additions & 22 deletions ByeBoo-iOS/ByeBoo-iOS/Data/Network/EndPoint/NotificationAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,68 +2,62 @@
// NotificationAPI.swift
// ByeBoo-iOS
//
// Created by APPLE on 11/22/25.
// Created by 더스틴 on 6/5/26.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

더스틴 하이

//

import Foundation

import Alamofire

enum NotificationAPI {
case saveToken(dto: FCMTokenDTO)
case updateToken(dto: FCMTokenDTO)
case deleteToken(dto: FCMTokenDTO)
case fetchNotificationList
}

extension NotificationAPI: EndPoint {

var basePath: String {
return "/api/v1/notification-tokens"
return "/api/v1/notifications"
}

var path: String {
switch self {
case .saveToken, .updateToken, .deleteToken:
return ""
case .fetchNotificationList:
""
}
}

var method: HTTPMethod {
switch self {
case .saveToken:
return .post
case .updateToken:
return .patch
case .deleteToken:
return .put
case .fetchNotificationList:
.get
}
}

var headers: HeaderType {
switch self {
case .saveToken, .updateToken, .deleteToken:
return .withAuth
case .fetchNotificationList:
.withAuth
}
}

var parameterEncoding: ParameterEncoding {
switch self {
case .saveToken, .updateToken, .deleteToken:
return JSONEncoding.default
case .fetchNotificationList:
JSONEncoding.default
}
}

var queryParameters: [String : String]? {
switch self {
case .saveToken, .updateToken, .deleteToken:
return nil
case .fetchNotificationList:
nil
}
}

var bodyParameters: Parameters? {
switch self {
case .saveToken(let dto), .updateToken(let dto), .deleteToken(let dto):
return try? dto.toDictionary()
case .fetchNotificationList:
nil
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//
// NotificationTokenAPI.swift
// ByeBoo-iOS
//
// Created by APPLE on 11/22/25.
//
Comment thread
dev-domo marked this conversation as resolved.

import Foundation

import Alamofire

enum NotificationTokenAPI {
case saveToken(dto: FCMTokenDTO)
case updateToken(dto: FCMTokenDTO)
case deleteToken(dto: FCMTokenDTO)
}

extension NotificationTokenAPI: EndPoint {

var basePath: String {
return "/api/v1/notification-tokens"
}

var path: String {
switch self {
case .saveToken, .updateToken, .deleteToken:
return ""
}
}

var method: HTTPMethod {
switch self {
case .saveToken:
return .post
case .updateToken:
return .patch
case .deleteToken:
return .put
}
}

var headers: HeaderType {
switch self {
case .saveToken, .updateToken, .deleteToken:
return .withAuth
}
}

var parameterEncoding: ParameterEncoding {
switch self {
case .saveToken, .updateToken, .deleteToken:
return JSONEncoding.default
}
}

var queryParameters: [String : String]? {
switch self {
case .saveToken, .updateToken, .deleteToken:
return nil
}
}

var bodyParameters: Parameters? {
switch self {
case .saveToken(let dto), .updateToken(let dto), .deleteToken(let dto):
return try? dto.toDictionary()
}
}
}
4 changes: 2 additions & 2 deletions ByeBoo-iOS/ByeBoo-iOS/Data/Repository/AuthRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ struct DefaultAuthRepository: AuthInterface {
let fcmToken = try await Messaging.messaging().token()
let fcmTokenDTO = FCMTokenDTO(token: fcmToken)
try await network.request(
NotificationAPI.saveToken(dto: fcmTokenDTO)
NotificationTokenAPI.saveToken(dto: fcmTokenDTO)
)
} catch (let error) {
ByeBooLogger.error(error)
Expand Down Expand Up @@ -127,7 +127,7 @@ struct DefaultAuthRepository: AuthInterface {
return false
}
try await network.request(
NotificationAPI.deleteToken(dto: .init(token: fcmToken))
NotificationTokenAPI.deleteToken(dto: .init(token: fcmToken))
)
}
catch (let error) {
Expand Down
Loading
Loading