Skip to content

[FEAT] 로딩 페이지 제작#561

Open
Chaejy wants to merge 1 commit intodevelopfrom
feat/loading-page
Open

[FEAT] 로딩 페이지 제작#561
Chaejy wants to merge 1 commit intodevelopfrom
feat/loading-page

Conversation

@Chaejy
Copy link
Contributor

@Chaejy Chaejy commented Mar 4, 2026

✅ 체크리스트

  • 코드에 any가 사용되지 않았습니다
  • 스토리북에 추가했습니다 (해당 시)
  • 이슈와 커밋이 명확히 연결되어 있습니다

🔗 관련 이슈

📌 작업 목적

  • apps/web의 전역 로딩 페이지를 제작하였습니다

🔨 주요 작업 내용

  • 로딩 애니메이션 css로 구현

🧪 테스트 방법

  • 로딩 시 화면 확인

✔️ 설치 라이브러리

📷 실행 영상 또는 스크린샷

💬 논의할 점

🙋🏻 참고 자료

Summary by CodeRabbit

  • 새로운 기능
    • 로딩 화면 애니메이션이 추가되었습니다. 순차적 애니메이션 효과가 적용된 다섯 개의 아이콘 기반 로딩 표시기와 한국어 로딩 메시지가 화면 중앙에 표시됩니다.

@vercel
Copy link

vercel bot commented Mar 4, 2026

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

Project Deployment Actions Updated (UTC)
surf-admin Ready Ready Preview, Comment Mar 4, 2026 1:26pm
surf-web Ready Ready Preview, Comment Mar 4, 2026 1:26pm

@coderabbitai
Copy link

coderabbitai bot commented Mar 4, 2026

📝 Walkthrough

Walkthrough

apps/web/src/app/loading.tsx 파일에 새로운 React 로딩 컴포넌트를 추가했습니다. 이 컴포넌트는 5개의 SVG 아이콘을 임포트하여 배열로 구성하고, 각 아이콘에 인라인 스타일을 통해 스태거된 애니메이션 딜레이를 적용하여 렌더링합니다. 레이아웃은 애니메이션을 중앙 정렬하며, 아래에 한국어 로딩 메시지를 표시합니다.


Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes


상세 피드백

📋 코드 구조 및 가독성

현재 상태: 인라인 스타일과 SVG 아이콘이 혼재되어 있어 가독성 저하 가능성이 있습니다.

개선안:

  • SVG 아이콘 배열을 별도의 상수로 분리하여 컴포넌트 로직 명확화
  • 애니메이션 딜레이 계산 로직을 함수로 추출
const LOADING_ICONS = [Icon1, Icon2, Icon3, Icon4, Icon5];

const getAnimationDelay = (index: number) => `${index * 0.1}s`;

♿ 접근성 (Accessibility)

문제점:

  • aria-label, role 속성 누락
  • 로딩 상태를 스크린 리더가 인식하지 못함

개선안:

<div role="status" aria-live="polite" aria-label="콘텐츠 로딩 중">
  {/* 로딩 아이콘 */}
</div>

🔒 유지보수성 및 확장성

문제점:

  • 5개 아이콘이 하드코딩되어 있어 개수 변경 시 코드 수정 필요
  • 애니메이션 딜레이 값이 고정되어 있음
  • 스타일(중앙정렬 등)이 인라인으로 작성되어 관리 어려움

개선안:

// 상수로 분리
const ANIMATION_CONFIG = {
  delayUnit: 0.1, // 초
  message: '로딩 중...',
};

// CSS 모듈 또는 Tailwind 클래스 사용
<div className="flex items-center justify-center">

🌐 브라우저 호환성

고려사항:

  • CSS 애니메이션 벤더 프리픽스 확인 필요
  • 트랜스폼 및 애니메이션 속성이 모든 브라우저에서 지원되는지 확인

개선안:

  • PostCSS Autoprefixer 사용으로 자동 벤더 프리픽스 적용

🧪 테스트

권장사항:

  • 로딩 애니메이션 렌더링 테스트 추가
  • 접근성 테스트 (WAVE, axe DevTools)
  • 성능 테스트 (불필요한 리렌더링 확인)

🏗️ Clean Architecture 검토

현재 구조: 로딩 페이지가 UI 레이어에 속함 (적절함)

개선 사항:

  • 애니메이션 관련 상수/설정을 별도 파일(loading.constants.ts)로 분리
  • 비즈니스 로직과 UI 표현 명확히 분리
  • 재사용 가능한 로딩 컴포넌트로 추상화 고려

핵심 개선 체크리스트

  • aria-label, role 속성 추가
  • SVG 아이콘 배열을 상수로 분리
  • 인라인 스타일을 CSS 클래스로 마이그레이션
  • 애니메이션 설정값 상수화
  • 유닛 테스트 추가
  • 접근성 검사 도구로 검증
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main objective: creating a loading page for the web app. It is concise and specific, accurately summarizing the primary change in the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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 feat/loading-page

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: 2

🧹 Nitpick comments (1)
apps/web/src/app/loading.tsx (1)

28-28: 로딩 문구 하드코딩은 다국어 확장 시 변경량을 키웁니다.

문제점: Line 28 문자열이 컴포넌트에 직접 하드코딩되어 있습니다.
원인: 공통 메시지 계층(i18n/message dictionary) 미사용.
대안: 메시지 키 기반으로 분리해 app 조립 레이어에서는 키만 사용하세요.
장단점: 지금은 한 단계 추가되지만, 다국어/브랜드 확장 시 비용이 크게 줄어듭니다.

As per coding guidelines, **의 “9) 확장 가능한 구조인지 검토: 다국어/테마 확장 시 변경량이 폭발하지 않는지.” 규칙을 반영했습니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/app/loading.tsx` at line 28, The span in loading.tsx currently
hardcodes "잠시만 기다려 주세요..."; replace this with a message key lookup from your
i18n/message dictionary (e.g., use t('app.loading') or messages.app.loading) so
the component only references the key; update the import/usage in the Loading
component to pull the translator or messages object (or accept it as a prop) and
ensure the message key 'app.loading' is added to the message dictionary for all
locales.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/app/loading.tsx`:
- Around line 17-29: The loading UI lacks accessibility attributes: add
role="status" and aria-live="polite" to the loading container (the top div that
wraps the spinner/characters) so screen readers are notified of the loading
state, ensure the visible message "잠시만 기다려 주세요..." is programmatically
associated (keep it inside that status container), and mark the decorative
character SVGs rendered by characters.map (the Character components) as
aria-hidden="true" (or add a prop to the Character components to render
aria-hidden when used here) so they are ignored by assistive tech; keep keys and
animation props unchanged.
- Around line 23-24: The loading SVG uses the CSS class "animate-float" (seen in
apps/web/src/app/loading.tsx on the element with className="animate-float" and
style animationDelay), but that utility is not defined; add a definition either
in Tailwind config (extend animation/keyframes with float and animate-float) or
in global CSS (add `@keyframes` float and .animate-float { animation: float 1.2s
ease-in-out infinite; }), then rebuild so the loading animation is applied.

---

Nitpick comments:
In `@apps/web/src/app/loading.tsx`:
- Line 28: The span in loading.tsx currently hardcodes "잠시만 기다려 주세요..."; replace
this with a message key lookup from your i18n/message dictionary (e.g., use
t('app.loading') or messages.app.loading) so the component only references the
key; update the import/usage in the Loading component to pull the translator or
messages object (or accept it as a prop) and ensure the message key
'app.loading' is added to the message dictionary for all locales.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3296fb25-9845-44c9-900d-79dab3fe334a

📥 Commits

Reviewing files that changed from the base of the PR and between ce5fb22 and 427a967.

⛔ Files ignored due to path filters (5)
  • apps/web/src/shared/assets/icons/loading/character-1.svg is excluded by !**/*.svg
  • apps/web/src/shared/assets/icons/loading/character-2.svg is excluded by !**/*.svg
  • apps/web/src/shared/assets/icons/loading/character-3.svg is excluded by !**/*.svg
  • apps/web/src/shared/assets/icons/loading/character-4.svg is excluded by !**/*.svg
  • apps/web/src/shared/assets/icons/loading/character-5.svg is excluded by !**/*.svg
📒 Files selected for processing (1)
  • apps/web/src/app/loading.tsx

Comment on lines +17 to +29
<div className="flex h-full w-full flex-col items-center justify-center">
<div className="flex flex-col items-center gap-10">
<div className="flex flex-row items-center">
{characters.map((Character, i) => (
<Character
key={i}
className="animate-float"
style={{ animationDelay: `${i * 0.1}s` }}
/>
))}
</div>
<span className="text-body-body8 text-foreground-tertiary">잠시만 기다려 주세요...</span>
</div>
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

로딩 상태 접근성(스크린리더 공지/장식 SVG 처리)이 빠져 있습니다.

문제점: 현재 마크업은 보조기기에 “로딩 상태”를 명확히 전달하지 못하고, SVG가 불필요하게 읽힐 수 있습니다.
원인: role="status", aria-live, 장식 아이콘의 aria-hidden 처리가 없습니다.
대안: 컨테이너에 상태 role을 추가하고 아이콘은 장식으로 숨기세요.
장단점: 구현 비용이 낮고 접근성/호환성이 즉시 개선됩니다.

♿ 제안 diff
-    <div className="flex h-full w-full flex-col items-center justify-center">
+    <div
+      className="flex h-full w-full flex-col items-center justify-center"
+      role="status"
+      aria-live="polite"
+      aria-busy="true"
+    >
       <div className="flex flex-col items-center gap-10">
         <div className="flex flex-row items-center">
           {characters.map((Character, i) => (
             <Character
               key={i}
               className="animate-float"
               style={{ animationDelay: `${i * 0.1}s` }}
+              aria-hidden="true"
+              focusable="false"
             />
           ))}
         </div>
-        <span className="text-body-body8 text-foreground-tertiary">잠시만 기다려 주세요...</span>
+        <span className="sr-only">로딩 중</span>
+        <span aria-hidden="true" className="text-body-body8 text-foreground-tertiary">
+          잠시만 기다려 주세요...
+        </span>
       </div>
     </div>

As per coding guidelines, **의 “6) 접근성: aria-label, role, 키보드 내비게이션, 포커스 트랩, 대비/색상 의존 금지.” 규칙을 근거로 한 지적입니다.

📝 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
<div className="flex h-full w-full flex-col items-center justify-center">
<div className="flex flex-col items-center gap-10">
<div className="flex flex-row items-center">
{characters.map((Character, i) => (
<Character
key={i}
className="animate-float"
style={{ animationDelay: `${i * 0.1}s` }}
/>
))}
</div>
<span className="text-body-body8 text-foreground-tertiary">잠시만 기다려 주세요...</span>
</div>
<div
className="flex h-full w-full flex-col items-center justify-center"
role="status"
aria-live="polite"
aria-busy="true"
>
<div className="flex flex-col items-center gap-10">
<div className="flex flex-row items-center">
{characters.map((Character, i) => (
<Character
key={i}
className="animate-float"
style={{ animationDelay: `${i * 0.1}s` }}
aria-hidden="true"
focusable="false"
/>
))}
</div>
<span className="sr-only">로딩 중</span>
<span aria-hidden="true" className="text-body-body8 text-foreground-tertiary">
잠시만 기다려 주세요...
</span>
</div>
</div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/app/loading.tsx` around lines 17 - 29, The loading UI lacks
accessibility attributes: add role="status" and aria-live="polite" to the
loading container (the top div that wraps the spinner/characters) so screen
readers are notified of the loading state, ensure the visible message "잠시만 기다려
주세요..." is programmatically associated (keep it inside that status container),
and mark the decorative character SVGs rendered by characters.map (the Character
components) as aria-hidden="true" (or add a prop to the Character components to
render aria-hidden when used here) so they are ignored by assistive tech; keep
keys and animation props unchanged.

Comment on lines +23 to +24
className="animate-float"
style={{ animationDelay: `${i * 0.1}s` }}
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

🧩 Analysis chain

🏁 Script executed:

# Search for animate-float and related animation definitions
rg -n --glob '!**/node_modules/**' 'animate-float|animate-loading-float|@keyframes.*float|loading.*float' -A 2

Repository: Tave-Makers/SURF-FE

Length of output: 269


🏁 Script executed:

# Check the loading.tsx file content
find . -name "loading.tsx" -type f | head -5

Repository: Tave-Makers/SURF-FE

Length of output: 93


🏁 Script executed:

# Check for tailwind config and globals.css
find . -name "tailwind.config.*" -o -name "globals.css" -o -name "global.css" | head -10

Repository: Tave-Makers/SURF-FE

Length of output: 179


🏁 Script executed:

# Read the loading.tsx file to understand full context
cat -n ./apps/web/src/app/loading.tsx

Repository: Tave-Makers/SURF-FE

Length of output: 1421


🏁 Script executed:

# Check apps/web globals.css for animation definitions
cat -n ./apps/web/src/shared/styles/globals.css

Repository: Tave-Makers/SURF-FE

Length of output: 1257


🏁 Script executed:

# Find tailwind config in apps/web
find ./apps/web -name "tailwind.config.*" -type f

Repository: Tave-Makers/SURF-FE

Length of output: 45


🏁 Script executed:

# Check packages/ui/styles/globals.css
cat -n ./packages/ui/styles/globals.css

Repository: Tave-Makers/SURF-FE

Length of output: 3223


🏁 Script executed:

# Find tailwind config at repo root
find . -maxdepth 2 -name "tailwind.config.*" -type f

Repository: Tave-Makers/SURF-FE

Length of output: 45


🏁 Script executed:

# Comprehensive search for animate-float definition in all CSS/JS files
rg -n 'animate-float|@keyframes.*float' --type css --type js

Repository: Tave-Makers/SURF-FE

Length of output: 45


🏁 Script executed:

# Search for tailwind.config more broadly (including package.json depth)
find . -name "tailwind.config.*" -o -name "tailwind.json"

Repository: Tave-Makers/SURF-FE

Length of output: 45


🏁 Script executed:

# Search for any keyframes definitions at all
rg -n '@keyframes' --type css

Repository: Tave-Makers/SURF-FE

Length of output: 45


🏁 Script executed:

# Check if animate-float is a Tailwind utility - search in tailwind config or extend section
rg -n 'animate.*float|animation.*float' --type js --type ts --type json

Repository: Tave-Makers/SURF-FE

Length of output: 134


animate-float 클래스 정의 누락으로 로딩 애니메이션이 동작하지 않습니다.

현재 코드는 SVG 컴포넌트에 animate-float 클래스를 적용하지만, 이 클래스가 프로젝트 어디에도 정의되어 있지 않습니다. 브라우저는 정의되지 않은 CSS 클래스를 자동으로 무시하므로 로딩 화면에서 애니메이션이 표시되지 않습니다.

해결책: Tailwind 설정에서 animate-float 애니메이션을 추가하거나, 전역 스타일에 @keyframes 정의를 추가하세요. 예를 들어:

tailwind.config.ts 예시
export default {
  theme: {
    extend: {
      animation: {
+       float: 'float 1.2s ease-in-out infinite',
      },
+     keyframes: {
+       float: {
+         '0%, 100%': { transform: 'translateY(0)' },
+         '50%': { transform: 'translateY(-6px)' },
+       },
+     },
    },
  },
}

또는 globals.css에 직접 정의:

`@keyframes` float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}

.animate-float {
  animation: float 1.2s ease-in-out infinite;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/app/loading.tsx` around lines 23 - 24, The loading SVG uses the
CSS class "animate-float" (seen in apps/web/src/app/loading.tsx on the element
with className="animate-float" and style animationDelay), but that utility is
not defined; add a definition either in Tailwind config (extend
animation/keyframes with float and animate-float) or in global CSS (add
`@keyframes` float and .animate-float { animation: float 1.2s ease-in-out
infinite; }), then rebuild so the loading animation is applied.

@Chaejy Chaejy self-assigned this Mar 6, 2026
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