Skip to content

Conversation

@Chasyuss
Copy link
Member

@Chasyuss Chasyuss commented Jan 4, 2026

✍️ 작업 내용 요약

dev 버전 최신화

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 랜딩 페이지에 가격 정보 섹션 추가
    • 전문가 리포트 기반 사업계획 선택 기능 추가 (상세 리포트 조회)
  • 업데이트

    • 랜딩 체크리스트 섹션 디자인·레이아웃 변경(텍스트 중심, 시작 버튼 추가)
    • 랜딩 관계 섹션 이미지 배치 조정
    • 전문가 상세 사이드바의 연결·결제 버튼 흐름 및 상태 표시 개선
    • 전문가 카드 로딩/상태 처리 단순화
    • 결제 화면의 총액 표시 레이아웃 개선

✏️ Tip: You can customize this high-level summary in your review settings.

@Chasyuss Chasyuss requested a review from parknari02 January 4, 2026 06:45
@Chasyuss Chasyuss self-assigned this Jan 4, 2026
@Chasyuss Chasyuss added the ☁️ DEPLOY 배포 관련 label Jan 4, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 4, 2026

Walkthrough

피드백 기반 API와 훅을 제거하고 전문가 리포트 상세 API/타입/훅으로 대체했으며, 이를 사용하는 여러 전문가 관련 컴포넌트와 랜딩 페이지에 새로운 결제 섹션을 추가 및 레이아웃을 조정했습니다.

Changes

Cohort / File(s) 변경 요약
API 계층
src/api/expert.ts
GetFeedBackExpert 삭제; GetExpertReportDetail(expertId): Promise<ExpertReportDetailResponse[]> 추가 및 ExpertReportDetailResponse 임포트 추가.
타입 정의
src/types/expert/expert.type.ts, src/types/expert/expert.detail.ts
getFeedBackExpertResponse 제거(src/types/expert/expert.type.ts). 새 인터페이스 ExpertReportDetailResponse 추가(src/types/expert/expert.detail.ts) — businessPlanId, businessPlanTitle, requestCount, isOver70.
쿼리 훅
src/hooks/queries/useExpert.ts
useGetFeedBackExpert 제거. useExpertReportDetail(expertId, options?) 추가(토큰 기반 활성화, GetExpertReportDetail 사용).
전문가 카드
src/app/expert/components/ExpertCard.tsx
피드백 관련 훅/로직 제거, 상태 로직 및 로딩 가드 단순화(항상 'active'). 의존성 배열/렌더 조건 간소화.
비즈니스 플랜 드롭다운
src/app/expert/detail/components/BusinessPlanDropdown.tsx
데이터 소스 변경: useGetMyBusinessPlansuseExpertReportDetail. 새 props 인터페이스 BusinessPlanDropdownProps { expertId, hasNoPlans? } 도입. 선택 핸들 타입 및 표시 필드 → ExpertReportDetailResponse.businessPlanTitle.
전문가 상세 사이드바
src/app/expert/detail/components/ExpertDetailSidebar.tsx
useExpertReportDetail 통합, 액세스 토큰 기반 게이팅, 선택된 리포트(플랜) 관련 로직 추가(isOver70 검사 등), BusinessPlanDropdown에 expertId/hasNoPlans 전달 및 버튼/네비게이션 로직 확장.
랜딩 페이지 및 컴포넌트
src/app/_components/landing/LandingChecklist.tsx, src/app/_components/landing/LandingRelation.tsx, src/app/_components/landing/LandingPaySection.tsx, src/app/page.tsx
LandingChecklist를 다크/프로모션 레이아웃으로 변경, LandingRelation 이미지 순서 조정, 새 LandingPaySection 컴포넌트 추가 및 page.tsx에 삽입.
결제 UI
src/app/pay/components/PaymentAmount.tsx
총 결제 금액 행 레이아웃 변경 및 데코레이션 바/보조 금액 텍스트 추가(로직 변경 없음).

