-
Notifications
You must be signed in to change notification settings - Fork 1
[FEAT] 메인 페이지 디자인 변경 및 토론 템플릿 섹션 추가 #356
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
Conversation
|
Caution Review failedThe pull request is closed. Walkthrough랜딩 페이지 레이아웃을 재구성하고 ScrollHint 및 TemplateSelection(템플릿 리스트/카드/신청) 컴포넌트를 추가했으며, 타임테이블·타이머·테이블·리뷰 섹션의 에셋·문구·레이아웃을 교체·조정하고 DebateTemplate 타입과 DEBATE_TEMPLATE 상수를 도입했다. Changes
Sequence Diagram(s)sequenceDiagram
participant U as 사용자
participant LP as LandingPage
participant SH as ScrollHint
U->>LP: 페이지 열기
LP->>SH: 마운트(topThreshold)
SH->>SH: window.scrollY 초기 검사
alt scrollY <= threshold
SH-->>U: 힌트 표시 (visible, aria-hidden=false)
else
SH-->>U: 힌트 숨김 (aria-hidden=true)
end
U-->>SH: 스크롤 이벤트
SH->>SH: 가시성 업데이트
sequenceDiagram
participant U as 사용자
participant TL as TemplateList
participant TC as TemplateCard
participant B as 브라우저
U->>TL: 템플릿 그리드 확인
TL->>TC: 카드 렌더링 (데이터 바인딩)
U->>TC: "토론하기" 클릭
TC->>B: action.href로 이동 (공유 URL 열기)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Assessment against linked issues
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
✨ Finishing Touches
🧪 Generate unit tests
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. Comment |
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.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/page/LandingPage/components/TamplateList.tsx (1)
1-22: 파일명에 오타가 있습니다파일명과 함수명에서 "Template"이 "Tamplate"로 잘못 작성되어 있습니다. 올바른 철자로 수정해야 합니다.
다음과 같이 수정을 권장합니다:
- 파일명:
TamplateList.tsx→TemplateList.tsx- 인터페이스명:
TamplateListProps→TemplateListProps- 함수명:
TamplateList→TemplateList- 주석에서 언급된 그리드 설명도 확인이 필요합니다 (Line 12: "작은 화면 1열"이라고 했지만 실제로는 2열로 설정됨)
-interface TamplateListProps { +interface TemplateListProps { data: DebateTemplate[]; } -export default function TamplateList({ data }: TamplateListProps) { +export default function TemplateList({ data }: TemplateListProps) { return ( <div className={[ 'grid gap-5', - // 작은 화면 1열, md에서 2열, xl에서 3열 + // 작은 화면 2열, lg에서 3열 'grid-cols-2 lg:grid-cols-3', ].join(' ')} >
🧹 Nitpick comments (20)
src/page/LandingPage/components/ReviewSection.tsx (4)
16-19: 헤딩 레벨 정리: h1 다중 사용 대신 h2로 통일 권장섹션 내부에 h1이 2개 있습니다. 페이지 내 단일 h1 원칙(혹은 섹션 스코프 헤딩 모델 미사용 시)을 고려해 h2로 내리는 편이 접근성/SEO에 안전합니다.
- <h1>이미 많은 사람들이 디베이트 타이머로</h1> - <h1>더 나은 토론환경을 만들고 있어요.</h1> + <h2>이미 많은 사람들이 디베이트 타이머로</h2> + <h2>더 나은 토론환경을 만들고 있어요.</h2>
26-31: button 기본 type 지정폼 내 포함될 가능성까지 고려하면 명시적 type="button"이 안전합니다.
- <button + <button + type="button" className="rounded-full border border-neutral-300 bg-brand px-20 py-2 text-[min(max(0.875rem,1.25vw),1.2rem)] font-medium text-default-black transition-all duration-100 hover:bg-semantic-table hover:text-default-white" onClick={onStartWithoutLogin} >
27-27: 색상 토큰 일관성다른 컴포넌트(TemplateCard)에서는 hover 시 text-white를 사용합니다. design token에 text-default-white가 없다면 효과가 적용되지 않을 수 있습니다.
- className="rounded-full border border-neutral-300 bg-brand px-20 py-2 text-[min(max(0.875rem,1.25vw),1.2rem)] font-medium text-default-black transition-all duration-100 hover:bg-semantic-table hover:text-default-white" + className="rounded-full border border-neutral-300 bg-brand px-20 py-2 text-[min(max(0.875rem,1.25vw),1.2rem)] font-medium text-default-black transition-all duration-100 hover:bg-semantic-table hover:text-white"
21-23: key 안정성 확인key를 review.user로 두셨는데 유저명이 중복될 가능성이 있으면 불안정합니다. 고유 id가 있으면 그 값으로 교체하는 것을 권장합니다.
src/type/type.ts (1)
75-86: 일반명 ‘Action’ 충돌 가능성 최소화 및 외부 재사용성 확보전역적으로 흔한 이름(Action)은 충돌 여지가 큽니다. 명확한 도메인 접두어를 붙여 export 하면 발견/재사용과 충돌 방지에 유리합니다.
-type Action = { +export type TemplateAction = { label: string; // 좌측에 표시할 토론 형식 이름 (예: "CEDA 토론") href: string; // 우측 "토론하기" 버튼의 이동 링크 }; export type DebateTemplate = { title: string; // 제목 (예: "서방정토") subtitle?: string; // 서브 제목 (예: "서강대") logoSrc?: string; // 로고 이미지 - actions: Action[]; + actions: TemplateAction[]; className?: string; // 카드의 추가 className이 필요하면 사용 };추가로, 기존 코드가
Action을 직접 import하지 않는다면 호환성 이슈는 없습니다. 만약 있다면 해당 사용처 타입만TemplateAction으로 교체하면 됩니다.src/page/LandingPage/components/TemplateCard.tsx (3)
15-16: Tailwind ring-3는 기본 스케일에 없음기본 Tailwind에서는 ring, ring-1, ring-2, ring-4, ring-8만 제공됩니다. 커스텀 설정이 없다면 ring-3는 미적용됩니다. ring-2로 조정 권장.
- 'ring-3 ring-brand/20', + 'ring-2 ring-brand/20',
21-22: 불필요한 공백 문자 정리className 문자열 앞 공백은 의미가 없습니다. 사소하지만 일관성 차원에서 제거 권장.
- <div className=" flex justify-between"> + <div className="flex justify-between">
43-64: action key와 링크 동작 확인
- key를 label+index로 구성하셨는데, label이 동일한 항목이 섞일 수 있으면 index 의존 키는 재정렬 시 리렌더 비용을 늘릴 수 있습니다. 가능하면 고유 id/slug 사용 권장.
- href가 외부 공유 URL(새 탭 열기 의도)이라면 target/rel 지정 검토 바람. 내부 라우팅이면 현재 형태 유지.
- <li key={`${a.label}-${i}`}> + <li key={`${a.label}-${i}`}> {/* 고유 id가 있다면 해당 id를 사용하세요 */} @@ - <a - href={a.href} + <a + href={a.href} + /* 외부 링크라면 아래 속성 추가 */ + /* target="_blank" rel="noopener noreferrer" */ className={[src/page/LandingPage/components/TamplateApplicationSection.tsx (3)
5-6: 모바일 반응형 레이아웃 보완현재 항상 가로 정렬입니다. 작은 화면에서 이미지와 텍스트가 비좁게 붙을 수 있어 세로 스택 후 md부터 가로 전환을 권장합니다.
- <section className="flex flex-row justify-between gap-1"> + <section className="flex flex-col-reverse items-center gap-6 md:flex-row md:justify-between">
13-24: 외부 이동은 a 태그가 접근성/SEO에 유리window.open을 버튼 onClick으로 처리하기보다 a 태그 + target/rel 사용이 표준적입니다.
- <button - onClick={() => - window.open( - LANDING_URLS.REPORT_FORM_URL, - '_blank', - 'noopener,noreferrer', - ) - } - className="rounded-full border border-neutral-300 bg-neutral-200 px-9 py-2 text-[min(max(0.875rem,1.25vw),1.2rem)] font-medium text-default-black transition-all duration-100 hover:bg-brand" - > - 신청하기 - </button> + <a + href={LANDING_URLS.REPORT_FORM_URL} + target="_blank" + rel="noopener noreferrer" + className="rounded-full border border-neutral-300 bg-neutral-200 px-9 py-2 text-[min(max(0.875rem,1.25vw),1.2rem)] font-medium text-default-black transition-all duration-100 hover:bg-brand" + > + 신청하기 + </a>
26-26: img 대체 텍스트 개선"section501"은 의미 없는 alt입니다. 장식 이미지면 alt=""로, 의미가 있으면 콘텐츠 설명으로 교체하세요. 또한 모바일 폭 대응을 위해 폭 클래스 보완을 권장합니다.
- <img src={section501} alt="section501" className="w-[30%]" /> + <img src={section501} alt="" className="w-10/12 max-w-[520px] md:w-[30%]" />src/page/LandingPage/components/TemplateSelection.tsx (1)
1-3: 이름 오타(Tamplate → Template) 정비 제안컴포넌트/파일/상수명이 혼재되어 검색성과 유지보수가 떨어집니다. 일괄 리네이밍을 권장합니다. (별도 PR로 진행해도 좋습니다)
-import { DEBATE_TAMPLATE } from '../../../constants/debate_tamplate'; -import TamplateApplicationSection from './TamplateApplicationSection'; -import TamplateList from './TamplateList'; +import { DEBATE_TAMPLATE } from '../../../constants/debate_tamplate'; // 상수/파일도 후속 PR에서 *template*으로 교체 권장 +import TemplateApplicationSection from './TemplateApplicationSection'; +import TemplateList from './TemplateList';아래 사용처도 동일하게 교체 필요:
- <TamplateList data={DEBATE_TAMPLATE.ONE} /> + <TemplateList data={DEBATE_TAMPLATE.ONE} /> @@ - <TamplateList data={DEBATE_TAMPLATE.TWO} /> + <TemplateList data={DEBATE_TAMPLATE.TWO} /> @@ - <TamplateList data={DEBATE_TAMPLATE.THREE} /> - <TamplateApplicationSection /> + <TemplateList data={DEBATE_TAMPLATE.THREE} /> + <TemplateApplicationSection />src/page/LandingPage/components/TableSection.tsx (1)
17-19: 접근성 개선을 위한 제안제목에
<br />태그를 사용하여 줄바꿈을 하고 있는데, 스크린 리더 사용자나 반응형 디자인 관점에서 더 나은 방법이 있습니다.CSS를 활용한 반응형 줄바꿈을 고려해보세요:
- 토론 정보 <br /> - 관리 및 기록 + <span className="block sm:inline">토론 정보</span> + <span className="block sm:inline"> 관리 및 기록</span>또는 모바일에서만 줄바꿈되도록:
- 토론 정보 <br /> - 관리 및 기록 + 토론 정보<br className="sm:hidden" /> 관리 및 기록src/page/LandingPage/LandingPage.tsx (1)
9-10: import 순서 정리 권장새로 추가된 컴포넌트 import들의 순서를 일관성 있게 정리하면 가독성이 향상됩니다.
import useLandingPageHandlers from './hooks/useLandingPageHandlers'; +import ScrollHint from './components/ScrollHint'; import TemplateSelection from './components/TemplateSelection'; -import ScrollHint from './components/ScrollHint';src/page/LandingPage/components/ScrollHint.tsx (1)
24-59: 주석 처리된 코드 정리 권장대량의 주석 처리된 코드가 있습니다. 이전 구현을 참고용으로 남겨둔 것 같지만, 코드 가독성을 위해 제거하는 것을 권장합니다.
Git 히스토리에서 이전 구현을 확인할 수 있으므로, 주석 처리된 코드는 제거해도 좋을 것 같습니다:
- // <div - // className={` - // pointer-events-none fixed inset-x-0 bottom-10 flex justify-center - // transition-all duration-300 - // ${visible ? 'translate-y-0 opacity-100' : 'translate-y-2 opacity-0'} - // `} - // aria-hidden={!visible} - // > - // <div - // className={` - // pointer-events-auto flex items-center gap-2 rounded-full - // bg-default-white/90 px-4 py-2 text-[min(max(0.85rem,1.2vw),1rem)] font-medium shadow-[0_6px_18px_rgba(0,0,0,0.12)] - // ring-1 - // ring-black/5 backdrop-blur - // transition-colors hover:bg-default-white - // `} - // > - // <svg - // width="18" - // height="18" - // viewBox="0 0 24 24" - // className="animate-bounce" - // aria-hidden - // > - // <path - // d="M6 9l6 6 6-6" - // fill="none" - // stroke="currentColor" - // strokeWidth="2" - // strokeLinecap="round" - // strokeLinejoin="round" - // /> - // </svg> - // 아래로 스크롤 - // </div> - // </div>src/constants/debate_tamplate.ts (1)
16-258: 템플릿 데이터 구조 개선 제안
- 템플릿 메타데이터와 인코딩된 URL을 분리해 관리하세요 (예:
TEMPLATE_METADATA+ENCODED_URL_DATA)- 각 항목이
DebateTemplate타입과 일치하는지 확인해 타입 안전성을 강화하세요- 인코딩된 URL이 올바르게 생성·동작하는지 유효성을 점검하세요 (현재 파일 내
createTableShareUrl(encodeData: string)는 로컬로 정의되어import.meta.env.VITE_SHARE_BASE_URL를 사용합니다)src/page/LandingPage/components/TimeTableSection.tsx (1)
8-9: 섹션 컨테이너 폭/정렬 일관화 제안TimerSection과 다르게 폭 제한/중앙 정렬이 없어 레이아웃 점프가 발생할 수 있습니다. 아래처럼 공통 컨테이너 규칙을 맞추는 것을 권장합니다.
- <section id="section1" className="flex flex-col gap-24"> + <section id="section1" className="mx-auto flex w-[95%] max-w-[1226px] flex-col gap-24 md:w-[64%]">src/page/LandingPage/components/TimerSection.tsx (3)
10-11: 섹션 폭 규칙 검토w-[95%]와 md:w-[64%] 사용은 의도일 수 있으나, TimeTableSection과 불일치합니다. 두 섹션의 컨테이너 폭·정렬을 통일해주세요(예: 공용 래퍼 컴포넌트).
17-20: 헤딩 내 줄바꿈
최소화문맥상 줄바꿈은 스타일로 제어하는 편이 번역/접근성에 안전합니다.
- <h2 className="mt-4 text-left text-[min(max(1.25rem,2.75vw),2.5rem)] font-bold"> - 원하는 때에 <br /> - 작전시간 사용하기 - </h2> + <h2 className="mt-4 text-left text-[min(max(1.25rem,2.75vw),2.5rem)] font-bold"> + <span className="block sm:inline">원하는 때에</span> 작전시간 사용하기 + </h2>
50-53: 헤딩 내
최소화(가독성/번역 고려)동일 맥락으로 줄바꿈을 스타일로 제어하는 편이 안전합니다.
- <h2 className="mt-4 text-left text-[min(max(1.25rem,2.75vw),2.5rem)] font-bold"> - 키보드 방향키로 <br />더 편리한 조작 - </h2> + <h2 className="mt-4 text-left text-[min(max(1.25rem,2.75vw),2.5rem)] font-bold"> + <span className="block sm:inline">키보드 방향키로</span> 더 편리한 조작 + </h2>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (25)
src/assets/landing/bell_setting.pngis excluded by!**/*.pngsrc/assets/landing/bottom_arrow.pngis excluded by!**/*.pngsrc/assets/landing/debate_info_setting.pngis excluded by!**/*.pngsrc/assets/landing/key_info.pngis excluded by!**/*.pngsrc/assets/landing/table_list.pngis excluded by!**/*.pngsrc/assets/landing/timebox_add_button.pngis excluded by!**/*.pngsrc/assets/landing/timebox_step.pngis excluded by!**/*.pngsrc/assets/landing/timebox_step_button.pngis excluded by!**/*.pngsrc/assets/landing/timeout_button.pngis excluded by!**/*.pngsrc/assets/landing/timer.pngis excluded by!**/*.pngsrc/assets/landing/timer_operation_time.pngis excluded by!**/*.pngsrc/assets/landing/timer_timebased.pngis excluded by!**/*.pngsrc/assets/landing/two_timer.pngis excluded by!**/*.pngsrc/assets/template_logo/government.pngis excluded by!**/*.pngsrc/assets/template_logo/han_alm.pngis excluded by!**/*.pngsrc/assets/template_logo/hantomak.pngis excluded by!**/*.pngsrc/assets/template_logo/igam.pngis excluded by!**/*.pngsrc/assets/template_logo/jungseonto.pngis excluded by!**/*.pngsrc/assets/template_logo/kogito.pngis excluded by!**/*.pngsrc/assets/template_logo/kondae_time.pngis excluded by!**/*.pngsrc/assets/template_logo/nogotte.pngis excluded by!**/*.pngsrc/assets/template_logo/osansi.pngis excluded by!**/*.pngsrc/assets/template_logo/seobangjeongto.pngis excluded by!**/*.pngsrc/assets/template_logo/todallae.pngis excluded by!**/*.pngsrc/assets/template_logo/visual.pngis excluded by!**/*.png
📒 Files selected for processing (12)
src/constants/debate_tamplate.ts(1 hunks)src/page/LandingPage/LandingPage.tsx(3 hunks)src/page/LandingPage/components/ReviewSection.tsx(2 hunks)src/page/LandingPage/components/ScrollHint.tsx(1 hunks)src/page/LandingPage/components/TableSection.tsx(2 hunks)src/page/LandingPage/components/TamplateApplicationSection.tsx(1 hunks)src/page/LandingPage/components/TamplateList.tsx(1 hunks)src/page/LandingPage/components/TemplateCard.tsx(1 hunks)src/page/LandingPage/components/TemplateSelection.tsx(1 hunks)src/page/LandingPage/components/TimeTableSection.tsx(1 hunks)src/page/LandingPage/components/TimerSection.tsx(2 hunks)src/type/type.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (6)
src/page/LandingPage/components/TemplateSelection.tsx (3)
src/page/LandingPage/components/TamplateList.tsx (1)
TamplateList(7-21)src/constants/debate_tamplate.ts (1)
DEBATE_TAMPLATE(16-258)src/page/LandingPage/components/TamplateApplicationSection.tsx (1)
TamplateApplicationSection(3-29)
src/page/LandingPage/components/TamplateApplicationSection.tsx (1)
src/constants/urls.ts (1)
LANDING_URLS(1-7)
src/page/LandingPage/LandingPage.tsx (3)
src/page/LandingPage/components/ScrollHint.tsx (1)
ScrollHint(8-75)src/page/LandingPage/components/TemplateSelection.tsx (1)
TemplateSelection(5-21)src/page/LandingPage/components/ReviewSection.tsx (1)
ReviewSection(8-35)
src/page/LandingPage/components/TamplateList.tsx (2)
src/type/type.ts (1)
DebateTemplate(80-86)src/page/LandingPage/components/TemplateCard.tsx (1)
TemplateCard(3-68)
src/page/LandingPage/components/TemplateCard.tsx (1)
src/type/type.ts (1)
DebateTemplate(80-86)
src/constants/debate_tamplate.ts (1)
src/util/arrayEncoding.ts (1)
createTableShareUrl(23-29)
🔇 Additional comments (8)
src/page/LandingPage/components/TamplateList.tsx (1)
16-18: title 대신 고유 식별자를 key로 사용하거나, title의 유니크 보장을 확인하세요.
- 동적 데이터에 동일한 title이 있을 경우 React key 중복으로 UI 재렌더링 오류가 발생할 수 있습니다.
- 데이터 소스에서 title 중복 여부를 검증하거나, 각 항목에
id같은 고유 필드를 추가해 key로 사용하도록 변경하세요.src/page/LandingPage/components/TableSection.tsx (2)
1-2: LGTM!새로운 디자인에 맞춰 이미지 에셋을 적절히 교체했습니다.
24-28: 콘텐츠 일관성 확인제목이 "토론 기본정보 설정"으로, 설명이 "시간표 이름부터 주제까지!"로 변경되었습니다. 이미지와 텍스트 내용이 실제 기능과 일치하는지 확인이 필요합니다.
src/page/LandingPage/LandingPage.tsx (2)
32-35: LGTM!새로운 ScrollHint와 TemplateSelection 컴포넌트가 적절한 위치에 배치되어 있고, 주석도 명확합니다.
50-58: 레이아웃 구조 개선세 개의 별도 wrapper div로 섹션들을 분리한 구조가 잘 구성되어 있습니다. 각각 다른 배경색으로 시각적 구분도 명확합니다.
src/page/LandingPage/components/ScrollHint.tsx (3)
4-6: 타입 정의가 적절합니다
ScrollHintProps타입에서topThreshold에 기본값과 주석이 잘 설정되어 있습니다.
11-21: 스크롤 이벤트 처리 로직 검토useEffect 내의 스크롤 이벤트 처리 로직이 적절하게 구현되어 있습니다. passive 옵션과 cleanup 함수도 올바르게 설정되어 있습니다.
68-72: 이미지 접근성 개선이미지의 alt 텍스트와 스타일링이 적절하게 설정되어 있습니다.
| import government from '../assets/template_logo/government.png'; | ||
| import igam from '../assets/template_logo/igam.png'; | ||
| import kondae_time from '../assets/template_logo/kondae_time.png'; | ||
| import han_alm from '../assets/template_logo/han_alm.png'; | ||
| import todallae from '../assets/template_logo/todallae.png'; | ||
| import jungseonto from '../assets/template_logo/jungseonto.png'; | ||
| import visual from '../assets/template_logo/visual.png'; | ||
| import hantomak from '../assets/template_logo/hantomak.png'; | ||
| import seobangjeongto from '../assets/template_logo/seobangjeongto.png'; | ||
| import osansi from '../assets/template_logo/osansi.png'; | ||
| import nogotte from '../assets/template_logo/nogotte.png'; | ||
| import kogito from '../assets/template_logo/kogito.png'; | ||
| function createTableShareUrl(encodeData: string): string { | ||
| return `${import.meta.env.VITE_SHARE_BASE_URL}/share?data=${encodeData}`; | ||
| } |
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하는 상수명에서 "Template"이 "Tamplate"로 잘못 작성되어 있습니다.
다음과 같이 수정해야 합니다:
- 파일명:
debate_tamplate.ts→debate_template.ts - 상수명:
DEBATE_TAMPLATE→DEBATE_TEMPLATE
-export const DEBATE_TAMPLATE = {
+export const DEBATE_TEMPLATE = {또한 이 변경사항은 이 상수를 사용하는 다른 파일들에도 영향을 미치므로 전체 프로젝트에서 일괄 수정이 필요합니다.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/constants/debate_tamplate.ts (lines 1-15) the filename and exported
constant use the misspelled "tamplate"/"TAMPLATE"; rename the file to
src/constants/debate_template.ts and rename the exported identifier from
DEBATE_TAMPLATE to DEBATE_TEMPLATE, update the internal symbol declarations
accordingly, and then update all import sites across the project to reference
the new filename and constant name; ensure your VCS moves/renames the file (not
a delete+create) to preserve history and run a global search-replace for the old
identifier and path to avoid missing usages.
| function createTableShareUrl(encodeData: string): string { | ||
| return `${import.meta.env.VITE_SHARE_BASE_URL}/share?data=${encodeData}`; | ||
| } |
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.
💡 Verification agent
🧩 Analysis chain
환경 변수 사용 확인
createTableShareUrl 함수에서 import.meta.env.VITE_SHARE_BASE_URL 환경 변수를 사용하고 있습니다. 이 환경 변수가 올바르게 설정되어 있는지 확인이 필요합니다.
다음 스크립트로 환경 변수 설정을 확인해보겠습니다:
🏁 Script executed:
#!/bin/bash
# Description: VITE_SHARE_BASE_URL 환경 변수 사용처 확인
# .env 파일들에서 VITE_SHARE_BASE_URL 변수 확인
echo "=== .env 파일들에서 VITE_SHARE_BASE_URL 확인 ==="
fd "\.env" -t f --exec grep -H "VITE_SHARE_BASE_URL" {} \; 2>/dev/null
echo -e "\n=== 코드에서 VITE_SHARE_BASE_URL 사용처 확인 ==="
rg "VITE_SHARE_BASE_URL" --type ts --type tsx -C 2Length of output: 328
다음 스크립트로 다시 확인해보겠습니다:
🏁 Script executed:
#!/bin/bash
# Description: VITE_SHARE_BASE_URL 환경 변수 설정 및 사용처 재확인
echo "=== .env* 파일들에서 VITE_SHARE_BASE_URL 확인 ==="
grep -R "VITE_SHARE_BASE_URL" .env* 2>/dev/null
echo -e "\n=== 코드에서 VITE_SHARE_BASE_URL 사용처 확인 (.ts, .tsx) ==="
rg -n -C2 VITE_SHARE_BASE_URL --glob "*.ts" --glob "*.tsx" .Length of output: 1533
VITE_SHARE_BASE_URL 환경 변수 정의 누락
import.meta.env.VITE_SHARE_BASE_URL가 src/constants/debate_tamplate.ts, src/hooks/useTableShare.tsx, src/page/LandingPage/hooks/useLandingPageHandlers.ts 등에서 사용 중이나 .env* 파일에서 정의가 확인되지 않습니다. .env.*(예: .env.development, .env.production)에 해당 변수를 추가하거나 배포 환경 변수 설정을 검증해 주세요.
🤖 Prompt for AI Agents
In src/constants/debate_tamplate.ts around lines 13-15, the code reads
import.meta.env.VITE_SHARE_BASE_URL but that env var is not defined in any
.env.* files; add VITE_SHARE_BASE_URL=<your_share_base_url> to your
.env.development, .env.production (and any other env files used), ensure the
variable name keeps the VITE_ prefix so Vite exposes it, commit/update
.env.example or README with the new variable, and verify CI/deployment env
settings include VITE_SHARE_BASE_URL and restart the dev server after changes.
| <img src={timer} alt="section301" className="flex w-1/2" /> | ||
| <div className="flex w-1/2 flex-col items-center gap-4"> |
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.
🛠️ Refactor suggestion
이미지 alt·lazy/async 권장
“section301”은 의미가 없어 접근성에 취약합니다. 지연 로딩으로 성능 개선도 권장합니다.
- <img src={timer} alt="section301" className="flex w-1/2" />
+ <img
+ src={timer}
+ alt="타이머 메인 화면"
+ loading="lazy"
+ decoding="async"
+ className="w-full md:w-1/2"
+ />📝 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.
| <img src={timer} alt="section301" className="flex w-1/2" /> | |
| <div className="flex w-1/2 flex-col items-center gap-4"> | |
| <img | |
| src={timer} | |
| alt="타이머 메인 화면" | |
| loading="lazy" | |
| decoding="async" | |
| className="w-full md:w-1/2" | |
| /> | |
| <div className="flex w-1/2 flex-col items-center gap-4"> |
🤖 Prompt for AI Agents
In src/page/LandingPage/components/TimerSection.tsx around lines 23-24, the img
uses a non-descriptive alt ("section301") and lacks lazy/async loading; replace
the alt with a meaningful, concise description of the image content (e.g.,
"countdown timer showing X" or similar accurate text for screen readers) and
enable deferred loading by adding loading="lazy" and decoding="async" (or switch
to Next/Image with appropriate priority if using Next.js) so the image is
accessible and performance-friendly.
| <img src={timer} alt="section301" className="flex w-1/2" /> | ||
| <div className="flex w-1/2 flex-col items-center gap-4"> | ||
| <h3 className="text-[min(max(1.1rem,1.75vw),1.8rem)] font-semibold"> | ||
| 토론자가 작전시간을 | ||
| <br /> | ||
| 요청하면{' '} | ||
| <img | ||
| src={timeoutButton} | ||
| alt="작전시간 사용" | ||
| className="inline-block h-[1.8rem] align-middle" | ||
| style={{ transform: 'translateY(-0.1em)' }} | ||
| />{' '} | ||
| <br /> | ||
| 버튼을 눌러 시간을 사용해요 | ||
| </h3> | ||
| </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.
🛠️ Refactor suggestion
헤딩(h3) 내부 인라인 이미지 제거/비노출 처리
헤딩 안의 이미지(아이콘)는 스크린리더에 중복 정보를 전달할 수 있습니다. 텍스트만 두거나 이미지를 비노출 처리하세요.
- <h3 className="text-[min(max(1.1rem,1.75vw),1.8rem)] font-semibold">
- 토론자가 작전시간을
- <br />
- 요청하면{' '}
- <img
- src={timeoutButton}
- alt="작전시간 사용"
- className="inline-block h-[1.8rem] align-middle"
- style={{ transform: 'translateY(-0.1em)' }}
- />{' '}
- <br />
- 버튼을 눌러 시간을 사용해요
- </h3>
+ <h3 className="text-[min(max(1.1rem,1.75vw),1.8rem)] font-semibold">
+ 토론자가 작전시간을 요청하면 버튼을 눌러 시간을 사용해요
+ </h3>(아이콘을 유지하려면 본문 단락에 alt="" aria-hidden="true"로 별도 배치 권장)
📝 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.
| <img src={timer} alt="section301" className="flex w-1/2" /> | |
| <div className="flex w-1/2 flex-col items-center gap-4"> | |
| <h3 className="text-[min(max(1.1rem,1.75vw),1.8rem)] font-semibold"> | |
| 토론자가 작전시간을 | |
| <br /> | |
| 요청하면{' '} | |
| <img | |
| src={timeoutButton} | |
| alt="작전시간 사용" | |
| className="inline-block h-[1.8rem] align-middle" | |
| style={{ transform: 'translateY(-0.1em)' }} | |
| />{' '} | |
| <br /> | |
| 버튼을 눌러 시간을 사용해요 | |
| </h3> | |
| </div> | |
| <img src={timer} alt="section301" className="flex w-1/2" /> | |
| <div className="flex w-1/2 flex-col items-center gap-4"> | |
| <h3 className="text-[min(max(1.1rem,1.75vw),1.8rem)] font-semibold"> | |
| 토론자가 작전시간을 요청하면 버튼을 눌러 시간을 사용해요 | |
| </h3> | |
| </div> |
🤖 Prompt for AI Agents
In src/page/LandingPage/components/TimerSection.tsx around lines 23 to 38, the
h3 currently contains an inline <img> which can create redundant information for
screen readers; remove the image from inside the heading and either keep only
the text or move the visual icon out of the h3 into a non-heading inline element
(e.g., a span/div immediately after the h3) and mark the image as decorative by
setting alt="" and aria-hidden="true" so it is ignored by assistive tech.
| <div className="flex flex-row items-center justify-center gap-8 px-4"> | ||
| <div className="flex w-1/2 flex-col items-center gap-4"> | ||
| <h3 className="text-[min(max(1.1rem,1.75vw),1.8rem)] font-semibold"> | ||
| 작전시간이 나타나면 | ||
| <br /> 원하는 시간을 입력하세요! | ||
| </h3> | ||
| </div> | ||
| <img src={timerOperationTime} alt="section302" className="flex w-1/2" /> |
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.
🛠️ Refactor suggestion
반응형 방향 전환 및 alt 보강
모바일에서 2열 강제는 축소를 유발합니다. md 이상에서 가로 배치하고 alt를 구체화하세요.
- <div className="flex flex-row items-center justify-center gap-8 px-4">
- <div className="flex w-1/2 flex-col items-center gap-4">
+ <div className="flex flex-col items-center justify-center gap-8 px-4 md:flex-row">
+ <div className="flex w-full flex-col items-center gap-4 md:w-1/2">
<h3 className="text-[min(max(1.1rem,1.75vw),1.8rem)] font-semibold">
작전시간이 나타나면
<br /> 원하는 시간을 입력하세요!
</h3>
</div>
- <img src={timerOperationTime} alt="section302" className="flex w-1/2" />
+ <img
+ src={timerOperationTime}
+ alt="작전시간 입력 UI"
+ loading="lazy"
+ decoding="async"
+ className="w-full md:w-1/2"
+ />📝 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.
| <div className="flex flex-row items-center justify-center gap-8 px-4"> | |
| <div className="flex w-1/2 flex-col items-center gap-4"> | |
| <h3 className="text-[min(max(1.1rem,1.75vw),1.8rem)] font-semibold"> | |
| 작전시간이 나타나면 | |
| <br /> 원하는 시간을 입력하세요! | |
| </h3> | |
| </div> | |
| <img src={timerOperationTime} alt="section302" className="flex w-1/2" /> | |
| <div className="flex flex-col items-center justify-center gap-8 px-4 md:flex-row"> | |
| <div className="flex w-full flex-col items-center gap-4 md:w-1/2"> | |
| <h3 className="text-[min(max(1.1rem,1.75vw),1.8rem)] font-semibold"> | |
| 작전시간이 나타나면 | |
| <br /> 원하는 시간을 입력하세요! | |
| </h3> | |
| </div> | |
| <img | |
| src={timerOperationTime} | |
| alt="작전시간 입력 UI" | |
| loading="lazy" | |
| decoding="async" | |
| className="w-full md:w-1/2" | |
| /> | |
| </div> |
🤖 Prompt for AI Agents
In src/page/LandingPage/components/TimerSection.tsx around lines 40 to 47, the
current layout forces two columns on all screen sizes and uses a vague img alt;
change the container and children to be column-first and switch to row at md
breakpoint (e.g., container: flex flex-col md:flex-row items-center
justify-center gap-8 px-4), set child widths to full on mobile and half on md
(e.g., w-full md:w-1/2) so it stacks on small screens and becomes two-column at
md+, and replace the img alt with a descriptive string in Korean that explains
the image content (for example describing the timer UI/operation) to improve
accessibility.
| <div> | ||
| <div className="relative inline-block text-[min(max(0.875rem,1.5vw),1.4rem)] font-semibold"> | ||
| <span className="relative z-10">시간표 설정 화면</span> | ||
| <span className="relative z-10">시간표 설정화면</span> |
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.
라벨 표기 어색한 띄어쓰기
“시간표 설정화면” → “시간표 설정 화면”이 자연스럽습니다.
- <span className="relative z-10">시간표 설정화면</span>
+ <span className="relative z-10">시간표 설정 화면</span>📝 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.
| <span className="relative z-10">시간표 설정화면</span> | |
| <span className="relative z-10">시간표 설정 화면</span> |
🤖 Prompt for AI Agents
In src/page/LandingPage/components/TimeTableSection.tsx around line 11, the
label text "시간표 설정화면" has awkward spacing; change it to "시간표 설정 화면" to use
natural Korean spacing. Update the span content to the corrected string and run
a quick UI/text check to ensure line breaks or CSS don't rejoin the words.
| <div className="flex flex-row items-center justify-center gap-8 px-4"> | ||
| <img src={timeboxStep} alt="section301" className="flex w-1/2" /> | ||
| <img src={timeboxButtons} alt="section301" className="flex w-1/3" /> | ||
| </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.
🛠️ Refactor suggestion
모바일 가독성·접근성 개선(반응형 방향/alt/지연로딩)
- 모바일에서 2열 강제는 과도한 축소를 유발합니다. md 이상에서만 가로 배치하세요.
- alt="section301"은 의미가 없습니다. 묘사형 alt 또는 장식이면 alt="".
- 이미지 lazy/async로 LCP 이외 지연 로딩.
- <div className="flex flex-row items-center justify-center gap-8 px-4">
- <img src={timeboxStep} alt="section301" className="flex w-1/2" />
- <img src={timeboxButtons} alt="section301" className="flex w-1/3" />
+ <div className="flex flex-col items-center justify-center gap-8 px-4 md:flex-row">
+ <img
+ src={timeboxStep}
+ alt="시간표 단계 안내 화면"
+ loading="lazy"
+ decoding="async"
+ className="w-full md:w-1/2"
+ />
+ <img
+ src={timeboxButtons}
+ alt="시간표 단계별 버튼 모음"
+ loading="lazy"
+ decoding="async"
+ className="w-full md:w-1/3"
+ />📝 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.
| <div className="flex flex-row items-center justify-center gap-8 px-4"> | |
| <img src={timeboxStep} alt="section301" className="flex w-1/2" /> | |
| <img src={timeboxButtons} alt="section301" className="flex w-1/3" /> | |
| </div> | |
| <div className="flex flex-col items-center justify-center gap-8 px-4 md:flex-row"> | |
| <img | |
| src={timeboxStep} | |
| alt="시간표 단계 안내 화면" | |
| loading="lazy" | |
| decoding="async" | |
| className="w-full md:w-1/2" | |
| /> | |
| <img | |
| src={timeboxButtons} | |
| alt="시간표 단계별 버튼 모음" | |
| loading="lazy" | |
| decoding="async" | |
| className="w-full md:w-1/3" | |
| /> | |
| </div> |
🤖 Prompt for AI Agents
In src/page/LandingPage/components/TimeTableSection.tsx around lines 18-21, the
current two-column layout forces excessive shrink on mobile and both img tags
use a non-descriptive alt and no lazy loading; update the container classes so
the images stack vertically on small screens and switch to horizontal only at md
(e.g., flex-col on small, md:flex-row), replace alt="section301" with meaningful
descriptive alt text for the primary informative image (or alt="" if purely
decorative) and provide an appropriate alt for the other image, and add
loading="lazy" and decoding="async" to images that are not critical LCP (keep
the LCP image eager or add fetchPriority="high") so non-LCP assets load
deferred.
| <h2 className="text-left text-[min(max(1.25rem,2.75vw),2.5rem)] font-bold"> | ||
| 시간표 추가 | ||
| </h2> | ||
| <img | ||
| src={timeboxAddButton} | ||
| alt="시간표 추가 버튼" | ||
| className="h-[min(max(1.7rem,3vw),2.7rem)] w-auto" | ||
| /> |
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.
🛠️ Refactor suggestion
헤딩 계층(A11y) 및 아이콘 대체텍스트
- 섹션 내 보조 타이틀은 h3가 적절합니다.
- 옆의 버튼 이미지는 장식에 가깝다면 스크린리더 제외 처리.
- <h2 className="text-left text-[min(max(1.25rem,2.75vw),2.5rem)] font-bold">
+ <h3 className="text-left text-[min(max(1.25rem,2.75vw),2.5rem)] font-bold">
시간표 추가
- </h2>
+ </h3>
<img
src={timeboxAddButton}
- alt="시간표 추가 버튼"
+ alt=""
+ aria-hidden="true"
className="h-[min(max(1.7rem,3vw),2.7rem)] w-auto"
/>📝 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.
| <h2 className="text-left text-[min(max(1.25rem,2.75vw),2.5rem)] font-bold"> | |
| 시간표 추가 | |
| </h2> | |
| <img | |
| src={timeboxAddButton} | |
| alt="시간표 추가 버튼" | |
| className="h-[min(max(1.7rem,3vw),2.7rem)] w-auto" | |
| /> | |
| <h3 className="text-left text-[min(max(1.25rem,2.75vw),2.5rem)] font-bold"> | |
| 시간표 추가 | |
| </h3> | |
| <img | |
| src={timeboxAddButton} | |
| alt="" | |
| aria-hidden="true" | |
| className="h-[min(max(1.7rem,3vw),2.7rem)] w-auto" | |
| /> |
🤖 Prompt for AI Agents
In src/page/LandingPage/components/TimeTableSection.tsx around lines 23 to 30,
change the section heading from an h2 to an h3 to preserve correct heading
hierarchy for the section, and treat the adjacent button image as decorative by
removing non-empty alt text and marking it hidden from assistive technology
(e.g., set alt="" and add aria-hidden="true" or role="presentation"); if the
image is inside an interactive element ensure the interactive element has
accessible label text (aria-label or visually-hidden text) instead of relying on
the image alt.
| <div className="flex flex-row items-center justify-center gap-8 px-4"> | ||
| <img src={twoTimer} alt="section302" className="flex w-1/2" /> | ||
| <div className="flex w-1/2 flex-col items-center gap-4"> | ||
| <h3 className="text-[min(max(1.1rem,1.75vw),1.8rem)] font-semibold"> | ||
| 두가지 타이머 | ||
| </h3> | ||
| <p className="text-[min(max(0.875rem,1.5vw),1.4rem)] font-medium text-neutral-600"> | ||
| 일반형과 자유토론형 타이머로, | ||
| <br /> | ||
| 다양한 토론 방식을 지원해요. | ||
| </p> | ||
| </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.
🛠️ Refactor suggestion
반응형 방향 전환 및 카피 띄어쓰기
- 모바일 세로, md 이상 가로 배치 권장.
- “두가지” → “두 가지”.
- <div className="flex flex-row items-center justify-center gap-8 px-4">
- <img src={twoTimer} alt="section302" className="flex w-1/2" />
- <div className="flex w-1/2 flex-col items-center gap-4">
+ <div className="flex flex-col items-center justify-center gap-8 px-4 md:flex-row">
+ <img
+ src={twoTimer}
+ alt="두 가지 타이머 화면"
+ loading="lazy"
+ decoding="async"
+ className="w-full md:w-1/2"
+ />
+ <div className="flex w-full flex-col items-center gap-4 md:w-1/2">
<h3 className="text-[min(max(1.1rem,1.75vw),1.8rem)] font-semibold">
- 두가지 타이머
+ 두 가지 타이머
</h3>📝 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.
| <div className="flex flex-row items-center justify-center gap-8 px-4"> | |
| <img src={twoTimer} alt="section302" className="flex w-1/2" /> | |
| <div className="flex w-1/2 flex-col items-center gap-4"> | |
| <h3 className="text-[min(max(1.1rem,1.75vw),1.8rem)] font-semibold"> | |
| 두가지 타이머 | |
| </h3> | |
| <p className="text-[min(max(0.875rem,1.5vw),1.4rem)] font-medium text-neutral-600"> | |
| 일반형과 자유토론형 타이머로, | |
| <br /> | |
| 다양한 토론 방식을 지원해요. | |
| </p> | |
| </div> | |
| <div className="flex flex-col items-center justify-center gap-8 px-4 md:flex-row"> | |
| <img | |
| src={twoTimer} | |
| alt="두 가지 타이머 화면" | |
| loading="lazy" | |
| decoding="async" | |
| className="w-full md:w-1/2" | |
| /> | |
| <div className="flex w-full flex-col items-center gap-4 md:w-1/2"> | |
| <h3 className="text-[min(max(1.1rem,1.75vw),1.8rem)] font-semibold"> | |
| 두 가지 타이머 | |
| </h3> | |
| <p className="text-[min(max(0.875rem,1.5vw),1.4rem)] font-medium text-neutral-600"> | |
| 일반형과 자유토론형 타이머로, | |
| <br /> | |
| 다양한 토론 방식을 지원해요. | |
| </p> | |
| </div> |
🤖 Prompt for AI Agents
In src/page/LandingPage/components/TimeTableSection.tsx around lines 32 to 43,
the layout should be vertical on mobile and horizontal from md up and the copy
needs spacing: change the container classes from "flex flex-row items-center
justify-center gap-8 px-4" to "flex flex-col md:flex-row items-center
justify-center gap-8 px-4" and update child sizing from fixed halves to
responsive widths (e.g., img class to "w-full md:w-1/2" and the text wrapper to
"w-full md:w-1/2") so they stack on small screens and sit side-by-side on md+,
and change the heading text "두가지 타이머" to "두 가지 타이머" (add the space). Ensure any
line-breaks or spacing in the paragraph still render correctly with the
responsive layout.
| <div className="flex flex-row items-center justify-center gap-8 px-4"> | ||
| <div className="flex w-1/2 flex-col items-center gap-4"> | ||
| <h3 className="text-[min(max(1.1rem,1.75vw),1.8rem)] font-semibold"> | ||
| 종소리 설정 | ||
| </h3> | ||
| <p className="text-[min(max(0.875rem,1.5vw),1.4rem)] font-medium text-neutral-600"> | ||
| 시간에 따른 종소리를 내마음대로 | ||
| <br /> | ||
| 커스터마이징 할 수 있어요. | ||
| </p> | ||
| </div> | ||
| <img src={bellSetting} alt="section302" className="flex w-1/2" /> | ||
| </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.
🛠️ Refactor suggestion
텍스트 품질·접근성(띄어쓰기/외래어·alt/lazy)
- “내마음대로” → “내 마음대로”.
- “커스터마이징 할 수 있어요.” → “커스터마이징할 수 있어요.” 또는 “사용자 지정할 수 있어요.”(권장).
- alt 구체화 및 lazy/async.
- <div className="flex flex-row items-center justify-center gap-8 px-4">
- <div className="flex w-1/2 flex-col items-center gap-4">
+ <div className="flex flex-col items-center justify-center gap-8 px-4 md:flex-row">
+ <div className="flex w-full flex-col items-center gap-4 md:w-1/2">
<h3 className="text-[min(max(1.1rem,1.75vw),1.8rem)] font-semibold">
종소리 설정
</h3>
<p className="text-[min(max(0.875rem,1.5vw),1.4rem)] font-medium text-neutral-600">
- 시간에 따른 종소리를 내마음대로
+ 시간에 따른 종소리를 내 마음대로
<br />
- 커스터마이징 할 수 있어요.
+ 사용자 지정할 수 있어요.
</p>
</div>
- <img src={bellSetting} alt="section302" className="flex w-1/2" />
+ <img
+ src={bellSetting}
+ alt="종소리 설정 화면"
+ loading="lazy"
+ decoding="async"
+ className="w-full md:w-1/2"
+ />📝 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.
| <div className="flex flex-row items-center justify-center gap-8 px-4"> | |
| <div className="flex w-1/2 flex-col items-center gap-4"> | |
| <h3 className="text-[min(max(1.1rem,1.75vw),1.8rem)] font-semibold"> | |
| 종소리 설정 | |
| </h3> | |
| <p className="text-[min(max(0.875rem,1.5vw),1.4rem)] font-medium text-neutral-600"> | |
| 시간에 따른 종소리를 내마음대로 | |
| <br /> | |
| 커스터마이징 할 수 있어요. | |
| </p> | |
| </div> | |
| <img src={bellSetting} alt="section302" className="flex w-1/2" /> | |
| </div> | |
| <div className="flex flex-col items-center justify-center gap-8 px-4 md:flex-row"> | |
| <div className="flex w-full flex-col items-center gap-4 md:w-1/2"> | |
| <h3 className="text-[min(max(1.1rem,1.75vw),1.8rem)] font-semibold"> | |
| 종소리 설정 | |
| </h3> | |
| <p className="text-[min(max(0.875rem,1.5vw),1.4rem)] font-medium text-neutral-600"> | |
| 시간에 따른 종소리를 내 마음대로 | |
| <br /> | |
| 사용자 지정할 수 있어요. | |
| </p> | |
| </div> | |
| <img | |
| src={bellSetting} | |
| alt="종소리 설정 화면" | |
| loading="lazy" | |
| decoding="async" | |
| className="w-full md:w-1/2" | |
| /> | |
| </div> |
🤖 Prompt for AI Agents
In src/page/LandingPage/components/TimeTableSection.tsx around lines 45 to 57,
fix Korean spacing and accessibility: change “내마음대로” to “내 마음대로” and replace
“커스터마이징 할 수 있어요.” with either “커스터마이징할 수 있어요.” or preferably “사용자 지정할 수 있어요.”,
and improve the img element by providing a more descriptive alt (e.g., “시간별 종소리
설정 일러스트” or similar) and enable lazy loading (add loading="lazy" or switch to an
image component that supports async/lazy loading).
i-meant-to-be
left a comment
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.
빠른 구현 고생하셨습니다! 리뷰 몇 가지 있어 확인해주시면 감사하겠습니당
| </h1> | ||
| <h2 className="mt-4 text-left text-[min(max(1.25rem,2.75vw),2.5rem)] font-bold"> | ||
| 원하는 때에 <br /> | ||
| 작전시간 사용하기 |
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.
대안: 띄어쓰기 추가
'작전 시간'으로 작성하면 더 깔끔해 보일 듯합니다.
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.
Actionable comments posted: 0
🧹 Nitpick comments (5)
src/page/LandingPage/components/TemplateSelection.tsx (5)
5-5: 컴포넌트 반환 타입 명시로 타입 안정성 강화반환 타입을 명시해 TS 추론 흔들림을 방지하세요.
-export default function TemplateSelection() { +export default function TemplateSelection(): JSX.Element {
14-16: 구분선 div → hr로 시맨틱/접근성 개선시맨틱 태그(hr) 사용 및 aria-hidden 처리로 스크린리더 노이즈를 줄이는 것이 좋습니다.
- <div className="mx-auto h-px w-11/12 bg-neutral-200" /> {/* 구분선 */} + <hr className="mx-auto w-11/12 border-0 border-t border-neutral-200" aria-hidden="true" /> - <div className="mx-auto h-px w-11/12 bg-neutral-200" /> + <hr className="mx-auto w-11/12 border-0 border-t border-neutral-200" aria-hidden="true" />
13-17: 반복 렌더링 DRY: 배열 map으로 단순화중복 코드를 제거하면 유지보수가 쉬워집니다. Fragment key를 위해 react에서 Fragment import가 필요합니다.
- <TamplateList data={DEBATE_TEMPLATE.ONE} /> - <hr className="mx-auto w-11/12 border-0 border-t border-neutral-200" aria-hidden="true" /> - <TamplateList data={DEBATE_TEMPLATE.TWO} /> - <hr className="mx-auto w-11/12 border-0 border-t border-neutral-200" aria-hidden="true" /> - <TamplateList data={DEBATE_TEMPLATE.THREE} /> + {[ + DEBATE_TEMPLATE.ONE, + DEBATE_TEMPLATE.TWO, + DEBATE_TEMPLATE.THREE, + ].map((group, idx, arr) => ( + <Fragment key={idx}> + <TamplateList data={group} /> + {idx < arr.length - 1 && ( + <hr + className="mx-auto w-11/12 border-0 border-t border-neutral-200" + aria-hidden="true" + /> + )} + </Fragment> + ))}추가: 파일 상단에 아래 import가 필요합니다.
import { Fragment } from 'react';
7-12: 섹션-헤딩 연계로 접근성 향상(aria-labelledby 연결)섹션이 어떤 헤딩에 의해 라벨링되는지 명시하면 내비게이션 보조기기에 유리합니다.
- <section id="template-selection" className="flex flex-col gap-12"> + <section id="template-selection" aria-labelledby="template-selection-heading" className="flex flex-col gap-12"> <div> - <h2 className="mt-4 text-left text-[min(max(1.25rem,2.75vw),2.5rem)] font-bold"> + <h2 id="template-selection-heading" className="mt-4 text-left text-[min(max(1.25rem,2.75vw),2.5rem)] font-bold"> 다양한 토론 템플릿을 원클릭으로 만나보세요! </h2> </div>
1-3: Tamplate → Template 네이밍 통일 권장
파일 전반에 걸쳐 Tamplate(오탈자) 표기가 발견됩니다. 기능 안정성 유지를 위해 이번 PR에는 그대로 두고, 다음 PR에서 일괄 리네이밍을 진행해주세요.# Tamplate 및 debate_tamplate 사용 위치 확인 rg -nP '\b(?:Tamplate|debate_tamplate)\b' -C1 --glob '*.{ts,tsx}'
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
src/constants/debate_tamplate.ts(1 hunks)src/page/LandingPage/components/TemplateSelection.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/constants/debate_tamplate.ts
🧰 Additional context used
🧬 Code graph analysis (1)
src/page/LandingPage/components/TemplateSelection.tsx (3)
src/page/LandingPage/components/TamplateList.tsx (1)
TamplateList(7-21)src/constants/debate_tamplate.ts (1)
DEBATE_TEMPLATE(22-264)src/page/LandingPage/components/TamplateApplicationSection.tsx (1)
TamplateApplicationSection(3-29)
🔇 Additional comments (1)
src/page/LandingPage/components/TemplateSelection.tsx (1)
7-7: id 중복 없음 확인됨전체 .tsx 파일에서
id="template-selection"가 한 번만 사용됨을 확인했습니다.
i-meant-to-be
left a comment
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.
확인했습니다. 빠른 반영 감사합니다, 치코!
작성한 리뷰 2건은 기술적인 내용은 아니라 승인 남겨요. 바쁘셨을 것 같은데 짬 내서 작업 쳐내주시느라 고생하셨습니다 😭
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.
권장: 스펠링 수정
아래처럼 스펠링을 수정하는 게 좋아 보여요:
- 파일 이름 TamplateApplicationSection.tsx > TemplateApplicationSection.tsx
- 함수 이름 TamplateApplicationSection > TemplateApplicationSection
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.
수정했어요. 감사합니다.
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.
권장: 스펠링 수정
아래처럼 스펠링을 수정하는 게 좋아 보여요:
- 파일 이름 TamplateList.tsx > TemplateList.tsx
- 함수 이름 TamplateList> TemplateList
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.
수정했습니다
useon
left a comment
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.
치코 ! 바쁘신데 빠르게 구현해 주셔서 감사합니다 !! 몇 가지 리뷰를 남겼어요 ~!!! PR에 잘 설명해 주셔서 이해하기 더 쉬웠어요 !!!!! 반응형으로 3개에서 2개 되는 것도 너무 좋네요 짱짱 ~!!!! 👍
| {/* 홈 설정 */} | ||
| <TableSection onLogin={handleTableSectionLoginButtonClick} /> | ||
| </div> | ||
| <div className="flex w-full flex-col items-center bg-black py-48"> |
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.
아하 홈설정에 리뷰가 원래 함께 들어가 있었는데 이번에 바뀌면서 분리를 한 것이군요?
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,75 @@ | |||
| // src/page/LandingPage/components/ScrollHint.tsx | |||
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.
해당 경로 주석을 달아놓은 이유가 궁금해요!
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.
gpt의 잔재... 아마 아이콘 변경해달라고 하면서 추가했나봅니다. 삭제하겠습니다.
| // </svg> | ||
| // 아래로 스크롤 | ||
| // </div> | ||
| // </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.
해당 주석은 왜 남겨놓으셨나용?
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.
아직 스크롤 디자인 확정나지 않아서 일단 주석처리했습니다. 회의를 통해 확정이 나왔으니 지우도록 하겠습니다.
| <img src={section302} alt="section302" className="flex w-1/2" /> | ||
| </div> | ||
|
|
||
| <div className="flex flex-col items-center justify-center gap-1 text-[min(max(1.25rem,2.75vw),2.5rem)] font-bold"> |
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.
바꾸는 김에 로그인해 주세요.로 띄어쓰기 해주면 좋을 것 같아요!
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,29 @@ | |||
| import section501 from '../../../assets/landing/section5-1.png'; | |||
| import { LANDING_URLS } from '../../../constants/urls'; | |||
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.
오 사이에 엔터 하나만 있으면 좋을 것 같아요!
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문과 컴포넌트 선언문 사이에 엔터를 추가하긴 했습니다.
| 템플릿 신청하기 | ||
| </p> | ||
| <p className="text-[min(max(0.875rem,1.25vw),1.2rem)] text-neutral-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.
이것도 신청해 볼까요?로 띄어쓰기 살짝만 수정해 주세오!!!!!
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.
넵
| topThreshold?: number; //최상단 판정 임계값 (px) | ||
| }; | ||
|
|
||
| export default function ScrollHint({ topThreshold = 10 }: ScrollHintProps) { |
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.
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.
|
|
||
| {/* 액션 리스트 */} | ||
| <ul className="mt-5 flex flex-col gap-1"> | ||
| {actions.map((a, i) => ( |
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.
a나 i 보다는 action, index 이렇게 구체적으로 명시하는 것은 어떨까요 ?!
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.
확인했습니다.
| ].join(' ')} | ||
| > | ||
| {data.map((t) => ( | ||
| <TemplateCard key={t.title} {...t} /> |
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.
템플릿을 간단하게 t라고 적은 것 같은데 ...t 이렇게 적는 것보다는 그냥 template를 명시하는 것이 더 명확하게 읽힐 것 같아요!
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.
넵 수정했습니다
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.
Actionable comments posted: 1
🧹 Nitpick comments (5)
src/constants/debate_template.ts (5)
14-16: 동일 명칭 함수로 인한 혼동 가능성 — 목적을 명확히 주석으로 구분하세요.util/arrayEncoding.ts의 createTableShareUrl(원본 객체를 받아 인코딩 수행)과 이름이 같아 오토임포트/코드 탐색 시 혼동 여지가 큽니다. 최소한 주석으로 “이미 인코딩된 문자열을 받는다”는 점을 명시하세요. (함수명 변경은 선택)
주석 예시:
+/** + * 이미 URL-safe 하게 인코딩된 문자열(encodedData)을 받아 공유 링크를 생성합니다. + * raw 데이터를 인코딩하는 util/arrayEncoding.ts의 동명 함수와 목적이 다릅니다. + */
23-89: 빈 문자열 subtitle은 생략 권장.subtitle이 선택 필드이므로 '' 대신 필드 자체를 생략하면 렌더링 분기와 타입 의미가 더 명확합니다. (아래는 대표 1건 예시)
{ title: '산업통상자원부', - subtitle: '', logoSrc: government,
1-13: 자산 변수 네이밍 통일(사소한 니트픽).snake_case 변수(kondae_time, han_alm 등)는 camelCase(kondaeTime, hanAlm)로 통일하면 코드 일관성이 좋아집니다. 현재 파일 내 참조가 많으므로 우선순위 낮게 점진 적용을 권장합니다.
22-264: 불변 상수 및 타입 정확성 강화 (as const + satisfies)
const assertion과 satisfies를 활용해 오탈자나 프로퍼티 누락 시 즉시 오류를 검출할 수 있습니다. TS 4.9 이상(현재 5.7.2) 지원됩니다.src/constants/debate_template.ts 수정:
-export const DEBATE_TEMPLATE: DebateTemplateList = { +export const DEBATE_TEMPLATE = { /* 내용 동일 */ -}; +} as const satisfies DebateTemplateList;
17-21: 의미 있는 카테고리 키 리팩터링 제안
DEBATE_TEMPLATE인터페이스의ONE/TWO/THREE대신 소비 코드에서 직관적인 키(예:governmentAndOrgs,universityClubs,localGovAndAlliances등)를 사용하세요. 변경 시 아래 소비처도 함께 업데이트가 필요합니다:
- src/page/LandingPage/components/TemplateSelection.tsx:13 (
DEBATE_TEMPLATE.ONE)- src/page/LandingPage/components/TemplateSelection.tsx:15 (
DEBATE_TEMPLATE.TWO)- src/page/LandingPage/components/TemplateSelection.tsx:17 (
DEBATE_TEMPLATE.THREE)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
src/constants/debate_template.ts(1 hunks)src/page/LandingPage/components/TableSection.tsx(2 hunks)src/page/LandingPage/components/TemplateSelection.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/page/LandingPage/components/TemplateSelection.tsx
- src/page/LandingPage/components/TableSection.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
src/constants/debate_template.ts (2)
src/util/arrayEncoding.ts (1)
createTableShareUrl(23-29)src/type/type.ts (1)
DebateTemplate(80-86)
🔇 Additional comments (1)
src/constants/debate_template.ts (1)
22-264: 액션 링크: target/rel 속성 확인
Action 타입에 target/rel 필드가 정의되어 있지 않습니다. 렌더러에서 공유 링크에 대해 기본적으로 target="_blank" 및 rel="noopener" (또는 rel="noopener noreferrer")가 적용되는지 직접 확인하세요.
| function createTableShareUrl(encodeData: string): string { | ||
| return `${import.meta.env.VITE_SHARE_BASE_URL}/share?data=${encodeData}`; | ||
| } |
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.
💡 Verification agent
🧩 Analysis chain
[중요] 환경변수 미설정 시 잘못된 링크 생성 가능 — 가드 추가 및 URL API로 안전하게 조립하세요.
VITE_SHARE_BASE_URL가 비어 있으면 href가 "undefined/share?data=…"로 생성됩니다. URL API를 사용해 베이스/슬래시 처리도 안전하게 해주세요.
적용 예시:
-function createTableShareUrl(encodeData: string): string {
- return `${import.meta.env.VITE_SHARE_BASE_URL}/share?data=${encodeData}`;
-}
+const SHARE_BASE_URL = import.meta.env.VITE_SHARE_BASE_URL as string | undefined;
+
+function createTableShareUrl(encodedData: string): string {
+ // dev/test 안전 가드: 베이스가 없으면 상대경로로 폴백
+ if (!SHARE_BASE_URL) {
+ return `/share?data=${encodedData}`;
+ }
+ const url = new URL('/share', SHARE_BASE_URL);
+ url.searchParams.set('data', encodedData);
+ return url.toString();
+}다음 스크립트로 .env* 파일에 VITE_SHARE_BASE_URL이 정의되어 있는지 확인해 주세요.
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "[.env*에서 VITE_SHARE_BASE_URL 검색]"
rg -n --glob ".env*" --hidden --no-ignore "VITE_SHARE_BASE_URL" || echo "없음"Length of output: 345
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "[.env* 파일 찾기]"
find . -maxdepth 2 -type f -name ".env*" || echo "env 파일이 없습니다"
echo "[.env* 파일에서 VITE_SHARE_BASE_URL 검색]"
find . -maxdepth 2 -type f -name ".env*" -print0 | xargs -0 rg -n "VITE_SHARE_BASE_URL" || echo "없음"Length of output: 555
VITE_SHARE_BASE_URL 가드 추가 및 URL API 활용
import.meta.env.VITE_SHARE_BASE_URL가 비어 있으면 “undefined/share?…” 형태의 잘못된 링크가 생성됩니다. URL API로 베이스/슬래시 처리를 안전하게 수행하고, 환경변수가 없을 땐 /share?data=…로 폴백하세요.
- function createTableShareUrl(encodeData: string): string {
- return `${import.meta.env.VITE_SHARE_BASE_URL}/share?data=${encodeData}`;
- }
+ const SHARE_BASE_URL = import.meta.env.VITE_SHARE_BASE_URL;
+
+ function createTableShareUrl(encodedData: string): string {
+ if (!SHARE_BASE_URL) {
+ return `/share?data=${encodedData}`;
+ }
+ const url = new URL('/share', SHARE_BASE_URL);
+ url.searchParams.set('data', encodedData);
+ return url.toString();
+ }적용 필요 위치:
- src/constants/debate_template.ts:14-16
- src/hooks/useTableShare.tsx:14
- src/page/LandingPage/hooks/useLandingPageHandlers.ts:18
📝 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.
| function createTableShareUrl(encodeData: string): string { | |
| return `${import.meta.env.VITE_SHARE_BASE_URL}/share?data=${encodeData}`; | |
| } | |
| // src/constants/debate_template.ts | |
| const SHARE_BASE_URL = import.meta.env.VITE_SHARE_BASE_URL; | |
| function createTableShareUrl(encodedData: string): string { | |
| if (!SHARE_BASE_URL) { | |
| return `/share?data=${encodedData}`; | |
| } | |
| const url = new URL('/share', SHARE_BASE_URL); | |
| url.searchParams.set('data', encodedData); | |
| return url.toString(); | |
| } |
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.
Actionable comments posted: 0
🧹 Nitpick comments (7)
src/page/LandingPage/components/TemplateApplicationSection.tsx (3)
6-6: 모바일 반응형·접근성(시맨틱)·외부링크(보안)·이미지 성능 소폭 개선 제안한 번에 정리된 제안입니다: 섹션에 heading 연계, 모바일 스택 정렬, 로 외부 링크 열기, 이미지 lazy 로딩/대체텍스트 정리.
- <section className="flex flex-row justify-between gap-1"> + <section + aria-labelledby="template-apply-heading" + className="flex flex-col items-center justify-between gap-6 md:flex-row" + > - <p className="text-[min(max(1.2rem,2vw),2.3rem)] font-semibold"> - 템플릿 신청하기 - </p> + <h2 + id="template-apply-heading" + className="text-[min(max(1.2rem,2vw),2.3rem)] font-semibold" + > + 템플릿 신청하기 + </h2> - <button - onClick={() => - window.open( - LANDING_URLS.REPORT_FORM_URL, - '_blank', - 'noopener,noreferrer', - ) - } - className="rounded-full border border-neutral-300 bg-neutral-200 px-9 py-2 text-[min(max(0.875rem,1.25vw),1.2rem)] font-medium text-default-black transition-all duration-100 hover:bg-brand" - > - 신청하기 - </button> + <a + href={LANDING_URLS.REPORT_FORM_URL} + target="_blank" + rel="noopener noreferrer" + className="rounded-full border border-neutral-300 bg-neutral-200 px-9 py-2 text-[min(max(0.875rem,1.25vw),1.2rem)] font-medium text-default-black transition-all duration-100 hover:bg-brand" + > + 신청하기 + </a> - <img src={section501} alt="section501" className="w-[30%]" /> + <img + src={section501} + alt="" + className="w-full max-w-[420px] md:w-[30%] h-auto" + loading="lazy" + decoding="async" + aria-hidden="true" + />메모:
- 외부 링크는 a + target/_blank + rel 조합이 기본기라 유지보수/보안/접근성 모두에 유리합니다.
- alt가 장식 이미지라면 빈 문자열이 적절합니다(스크린리더 무시). 의미가 있다면 구체적인 대체텍스트로 바꿔주세요.
Also applies to: 8-13, 14-25, 27-27
8-13: 카피 국제화(i18n) 대응 여지고정 한글 문자열은 국제화 리소스로 분리해두면 향후 다국어 확장 시 변경 범위가 줄어듭니다.
Also applies to: 24-24
1-1: 이미지 포맷 최적화 검토가능하면 PNG 대신 WebP/AVIF 소스도 제공(
혹은 빌드타임 변환)해 LCP/전송량을 낮추는 것을 권장합니다. src/page/LandingPage/components/TemplateList.tsx (4)
1-1: 타입 전용 import, 불변 Props, prop 명 명확화 제안
- 타입만 가져오는 경우
import type로 전환해 트리셰이킹/빌드 최적화.- 외부에서 전달되는 배열은 수정 불가하도록
ReadonlyArray로 선언.data대신 도메인 의미가 드러나는templates로 명명.-import { DebateTemplate } from '../../../type/type'; +import type { DebateTemplate } from '../../../type/type'; -interface TemplateListProps { - data: DebateTemplate[]; -} +interface TemplateListProps { + templates: ReadonlyArray<DebateTemplate>; +} -export default function TemplateList({ data }: TemplateListProps) { +export default function TemplateList({ templates }: TemplateListProps) { - {data.map((template) => ( + {templates.map((template) => (Also applies to: 4-6, 7-7, 12-12
10-10: 불필요한 JSX 중괄호 제거리터럴 문자열엔 중괄호 불필요합니다.
- className={'grid grid-cols-2 gap-5 lg:grid-cols-3'} // 2열, lg에서 3열 + className="grid grid-cols-2 gap-5 lg:grid-cols-3" // 2열, lg에서 3열
12-15: 빈 목록(0개) 렌더링 처리템플릿이 비어 있을 때의 사용자 피드백(문구/스켈레톤)을 추가하면 UX가 좋아집니다. 현재 코드 기준으로 바로 적용 가능한 예시는 아래와 같습니다.
- {data.map((template) => ( - <TemplateCard key={template.title} {...template} /> - ))} + {data.length === 0 ? ( + <p className="col-span-full text-center text-neutral-500"> + 템플릿이 없습니다. + </p> + ) : ( + data.map((template) => ( + <TemplateCard key={template.title} {...template} /> + )) + )}
12-14: 고유 id 도입 권장 (옵션)현재 모든
template.title값이 유니크하여 key 충돌 우려는 없으나, 향후 데이터 변경 및 재정렬 시 안정적인 렌더링을 위해id필드를 도입하고 key로 사용하는 것을 권장합니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (6)
src/page/LandingPage/components/ScrollHint.tsx(1 hunks)src/page/LandingPage/components/TableSection.tsx(3 hunks)src/page/LandingPage/components/TemplateApplicationSection.tsx(1 hunks)src/page/LandingPage/components/TemplateCard.tsx(1 hunks)src/page/LandingPage/components/TemplateList.tsx(1 hunks)src/page/LandingPage/components/TemplateSelection.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- src/page/LandingPage/components/TemplateCard.tsx
- src/page/LandingPage/components/ScrollHint.tsx
- src/page/LandingPage/components/TemplateSelection.tsx
- src/page/LandingPage/components/TableSection.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
src/page/LandingPage/components/TemplateApplicationSection.tsx (1)
src/constants/urls.ts (1)
LANDING_URLS(1-7)
src/page/LandingPage/components/TemplateList.tsx (2)
src/type/type.ts (1)
DebateTemplate(80-86)src/page/LandingPage/components/TemplateCard.tsx (1)
TemplateCard(3-68)
🔇 Additional comments (1)
src/page/LandingPage/components/TemplateApplicationSection.tsx (1)
4-30: 초기 구현 전반 LGTM기본 레이아웃/카피/링크 연동 모두 무난합니다. 아래는 접근성/반응형/미세 성능 개선 위주의 제안입니다.
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.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/constants/urls.ts (1)
7-7: 용어 정합성(REGISTER vs SUBMIT) 팀 가이드와 일치하는지 재확인 권장PR 설명에서 “템플릿 제출 링크”라고 표기되어 있어, 키를
TEMPLATE_SUBMISSION_URL(또는TEMPLATE_SUBMIT_URL)처럼 명사형/일관 용어로 맞추는 방안도 고려해볼 수 있습니다. 지금 그대로도 문제는 없으므로 선택 사항입니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/constants/debate_template.ts(1 hunks)src/constants/urls.ts(1 hunks)src/page/LandingPage/components/TemplateApplicationSection.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/page/LandingPage/components/TemplateApplicationSection.tsx
- src/constants/debate_template.ts
🔇 Additional comments (2)
src/constants/urls.ts (2)
7-7: LGTM — 새 템플릿 제출 URL 상수 추가가 일관적입니다.키 네이밍과
_URL접미사,as const사용까지 기존 패턴과 잘 맞습니다.
7-7: 검증 완료: 외부 링크 안전 조치 적용됨
TemplateApplicationSection의window.open호출에 이미'noopener,noreferrer'가 포함되어 있고, 템플릿 제출용<a>태그 사용처도 없습니다.
useon
left a comment
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.
제가 요청한 부분 반영 확인했습니다 꼼꼼하게 반영해 주셔서 감사해요오 ~ !!!! 바로 어프루브 ,,ㅎㅎ


🚩 연관 이슈
closed #355
📝 작업 내용
주의
일단 1차적으로 UI 구현이나 구현에 미흡한점이 있는지 평가해주시면 감사하겠습니다.
수정 파일
메인 페이지를 써니의 디자인 시안에 맞게 변경
2025-08-31.8.18.55.mov
토론 템플릿 섹션 추가
브라우저 너비에 따라 3열과 2로 변경됩니다.
3열 표시
2열 표시
🏞️ 스크린샷 (선택)
전체 이미지
🗣️ 리뷰 요구사항 (선택)
제 환경에서는 문제 없이 동작하는 것 처럼 보입니다. 한번씩 본인들 환경에서 확인해주세요
Summary by CodeRabbit
New Features
Style
Chores