Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Projects 페이지 퍼블리싱#9 #10

Merged
merged 8 commits into from
Feb 18, 2025
Merged

Projects 페이지 퍼블리싱#9 #10

merged 8 commits into from
Feb 18, 2025

Conversation

2hanbyeol1
Copy link
Owner

@2hanbyeol1 2hanbyeol1 commented Feb 17, 2025

Summary by CodeRabbit

  • 새로운 기능
    • 체크박스 컴포넌트 추가.
    • 스크롤 위치에 따라 애니메이션 진행 표시기 추가.
    • 슬라이드 인 애니메이션을 적용한 새로운 컴포넌트 추가.
    • 경험 및 프로젝트 섹션에 대한 새로운 컴포넌트 추가.
    • 기술 섹션을 위한 새로운 컴포넌트 추가.
    • 섹션 가시성을 모니터링하는 새로운 컴포넌트 추가.
    • 웨이브 아이콘 애니메이션 컴포넌트 추가.
  • 버그 수정
    • 내비게이션 아이템 구조 수정.
  • 문서
    • 개발 환경에 모션 라이브러리 배지가 추가됨.
    • 페이지 제목이 '이한별 | 프론트엔드 개발자'로 변경됨.
  • 스타일
    • 내비게이션 간격 및 색상 팔레트 개선, 스크롤바 가시성 조정으로 전반적인 디자인 최적화.

@2hanbyeol1 2hanbyeol1 self-assigned this Feb 17, 2025
@2hanbyeol1 2hanbyeol1 linked an issue Feb 17, 2025 that may be closed by this pull request
Copy link

vercel bot commented Feb 17, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
hanbyeol ✅ Ready (Inspect) Visit Preview 💬 Add feedback Feb 17, 2025 5:40pm

Copy link

coderabbitai bot commented Feb 17, 2025

"""

Walkthrough

이번 변경 사항은 모션 라이브러리 도입을 위한 준비로, README와 package.json에 모션 관련 뱃지 및 의존성을 추가하고 다양한 UI 컴포넌트를 새로운 디렉토리 구조(src/app/)에서 도입 또는 수정하였습니다. 또한, 섹션 감시 및 애니메이션 효과를 위한 새로운 컴포넌트와 데이터 인터페이스가 추가되었으며, 기존 컴포넌트, 헬퍼 파일, 상수, 커스텀 훅 등이 제거되는 구조 재편이 이루어졌습니다.

Changes

파일 변경 요약
README.md, package.json 모션 라이브러리 관련: README에 모션 뱃지 추가, package.json에 "motion": "^12.4.2" 의존성 추가
src/app/_components/*
(Checkbox, HeaderNav, HeaderProgress, SlideInView)
새로운/개선된 컴포넌트 추가: 체크박스 컴포넌트 도입, 헤더 네비게이션 수정, 모션 기반 스크롤 진행 및 슬라이드 인 효과 컴포넌트 추가
src/app/_data/*
(experience.ts, project.ts, skill.ts)
데이터 구조 개선: 경험, 프로젝트, 스킬 정보를 위한 인터페이스와 상수(EXPERIENCE_CONTENTS, PROJECT_CONTENTS, SKILL_CONTENTS) 추가
src/app/_sections/*
(ContactSection, Experience, ExperiencesSection, IntroSection, WaveIcon, Project, ProjectsSection, SkillsSection, SectionWatcher)
섹션 컴포넌트 도입 및 수정: 기존 SectionWrapper를 SectionWatcher로 대체, 각 섹션 컴포넌트에서 인터페이스 활용, 애니메이션 및 UI 개선 적용
src/app/globals.css, tailwind.config.ts 스타일 업데이트: keyframe 애니메이션 제거, 스크롤바 숨김 적용, Tailwind 색상(dark3) 변경
src/app/page.tsx 경로 재구성: 새로운 디렉토리 구조에 맞춰 컴포넌트 import 경로 수정
삭제된 파일 (예: src/components/*, src/constants/section.ts, src/data/*, src/hooks/*) 레거시 제거: 기존 컴포넌트, 상수, 데이터 파일, 커스텀 훅 제거 및 정리
src/stores/useActiveSectionIdStore.ts 스토어 업데이트: 활성 섹션 관리를 위한 로직 개선 및 TSectionId 타입 추가

Sequence Diagram(s)

sequenceDiagram
    participant 사용자 as 사용자
    participant 페이지 as Page 컴포넌트
    participant 감시자 as SectionWatcher
    participant 저장소 as ActiveSectionStore

    사용자->>페이지: 페이지 스크롤
    페이지->>감시자: 각 섹션 렌더링
    감시자->>저장소: activate(sectionId) 호출
    저장소-->>감시자: 활성 섹션 업데이트
    감시자->>저장소: deactivate(sectionId) 호출
Loading

Poem

코드 정원 속을 달리며
모션 뱃지와 컴포넌트 춤을 추네
새로운 인터페이스와 데이터 흐름에
발자국 남기는 귀여운 토끼
한 줄 한 줄 사랑을 담아 🐰💻
"""

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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