Sequence Diagram(s)

sequenceDiagram
  participant UI as Client UI (Sidebar / Dropdown)
  participant Hook as useExpertReportDetail
  participant API as GetExpertReportDetail (frontend API)
  participant Server as Experts Service

  Note over UI,Hook: 사용자 상호작용 — 전문가 상세 페이지 로드 / 드롭다운 열기
  UI->>Hook: useExpertReportDetail(expertId) 요청 (enabled: token present)
  Hook->>API: 호출 GetExpertReportDetail(expertId)
  API->>Server: GET /v1/experts/{expertId}/business-plans/ai-reports
  Server-->>API: 200 OK (list of ExpertReportDetailResponse)
  API-->>Hook: 반환된 데이터 배열
  Hook-->>UI: 쿼리 결과 전달 (reportDetails)
  alt reportDetails 존재
    UI->>UI: 렌더 드롭다운 항목 (businessPlanTitle)
    UI->>UI: 선택 시 isOver70 등 검사 및 버튼 상태 결정
  else 빈 상태
    UI->>UI: 빈 상태 메시지 / 생성 흐름 제안
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • #19 — 동일 영역의 전문가 API 교체 관련 PR (GetFeedBackExpert 제거/대체와 직접적 연관).
  • #90 — 동일 코드 수준의 변경(피드백 API 제거·대체, 훅·타입·컴포넌트 업데이트)을 수행한 PR.
  • #84 — BusinessPlanDropdown·ExpertDetailSidebar 등 동일 컴포넌트 변경을 포함하는 PR.

Suggested labels

✨ FEAT, 🧵 REFACTOR

Suggested reviewers

  • parknari02

🐰 피드백은 가고 리포트가 왔네,
전문가의 기록이 줄줄이 쌓이고,
결제 섹션 반짝, 랜딩은 새 옷을 입네.
작은 당근 들고 축하할래요 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive PR 제목 'dev 최신화'는 매우 모호하고 구체적이지 않아 변경 사항의 핵심을 명확하게 전달하지 못합니다. 제목을 'Expert report detail API 변경 및 랜딩 페이지 UI 업데이트'와 같이 구체적인 변경 사항을 포함하도록 변경하세요.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (6)
src/app/_components/landing/LandingPaySection.tsx (2)

6-6: 반응형 레이아웃 개선을 권장합니다.

고정된 수평 패딩 px-[375px]는 작은 화면에서 레이아웃 문제나 가로 스크롤을 유발할 수 있습니다. 다양한 화면 크기에 대응하기 위해 반응형 패딩이나 max-width 패턴을 사용하는 것을 권장합니다.

🔎 반응형 레이아웃 개선 예시
-    <div className="flex h-[978px] w-full flex-col items-center justify-center gap-[67px] px-[375px] py-[120px]">
+    <div className="flex h-auto min-h-[978px] w-full flex-col items-center justify-center gap-[67px] px-6 py-[120px] sm:px-12 lg:px-[132px] xl:px-[375px]">

22-45: LGTM! 향후 컨텐츠 관리 개선 고려

가격 카드가 깔끔하게 구현되었습니다. 현재 가격과 기능이 하드코딩되어 있는데, 랜딩 페이지의 특성상 허용 가능하지만, 향후 컨텐츠를 자주 변경해야 하거나 A/B 테스트가 필요한 경우 props나 CMS 기반 구조로 리팩토링을 고려해볼 수 있습니다.

src/api/expert.ts (1)

85-96: 중복된 params 전달 확인 필요

expertId가 이미 URL 경로(/v1/experts/${expertId}/business-plans/ai-reports)에 포함되어 있으므로, Line 91의 params: { expertId }는 불필요합니다. 이는 동일한 ID를 경로와 쿼리 파라미터로 두 번 전송하게 됩니다.

