Skip to content

fix: 공유하기 링크 404·카드 아이콘 누락 수정 - #41

Merged
rrheon merged 2 commits into
developfrom
fix/share-icon-link
Aug 14, 2026
Merged

fix: 공유하기 링크 404·카드 아이콘 누락 수정#41
rrheon merged 2 commits into
developfrom
fix/share-icon-link

Conversation

@rrheon

@rrheon rrheon commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

요약

공유하기에서 링크가 열리지 않고 공유 카드에 아이콘·제목이 빠지던 문제 수정.

🐛 버그 수정

  1. 공유 링크 연결 실패 버그
  • 서버 측: 배틀 상세 shareUrl이 접속 불가능한 무관한 도메인(pique.app)으로 응답됨.
  • 클라이언트 폴백 측: 서버 값이 없을 때 사용하는 클라이언트 기본 링크가 존재하지 않는 복수형 경로(picke.store/battles/{id})로 설정되어 403 에러 발생 (실제 랜딩 경로는 단수형 /battle/{id}).

해결: 공유 링크 생성 PickeShareURL 추가

서버 응답 shareUrl이 picke.store(서브도메인 포함)인지 검증하여 신뢰할 수 있을 때만 사용.

도메인이 다르거나 값이 없으면, 실제 존재하는 단수형 경로(/battle/{id})로 클라이언트가 직접 생성하도록 로직을 추가
(적용: 사전투표·최종투표는 서버값 검증 후 사용, 빠른배틀은 모델에 서버값이 없어 항상 직접 생성)

  1. 공유 카드에 철학자 아이콘 누락 (빈 원으로 캡처되는 현상)

원인: KFImage 비동기 로딩 특성상, ImageRenderer가 화면을 동기적으로 캡처하는 시점에는 이미지가 로드되지 않아 플레이스홀더만 찍힘.

해결:

사전/최종투표: RecapView에 적용했던 avatarOverride 패턴(QA 픽스 eebbe2d)을 PreVoteView에 적용. Kingfisher로 이미지를 선로드한 뒤 뷰에 주입하여 정상적으로 렌더링되게 수정.

빠른배틀: URLSession으로 배틀 이미지를 먼저 다운로드한 뒤 UIImage 형태로 첨부하도록 처리.

  1. 최종투표 공유 카드에서 제목 문제

원인: 최종투표(post) 카드의 배경색이 밝은 beige50인데, 텍스트 색상(titleColor)도 동일한 beige50으로 설정되어 글씨가 배경에 묻힘.

해결: 스냅샷 렌더링 시점에만 titleColorOverride: .neutral500 속성을 적용.

테스트 플랜

  • 사전투표 공유 → 링크 picke.store/battle/{id} 접속, 카드에 아이콘·제목 렌더
  • 최종투표 공유 → 링크 동일, 밝은 배경에서 제목 가독
  • 빠른배틀 공유 → 링크 정상, 배틀 이미지 첨부
  • Recap 공유 → 기존과 동일(텍스트 + 카드 이미지)

공유하기에서 두 가지가 깨져 있었다.

1) 링크가 열리지 않음
   서버 배틀 상세의 shareUrl 이 무관한 도메인(pique.app)으로 내려오고,
   클라 폴백도 복수형 /battles/{id} 라 403 — 이중으로 죽은 링크였다.
   실존하는 웹 랜딩은 단수형 /battle/{id} 뿐이다.
   PickeShareURL 을 신설해 picke.store(서브도메인 포함) 링크만 신뢰하고,
   아니면 단수형 링크를 직접 만들도록 일원화했다.
   (서버 shareUrl 도메인 교정은 서버 측 후속 과제)

2) 공유 카드에 아이콘·제목이 빠짐
   KFImage 는 ImageRenderer 동기 렌더 시점에 항상 로드 전이라 빈 원으로
   캡처된다. RecapView 의 avatarOverride 패턴을 PreVoteView 에 이식해
   Kingfisher 로 선로드한 이미지를 주입해 렌더한다.
   빠른배틀은 배틀 이미지를 URLSession 으로 받아 첨부하도록 변경.
   최종투표(post)는 밝은 제목색이 밝은 스냅샷 배경에 묻혀 보이지 않아
   스냅샷에서만 어두운 제목색으로 고정했다.

Stage 빌드로 4개 공유 지점(사전투표·최종투표·빠른배틀·Recap) 실기 확인.
@github-actions

Copy link
Copy Markdown
Contributor

공유 기능 관련 버그 수정에 대한 PR을 검토했습니다.

새로운 PickeShareURL 엔티티를 도입하여 공유 링크 생성 로직을 Domain/Entity 레이어에서 일원화하고, 서버에서 잘못된 URL이 내려올 경우를 방어하는 견고한 로직을 추가했습니다. 이는 클린 아키텍처 원칙에 부합합니다.

공유 카드 스냅샷 시 아이콘(철학자 이미지) 및 제목이 올바르게 렌더링되지 않던 문제 또한 효과적으로 해결되었습니다. PreVoteView에서는 Kingfisher를 이용한 비동기 이미지 선로드 후 ImageRenderer에 주입하여 동기 렌더링 문제를 해결했고, BattleFeature에서도 URLSession을 통한 이미지 로드 및 ShareItem 구성을 적용했습니다. 또한, 최종투표(post) 화면의 제목 색상 문제를 titleColorOverride 패턴을 사용하여 수정했습니다.

TCA 컨벤션에 따라 비동기 작업(prepareShare)은 Effect.run을 통해 처리하고, state 업데이트는 InnerAction으로 분리하여 부작용을 관리하는 등 모범적인 패턴을 따르고 있습니다. SwiftUI 뷰 코드 역시 프로젝트의 @ViewBuilder 함수 패턴을 잘 준수하며 가독성 좋게 작성되었습니다.

전반적으로 설계가 견고하고, 모든 변경 사항이 명확하며 코드 품질도 높습니다. 특별히 지적할 만한 문제점은 발견되지 않았습니다.

@Roy-wonji Roy-wonji left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

리뷰 확인 해주세요

}
.cancellable(id: CancelID.fetchToday, cancelInFlight: true)

case let .prepareShare(text, url, imageURL):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

이걸 좀더 더 나은 방식으로 할수 없을까여?


Button {
send(.shareTapped(snapshot: captureCardSnapshot()))
shareWithSnapshot()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

이거 tca action 으로 할수는 없나요 ??

/// 좌/우 옵션의 원격 아바타를 Kingfisher 로 선로드 (실패한 쪽은 제외 → KFImage 폴백).
@MainActor
private func captureCardSnapshot() -> Data? {
private func loadOptionAvatarImages() async -> [Int: UIImage] {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

이런 로직은 뷰에서 빼줘 야 할거 같습니다 ...

var images: [Int: UIImage] = [:]
for option in [battle.leftOption, battle.rightOption] {
guard let url = URL(string: option.imageURL) else { continue }
let image: UIImage? = await withCheckedContinuation { continuation in

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

일것도 uscase 또는 내부에 서 해야 할거 같습니다

리뷰에서 받은 지적을 이렇게 반영했다.

- "공유 버튼을 TCA 액션으로" → 버튼은 send(.shareTapped) 만 보내고,
  나머지 흐름은 전부 리듀서 액션 체인으로 처리
- "아바타 로드 로직을 뷰에서 빼 달라" → 리듀서의 loadShareAvatars 로 이동
- "다운로드는 usecase 에서" → ShareUseCase 를 새로 만들어
  이미지 다운로드(loadImageData)와 공유 아이템 조립(makeShareItem)을 담당
- "BattleFeature 쪽도 더 나은 방식으로" → 이펙트 안의 생 URLSession 조립을
  없애고 같은 ShareUseCase + ShareContent 경로로 통일

카드 렌더(ImageRenderer)는 SwiftUI 뷰만 그릴 수 있어 뷰에 남겼고,
리듀서가 요청하면 그려서 돌려주는 역할만 한다.

Stage 빌드 + 시뮬레이터에서 공유 동작 재확인(링크 picke.store, 카드 아바타 렌더).
@rrheon
rrheon force-pushed the fix/share-icon-link branch from 262d9a2 to 413989e Compare August 13, 2026 04:52
@github-actions

Copy link
Copy Markdown
Contributor

공유하기 기능에 대한 전반적인 수정 사항은 TCA 아키텍처 및 Swift Convention을 잘 따르고 있습니다. PickeShareURL을 통한 안정적인 링크 생성, ShareUseCase를 통한 공유 아이템 조립, 그리고 비동기 이미지 로딩과 UI 스냅샷 렌더링을 위한 Reducer-View 간의 유기적인 TCA 플로우가 잘 구현되었습니다.

주요 버그 (404 링크, 아이콘 누락, 제목 가독성) 수정도 효과적으로 처리되었습니다. 전반적으로 높은 품질의 코드입니다.

현재 코드에 Critical, Major, Minor 수준의 문제는 발견되지 않았습니다. P4 Readability 수준의 개선 사항도 엄격한 기준에 따라 요청된 특정 서식 규칙에 위배되지 않는다고 판단하여, 추가 코멘트 없이 최종 제출합니다.

@rrheon
rrheon merged commit bd96afe into develop Aug 14, 2026
5 of 6 checks passed
@rrheon
rrheon deleted the fix/share-icon-link branch August 14, 2026 06:55
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.

2 participants