🧹 Nitpick comments (11)
src/app/_sections/ContactSection/ContactSection.tsx (1)

3-12: 실제 연락처 섹션 컨텐츠 구현 필요

현재는 "ContactSection" 텍스트만 표시되고 있습니다. 연락처 정보, 소셜 미디어 링크, 또는 연락 양식 등 실제 컨텐츠를 구현해 주세요.

연락처 섹션에 필요한 컴포넌트 구현을 도와드릴까요?

src/app/_sections/IntroSection/IntroSection.tsx (1)

7-9: 섹션 ID 상수화 권장

하드코딩된 섹션 ID를 상수로 관리하면 재사용성과 유지보수성이 향상됩니다.

섹션 ID를 위한 상수 파일을 생성하고 다음과 같이 수정하는 것을 추천드립니다:

+import { SECTION_ID } from '@/constants';

-      sectionId="intro"
+      sectionId={SECTION_ID.intro}
src/app/_components/Header/HeaderProgress.tsx (1)

9-21: 접근성 개선 필요

스크롤 진행 상태를 나타내는 요소에 접근성 레이블이 없습니다.

다음과 같이 aria-label을 추가하여 접근성을 개선해 주세요:

      <motion.div
+        role="progressbar"
+        aria-label="가로 스크롤 진행률"
        style={{
          scaleX: scrollYProgress,
        }}
        className="z-10 h-1 origin-left bg-primary2 max-tablet:hidden"
      ></motion.div>
      <motion.div
+        role="progressbar"
+        aria-label="세로 스크롤 진행률"
        style={{
          scaleY: scrollYProgress,
        }}
        className="z-10 w-1 origin-top bg-primary2 tablet:hidden"
      ></motion.div>
src/app/_components/SlideInView/SlideInView.tsx (1)

9-29: 애니메이션 구현이 잘 되어있습니다.

다만, 성능 최적화를 위해 다음과 같은 개선을 제안합니다:

  • 하드웨어 가속을 위해 transform 속성 사용
  • will-change 속성 추가
 <motion.div
-  initial={{ opacity: 0, translateY: 30 }}
+  initial={{ opacity: 0, transform: 'translateY(30px)' }}
   whileInView={{
     opacity: 1,
-    translateY: 0,
+    transform: 'translateY(0)',
     transition: {
       duration: 0.7,
       delay,
     },
   }}
-  viewport={{ once: true, amount: 0.3 }}
+  viewport={{ once: true, amount: 0.3 }}
+  style={{ willChange: 'transform, opacity' }}
 >
src/app/_sections/SkillsSection/SkillsSection.tsx (1)

11-18: 애니메이션 딜레이 로직 개선이 필요합니다.

현재 짝수/홀수 인덱스에 따른 고정된 딜레이 값 대신, 더 자연스러운 시차 효과를 위해 동적인 딜레이 계산을 제안합니다.

 {SKILL_CONTENTS.map((skill, idx) => (
   <SlideInView
     key={`ski-${skill.title}`}
-    delay={idx % 2 === 0 ? 0 : 0.5}
+    delay={idx * 0.2}
   >
     <Skill skill={skill} />
   </SlideInView>
 ))}
src/app/_components/Header/HeaderNav.tsx (1)

8-14: 상수를 컴포넌트 외부로 이동 권장

NAV_ITEMS 상수를 컴포넌트 외부로 이동하면 불필요한 재생성을 방지하고 메모리 사용을 최적화할 수 있습니다.