🔎 제안된 수정
 export async function GetExpertReportDetail(
   expertId: number
 ): Promise<ExpertReportDetailResponse[]> {
   const res = await api.get<{ data: ExpertReportDetailResponse[] }>(
-    `/v1/experts/${expertId}/business-plans/ai-reports`,
-    {
-      params: { expertId },
-    }
+    `/v1/experts/${expertId}/business-plans/ai-reports`
   );

   return res.data.data;
 }

참고: GetExpertDetail 함수(Line 72-83)에서도 동일한 패턴이 사용되고 있어, 의도된 것일 수 있습니다. 백엔드 API 요구사항을 확인해 주세요.

src/app/expert/detail/components/ExpertDetailSidebar.tsx (2)

50-64: 복잡한 중첩 삼항 연산자 가독성 개선 제안

ButtonIconbuttonText의 중첩 삼항 연산자가 가독성을 저하시킵니다. 유지보수성을 위해 헬퍼 함수나 객체 맵핑으로 리팩토링을 고려해 주세요.

🔎 제안된 리팩토링 예시
const getButtonConfig = () => {
  if (shouldShowCreateButton) {
    return { icon: WhitePlus, text: '사업계획서 생성' };
  }
  if (hasRequested) {
    return { icon: GrayPlus, text: '신청완료' };
  }
  if (disabled && !isSelectedPlanOver70) {
    return { icon: GrayCheck, text: '전문가 연결' };
  }
  if (disabled) {
    return { icon: GrayPlus, text: '전문가 연결' };
  }
  return { icon: WhitePlus, text: '전문가 연결' };
};

const { icon: ButtonIcon, text: buttonText } = getButtonConfig();

29-32: 동일 데이터 중복 fetch 검토

ExpertDetailSidebarBusinessPlanDropdown 모두 useExpertReportDetail(expert.id)를 호출합니다. React Query가 동일한 queryKey로 요청을 중복 제거하지만, reportDetails를 props로 전달하면 코드 중복을 줄이고 컴포넌트 간 일관성을 보장할 수 있습니다.

현재 구조가 컴포넌트 독립성을 위해 의도된 것인지 확인해 주세요. 의도된 것이 아니라면 데이터를 props로 전달하는 방식을 고려해 보세요.

Also applies to: 103-106

src/app/expert/detail/components/BusinessPlanDropdown.tsx (1)

66-87: hasNoPlans가 true일 때 드롭다운 비활성화 검토

hasNoPlans가 true일 때도 드롭다운을 클릭할 수 있어 빈 목록이 표시됩니다. 사용자 경험 개선을 위해 해당 경우 드롭다운 버튼을 비활성화하거나 클릭을 방지하는 것을 고려해 보세요.

🔎 제안된 수정
       <button
         type="button"
-        onClick={() => setIsOpen(!isOpen)}
+        onClick={() => !hasNoPlans && setIsOpen(!isOpen)}
+        disabled={hasNoPlans}
         className={`ds-subtext flex w-full cursor-pointer items-center justify-between rounded-lg px-3 py-2 text-left font-medium outline-none ${
           selectedPlan
             ? 'bg-primary-50 text-primary-500'
-            : 'bg-gray-100 text-gray-500'
+            : hasNoPlans
+              ? 'cursor-not-allowed bg-gray-100 text-gray-400'
+              : 'bg-gray-100 text-gray-500'
         }`}
       >
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 42a641e and 99a6ba9.

⛔ Files ignored due to path filters (4)
  • public/images/landing/landing_promotion.png is excluded by !**/*.png
  • src/assets/icons/big_check.svg is excluded by !**/*.svg
  • src/assets/icons/chevron_right.svg is excluded by !**/*.svg
  • src/assets/icons/white_right.svg is excluded by !**/*.svg
📒 Files selected for processing (11)
  • src/api/expert.ts
  • src/app/_components/landing/LandingChecklist.tsx
  • src/app/_components/landing/LandingPaySection.tsx
  • src/app/_components/landing/LandingRelation.tsx
  • src/app/expert/components/ExpertCard.tsx
  • src/app/expert/detail/components/BusinessPlanDropdown.tsx
  • src/app/expert/detail/components/ExpertDetailSidebar.tsx
  • src/app/page.tsx
  • src/hooks/queries/useExpert.ts
  • src/types/expert/expert.detail.ts
  • src/types/expert/expert.type.ts
💤 Files with no reviewable changes (1)
  • src/types/expert/expert.type.ts
🧰 Additional context used
🧬 Code graph analysis (5)
src/app/expert/components/ExpertCard.tsx (3)
src/types/expert/label.ts (2)
  • TAB_LABELS (1-7)
  • TabLabel (9-9)
src/hooks/queries/useExpert.ts (1)
  • useGetExpert (8-13)
src/types/expert/expert.props.ts (2)
  • adaptMentor (29-39)
  • MentorProps (4-14)
src/api/expert.ts (1)
src/types/expert/expert.detail.ts (1)
  • ExpertReportDetailResponse (22-27)
src/app/expert/detail/components/BusinessPlanDropdown.tsx (4)
src/store/business.store.ts (1)
  • useBusinessStore (44-379)
src/store/user.store.ts (1)
  • useUserStore (15-54)
src/hooks/queries/useExpert.ts (1)
  • useExpertReportDetail (23-33)
src/types/expert/expert.detail.ts (1)
  • ExpertReportDetailResponse (22-27)
src/app/expert/detail/components/ExpertDetailSidebar.tsx (1)
src/hooks/queries/useExpert.ts (1)
  • useExpertReportDetail (23-33)
src/hooks/queries/useExpert.ts (1)
src/api/expert.ts (1)
  • GetExpertReportDetail (85-96)
🔇 Additional comments (12)
src/app/page.tsx (2)

4-4: LGTM!

새로운 컴포넌트 임포트가 올바르게 추가되었습니다.


31-31: LGTM!

프로모션 섹션이 적절한 위치에 배치되었습니다.

src/app/_components/landing/LandingRelation.tsx (1)

73-81: LGTM!

이미지 컴포넌트의 렌더링 순서 변경이 적절합니다. 레이아웃 조정만 이루어졌으며 기능적 문제는 없습니다.

src/app/_components/landing/LandingChecklist.tsx (2)

6-12: LGTM!

새로운 프로모션 헤더 섹션이 깔끔하게 구현되었습니다.


36-45: LGTM!

프로모션 이미지로의 변경이 적절하며, quality={100} 설정으로 고품질 렌더링이 보장됩니다.

src/app/expert/components/ExpertCard.tsx (3)

2-4: LGTM!

피드백 기반 로직 제거에 따른 의존성 정리가 적절히 수행되었습니다.


15-21: LGTM! 향후 상태 로직 통합 고려

피드백 기반 상태 로직을 제거하고 status를 'active'로 단순화한 것은 API 리팩토링의 일환으로 적절합니다.

향후 useExpertReportDetail에서 제공하는 데이터를 활용하여 전문가별 상태나 메타데이터를 표시할 필요가 있을 경우, 해당 시점에 통합을 검토하시기 바랍니다.

Based on learnings from the AI summary, this change aligns with the broader migration from feedback-based data to ExpertReportDetail data flow.


28-32: LGTM!

로딩 상태 체크가 피드백 의존성 제거에 맞게 올바르게 단순화되었습니다.

src/app/_components/landing/LandingPaySection.tsx (2)

1-3: LGTM!

아이콘 임포트가 올바르게 구성되었습니다.


52-61: LGTM!

가격 정보에 대한 설명 텍스트가 명확하게 제공되어 사용자 이해를 돕습니다.

src/types/expert/expert.detail.ts (1)

22-27: LGTM!

새로운 ExpertReportDetailResponse 인터페이스가 잘 정의되어 있습니다. 필드명이 명확하고 타입이 적절합니다.

src/app/expert/detail/components/BusinessPlanDropdown.tsx (1)

16-33: LGTM!

BusinessPlanDropdown 컴포넌트가 useExpertReportDetail 훅과 잘 통합되었습니다. Props 인터페이스가 명확하고, 로딩 상태 및 빈 상태 처리가 적절합니다.

Comment on lines +14 to +28
<div className="flex flex-col gap-6">
<p className="ds-title font-semibold text-gray-300">
2026 지원사업 대비 모든 기능 무료 프로모션 (~1/10)
</p>

<Image
src="/images/landing/landing_checklist_2.png"
alt="랜딩 체크리스트2"
width={368}
height={480}
className="h-[480px] w-[368px]"
priority
unoptimized={true}
/>
<div className="flex flex-row items-start gap-3">
{['10일', '4시간', '19분', '20초'].map((time) => (
<div
key={time}
className="ds-heading flex h-[86px] w-[120px] items-center justify-center rounded-lg bg-gray-900 py-10 font-semibold text-white"
>
{time}
</div>
))}
</div>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Check if the file exists and read the content
wc -l src/app/_components/landing/LandingChecklist.tsx

Repository: StartUpLight/STARLIGHT_FE

Length of output: 120


🏁 Script executed:

# Read the relevant lines and surrounding context
cat -n src/app/_components/landing/LandingChecklist.tsx | head -40

Repository: StartUpLight/STARLIGHT_FE

Length of output: 1822


🏁 Script executed:

# Search for any existing timer or countdown logic in the file
rg -A 5 -B 5 "useEffect|useState|setInterval|countdown|timer" src/app/_components/landing/LandingChecklist.tsx

Repository: StartUpLight/STARLIGHT_FE

Length of output: 51


🏁 Script executed:

# Search for any other timer/countdown implementations in the project
rg -i "countdown|timer|setInterval|endDate" src/ --type tsx --type ts -A 3 | head -50

Repository: StartUpLight/STARLIGHT_FE

Length of output: 96


🏁 Script executed:

# Check if there are other similar promotional sections with timers
rg "map.*time|days.*hours.*minutes.*seconds" src/ --type tsx -B 2 -A 2

Repository: StartUpLight/STARLIGHT_FE

Length of output: 96


🏁 Script executed:

# Search for any timer/countdown implementations without file type specification
rg -i "countdown|setInterval|endDate|useEffect.*timer" src/ -A 3 | head -80

Repository: StartUpLight/STARLIGHT_FE

Length of output: 467


🏁 Script executed:

# Check component structure more broadly for patterns
rg "use client|'use client'" src/app/_components/ | head -20

Repository: StartUpLight/STARLIGHT_FE

Length of output: 582


정적 타이머를 동적 카운트다운으로 구현하거나 제거하세요.

현재 타이머 값(['10일', '4시간', '19분', '20초'])이 하드코딩되어 있어 실제로 카운트다운되지 않습니다. 사용자는 타이머가 실시간으로 업데이트될 것으로 기대하므로, 이는 혼란스러운 UX를 제공합니다.

프로모션 종료 시점(~1/10)까지 실제 카운트다운 로직을 구현하거나, 타이머 UI를 제거하고 정적 텍스트로 표시하는 것을 권장합니다. 카운트다운을 구현하는 경우 'use client' 지시문을 추가하여 클라이언트 컴포넌트로 전환해야 합니다.

🤖 Prompt for AI Agents
In src/app/_components/landing/LandingChecklist.tsx around lines 14 to 28, the
countdown blocks use a hardcoded array ['10일','4시간','19분','20초'] and must be
replaced with either a real client-side countdown or a static label: to
implement a live countdown, convert the file to a client component by adding
'use client' at the top, create state (e.g., remainingMs) and a useEffect that
sets an interval (1000ms) to compute time left until the promotion end date
(~Jan 10) by subtracting Date.now() from the target Date, derive
days/hours/minutes/seconds from remainingMs, update state on each tick and clear
the interval on unmount, then render the dynamic values instead of the hardcoded
array; alternatively, if you prefer to keep it static, remove the mapped array
and replace it with a single descriptive text element showing the end date or a
non-updating label.

