-
Couldn't load subscription status.
- Fork 3
feat: 서비스 소개 배너 #124
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
feat: 서비스 소개 배너 #124
The head ref may contain hidden characters: "QI1-218-\uC11C\uBE44\uC2A4-\uC18C\uAC1C-\uC548\uB0B4-\uBC30\uB108-1\uAC1C"
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary of Changes
Hello @yshls, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request introduces a new interactive service introduction banner to the homepage. Its primary purpose is to provide users with a dynamic and engaging overview of the service's core values, key features, and available trading styles, enhancing the initial user experience and information accessibility.
Highlights
- New Service Introduction Component: I've added a new
Introductioncomponent (app/home/components/introduction.tsx) that serves as a dynamic, multi-slide banner to showcase the service's key aspects. - Homepage Integration: The
HomePage.tsxfile has been updated to import and render this newIntroductioncomponent directly below the existingBanner, ensuring it's prominently displayed on the main page. - Interactive UI/UX: The
Introductioncomponent features an auto-playing carousel with manual navigation (arrows, drag gestures, and pagination dots), leveragingframer-motionfor smooth transitions and animations, enhancing user engagement. - Rich Content Display: The banner supports various slide types, including a hero section, core values, key features, and different trade styles, each with dedicated layouts and icons (from
lucide-react), allowing for comprehensive information delivery. - Dependency Updates: I've updated
framer-motionand addedlucide-reactandreact-intersection-observerto the project dependencies to support the new component's functionality and styling.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.
| Feature | Command | Description |
|---|---|---|
| Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
| Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
| Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
| Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments or fill out our survey to provide feedback.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
이번 PR은 서비스 소개 배너 컴포넌트를 추가하는 내용이네요. 전반적으로 잘 작성되었지만, 몇 가지 개선점을 제안합니다.
주요 피드백은 다음과 같습니다:
- 네이밍 컨벤션: 컴포넌트와 상수의 이름을 스타일 가이드에 맞게 수정하여 일관성을 높였습니다.
- 코드 가독성: 매직 넘버를 상수로 추출하여 코드의 의도를 명확히 하도록 제안했습니다.
- 웹 접근성: 키보드 사용자와 스크린 리더 사용자를 위해 페이지네이션 UI를 개선했습니다.
- 최신 기술 적용: Next.js의
Image컴포넌트에서 deprecated된 prop을 최신 방식으로 수정했습니다. - 스타일 가이드 준수: import 순서와 JSDoc 작성 등 스타일 가이드를 준수하도록 수정 제안을 포함했습니다.
자세한 내용은 각 파일의 리뷰 코멘트를 참고해주세요.
| src={style.visual} | ||
| alt={style.title} | ||
| layout="fill" | ||
| objectFit="contain" | ||
| /> | ||
| </div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| import React, { useState, useEffect, useCallback } from 'react'; | ||
| import { motion, AnimatePresence } from 'framer-motion'; | ||
| import Image from 'next/image'; | ||
| import { | ||
| Newspaper, | ||
| Zap, | ||
| Clock, | ||
| CreditCard, | ||
| ShieldCheck, | ||
| Users, | ||
| ArrowLeft, | ||
| ArrowRight, | ||
| LogIn, // LogIn 아이콘 import | ||
| } from 'lucide-react'; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
스타일 가이드에 따라 import 구문을 그룹화하고 정렬해야 합니다.1 React 관련 import를 먼저, 그 다음 외부 라이브러리, 그리고 내부 모듈 순으로 정렬하는 것이 좋습니다. 각 그룹 내에서는 알파벳 순으로 정렬해주세요. 또한, named import 목록도 알파벳 순으로 정렬하는 것이 좋습니다.
import React, { useCallback, useEffect, useState } from 'react';
import { AnimatePresence, motion } from 'framer-motion';
import {
ArrowLeft,
ArrowRight,
Clock,
CreditCard,
Lock,
LogIn, // LogIn 아이콘 import
Newspaper,
ShieldCheck,
Users,
Zap,
} from 'lucide-react';
import Image from 'next/image';Style Guide References
Footnotes
|
|
||
| // --- 슬라이드 데이터 --- | ||
| const slides: Slide[] = [ | ||
| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
|
||
| // --- 메인 배너 컴포넌트 --- | ||
| export default function Banner() { | ||
| const [[page, direction], setPage] = useState([0, 0]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
컴포넌트의 이름이 파일명(introduction.tsx) 및 HomePage.tsx에서의 import 이름(Introduction)과 일치하지 않습니다. 현재 Banner로 되어 있는데, 일관성을 위해 Introduction으로 변경하는 것이 좋겠습니다. 이는 코드의 가독성과 유지보수성을 높여줍니다.1
또한, 스타일 가이드에 따라 공개된 모든 함수와 컴포넌트에는 JSDoc 주석을 작성해야 합니다.2 이 컴포넌트의 목적, props 등에 대한 설명을 JSDoc 형식으로 추가하면 코드 이해에 도움이 됩니다.
/**
* 서비스의 핵심 가치와 기능을 소개하는 슬라이드 배너 컴포넌트입니다.
*/
export default function Introduction() {Style Guide References
Footnotes
| const interval = setInterval(() => { | ||
| paginate(1); | ||
| }, 5000); | ||
| return () => clearInterval(interval); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| const slideIndex = ((page % slides.length) + slides.length) % slides.length; | ||
|
|
||
| const variants = { | ||
| enter: (direction: number) => ({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| paginate(1); | ||
| } else if (swipe > 10000) { | ||
| paginate(-1); | ||
| } | ||
| }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| key={i} | ||
| onClick={() => setPage([i, i > slideIndex ? 1 : -1])} | ||
| className={`h-2 w-2 rounded-full cursor-pointer transition-all duration-300 ${ | ||
| slideIndex === i ? 'w-6 bg-teal-green' : 'bg-gray-400' | ||
| }`} | ||
| /> | ||
| ))} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
페이지네이션 인디케이터로 사용되는 div 요소는 onClick 핸들러를 가지고 있지만 키보드로는 접근할 수 없으며 스크린 리더 사용자에게 적절한 정보를 제공하지 않습니다. 웹 접근성을 향상시키기 위해 div 대신 button 요소를 사용하거나, div에 role="button", tabIndex="0", 그리고 키보드 이벤트 핸들러(onKeyDown)를 추가하는 것을 고려해주세요.
<button
key={i}
onClick={() => setPage([i, i > slideIndex ? 1 : -1])}
className={`h-2 w-2 rounded-full cursor-pointer transition-all duration-300 ${
slideIndex === i ? 'w-6 bg-teal-green' : 'bg-gray-400'
}`}
aria-label={`${i + 1}번 슬라이드로 이동`}
aria-current={slideIndex === i}
/>|
|
|
/gemini review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
안녕하세요. 서비스 소개 배너 기능 추가 PR 리뷰입니다. 전반적으로 framer-motion을 활용하여 동적인 캐러셀 컴포넌트를 잘 구현하셨습니다. 다만, 코드의 유지보수성과 가독성을 높이기 위한 몇 가지 개선점을 제안합니다. 주요 내용으로는 스타일 가이드 준수, 매직 넘버 상수화, deprecated된 next/image prop 교체 등이 있습니다. 또한, 새로 추가된 컴포넌트가 실제 페이지에 적용되지 않은 부분과 사용하지 않는 의존성이 추가된 점도 확인이 필요해 보입니다. 자세한 내용은 각 코드 라인에 남긴 코멘트를 참고해주세요.
| ]; | ||
|
|
||
| // --- 메인 배너 컴포넌트 --- | ||
| export default function Banner() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| @@ -0,0 +1,335 @@ | |||
| 'use client'; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| type Slide = HeroSlide | CoreValuesSlide | FeaturesSlide | TradeStylesSlide; | ||
|
|
||
| // --- 슬라이드 데이터 --- | ||
| const slides: Slide[] = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
|
||
| // --- 메인 배너 컴포넌트 --- | ||
| export default function Banner() { | ||
| const [[page, direction], setPage] = useState([0, 0]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[[page, direction], setPage]와 같은 배열 비구조화 할당은 간결하지만, 처음 보는 개발자에게는 상태의 의미를 파악하기 어려울 수 있습니다. 상태를 객체로 관리하거나 두 개의 useState로 분리하면 가독성을 높일 수 있습니다.
제안 1: 상태 객체 사용
const [slideState, setSlideState] = useState({ page: 0, direction: 0 });제안 2: 개별 상태 사용
const [page, setPage] = useState(0);
const [direction, setDirection] = useState(0);| useEffect(() => { | ||
| const interval = setInterval(() => { | ||
| paginate(1); | ||
| }, 5000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| <Image | ||
| src={style.visual} | ||
| alt={style.title} | ||
| layout="fill" | ||
| objectFit="contain" | ||
| /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "prismjs": "^1.30.0", | ||
| "react": "19.1.0", | ||
| "react-dom": "19.1.0", | ||
| "react-intersection-observer": "^9.16.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📝 변경 사항
🔍 변경 사항 세부 설명
🕵️♀️ 요청사항
📷 스크린샷 (선택)