[Refactor] #256 - 피드 새로고침 경로 통일·피드 탭 상시 mount 보존 + 온보딩 QA·UI 마감 - #258
Merged
Merged
Conversation
…g+초기 로드식 재로드로 통일 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbPWwtae6Rk1k1dZdC4s6k
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbPWwtae6Rk1k1dZdC4s6k
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbPWwtae6Rk1k1dZdC4s6k
- BaseData: StorageKey `.isRegistered`(Bool) 추가 — 키 없음=가입 완료로 간주(기존 로그인 유저 하위호환) - AuthData: 로그인 성공 시 서버 `isRegister`를 로컬에 저장, 로그아웃/탈퇴/재로그인 세션 경계(clearUserScopedCache)에서 삭제 - ProfileData: `registerProfile` 서버 성공 뒤 `.isRegistered=true` 기록(서버 확정 후에만 로컬 갱신) - SplashDomain: `LaunchGateRepository.isOnboardingCompleted()` 추가, 부트스트랩 게이트 2-1(세션 다음)로 미가입이면 `.intro` 반환 - SplashData: `DefaultLaunchGateRepository`가 AppStorage에서 `?? true`로 읽음(BaseData 의존 추가), Factory·App DI 배선 - 테스트: Bootstrap 게이트 5건·LaunchGate 3건·Auth 저장/삭제 4건·Profile 등록 기록 2건 추가(전부 green) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J5LLGdzCkgZstkLt7m776m
- 인트로: 사용자 취소(Apple `.canceled`·Kakao `.Cancelled`)는 서버 오류와 구분해 토스트 미표시(`.loginCancelled` 액션 추가) - 인트로: SE에서 토스트가 밀려나던 문제 수정 — GeometryReader(.ignoresSafeArea)로 배경 full-bleed·전경 세이프에어리어 패딩 분리, 토스트는 윈도우 바닥 기준 고정(1.5s 자동 닫힘은 공용 모디파이어와 동일 패턴) - 장르 선택: 성별/출생년도 확정 시 lazy mount가 만들던 opacity 삽입 전환 제거 — GenreSelectionViewModel을 항상 mount하고 프로필 문맥은 `.setProfileContext`로 확정 시점에 주입, 닉네임→성별과 동일한 슬라이드로 통일 - 닉네임: "다음으로" 진행 시 키보드 내림(`isKeyboardFocused = false`) - 완료: 로띠 `.playOnce`로 1회만 재생 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J5LLGdzCkgZstkLt7m776m
- WSSNicknameField에 `treatsFilledAsFocused: Bool = false` opt-in 추가 — 켜면 값이 비어있지 않은 동안 포커스 시 모양(흰 배경+gray70 폴백 테두리)을 유지. 배경만 희게 하면 검증 테두리 없는 상태에서 흰 화면 위 필드 윤곽이 사라져 배경·테두리를 한 조건으로 묶음 - 온보딩 닉네임 화면만 켬 — MyPageEditView는 기본값(꺼짐) 유지(닉네임이 항상 채워져 있어 상시 흰 배경이 되고 소개글 필드와 톤이 갈라짐, 통일은 디자인 확인 후) - 시뮬 실측: 입력 후 포커스 해제 → 흰 배경 유지 / 값 비우면 gray50 복귀 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J5LLGdzCkgZstkLt7m776m
내 피드↔소소피드 전환 시 이미 세운 탭은 재조회하지 않고 캐시를 그대로 보여준다(selectTab이 hasLoaded면 생략). View는 두 탭 ScrollView를 ZStack에 상시 mount하고 보이는 쪽만 켠다 — if/else 갈아끼우기는 branch 이탈 시 UIScrollView가 파괴돼 스크롤이 리셋되기 때문. 파생 조치로 threedots 앵커 딕셔너리를 탭별로 분리(내 글은 같은 feedId가 양쪽에 있어 덮어씀 방지)하고, .loadMore에 발화 탭을 실어 숨은 리스트 셀 실현이 현재 탭 페이지를 당기지 않게 가드했다. scrollIdentity는 탭 축을 빼고 자기 축만 남김. 시뮬레이터 실측 8항목(전환 0요청·탭별 깊이 보존·첫 전환만 로드·작성 복귀 리셋·축 전환은 그 탭만·앵커 분리·당겨서 새로고침·두 배열 동시 갱신) PASS. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbPWwtae6Rk1k1dZdC4s6k
삭제·셀 동기화(notFound/forbidden)로 removeCell이 셀을 지워도 myFeedsTotalCount는 그대로라, 다 지운 뒤 헤더는 "4개의 기록"·본문은 빈 뷰인 모순이 남았다(탭 전환 검증 중 실측 발견 — 이번 상시 mount 변경과 무관한 기존 결함). myFeeds에 있던 셀을 지울 때 카운트를 함께 내린다. 로드된 범위만 판별 가능한 best-effort고 놓친 케이스는 당겨서 새로고침이 서버 값으로 복구한다. 시뮬 실측: 작성 2건(0→1→2개) 후 소소피드 크로스탭 삭제 → 내 피드 전환 요청 0건에 헤더 2→1, 마지막 삭제 후 "0개의 기록"+빈 뷰 확인. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbPWwtae6Rk1k1dZdC4s6k
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbPWwtae6Rk1k1dZdC4s6k
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbPWwtae6Rk1k1dZdC4s6k
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbPWwtae6Rk1k1dZdC4s6k
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbPWwtae6Rk1k1dZdC4s6k
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbPWwtae6Rk1k1dZdC4s6k
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbPWwtae6Rk1k1dZdC4s6k
- #257 토스트 작업의 화면 전체 ignoresSafeArea 배선이 페이지형 TabView를 깨던 회귀(두 번째 페이지부터 상태바 높이만큼 솟구침·전환 멈춤) → 소거를 배경 레이어에만 한정, 토스트는 세이프에어리어 프레임 클램프 구조로 동일 위치 유지 - 레이아웃을 고쳐도 실기기에선 withAnimation 프로그램 전환이 선두 클론으로 애니메이션된 뒤 내부 페이지와 selection이 어긋나는 별개 결함 잔존(시뮬레이터 미재현) → ScrollView + scrollTargetBehavior(.paging) + scrollPosition(id:) 페이저로 교체(클론 패딩·자동 전환·클론 되감기 로직은 그대로) - Feature·OnboardingFeature CLAUDE.md에 함정 기록(자동 캐러셀에 TabView(.page) 금지) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbPWwtae6Rk1k1dZdC4s6k
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbPWwtae6Rk1k1dZdC4s6k
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbPWwtae6Rk1k1dZdC4s6k
…정 테스트) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbPWwtae6Rk1k1dZdC4s6k
… 명시) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbPWwtae6Rk1k1dZdC4s6k
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbPWwtae6Rk1k1dZdC4s6k
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbPWwtae6Rk1k1dZdC4s6k
테스트 커버리지 리포트
Generated by CI on 2026-09-10 01:49 KST |
… 실패 토스트) - 죽은 errorMessage를 탭별 myFeeds/sosoFeedsLoadError(RepositoryError?)로 교체, 실패 시 그 탭 콘텐츠 자리를 NetworkErrorView(재시도)로 대체(실패를 목록보다 먼저 판단) - 재시도(.retryLoad)는 그 탭을 비우고 reloadFromScratch — 작성 복귀 재로드 실패 시 "아직 남긴 기록이 없어요" 빈 화면 트랩(감수 사항) 해소 - 좋아요·삭제·신고 실패는 .networkDelay 토스트 lane(FeedDetail과 동일) - 인증 만료 라우팅은 여전히 미배선(실패 뷰로 흡수) — docs/TODO.md 12절에 잔여 갭 등재 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbPWwtae6Rk1k1dZdC4s6k
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
💡 Issue
💭 Summary
피드 최신화 전략을 앱 전역에서 하나로 통일했어요 — "재진입엔 다녀온 셀만 상세 API로 동기화, 새 글은 그 화면발 작성 성공 복귀 신호로만 리셋"이 소소피드와 작품 상세 피드 탭에 똑같이 적용돼요.
여기에 피드 서브탭 상시 mount(탭별 스크롤 보존), 온보딩 QA(#257 통합), UI 마감 수정 여러 건이 함께 실려 있어요.
🔑 Key Changes
피드 새로고침 통일 (핵심)
NovelFeedPageSizePolicy)는 새 글 유입 시 기존 글이 밀려나는 실결함이 있어 삭제했어요.Binding)로만 — 예전 앱 전역 신호(FeedListInvalidation)는 제거했어요.NetworkErrorView(재시도)가 뜨고, 좋아요·삭제·신고 실패는 토스트예요(예전엔 전부 무표시 — 아래 To Reviewer 참고).피드 서브탭 상시 mount (2026-09-09 확정)
ZStack에 상시 mount해 탭별 스크롤 깊이까지 보존해요.loadingTab: FeedTab?으로 "어느 탭의 로드인지"를 들고 다녀요(공유 Bool이면 엉뚱한 탭에 스피너가 뜨는 문제 — 리뷰 반영).onRoute(.createFeed))으로 배선했어요(죽은 버튼이었어요).온보딩 QA (#257 통합)
isOnboardingCompleted로컬 저장 + 부트스트랩 게이트, Domain 테스트 5개 포함).TabView→ 순수 SwiftUI 페이저로 교체(실기기에서selection어긋나는 UIKit 브리지 버그 회피).UI 마감·기타
WSSNovelCoverImage에.backdropplaceholder 신설 — 블러 아래 로딩 스피너가 회색 네모 잔상으로 보이던 문제 수정(홈 오늘의 발견·작품 상세 헤더).compositingGroup— 기본 스타일은 층별로 옅어져 표지만 도드라졌어요).wssCustomNavigationBar의swipeBackEnabled: Bool→swipeBackConfirmation: (() -> Void)?교체).QueryItemConvertible빈 배열은 쿼리 자체를 생략(서버는 미전송과 동일 취급).docs/ARCHITECTURE.mdSplashFeature 배선 서술 정정, [Fix] 작품 상세 — 피드 목록 변경 직후 화면 전환 시 무한 레이아웃 루프(라이브락) #239 라이브락 옛 결정론 조건(피드 3개+작성 복귀) 3회 재관찰 미재현 기록.📱 Simulation
(첨부 예정)
🧑🧒🧒 To Reviewer
리뷰 수렴 내역 — wss-pr-reviewer(opus)·wss-feature-reviewer(opus)·Codex CLI(코드)·Codex CLI(문서 감사) 4자 병렬 리뷰를 돌렸고, 🔴 0·🟡 9건을 전부 반영/처리했어요(2라운드 delta 검증까지 완료).
결정이 필요한 것 1→ 해소 — 작성 복귀 리셋의 실패 갭 (2026-09-10 구현)errorMessage를 탭별RepositoryError?로 교체하고, 첫 페이지·더보기·당겨서 새로고침·작성 복귀 재로드 어느 실패든 그 탭 콘텐츠 자리에NetworkErrorView(재시도)가 떠요.NovelDetail.retryFeeds와 같은 결) — "아직 남긴 기록이 없어요" 빈 화면 트랩이 사라졌어요. 좋아요·삭제·신고 실패는.networkDelay토스트로 표현해요(역시 무표시였던 갭).docs/TODO.md12절에 후속 등재.확인 요청 1→ 확인 완료 — 상세탐색 무필터 서버 회귀 없음/novels/filtered)에 파라미터 생략 버전과 빈 값(?genres=&…) 버전을 각각 보내 비교했어요(2026-09-09).resultCount95,598·반환 목록 완전 동일 / 장르(romance)만: 두 방식 모두 38,944·목록 동일.Projects/Core/Networking/CLAUDE.md).반영하지 않고 남긴 Nit (전부 리포트 원문 기준, 판단 필요하거나 무해)
selection상한 클램프 — 도달 경로를 못 찾았고 실기기 검증된 코드라 재검증 없이 안 건드렸어요.needs…ForCreatedFeed: Binding<Bool> = .constant(false)Factory 기본값 제거 — 새 조립 지점의 배선 누락을 컴파일러가 잡게 하려면 제거가 맞지만 API 변경이라 보류.novelID미탑재(엉뚱한 상세가 소비해도 피해는 재조회 1회), 작성 복귀 직후 "0개의 기록" 순간 노출,cellTopYs딕셔너리의 옛 ID 누적(무해), 상시 mount 렌더 비용(SE급 스크롤 프레임 확인 권장),tabButton높이 44pt 미달,UnifiedFadeButtonStyle두 번째 사용처 생기면 WSSComponent 승격.※ Reference
Projects/Feature/FeedFeature/CLAUDE.md화면 동작 계약(피드 목록) — 이번 통일의 정본Projects/Feature/NovelDetailFeature/CLAUDE.md로드 절 2026-09-08 재판정docs/TODO.md14절 — [Feat] 앱 배선 — 스플래시 부트스트랩·강제 업데이트 알럿·세션 복원·캐시 삭제·검색 네비·크로스스크린 피드백 채널 #236 실기기 QA 목록(이번 변경 검증 시 함께 참고)🤖 Generated with Claude Code