+const NAV_ITEMS: TSectionId[] = ['intro', 'skills', 'experiences', 'projects', 'contact'] as const;

 function HeaderNav() {
-  const NAV_ITEMS: TSectionId[] = ['intro', 'skills', 'experiences', 'projects', 'contact'];
   // ... rest of the component
 }
src/app/_sections/ProjectsSection/ProjectsSection.tsx (2)

20-20: 스크롤 계산식 최적화 필요

현재 스크롤 위치 계산식이 복잡하고 이해하기 어렵습니다. 가독성과 유지보수성을 위해 계산식을 상수나 함수로 분리하는 것이 좋습니다.

+ const calculateScrollOffset = (count: number) => -(320 * (count - 1));
- [0, Math.min(0, -(320 * (PROJECT_COUNT - 1)))],
+ [0, Math.min(0, calculateScrollOffset(PROJECT_COUNT))],

34-34: 하드코딩된 값 상수화 필요

mt-[32rem]h-[320rem]과 같은 하드코딩된 값들은 유지보수를 어렵게 만듭니다.

+ const SECTION_MARGIN_TOP = '32rem';
+ const SECTION_HEIGHT = '320rem';
- className="mt-[32rem] h-[320rem] px-8"
+ className={`mt-[${SECTION_MARGIN_TOP}] h-[${SECTION_HEIGHT}] px-8`}
src/app/_data/skill.ts (1)

78-78: 상태 관리 라이브러리 사용 경험 구체화 필요

각 상태 관리 라이브러리의 사용 경험을 더 구체적으로 설명하면 좋을 것 같습니다.

- '상태 관리 라이브러리로 <b>Recoil, Zustand, Tanstack Query</b> 등을 사용한 경험이 있습니다.',
+ '상태 관리 라이브러리 경험: <b>Recoil</b>(전역 상태 관리), <b>Zustand</b>(상태 지속성), <b>Tanstack Query</b>(서버 상태 관리)'
src/app/_sections/ProjectsSection/Project.tsx (1)

19-25: 이미지 최적화 필요

Next.js Image 컴포넌트 사용 시 다음 사항들을 고려해주세요:

  1. height 속성에 0 대신 실제 값 지정
  2. 반응형 이미지를 위한 sizes 속성 추가
  3. 이미지 품질 최적화를 위한 quality 속성 설정
 <Image
   width={60}
-  height={0}
+  height={60}
+  sizes="60px"
+  quality={75}
   src={`/image/projects/${id}.png`}
   alt={title}
   className="h-auto duration-100 group-hover/project:scale-125"
 />
src/app/_data/experience.ts (1)

1-9: 인터페이스 타입 제약 추가 필요

TExperience 인터페이스의 배열 타입들에 대해 최소 길이 제약을 추가하면 좋을 것 같습니다.

 export interface TExperience {
   title: string;
   subtitle: string;
   duration: [Date, Date];
   description?: string;
-  activities: string[];
-  achievements: string[];
+  activities: [string, ...string[]];  // 최소 1개 이상
+  achievements: [string, ...string[]];  // 최소 1개 이상
   links?: { text: string; url: string }[];
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e2bed1b and 6bc251a.

⛔ Files ignored due to path filters (18)
  • package-lock.json is excluded by !**/package-lock.json
  • public/image/projects/chat-chat.png is excluded by !**/*.png
  • public/image/projects/culture-train.png is excluded by !**/*.png
  • public/image/projects/egomogo.png is excluded by !**/*.png
  • public/image/projects/liberty-52.png is excluded by !**/*.png
  • public/image/projects/movie-movie.png is excluded by !**/*.png
  • public/image/projects/oosie.png is excluded by !**/*.png
  • public/image/projects/portfolio-2.png is excluded by !**/*.png
  • public/image/projects/searchright.png is excluded by !**/*.png
  • public/image/skills/css.png is excluded by !**/*.png
  • public/image/skills/javascript.png is excluded by !**/*.png
  • public/image/skills/node.png is excluded by !**/*.png
  • public/image/skills/styled.png is excluded by !**/*.png
  • public/image/skills/supabase.png is excluded by !**/*.png
  • public/image/skills/tailwind.png is excluded by !**/*.png
  • public/image/skills/tanstack-query.png is excluded by !**/*.png
  • public/image/skills/typescript.png is excluded by !**/*.png
  • public/image/skills/zustand.png is excluded by !**/*.png
📒 Files selected for processing (36)
  • README.md (1 hunks)
  • package.json (1 hunks)
  • src/app/_components/Checkbox/Checkbox.tsx (1 hunks)
  • src/app/_components/Header/HeaderNav.tsx (1 hunks)
  • src/app/_components/Header/HeaderProgress.tsx (1 hunks)
  • src/app/_components/SlideInView/SlideInView.tsx (1 hunks)
  • src/app/_data/experience.ts (1 hunks)
  • src/app/_data/project.ts (1 hunks)
  • src/app/_data/skill.ts (1 hunks)
  • src/app/_sections/ContactSection/ContactSection.tsx (1 hunks)
  • src/app/_sections/ExperiencesSection/Experience.tsx (1 hunks)
  • src/app/_sections/ExperiencesSection/ExperiencesSection.tsx (1 hunks)
  • src/app/_sections/IntroSection/IntroSection.tsx (1 hunks)
  • src/app/_sections/IntroSection/WaveIcon.tsx (1 hunks)
  • src/app/_sections/ProjectsSection/Project.tsx (1 hunks)
  • src/app/_sections/ProjectsSection/ProjectsSection.tsx (1 hunks)
  • src/app/_sections/SectionWatcher.tsx (1 hunks)
  • src/app/_sections/SkillsSection/Skill.tsx (2 hunks)
  • src/app/_sections/SkillsSection/SkillsSection.tsx (1 hunks)
  • src/app/globals.css (1 hunks)
  • src/app/page.tsx (1 hunks)
  • src/components/Header/HeaderProgress.tsx (0 hunks)
  • src/components/Sections/ContactSection/ContactSection.tsx (0 hunks)
  • src/components/Sections/ExperiencesSection/Experience.tsx (0 hunks)
  • src/components/Sections/ProjectsSection/ProjectsSection.tsx (0 hunks)
  • src/components/Sections/SectionWrapper.tsx (0 hunks)
  • src/components/Sections/SkillsSection/SkillsSection.tsx (0 hunks)
  • src/components/SlideInView/SlideInView.tsx (0 hunks)
  • src/constants/section.ts (0 hunks)
  • src/data/experience.ts (0 hunks)
  • src/data/skill.ts (0 hunks)
  • src/hooks/useIntersection.ts (0 hunks)
  • src/hooks/useScrollProgress.ts (0 hunks)
  • src/hooks/useThrottle.ts (0 hunks)
  • src/stores/useActiveSectionIdStore.ts (1 hunks)
  • tailwind.config.ts (1 hunks)
💤 Files with no reviewable changes (13)
  • src/constants/section.ts
  • src/data/skill.ts
  • src/components/Sections/SectionWrapper.tsx
  • src/components/Sections/ContactSection/ContactSection.tsx
  • src/data/experience.ts
  • src/hooks/useScrollProgress.ts
  • src/components/SlideInView/SlideInView.tsx
  • src/components/Header/HeaderProgress.tsx
  • src/components/Sections/SkillsSection/SkillsSection.tsx
  • src/components/Sections/ExperiencesSection/Experience.tsx
  • src/hooks/useThrottle.ts
  • src/components/Sections/ProjectsSection/ProjectsSection.tsx
  • src/hooks/useIntersection.ts
✅ Files skipped from review due to trivial changes (1)
  • src/app/page.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
src/app/_sections/ExperiencesSection/Experience.tsx

[error] 51-51: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)


[error] 63-63: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

src/app/_sections/SkillsSection/Skill.tsx

[error] 26-26: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

🪛 markdownlint-cli2 (0.17.2)
README.md

15-15: Images should have alternate text (alt text)
null

(MD045, no-alt-text)

🔇 Additional comments (10)
src/app/globals.css (2)

9-11: body 요소의 스크롤바 제거 스타일 적용
새롭게 추가된 body { -ms-overflow-style: none; } 구문은 IE 및 구형 브라우저에서 스크롤바를 감추어, 모션 라이브러리 도입에 따른 깔끔한 UI 제공에 기여합니다.


12-14: WebKit 브라우저 스크롤바 숨김 처리
body::-webkit-scrollbar { display: none; }를 통해 Chrome, Safari 등 WebKit 기반 브라우저에서 스크롤바를 완전히 숨기는 방식이 효과적입니다. 이 변경은 불필요한 UI 요소를 제거하여 사용자 경험을 개선할 수 있습니다.

src/app/_components/SlideInView/SlideInView.tsx (1)

5-7: Props 인터페이스 구조가 명확합니다.

delay prop의 타입이 적절하게 정의되어 있습니다.

src/app/_sections/ExperiencesSection/ExperiencesSection.tsx (2)

1-3: import 경로가 새로운 디렉토리 구조를 반영합니다.

app 디렉토리로의 마이그레이션이 잘 이루어졌습니다.


8-9: 반응형 디자인 구현이 개선되었습니다.

gap과 padding 값의 조정으로 모바일/태블릿 환경에서의 레이아웃이 개선되었습니다.

src/stores/useActiveSectionIdStore.ts (1)

3-8: 섹션 ID 타입 정의가 명확합니다.

유니온 타입을 사용하여 가능한 섹션 ID 값을 제한한 것이 좋습니다.

src/app/_sections/SkillsSection/SkillsSection.tsx (1)

9-10: 반응형 그리드 레이아웃이 잘 구현되어 있습니다.

배경 효과와 함께 스킬 섹션의 시각적 구조가 잘 설계되었습니다.

src/app/_data/project.ts (1)

3-11: 인터페이스 구조가 잘 설계되었습니다!

프로젝트 데이터를 위한 인터페이스가 명확하게 정의되어 있으며, 필요한 모든 필드가 포함되어 있습니다. 특히 description을 string 또는 string[] 타입으로 유연하게 정의한 점이 좋습니다.

src/app/_sections/ExperiencesSection/Experience.tsx (1)

6-87: 컴포넌트 구조가 체계적으로 잘 구성되었습니다!

  • 타입스크립트 인터페이스를 잘 활용했습니다
  • 조건부 렌더링이 깔끔하게 처리되었습니다
  • Tailwind 클래스를 활용한 스타일링이 일관성 있게 적용되었습니다
🧰 Tools
🪛 Biome (1.9.4)

[error] 51-51: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)


[error] 63-63: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

package.json (1)

12-12:

✅ Verification successful

motion 라이브러리 버전 호환성 확인 필요

motion 라이브러리의 버전(12.4.2)이 React 19 및 Next.js 15.1.5와 호환되는지 확인해주세요.


🌐 Web query:

Is Framer Motion v12.4.2 compatible with React 19 and Next.js 15?

💡 Result:

Framer Motion v12.4.2 (now rebranded as Motion for React) is compatible with React 19 and Next.js 15 when using the updated motion package instead of framer-motion. Here's what you need to know:

Key Compatibility Points

  1. Package Renaming

    • Replace framer-motion with motion in your dependencies[1][3].
    • Use imports from "motion/react" instead of "framer-motion"[1][3]:
      npm uninstall framer-motion
      npm install motion
  2. React 19 Support

    • Motion v12+ aligns with React 19’s changes (e.g., ref handling in props)[5][9].
    • Next.js 15’s App Router uses React 19 RC by default[2][4], but ensure third-party libraries like Motion are updated to avoid conflicts[6][7].
  3. Next.js Compatibility

    • Next.js 15 supports both React 18 (Pages Router) and React 19 (App Router)[2][4].
    • For server components, use motion/react-client imports[5]:
      import * as motion from "motion/react-client";

Common Issues & Fixes

  • Peer Dependency Conflicts: Earlier alphas (e.g., 12.0.0-alpha.0) had issues with React 19 due to hardcoded peer dependencies on React 18[6][7]. This was resolved in stable releases like v12.4.2.
  • Testing: Update Jest tests to await microtask renders introduced in React 19[1].

Example Integration

// Client Component
import { motion } from "motion/react";

export default function AnimatedComponent() {
  return (
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      transition={{ duration: 0.5 }}
    />
  );
}

For server components, use a client-side wrapper or dynamic imports[8].

Summary: Use motion@12.4.2 with next@15 and react@19 by following updated import paths and ensuring dependencies are cleanly upgraded[1][3][9].

Citations:


모션 라이브러리 버전 호환성 검증 완료

현재 "motion": "^12.4.2"는 최신 업데이트에 따라 React 19 및 Next.js 15와 호환되는 것으로 확인되었습니다. 다만, 패키지 이름이 기존의 framer-motion에서 motion으로 변경되었으므로, 올바른 import 경로(예: 클라이언트 컴포넌트의 경우 "motion/react", 서버 컴포넌트의 경우 "motion/react-client")를 사용하고 있는지 다시 한번 확인해 주세요.

  • 확인 사항
    • 기존 framer-motion 관련 import가 남아있지 않은지.
    • 클라이언트와 서버 컴포넌트에서 각각 올바른 모듈(import 경로)을 사용 중인지.

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

♻️ Duplicate comments (2)
src/app/_sections/ProjectsSection/Project.tsx (1)

51-56: 🛠️ Refactor suggestion

툴팁 접근성 개선이 필요합니다.

현재 툴팁 구현은 스크린 리더 사용자에게 접근이 어려울 수 있습니다.

 <span
   className="hover absolute left-1/2 top-[140%] hidden -translate-x-1/2 whitespace-nowrap rounded-sm bg-black/50 px-2 py-1 text-white group-hover/skill:block"
-  aria-label={`사용된 기술: ${skill}`}
+  role="tooltip"
+  aria-label={`사용된 기술: ${skill}`}
 >
   {skill}
 </span>
src/app/_data/project.ts (1)

43-43: ⚠️ Potential issue

프로젝트 날짜를 현재 시점으로 수정해주세요.

일부 프로젝트의 날짜가 미래로 설정되어 있습니다. 포트폴리오의 신뢰성을 위해 현재 시점(2024년 2월)을 기준으로 날짜를 수정하는 것이 좋겠습니다.

Also applies to: 52-52, 60-60, 69-69, 77-77, 91-91

🧹 Nitpick comments (4)
src/app/_sections/ProjectsSection/Project.tsx (2)

19-25: 이미지 최적화 개선이 필요합니다.

Next.js Image 컴포넌트 사용 시 다음 사항들을 개선하면 좋겠습니다:

  • height 속성에 0 대신 실제 값을 지정
  • 이미지 품질과 로딩 성능을 위해 qualitypriority 속성 추가 고려
 <Image
   width={60}
-  height={0}
+  height={60}
   src={`/image/projects/${id}.png`}
   alt={title}
+  quality={90}
+  priority={true}
   className="h-auto duration-100 group-hover/project:scale-125"
 />

28-36: 설명 텍스트의 높이 제한이 UX에 영향을 줄 수 있습니다.

h-12 클래스로 인해 설명 텍스트가 잘릴 수 있습니다. 다음과 같은 개선을 제안합니다:

  • 높이 제한 제거
  • 말줄임표(...) 처리
  • 또는 동적 높이 조정
-<p className="mx-4 mb-5 h-12 text-center text-lg">
+<p className="mx-4 mb-5 text-center text-lg line-clamp-2">
src/app/_data/project.ts (2)

18-18: 날짜 형식을 일관성 있게 수정해주세요.

날짜 문자열 형식이 일관되지 않습니다. YYYY.MM 형식으로 통일하는 것이 좋겠습니다.

-  duration: [new Date('2023.03'), new Date('2023.12')],
+  duration: [new Date('2023.03.01'), new Date('2023.12.31')],

Also applies to: 26-26, 34-34


3-11: 타입 정의 개선이 필요합니다.

더 엄격한 타입 체크를 위해 다음 개선사항을 제안합니다:

  • id에 가능한 값들을 유니온 타입으로 정의
  • duration 타입을 커스텀 타입으로 분리하여 재사용성 확보
+type ProjectId = 'liberty-52' | 'egomogo' | 'chat-chat' | 'movie-movie' | 'culture-train' | 'oosie' | 'searchright' | 'portfolio-2';
+type ProjectDuration = [Date, Date];

 export interface TProject {
-  id: string;
+  id: ProjectId;
   title: string;
   description: string | string[];
-  duration: [Date, Date];
+  duration: ProjectDuration;
   mainSkills: TSkillImgFileName[];
   isMain: boolean;
   bgDark?: boolean;
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6bc251a and d6f6996.

📒 Files selected for processing (2)
  • src/app/_data/project.ts (1 hunks)
  • src/app/_sections/ProjectsSection/Project.tsx (1 hunks)

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

♻️ Duplicate comments (2)
src/app/_sections/SkillsSection/Skill.tsx (1)

25-27: ⚠️ Potential issue

dangerouslySetInnerHTML 사용에 대한 보안 경고

HTML 콘텐츠를 안전하게 렌더링하기 위해 DOMPurify와 같은 sanitization 라이브러리를 사용하는 것을 권장드립니다. XSS 공격 위험을 방지하기 위해 이 부분을 수정해 주시기 바랍니다.

🧰 Tools
🪛 Biome (1.9.4)

[error] 26-26: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

src/app/_sections/ExperiencesSection/Experience.tsx (1)

57-57: ⚠️ Potential issue

dangerouslySetInnerHTML 사용에 대한 보안 위험

dangerouslySetInnerHTML의 사용은 XSS 공격에 취약할 수 있습니다. HTML 콘텐츠를 안전하게 렌더링하기 위해 다음과 같은 대안을 고려해보세요:

  1. DOMPurify 라이브러리 사용
  2. 마크다운 렌더러 사용 (예: react-markdown)
  3. 허용된 HTML 태그만 파싱하는 커스텀 컴포넌트 구현

Also applies to: 69-69

🧰 Tools
🪛 Biome (1.9.4)

[error] 57-57: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

🧹 Nitpick comments (4)
src/app/_sections/SkillsSection/Skill.tsx (1)

15-15: 이미지 대체 텍스트를 더 설명적으로 개선하세요.

현재 alt 텍스트는 파일 이름에 "아이콘"을 붙인 형태입니다. 스크린 리더 사용자를 위해 기술의 실제 이름을 사용하는 것이 더 도움이 될 것 같습니다.

예시:

-alt={`${imgFileName} 아이콘`}
+alt={`${title} 기술 아이콘`}
src/app/_sections/ProjectsSection/Project.tsx (1)

19-25: 이미지 대체 텍스트 개선 필요

현재 alt 텍스트는 단순히 "로고"만 언급하고 있습니다. 스크린 리더 사용자를 위해 더 자세한 설명을 제공하면 좋을 것 같습니다.

- alt={`${title} 로고`}
+ alt={`${title} 프로젝트 로고 이미지`}
src/app/_sections/ExperiencesSection/Experience.tsx (1)

74-90: 링크 섹션의 접근성 개선이 필요합니다.

링크의 목적이나 대상을 명확히 하기 위해 aria-label을 추가하는 것이 좋습니다.

다음과 같이 수정해보세요:

-                <Link href={link.url}>{link.text}</Link>
+                <Link 
+                  href={link.url}
+                  aria-label={`${link.text} - 새 탭에서 열기`}
+                  target="_blank"
+                  rel="noopener noreferrer"
+                >
+                  {link.text}
+                </Link>
src/app/_sections/SectionWatcher.tsx (1)

24-34: viewport margin을 props로 설정하는 것을 고려해보세요

현재 viewport margin이 하드코딩되어 있어 재사용성이 제한될 수 있습니다. 이를 props로 받아 더 유연하게 사용할 수 있도록 개선하는 것이 좋겠습니다.

 function SectionWatcher({
   sectionId,
   children,
   className,
+  viewportMargin = '0px 0px -10%',
-}: { sectionId: TSectionId } & ComponentProps<'section'>) {
+}: { sectionId: TSectionId; viewportMargin?: string } & ComponentProps<'section'>) {
   // ...
   return (
     <motion.section
       id={sectionId}
       className={className}
       onViewportEnter={onViewportEnter}
       onViewportLeave={onViewportLeave}
-      viewport={{ margin: '0px 0px -10%' }}
+      viewport={{ margin: viewportMargin }}
     >
       {children}
     </motion.section>
   );
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d6f6996 and fa34bc5.

⛔ Files ignored due to path filters (2)
  • public/image/skills/styled-component.png is excluded by !**/*.png
  • public/image/skills/tailwind-css.png is excluded by !**/*.png
📒 Files selected for processing (10)
  • src/app/_data/experience.ts (1 hunks)
  • src/app/_sections/ExperiencesSection/Experience.tsx (1 hunks)
  • src/app/_sections/ExperiencesSection/ExperiencesSection.tsx (1 hunks)
  • src/app/_sections/ProjectsSection/Project.tsx (1 hunks)
  • src/app/_sections/ProjectsSection/ProjectsSection.tsx (1 hunks)
  • src/app/_sections/SectionWatcher.tsx (1 hunks)
  • src/app/_sections/SkillsSection/Skill.tsx (2 hunks)
  • src/app/_sections/SkillsSection/SkillsSection.tsx (1 hunks)
  • src/app/layout.tsx (1 hunks)
  • src/utils/util.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/app/layout.tsx
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/app/_sections/SkillsSection/SkillsSection.tsx
  • src/app/_data/experience.ts
  • src/app/_sections/ExperiencesSection/ExperiencesSection.tsx
  • src/app/_sections/ProjectsSection/ProjectsSection.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
src/app/_sections/ExperiencesSection/Experience.tsx

[error] 57-57: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)


[error] 69-69: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

src/app/_sections/SkillsSection/Skill.tsx

[error] 26-26: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

🔇 Additional comments (10)
src/app/_sections/SkillsSection/Skill.tsx (1)

1-1: 타입 변경이 일관성 있게 적용되었습니다!

TSkillContent에서 TSkill로의 타입 변경이 import문과 함수 매개변수에 모두 올바르게 반영되었습니다.

Also applies to: 7-7

src/app/_sections/ProjectsSection/Project.tsx (4)

1-10: 코드가 깔끔하고 잘 구성되어 있습니다!

타입스크립트를 활용한 props 정의와 필요한 컴포넌트들의 import가 잘 되어있습니다.


28-36: 설명 텍스트 표시 방식 검토 필요

h-12로 고정된 높이와 line-clamp-2를 사용하고 있어, 긴 설명 텍스트가 잘릴 수 있습니다. 사용자가 전체 내용을 확인할 수 있는 방법을 고려해보세요.

다음과 같은 대안을 고려해볼 수 있습니다:

  1. 툴팁으로 전체 내용 표시
  2. 호버 시 전체 내용 표시
  3. "더 보기" 버튼 추가

37-44: 접근성을 고려한 날짜 표시 구현이 잘 되어있습니다!

aria-label을 사용한 날짜 정보 전달과 장식용 구분자의 aria-hidden 처리가 적절합니다.


54-60: 이전 리뷰의 접근성 개선 사항이 잘 반영되었습니다!

툴팁에 role="tooltip"과 aria-label을 추가하여 스크린 리더 사용자의 접근성이 개선되었습니다.

src/utils/util.ts (1)

7-8: LGTM! 접근성을 고려한 좋은 구현입니다.

날짜를 한국어 형식으로 변환하여 스크린 리더 사용자에게 더 자연스러운 경험을 제공합니다.

src/app/_sections/ExperiencesSection/Experience.tsx (2)

22-29: 접근성이 잘 고려된 구현입니다!

날짜 범위에 대한 aria-label이 적절하게 구현되어 있으며, 구분자("-")에 aria-hidden을 적용한 것이 좋습니다.


30-41: 이미지의 접근성 처리가 잘 되어있습니다.

장식용 별 이미지에 aria-hidden을 적용한 것이 적절합니다. 또한 시맨틱 HTML을 사용하여 제목의 계층 구조를 잘 표현하였습니다.

src/app/_sections/SectionWatcher.tsx (2)

8-15: 깔끔한 props 및 hooks 구현입니다!

타입 정의와 상태 관리가 잘 구현되어 있습니다.


16-22: 이벤트 핸들러가 깔끔하게 구현되었습니다!

이전 리뷰 코멘트에서 지적된 console.log 문이 제거되어 있고, 이벤트 핸들러가 간결하게 구현되어 있습니다.

@2hanbyeol1 2hanbyeol1 merged commit 8e5fa99 into main Feb 18, 2025
3 checks passed
@2hanbyeol1 2hanbyeol1 deleted the publish/projects branch February 18, 2025 03:23
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.

Projects 페이지 퍼블리싱
1 participant