Skip to content

Conversation

@Nico1eKim
Copy link
Contributor

@Nico1eKim Nico1eKim commented Oct 2, 2025

🚀 이슈번호

✏️ 변경사항

  • 내 동아리/학과 목록 조회 api 연결 완료
  • 재실자 조회 api 연결 완료
  • 출근하기/퇴근하기 api 연결 완료
  • refresh button 누르면 재로딩하기
  • 사이드바 열렸을 때 뒤로가기 누르면 사이드바 닫히게 수정

📷 스크린샷

안드로이드

1000032994.mp4

iOS

Simulator.Screen.Recording.-.iPhone.17.Pro.-.2025-10-02.at.18.03.32.mov

🎸 기타

  • token은 일단 하드코딩으로 넣어놨습니다 ~ 담당자분이 수정해주세여

Summary by CodeRabbit

  • 신규 기능

    • 홈 화면이 내 클럽 목록과 현재 참석자 목록을 불러와 표시하며, 출석 체크인/체크아웃, 새로고침, 로딩/에러 상태 표시를 지원합니다.
    • 뒤로가기 시 사이드바(드로어)가 자동으로 닫히도록 동작이 추가되었습니다.
  • 버그 수정

    • 외부 API 호출에 인증 헤더가 잘못 포함되던 문제를 방지했습니다.
    • Android/iOS에서 특정 도메인에 대한 평문(HTTP) 트래픽을 허용해 네트워크 연결 안정성을 개선했습니다.
  • 스타일

    • 사이드바 항목 탭 시 기본 리플 피드백을 적용했습니다.

@Nico1eKim Nico1eKim self-assigned this Oct 2, 2025
@Nico1eKim Nico1eKim added FEAT 기능 개발 REFACTOR 기능을 건드리지 않는 리팩토링 OK Merge 완료된 PR labels Oct 2, 2025
@coderabbitai
Copy link

coderabbitai bot commented Oct 2, 2025

Walkthrough

Home 화면의 API 연동을 추가하고, ViewModel 기반 UI 상태 관리로 화면 로직을 이관했습니다. 클럽 목록/재실자 조회, 출퇴근 API 호출을 데이터 계층과 리포지토리에 구현했습니다. MPP 공통 BackHandler를 도입하고 플랫폼별 actual을 추가했습니다. Ktor 클라이언트의 인증 헤더 부착 로직을 호스트/경로 기준으로 분기했습니다. Android/iOS에서 명시적으로 평문 트래픽을 허용했습니다. iOS 프로젝트 빌드 설정이 갱신되었습니다.

Changes

Cohort / File(s) Summary
Home UI & 상태 관리
composeApp/src/commonMain/kotlin/org/whosin/client/presentation/home/HomeScreen.kt, .../HomeViewModel.kt, .../presentation/home/component/MyClubSidebar.kt, .../presentation/home/component/PresentMembersList.kt, .../presentation/home/mock/PresentMember.kt, .../core/navigation/WhosInNavGraph.kt
HomeScreen가 ViewModel의 uiState를 구독하도록 변경, 뒤로가기 처리(CommonBackHandler) 연동, 로딩/에러 상태 추가, 출퇴근 토글/갱신 연동. ViewModel에 상태/액션(load, refresh, toggleAttendance) 추가. Sidebar 클릭 처리 간소화. 멤버 UI 타입을 PresentMemberUi로 통일하고 mock PresentMember 제거. NavGraph에서 HomeScreen의 onNavigateBack 제거.
데이터 계층 (클럽)
.../data/dto/response/ClubPresencesResponseDto.kt, .../data/remote/RemoteClubDataSource.kt, .../data/repository/ClubRepository.kt
재실자 응답 DTO 추가. 원격 데이터 소스에 내 클럽 목록/재실자 조회, 출근/퇴근 API 추가. 리포지토리에 동일 기능 위임 메서드 4종 추가.
네트워크 인증 분기
.../core/network/HttpClientFactory.kt
BASE_URL의 호스트를 파싱하여 동일 호스트에만 Authorization 부착. 토큰 재발급 등 no-auth 경로 확장(member/reissue). 외부 호스트는 인증 헤더 미부착. 기본 토큰 값 및 경로 검사 로직 정리.
멀티플랫폼 BackHandler
.../presentation/component/BackHandler.kt, src/androidMain/.../BackHandler.kt, src/iosMain/.../BackHandler.kt, src/jvmMain/.../BackHandler.jvm.kt, src/wasmJsMain/.../BackHandler.wasmJs.kt
expect CommonBackHandler 추가 및 각 플랫폼 actual 구현. Android는 Compose BackHandler에 위임, 기타(iOS/JVM/WASM)는 no-op 본문.
플랫폼 네트워크 보안 설정
composeApp/src/androidMain/AndroidManifest.xml, iosApp/iosApp/Info.plist
AndroidManifest에 usesCleartextTraffic="true" 추가. iOS Info.plist에 ATS 예외 도메인(whosinroom.store 및 서브도메인) 추가로 HTTP 허용.
iOS 프로젝트 설정
iosApp/iosApp.xcodeproj/project.pbxproj
Debug/Release 빌드 설정 블록 재구성, LastUpgradeCheck 갱신, 구성 목록 교체/재배치 등 Xcode 프로젝트 빌드 설정 전반 갱신.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User as 사용자
  participant UI as HomeScreen
  participant VM as HomeViewModel
  participant Repo as ClubRepository
  participant Remote as RemoteClubDataSource
  participant API as Server API

  User->>UI: 화면 진입
  UI->>VM: collect uiState 시작
  VM->>Repo: getMyClubs()
  Repo->>Remote: GET /clubs/my
  Remote->>API: 요청
  API-->>Remote: 클럽 목록
  Remote-->>Repo: ApiResult.Success
  Repo-->>VM: 결과
  VM->>VM: 첫 클럽 선택
  VM->>Repo: getPresentMembers(clubId)
  Repo->>Remote: GET /clubs/{id}/presences
  Remote->>API: 요청
  API-->>Remote: 재실자 목록
  Remote-->>Repo: ApiResult.Success
  Repo-->>VM: 결과
  VM-->>UI: uiState 업데이트(클럽/재실자/로딩)

  User->>UI: 출근/퇴근 토글
  UI->>VM: toggleAttendance()
  alt 출근 필요
    VM->>Repo: checkIn(clubId)
    Repo->>Remote: POST /clubs/{id}/check-in
  else 퇴근 필요
    VM->>Repo: checkOut(clubId)
    Repo->>Remote: DELETE /clubs/{id}/check-out
  end
  Remote->>API: 요청
  API-->>Remote: 상태 코드
  Remote-->>Repo: ApiResult
  Repo-->>VM: 결과
  VM->>Repo: getPresentMembers(clubId) 재조회
  Repo->>Remote: GET /clubs/{id}/presences
  Remote->>API: 요청
  API-->>Remote: 재실자 목록
  Remote-->>Repo: ApiResult.Success
  Repo-->>VM: 결과
  VM-->>UI: uiState 업데이트(참여 상태/재실자)
Loading
sequenceDiagram
  autonumber
  participant HC as HttpClient (Ktor)
  participant INT as Internal Host(BASE_URL)
  participant EXT as External Host

  Note over HC: 요청 전 인터셉터
  HC->>HC: 요청 URL 파싱(host, path)
  alt host == BASE_URL.host
    alt path ∈ no-auth 목록(로그인/재발급 등)
      HC->>HC: Authorization 미부착
    else
      HC->>HC: Authorization: Bearer <token> 부착
    end
  else host != BASE_URL.host
    HC->>HC: Authorization 미부착
  end
  HC-->>INT: 내부호스트 요청(필요 시 인증)
  HC-->>EXT: 외부호스트 요청(무인증)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

새벽 빌드에 별이 반짝 ✨
홈의 길 열고, API 춤을 춘다
체크인 한 번, 체크아웃 두 번
바람처럼 흐르는 uiState 🌬️
뒤로가긴 부드럽게, 플랫폼마다 인사 🙇
오늘도 트래픽은 맑음(HTTP 살짝 허용) ☕️

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning 이 PR에는 홈 화면 API 통신과 직접 관련이 없는 범용 BackHandler expect/actual 구현, 네비게이션 함수 시그니처 변경, MyClubSidebar 스타일 리팩토링, 목 Mock 데이터 타입 정리, iOS 프로젝트 빌드 설정 및 Xcode 프로젝트 파일 대규모 재구성 등의 변경이 포함되어 있습니다. 이러한 변경은 이슈 #25의 API 통신 구현 범위를 벗어나므로 별도 관리가 필요합니다. API 통신 기능과 그 외 UI/플랫폼 설정 변경을 별도 PR로 분리하거나 범위를 벗어난 변경을 제거하여 기능별 리뷰와 유지보수를 용이하게 하는 것을 권장합니다.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed PR 제목 “[API] home api 통신”은 홈 화면 API 통신 구현이라는 주요 변경 사항을 명확하게 요약하고 있어 스캔하는 팀원이 주된 변경점을 바로 파악할 수 있습니다.
Linked Issues Check ✅ Passed 이 PR은 원문 이슈 #25의 홈 화면 API 통신 요구사항인 내 동아리/학과 목록 조회, 재실자 조회, 출퇴근 체크인·체크아웃 기능을 RemoteDataSource, Repository, ViewModel, UI 레이어 전반에 걸쳐 구현하여 Linked Issue와 완전히 일치합니다.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 112c245 and 3df6b5c.

📒 Files selected for processing (18)
  • composeApp/src/androidMain/AndroidManifest.xml (1 hunks)
  • composeApp/src/androidMain/kotlin/org/whosin/client/presentation/component/BackHandler.kt (1 hunks)
  • composeApp/src/commonMain/kotlin/org/whosin/client/core/navigation/WhosInNavGraph.kt (0 hunks)
  • composeApp/src/commonMain/kotlin/org/whosin/client/core/network/HttpClientFactory.kt (2 hunks)
  • composeApp/src/commonMain/kotlin/org/whosin/client/data/dto/response/ClubPresencesResponseDto.kt (1 hunks)
  • composeApp/src/commonMain/kotlin/org/whosin/client/data/remote/RemoteClubDataSource.kt (1 hunks)
  • composeApp/src/commonMain/kotlin/org/whosin/client/data/repository/ClubRepository.kt (1 hunks)
  • composeApp/src/commonMain/kotlin/org/whosin/client/presentation/component/BackHandler.kt (1 hunks)
  • composeApp/src/commonMain/kotlin/org/whosin/client/presentation/home/HomeScreen.kt (7 hunks)
  • composeApp/src/commonMain/kotlin/org/whosin/client/presentation/home/HomeViewModel.kt (1 hunks)
  • composeApp/src/commonMain/kotlin/org/whosin/client/presentation/home/component/MyClubSidebar.kt (2 hunks)
  • composeApp/src/commonMain/kotlin/org/whosin/client/presentation/home/component/PresentMembersList.kt (2 hunks)
  • composeApp/src/commonMain/kotlin/org/whosin/client/presentation/home/mock/PresentMember.kt (1 hunks)
  • composeApp/src/iosMain/kotlin/org/whosin/client/presentation/component/BackHandler.kt (1 hunks)
  • composeApp/src/jvmMain/kotlin/org/whosin/client/presentation/component/BackHandler.jvm.kt (1 hunks)
  • composeApp/src/wasmJsMain/kotlin/org/whosin/client/presentation/component/BackHandler.wasmJs.kt (1 hunks)
  • iosApp/iosApp.xcodeproj/project.pbxproj (7 hunks)
  • iosApp/iosApp/Info.plist (1 hunks)
💤 Files with no reviewable changes (1)
  • composeApp/src/commonMain/kotlin/org/whosin/client/core/navigation/WhosInNavGraph.kt
🧰 Additional context used
🧬 Code graph analysis (2)
composeApp/src/commonMain/kotlin/org/whosin/client/presentation/home/component/PresentMembersList.kt (1)
composeApp/src/commonMain/kotlin/org/whosin/client/presentation/home/component/PresentMembersItem.kt (1)
  • PresentMembersItem (27-88)
composeApp/src/commonMain/kotlin/org/whosin/client/presentation/home/HomeScreen.kt (6)
composeApp/src/androidMain/kotlin/org/whosin/client/presentation/component/BackHandler.kt (1)
  • CommonBackHandler (6-9)
composeApp/src/commonMain/kotlin/org/whosin/client/presentation/component/BackHandler.kt (1)
  • CommonBackHandler (5-6)
composeApp/src/iosMain/kotlin/org/whosin/client/presentation/component/BackHandler.kt (1)
  • CommonBackHandler (5-7)
composeApp/src/jvmMain/kotlin/org/whosin/client/presentation/component/BackHandler.jvm.kt (1)
  • CommonBackHandler (5-7)
composeApp/src/wasmJsMain/kotlin/org/whosin/client/presentation/component/BackHandler.wasmJs.kt (1)
  • CommonBackHandler (5-7)
composeApp/src/commonMain/kotlin/org/whosin/client/presentation/home/component/PresentMembersList.kt (1)
  • PresentMembersList (30-67)
🪛 Gitleaks (8.28.0)
composeApp/src/commonMain/kotlin/org/whosin/client/core/network/HttpClientFactory.kt

[high] 51-51: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: ios-build
🔇 Additional comments (9)
composeApp/src/commonMain/kotlin/org/whosin/client/presentation/home/component/MyClubSidebar.kt (1)

77-79: 더 간결한 Modifier 체인으로 개선됨

기존 코드는 background(shape) + clickable(interactionSource, indication=null)로 리플 효과를 억제했지만, 새 코드는 clipbackgroundclickable로 단순화하면서 기본 리플 효과를 사용하게 되었습니다. 이는 더 관용적인(idiomatic) 패턴이며, 사이드바 항목 선택 시 리플 효과가 표시되는 것이 UX 측면에서 일반적으로 적절합니다.

다만, 기존에 리플 효과를 의도적으로 제거했던 것이라면 clickableindication = null 파라미터를 추가하여 리플을 억제할 수 있습니다.

composeApp/src/commonMain/kotlin/org/whosin/client/presentation/home/component/PresentMembersList.kt (1)

25-25: 타입 마이그레이션 잘 완료됨

PresentMember에서 PresentMemberUi로의 타입 전환과 필드명 변경(nicknameuserName)이 정확하게 적용되었습니다. ViewModel의 UI 모델과 일관성 있게 연결되어 있습니다.

Also applies to: 32-32, 61-61

composeApp/src/androidMain/kotlin/org/whosin/client/presentation/component/BackHandler.kt (1)

1-9: Android actual 구현 정확함

플랫폼별 BackHandler에 정확히 위임하고 있으며, 시그니처도 expect 선언과 일치합니다.

composeApp/src/iosMain/kotlin/org/whosin/client/presentation/component/BackHandler.kt (1)

1-7: iOS actual 구현 적절함

iOS는 시스템 백 버튼이 없으므로 빈 구현이 적절합니다.

composeApp/src/wasmJsMain/kotlin/org/whosin/client/presentation/component/BackHandler.wasmJs.kt (1)

1-7: WASM/JS actual 구현 적절함

WASM/JS 타겟에서는 네이티브 백 버튼 개념이 없으므로 빈 구현이 적절합니다.

composeApp/src/commonMain/kotlin/org/whosin/client/presentation/component/BackHandler.kt (1)

1-6: 멀티플랫폼 BackHandler API 선언 정확함

expect 함수 시그니처가 명확하며, 각 플랫폼별 actual 구현이 제공되어 있습니다.

composeApp/src/jvmMain/kotlin/org/whosin/client/presentation/component/BackHandler.jvm.kt (1)

1-7: JVM actual 구현 적절함

데스크톱 환경에서는 시스템 백 버튼이 없으므로 빈 구현이 적절합니다.

composeApp/src/commonMain/kotlin/org/whosin/client/presentation/home/mock/PresentMember.kt (1)

3-11: Mock 데이터가 새 타입으로 정확히 업데이트됨

PresentMember를 제거하고 PresentMemberUi로 마이그레이션이 올바르게 완료되었습니다. 생성자 호출과 필드명이 일관성 있게 적용되어 있습니다.

iosApp/iosApp/Info.plist (1)

8-20: iOS ATS 예외 설정 확인 필요
Info.plist에서 whosinroom.store에 대한 ATS 예외를 추가해 암호화되지 않은 HTTP 통신을 허용하고 있습니다. 현재 해당 도메인이 HTTP/HTTPS 모두에서 연결되지 않고 SSL/TLS 인증서가 없어 보안 위험이 큽니다.

  • 도메인 주소 정확성 및 HTTPS 지원 계획 확인
  • 프로덕션 전까지 ATS 예외 제거 및 HTTPS 전용 연결 유지 권장

android:supportsRtl="true"
android:theme="@android:style/Theme.Material.Light.NoActionBar">
android:theme="@android:style/Theme.Material.Light.NoActionBar"
android:usesCleartextTraffic="true">
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

❓ Verification inconclusive

평문 트래픽 허용은 보안 위험이 있습니다.

android:usesCleartextTraffic="true" 설정은 암호화되지 않은 HTTP 통신을 허용합니다. iOS 측 Info.plist와 동일하게, 이는 중간자 공격에 노출될 수 있는 보안 위험이 있습니다.

개발 단계라면 임시로 사용할 수 있지만, 프로덕션 릴리스 전에는 반드시:

  1. 백엔드 API를 HTTPS로 전환
  2. 이 설정을 false로 변경하거나 제거

해야 합니다. Android 9(API 28) 이상에서는 기본적으로 cleartext 트래픽이 차단되므로, 보안을 위해 HTTPS 사용을 권장합니다.


AndroidManifest.xml(14행) cleartext 트래픽 허용 설정 제거
android:usesCleartextTraffic="true"는 중간자 공격 등에 취약하므로 개발용 임시 설정을 제외하고 프로덕션 전에는 false로 변경하거나 제거하고, 백엔드 API를 HTTPS로 전환해야 합니다.

🤖 Prompt for AI Agents
In composeApp/src/androidMain/AndroidManifest.xml around line 14, remove or set
android:usesCleartextTraffic="false" instead of true so the app does not allow
cleartext (HTTP) traffic in production; ensure backend endpoints use HTTPS and,
if necessary for development, gate any temporary cleartext allowance behind a
debug-only manifest or network security config not shipped to production.

Comment on lines +51 to 54
val accessToken = tokenManager.getAccessToken() ?: "eyJhbGciOiJIUzI1NiJ9.eyJ0b2tlblR5cGUiOiJhY2Nlc3MiLCJ1c2VySWQiOjUsInByb3ZpZGVySWQiOiJsb2NhbGhvc3QiLCJuYW1lIjoi7Iug7KKF7JykIiwicm9sZSI6IlJPTEVfTUVNQkVSIiwiaWF0IjoxNzU5MzgyMzg3LCJleHAiOjE3NTk5ODcxODd9.kT9IH60aCA-6ByEITb-_qPAJY0Oik1bbPKqcBWXzHIk"
val refreshToken = tokenManager.getRefreshToken() ?: "no_token"
BearerTokens(accessToken = accessToken, refreshToken = refreshToken)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

하드코드된 JWT 토큰을 즉시 제거해주세요

loadTokens 기본값으로 실제 JWT를 넣어 둔 상태입니다. 이는 비공개 자격 증명이 저장소에 노출되는 심각한 보안 사고이자, 토큰이 없어도 항상 해당 계정으로 인증 요청을 날리게 만들어 시스템 오용 위험까지 초래합니다. 토큰이 없을 때는 전송을 건너뛰도록 처리하고, 하드코드된 문자열을 삭제해 주세요.

-                        val accessToken = tokenManager.getAccessToken() ?: "eyJhbGciOiJIUzI1NiJ9.eyJ0b2tlblR5cGUiOiJhY2Nlc3MiLCJ1c2VySWQiOjUsInByb3ZpZGVySWQiOiJsb2NhbGhvc3QiLCJuYW1lIjoi7Iug7KKF7JykIiwicm9sZSI6IlJPTEVfTUVNQkVSIiwiaWF0IjoxNzU5MzgyMzg3LCJleHAiOjE3NTk5ODcxODd9.kT9IH60aCA-6ByEITb-_qPAJY0Oik1bbPKqcBWXzHIk"
-                        val refreshToken = tokenManager.getRefreshToken() ?: "no_token"
-                        BearerTokens(accessToken = accessToken, refreshToken = refreshToken)
+                        val accessToken = tokenManager.getAccessToken()
+                        val refreshToken = tokenManager.getRefreshToken()
+                        if (accessToken.isNullOrBlank() || refreshToken.isNullOrBlank()) {
+                            return@loadTokens null
+                        }
+                        BearerTokens(accessToken = accessToken, refreshToken = refreshToken)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
val accessToken = tokenManager.getAccessToken() ?: "eyJhbGciOiJIUzI1NiJ9.eyJ0b2tlblR5cGUiOiJhY2Nlc3MiLCJ1c2VySWQiOjUsInByb3ZpZGVySWQiOiJsb2NhbGhvc3QiLCJuYW1lIjoi7Iug7KKF7JykIiwicm9sZSI6IlJPTEVfTUVNQkVSIiwiaWF0IjoxNzU5MzgyMzg3LCJleHAiOjE3NTk5ODcxODd9.kT9IH60aCA-6ByEITb-_qPAJY0Oik1bbPKqcBWXzHIk"
val refreshToken = tokenManager.getRefreshToken() ?: "no_token"
BearerTokens(accessToken = accessToken, refreshToken = refreshToken)
}
val accessToken = tokenManager.getAccessToken()
val refreshToken = tokenManager.getRefreshToken()
if (accessToken.isNullOrBlank() || refreshToken.isNullOrBlank()) {
return@loadTokens null
}
BearerTokens(accessToken = accessToken, refreshToken = refreshToken)
🧰 Tools
🪛 Gitleaks (8.28.0)

[high] 51-51: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)

🤖 Prompt for AI Agents
In
composeApp/src/commonMain/kotlin/org/whosin/client/core/network/HttpClientFactory.kt
around lines 51-54, remove the hardcoded JWT and the "no_token" default and
change the logic so that when tokenManager.getAccessToken() or getRefreshToken()
returns null you do not construct or return BearerTokens; instead return null
(or an empty/absent marker) so the caller can skip attaching Authorization
headers. Delete the literal JWT string and "no_token", make the function return
a nullable BearerTokens (or Optional-equivalent) and ensure callers handle the
null case by not sending auth headers or requests that require auth.

Comment on lines +49 to +55
is ApiResult.Success -> {
val clubs = result.data.data.userClubs.map { ClubUi(it.clubId, it.clubName) }
_uiState.update { it.copy(isClubsLoading = false, clubs = clubs) }
// 첫 번째 클럽을 자동으로 선택하고 멤버 목록 로드
clubs.firstOrNull()?.let { firstClub ->
onClubSelected(firstClub)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

성공 시 오류 메시지 초기화가 누락됐습니다.

이전 호출이 실패하면 errorMessage가 채워진 상태로 남는데, 이후 성공 케이스에서 errorMessagenull로 되돌리지 않아 UI에 오류가 계속 노출됩니다. 성공 분기에서 errorMessage = null을 함께 세팅해 주세요.

🤖 Prompt for AI Agents
In
composeApp/src/commonMain/kotlin/org/whosin/client/presentation/home/HomeViewModel.kt
around lines 49-55, the success branch updates isClubsLoading and clubs but does
not clear a previous errorMessage; modify the _uiState.update call in the
ApiResult.Success branch to also set errorMessage = null so any prior error is
cleared when clubs load successfully (i.e., include errorMessage = null
alongside isClubsLoading = false and clubs = clubs).

Comment on lines +179 to +207
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = iosApp/Info.plist;
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
803A8C7FA01596D81A28696E /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = iosApp/Info.plist;
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Info.plist 자동 생성으로 ATS 예외가 사라집니다
GENERATE_INFOPLIST_FILE = YES로 바뀌면서 기존 iosApp/Info.plist에 정의해 둔 NSAppTransportSecurity 예외가 빌드 산출물에서 빠집니다. HTTP 엔드포인트 호출이 다시 막혀서 이번 PR 목적(홈 API 연동)이 바로 깨집니다. 수동 Info.plist를 그대로 쓰도록 원래대로 NO로 돌려주세요.

-				GENERATE_INFOPLIST_FILE = YES;
+				GENERATE_INFOPLIST_FILE = NO;

위 변경을 Debug/Release 모두에 적용하면 됩니다.

🤖 Prompt for AI Agents
In iosApp/iosApp.xcodeproj/project.pbxproj around lines 179 to 207,
GENERATE_INFOPLIST_FILE was set to YES for the Debug and Release build
configurations which causes the manually maintained iosApp/Info.plist (and its
NSAppTransportSecurity HTTP exceptions) to be ignored; revert these entries to
use the manual Info.plist by setting GENERATE_INFOPLIST_FILE = NO for both Debug
and Release so the existing NSAppTransportSecurity exceptions remain included in
the build artifacts.

@casper-jr casper-jr merged commit 0b83617 into WhosInRoom:develop Oct 3, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

FEAT 기능 개발 OK Merge 완료된 PR REFACTOR 기능을 건드리지 않는 리팩토링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[API] home api 통신

2 participants