Skip to content

[Refactor/#89] 아카이빙 사진 뷰어를 공용 PhotoGallery로 통합 - #90

Open
LSJ102510 wants to merge 7 commits into
feat/#31-archive-list-screenfrom
refactor/#89-archives-photo-gallery
Open

LSJ102510 wants to merge 7 commits into
feat/#31-archive-list-screenfrom
refactor/#89-archives-photo-gallery

Conversation

@LSJ102510

@LSJ102510 LSJ102510 commented Oct 1, 2026 •

Copy link
Copy Markdown
스크린샷 2026-10-01 오후 7 07 36 image image image

#️⃣연관된 이슈

base가 feat/#31-archive-list-screen입니다(PR #40 위에 쌓은 PR). #40이 머지되면 base가 자동으로 main으로 바뀝니다.

🎯 해결하려는 문제가 무엇인가요?

아카이빙 사진 뷰어(ArchivesPhotoViewerScreen)와 공용 components/ui/PhotoGallery.tsx가 가로 스크롤 스냅 + PageCounter를 각자 구현하고 있었습니다. 뷰어를 공용 갤러리로 합칩니다.

❓ 왜 해결해야 하나요?

같은 인터랙션이 두 곳에 있으면 한쪽만 고치는 일이 생깁니다. 실제로 "세게 밀어도 한 장만 넘어가는" 처리(PR #40 리뷰 반영)는 뷰어에만 들어가 있었습니다.

⭐ 어떻게 해결했나요?

PhotoGallery에 아래를 추가하고, 뷰어를 그 위에서 다시 조립했습니다. 기존 호출부(공지 상세·행사 상세)는 그대로 동작합니다.

  • photos — 실제 사진 배열({ src, alt }). 기존 photoCount(회색 placeholder)와는 유니온 타입이라 둘 중 하나만 받습니다
  • initialPage / onPageChange — 누른 사진에서 열고, 현재 장을 바깥에 알립니다(뷰어의 흐린 배경이 따라갑니다)
  • background — 슬라이드 뒤에 깔리는 슬롯(뷰어의 흐린 사진)
  • snapAlign / snapStop — 뷰어는 center + 한 장씩 멈춤, 공지·행사는 기존 start 유지
  • className / photoClassName / counterClassName / counterAlternative — 전체 화면 배치와 하단 가운데 카운터

여기에 더해 사진 로딩도 정리했습니다.

  • components/ui/LazyImage.tsx 추가 — 사진이 오기 전에는 회색 자리(thumbnail-placeholder)를 보여주고 도착하면 0.3s 페이드인합니다. 받는 시점은 브라우저 기본 지연 로딩(loading="lazy")에 맡겼습니다
  • 카드가 길게 이어지는 아카이빙 목록과 현장 사진 격자 두 곳에만 적용했습니다. 상세 대표 사진·3칸 미리보기·뷰어는 평범한 <img>입니다

리뷰에서 나온 것들도 함께 고쳤습니다.

  • 오버스크롤 버그 — scrollLeft를 클램프하지 않아 마지막 장을 세게 밀면 카운터가 "27 / 26"이 되고, 뷰어가 photos[26](undefined)을 흐린 배경 src로 넣어 배경이 사라졌습니다. FeedbacksDetailScreen에 이미 있던 같은 처리를 공용 컴포넌트에도 넣었습니다
  • onPageChange를 스크롤 이벤트마다가 아니라 장이 바뀔 때만 호출합니다
  • 뷰어 사진을 자르지 않습니다(object-contain) — 비율이 다른 사진이 좌우로 잘리던 문제
  • 하단 Home Bar 여백 복붙 3곳을 components/ui/ScreenBottomSafeArea.tsx로 묶었습니다
  • 필터 칩에 aria-pressed를 넣었습니다(아카이빙 연도 필터 + 빌릴게·행사 필터)
  • 목록 열을 ArchivesPhotoColumn으로 분리하고, 정보 그리드 라벨 칸을 minmax(51px,auto)로 바꿨습니다

🧩 이 PR의 한계 & 트레이드오프

  • PhotoGallery의 props가 늘었습니다. 화면마다 배치가 달라 레이아웃 클래스를 받는 prop이 몇 개 생겼습니다
  • 지연 로딩은 긴 화면(목록)에서만 효과가 뚜렷합니다. 현장 사진 격자는 전체 높이가 브라우저의 선로딩 거리 안이라 대부분 미리 받습니다
  • 뷰어에서 사진 비율이 제각각이면 넘길 때 높이가 바뀝니다. 틀을 고정하면 사라지지만 좌우에 여백이 생겨서, 가로를 꽉 채우는 쪽을 택했습니다
  • PhotoGallery·FeedbacksDetailScreen·FeedbacksListScreen에 스냅 스크롤 계산이 각각 들어 있습니다. 공용 훅(useSnapPager)으로 빼는 건 열린피드백 화면까지 건드려야 해서 이번 범위에서 뺐습니다
  • 블러업(저해상도 썸네일 → 원본)은 썸네일이 없어서 페이드인으로 대체했습니다

⛓️ 기존 기능에 미치는 영향

  • 공용 PhotoGallery를 수정했습니다. 공지 상세·행사 상세는 photos·background를 넘기지 않아 placeholder 동작이 그대로지만, 리뷰 시 한 번 봐주시면 좋겠습니다
  • 슬라이드 영역에 relative를 추가했습니다(배경 슬롯이 일반 흐름 슬라이드 위에 그려지는 문제 때문). 기존 화면 배치에는 영향이 없습니다

🔀 Edge Case & 실패 시나리오

  • 주소의 photoIndex가 숫자가 아니거나 범위를 벗어나면 첫 장/마지막 장으로 맞춥니다
  • 캐시된 사진은 React가 onLoad를 붙이기 전에 로딩이 끝나 이벤트가 오지 않습니다 — 마운트 시 complete를 확인해 회색 자리에 멈추지 않게 했습니다
  • 사진이 1장이면 화살표와 스크롤 핸들러가 붙지 않습니다

📋 검토한 대안과 선택 이유

  • 스크롤 스냅·페이지 계산만 훅으로 빼고 레이아웃은 화면마다 두는 방안도 있었지만, 공용 컴포넌트가 이미 있어서 거기에 prop을 더하는 쪽을 골랐습니다
  • 지연 로딩에 IntersectionObserver를 직접 두는 방안은 뺐습니다 — loading="lazy"와 같은 일을 두 번 하게 되고, 스크롤 컨테이너가 중첩된 구조라 기준을 또 관리해야 합니다

💬 리뷰 포인트

  • [r] PhotoGallery의 늘어난 props 범위 — 더 줄일 여지가 있는지
  • [c] 공지 상세·행사 상세 갤러리가 전과 같은지
  • [a] LazyImage의 캐시 처리(complete 확인)

확인 방법

헤드리스 Chrome(390×844)으로 목데이터를 임시로 늘려 측정했습니다(임시 패치는 커밋하지 않았습니다).

  • 카드 40장 기준 — DOM <img> 40개, 스크롤 전 이미지 요청 15건, 맨 아래까지 스크롤 후 24건
  • 사진 요청을 막은 상태 — 회색 자리 rgb(217,217,217), 사진 opacity: 0, 도착 후 opacity: 1(transition: opacity 0.3s)

@coderabbitai

coderabbitai Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: c1bea484-3cb8-4a42-8f68-33f1ce134971

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


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.

이승준 added 3 commits October 1, 2026 18:26
Safari 탄성 오버스크롤에서 scrollLeft가 범위를 벗어나 마지막 장을 세게 밀면 카운터가
"27 / 26"이 되고 뷰어의 흐린 배경이 사라졌다. FeedbacksDetailScreen과 같은 방식으로 클램프한다.
장이 실제로 바뀔 때만 onPageChange를 호출하고, 뷰어 사진은 자르지 않고 가로를 꽉 채운다.
- 지연 로딩은 목록이 긴 아카이빙 목록·현장 사진 목록에만 둔다
- 하단 Home Bar 여백 복붙 3곳을 ScreenBottomSafeArea로 묶는다
- 필터 칩 선택 상태를 aria-pressed로 알린다
- 목록 열을 ArchivesPhotoColumn 컴포넌트로 분리한다
- 정보 그리드 라벨 칸을 minmax로 바꿔 긴 라벨이 넘치지 않게 한다
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