Comment on lines +23 to +33
export function useExpertReportDetail(
expertId: number,
options?: { enabled?: boolean }
) {
const hasToken = localStorage.getItem('accessToken');
return useQuery({
queryKey: ['GetExpertReportDetail', expertId, hasToken],
queryFn: () => GetExpertReportDetail(expertId),
enabled: expertId > 0 && !!hasToken && (options?.enabled ?? true),
});
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

SSR 환경에서 localStorage 접근 시 에러 발생 가능

Line 27에서 localStorage.getItem('accessToken')을 직접 호출하고 있습니다. 이 훅이 서버 사이드에서 실행될 경우 localStorage is not defined 에러가 발생할 수 있습니다.

🔎 제안된 수정
 export function useExpertReportDetail(
   expertId: number,
   options?: { enabled?: boolean }
 ) {
-  const hasToken = localStorage.getItem('accessToken');
+  const hasToken =
+    typeof window !== 'undefined'
+      ? localStorage.getItem('accessToken')
+      : null;
   return useQuery({
     queryKey: ['GetExpertReportDetail', expertId, hasToken],
     queryFn: () => GetExpertReportDetail(expertId),
     enabled: expertId > 0 && !!hasToken && (options?.enabled ?? true),
   });
 }

참고: ExpertDetailSidebar.tsx에서는 이미 typeof window !== 'undefined' 가드를 사용하고 있습니다(Line 25-26).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function useExpertReportDetail(
expertId: number,
options?: { enabled?: boolean }
) {
const hasToken = localStorage.getItem('accessToken');
return useQuery({
queryKey: ['GetExpertReportDetail', expertId, hasToken],
queryFn: () => GetExpertReportDetail(expertId),
enabled: expertId > 0 && !!hasToken && (options?.enabled ?? true),
});
}
export function useExpertReportDetail(
expertId: number,
options?: { enabled?: boolean }
) {
const hasToken =
typeof window !== 'undefined'
? localStorage.getItem('accessToken')
: null;
return useQuery({
queryKey: ['GetExpertReportDetail', expertId, hasToken],
queryFn: () => GetExpertReportDetail(expertId),
enabled: expertId > 0 && !!hasToken && (options?.enabled ?? true),
});
}
🤖 Prompt for AI Agents
In src/hooks/queries/useExpert.ts around lines 23-33, the hook directly calls
localStorage.getItem('accessToken') which will throw "localStorage is not
defined" during SSR; replace that call with a safe guard such as computing
hasToken only when typeof window !== 'undefined' (e.g. const hasToken = typeof
window !== 'undefined' ? localStorage.getItem('accessToken') : null) and then
use that hasToken in queryKey and the enabled condition (enabled: expertId > 0
&& !!hasToken && (options?.enabled ?? true)); ensure no other direct
window/localStorage access remains in this function so the hook is safe to
import/run on the server.

Copy link
Contributor

@parknari02 parknari02 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

확인했습니다. 수고하셨습니다 ~!

[SRLT-123] 랜딩페이지 버튼 라우터 연결
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

🧹 Nitpick comments (1)
src/app/pay/components/PaymentAmount.tsx (1)

4-5: 가격 데이터를 props로 받도록 개선을 권장합니다.

현재 unitPricetotalAmount가 하드코딩되어 있어 컴포넌트의 재사용성과 유지보수성이 제한됩니다. 프로모션 가격이 변경되거나 다른 요금제에서 이 컴포넌트를 재사용할 경우 코드 수정이 필요합니다.

props를 통해 동적으로 가격을 전달받도록 리팩토링하는 것을 권장합니다.

🔎 제안하는 리팩토링
+interface PaymentAmountProps {
+  unitPrice?: number;
+  totalAmount?: number;
+  originalAmount?: number;
+}
+
-const PaymentAmount = () => {
-  const unitPrice = 49000;
-  const totalAmount = 49000;
+const PaymentAmount = ({ 
+  unitPrice = 49000, 
+  totalAmount = 49000,
+  originalAmount = 49000 
+}: PaymentAmountProps = {}) => {
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 99a6ba9 and 0d3381d.

📒 Files selected for processing (3)
  • src/app/_components/landing/LandingChecklist.tsx
  • src/app/_components/landing/LandingPaySection.tsx
  • src/app/pay/components/PaymentAmount.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/app/_components/landing/LandingChecklist.tsx
  • src/app/_components/landing/LandingPaySection.tsx

Comment on lines +25 to +35
<div className="flex items-center gap-3">
<span className="relative inline-block">
<span className="absolute inset-0 flex items-center">
<span className="bg-primary-500 h-[3px] w-full"></span>
</span>
<span className="ds-text relative font-semibold text-gray-900">
{totalAmount.toLocaleString()}
</span>
</span>
<span className="ds-text font-semibold text-gray-900">0원</span>
</div>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

할인 정보 표시 및 접근성 개선이 필요합니다.

현재 구현에서 49,000원이 취소선 처리되고 0원이 표시되는데, 다음 사항들을 고려해주세요:

  1. UX 명확성: 100% 할인이 적용된 이유나 조건에 대한 설명이 없어 사용자가 혼란스러울 수 있습니다. "프로모션 할인", "이벤트 가격" 등의 레이블을 추가하는 것을 권장합니다.

  2. 접근성: 취소선이 순수하게 시각적 요소(색상 바)로만 구현되어 있어 스크린 리더 사용자에게 의미가 전달되지 않습니다.

🔎 접근성 및 UX 개선 제안
         <div className="flex items-center gap-3">
-          <span className="relative inline-block">
-            <span className="absolute inset-0 flex items-center">
-              <span className="bg-primary-500 h-[3px] w-full"></span>
-            </span>
-            <span className="ds-text relative font-semibold text-gray-900">
+          <del 
+            className="ds-text font-semibold text-gray-500 decoration-primary-500 decoration-2"
+            aria-label="정가"
+          >
-              {totalAmount.toLocaleString()}원
+            {totalAmount.toLocaleString()}원
-            </span>
-          </span>
+          </del>
-          <span className="ds-text font-semibold text-gray-900">0원</span>
+          <div className="flex flex-col items-end">
+            <span className="ds-text font-semibold text-primary-500">0원</span>
+            <span className="ds-caption text-gray-500">프로모션 가격</span>
+          </div>
         </div>

이렇게 하면:

  • 시맨틱 <del> 태그로 스크린 리더가 취소된 가격임을 인식
  • 할인된 가격에 대한 명확한 컨텍스트 제공
  • Tailwind의 기본 text-decoration 유틸리티 활용으로 더 안정적인 구현
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div className="flex items-center gap-3">
<span className="relative inline-block">
<span className="absolute inset-0 flex items-center">
<span className="bg-primary-500 h-[3px] w-full"></span>
</span>
<span className="ds-text relative font-semibold text-gray-900">
{totalAmount.toLocaleString()}
</span>
</span>
<span className="ds-text font-semibold text-gray-900">0원</span>
</div>
<div className="flex items-center gap-3">
<del
className="ds-text font-semibold text-gray-500 decoration-primary-500 decoration-2"
aria-label="정가"
>
{totalAmount.toLocaleString()}
</del>
<div className="flex flex-col items-end">
<span className="ds-text font-semibold text-primary-500">0원</span>
<span className="ds-caption text-gray-500">프로모션 가격</span>
</div>
</div>

@Chasyuss Chasyuss merged commit 60ac4cd into develop Jan 4, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

☁️ DEPLOY 배포 관련

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants