Skip to content

feat: 이미지 Lazy Loading 적용으로 피드 렌더링 성능 개선#317

Merged
heeeeyong merged 3 commits into
refactorfrom
refactor-feed-initial-rendering
Mar 2, 2026
Merged

feat: 이미지 Lazy Loading 적용으로 피드 렌더링 성능 개선#317
heeeeyong merged 3 commits into
refactorfrom
refactor-feed-initial-rendering

Conversation

@heeeeyong

@heeeeyong heeeeyong commented Feb 28, 2026

Copy link
Copy Markdown
Collaborator

📝작업 내용

피드 성능 이슈를 점검한 결과, 초기 구간에서 뷰포트 밖 이미지까지 동시에 요청/디코딩되는 비용이 컸습니다.
(React.lazy는 컴포넌트(JS 번들) 지연 로딩 용도이며, 이번 개선은 이미지 리소스 병목 해소가 목적이라 별도로 적용하지 않았습니다.)
따라서, IntersectionObserver 방식을 사용한 이미지 로딩 최적화를 적용하고자 했습니다.

적용 방식

  • IntersectionObserver로 이미지 엘리먼트가 뷰포트 근처에 들어왔을 때만 실제 src를 로드
  • 로딩 완료 전에는 placeholder를 유지해 불필요한 요청을 지연
  • 로딩 완료 시 blur/fade/scale 전환으로 시각적 품질 개선

구현 내용

  • LazyImage 컴포넌트에서 shouldLoad, isLoaded 상태 분리
  • src 변경 시 isLoaded 리셋
  • 이미지 속성 최적화 유지
  • loading="lazy"
  • decoding="async"
  • fetchPriority="low"

위키

자세한 내용은 위키를 참고해주세요!

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 이미지 지연 로딩 기능 추가로 성능 향상
    • 게시물에 작성자 별칭 표시 기능 추가 (커스텀 이름 및 색상 지원)
  • 개선 사항

    • 인증 토큰 처리 로직 최적화 및 중복 요청 제거
    • 인증 상태 관리 강화

@heeeeyong heeeeyong self-assigned this Feb 28, 2026
@vercel

vercel Bot commented Feb 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
thip Ready Ready Preview, Comment Feb 28, 2026 9:04am

@coderabbitai

coderabbitai Bot commented Feb 28, 2026

Copy link
Copy Markdown

Walkthrough

인증 준비 상태 관리, 지연 로딩 이미지 렌더링, 소셜 로그인 토큰 중복 제거 로직을 추가하고, 게시물 헤더에 별칭 필드를 확장하며, 검색 결과에 작성자 정보와 별칭 색상을 전달합니다.

Changes

Cohort / File(s) Summary
인증 및 토큰 처리
src/components/common/Layout.tsx, src/hooks/useSocialLoginToken.ts
인증 준비 상태를 관리하는 훅 추가 및 토큰 대기 기능을 포함한 social login 토큰 처리 로직 개선. 동시 요청 중복 제거 및 localStorage 기반 토큰 저장소 업데이트 포함.
이미지 지연 로딩
src/components/common/Post/LazyImage.tsx, src/components/common/Post/PostBody.tsx
IntersectionObserver 기반 이미지 지연 로딩 컴포넌트 신규 추가 및 기존 img 태그를 LazyImage로 교체.
게시물 메타데이터 확장
src/types/post.ts, src/components/common/Post/PostHeader.tsx, src/pages/searchBook/SearchBook.tsx
PostData 인터페이스에 별칭 필드 추가, PostHeader에서 별칭명 조건부 렌더링, 검색 결과에서 FeedPost에 작성자 정보 및 별칭 색상 전달.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

✨ Feature

Suggested reviewers

  • ljh130334
  • ho0010

Poem

🐰 지연된 이미지가 살금살금 나타나고,
로그인 토큰이 한 번만 기다리며,
별칭으로 게시물이 더욱 예뻐지니,
우리의 코드는 오늘도 한 발 더 앞으로!
✨🖼️

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 Lazy Loading 적용을 통한 성능 개선이라는 주요 변경사항을 정확하게 요약하고 있으며, 실제 변경 내용(LazyImage 컴포넌트 추가, IntersectionObserver 적용)과 일치합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor-feed-initial-rendering

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.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/components/common/Layout.tsx (1)

46-46: 인증 대기 중 null 렌더 대신 최소 로딩 UI를 두는 것을 권장합니다.

Line [46]은 준비 전 화면이 완전히 비어 보여 체감 화이트스크린으로 보일 수 있습니다. 간단한 fallback을 두면 UX가 더 안정적입니다.

♻️ 제안 diff
-      {isAuthReady ? <Outlet /> : null}
+      {isAuthReady ? (
+        <Outlet />
+      ) : (
+        <div role="status" aria-live="polite" aria-busy="true" />
+      )}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/common/Layout.tsx` at line 46, Layout component currently
renders nothing while waiting for auth (uses {isAuthReady ? <Outlet /> : null});
replace the null fallback with a minimal loading UI (e.g., a small spinner,
skeleton bar, or an accessible "Loading..." status element) so the screen isn't
blank. Update the render in the Layout component to show that fallback when
isAuthReady is false (you can create a tiny LoadingFallback component or inline
element) and ensure it is accessible (role/status or aria-busy) and visually
lightweight.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/hooks/useSocialLoginToken.ts`:
- Around line 24-53: The race occurs because the async IIFE always calls
setReady(true) in finally even if a newer loginTokenKey started; modify the
logic in the sharedTokenPromise creation (the async IIFE inside the if that sets
sharedLoginTokenKey/sharedTokenPromise) to capture the current
loginTokenKey/sharedTokenPromise into local constants (e.g., const capturedKey =
sharedLoginTokenKey and const capturedPromise = sharedTokenPromise) and, instead
of unconditionally calling setReady(true) in finally, only call setReady(true)
when the captured values still match the latest ones (e.g., sharedLoginTokenKey
=== capturedKey && sharedTokenPromise === capturedPromise); keep all getToken,
success/failure handling unchanged so only the readiness flip is gated to the
latest request.

---

Nitpick comments:
In `@src/components/common/Layout.tsx`:
- Line 46: Layout component currently renders nothing while waiting for auth
(uses {isAuthReady ? <Outlet /> : null}); replace the null fallback with a
minimal loading UI (e.g., a small spinner, skeleton bar, or an accessible
"Loading..." status element) so the screen isn't blank. Update the render in the
Layout component to show that fallback when isAuthReady is false (you can create
a tiny LoadingFallback component or inline element) and ensure it is accessible
(role/status or aria-busy) and visually lightweight.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9f45089 and e707809.

📒 Files selected for processing (7)
  • src/components/common/Layout.tsx
  • src/components/common/Post/LazyImage.tsx
  • src/components/common/Post/PostBody.tsx
  • src/components/common/Post/PostHeader.tsx
  • src/hooks/useSocialLoginToken.ts
  • src/pages/searchBook/SearchBook.tsx
  • src/types/post.ts

Comment thread src/hooks/useSocialLoginToken.ts
@heeeeyong heeeeyong merged commit 64a6adc into refactor Mar 2, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant