Skip to content

Conversation

@Chasyuss
Copy link
Member

@Chasyuss Chasyuss commented Jan 7, 2026

#️⃣ 관련 이슈

  • SRLT-127

✍️ 작업 내용 요약

랜딩-프로모션 부분 시간 타이머 설정 구현

💡 작업 내용

기능

  • 2/28일까지 프로모션 시간 실시간 타이머 설정

🖥️ 구현 화면

image

기타 사항

x

Summary by CodeRabbit

  • 새로운 기능

    • 2026년 2월 28일까지의 실시간 카운트다운 타이머가 추가되었습니다.
    • 카운트다운은 일·시간·분·초 단위로 동적으로 표시됩니다.
  • 스타일 / 레이아웃

    • 주요 랜딩 레이아웃이 중앙 정렬로 조정되어 더 컴팩트하게 표시됩니다.
    • 홍보 문구가 "~1/10"에서 "~2/28"로 변경되었습니다.

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

@Chasyuss Chasyuss requested a review from parknari02 January 7, 2026 09:40
@Chasyuss Chasyuss self-assigned this Jan 7, 2026
@Chasyuss Chasyuss added the ✨ FEAT 새로운 기능 구현 label Jan 7, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 7, 2026

Walkthrough

새로운 useCountdown 훅을 추가하고 LandingChecklist를 수정해 목표일(2026-02-28T23:59:59) 기준의 실시간 카운트다운(일/시간/분/초)을 매초 갱신해 렌더링하도록 정적 표시를 동적으로 교체했습니다.

Changes

Cohort / File(s) 설명
새 훅
src/hooks/useCountdown.ts
목표 날짜 문자열을 받아 SSR 안전하게 남은 days/hours/minutes/seconds를 계산하고, 1초 간격으로 상태를 갱신해 반환하는 React 훅 추가
카운트다운 통합 및 UI 변경
src/app/_components/landing/LandingChecklist.tsx
useCountdown 훅을 임포트 및 초기화, 정적 카운트다운을 동적 값으로 대체(맵핑 렌더링), 레이아웃 클래스 조정 및 프로모션 텍스트을 "~2/28"로 업데이트

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Browser as Browser (LandingChecklist)
    participant Hook as useCountdown Hook
    participant Timer as setInterval (환경 타이머)
    participant Render as React Renderer

    Note over Browser,Hook: 컴포넌트 마운트 시
    Browser->>Hook: useCountdown(targetDate)
    Hook->>Hook: calculateTimeLeft(targetDate) (초기 계산)
    Hook-->>Browser: 초기 timeLeft 반환 (state)
    Hook->>Timer: setInterval(1s) 시작
    Timer->>Hook: tick -> calculateTimeLeft(targetDate)
    Hook-->>Browser: 업데이트된 timeLeft (state 변경)
    Browser->>Render: re-render countdown UI (days/hours/minutes/seconds)
    Note over Hook,Timer: 목표일 경과 시 timeLeft = 0으로 고정 및 타이머 정리
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • dev 최신화 #92: 동일 컴포넌트(LandingChecklist.tsx)의 카운트다운/프로모션 UI 변경과 직접적인 겹침 가능성 있음.
  • [SRLT-39] 홈화면 랜딩페이지 ui #20: 해당 컴포넌트의 초기 도입 PR로, 새 훅 통합 시 코드 충돌 또는 중복 로직 존재 가능성 있음.

Suggested reviewers

  • parknari02

🐰 뀨르릉 시계가 쿵쾅
훅 하나로 초가 모여
분이 되고 시가 되고
2월까지 토끼가 폴짝
🥕✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 변경사항의 주요 내용을 명확하게 반영하고 있습니다. 랜딩 페이지 프로모션 실시간 타이머 구현이라는 핵심 목표를 정확히 설명합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 26c4dc0 and f292996.

📒 Files selected for processing (1)
  • src/hooks/useCountdown.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/hooks/useCountdown.ts

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

🤖 Fix all issues with AI agents
In @src/app/_components/landing/LandingChecklist.tsx:
- Around line 5-9: LandingChecklist is directly calling useCountdown during SSR
which causes hydration mismatch and non-deterministic timezone behavior; fix by
moving countdown logic to a client-only component (e.g., create CountdownTimer
that uses useCountdown('2026-02-28T23:59:59+09:00')) and dynamically import it
in LandingChecklist (use Next.js dynamic import or React.lazy with suspense) so
useCountdown runs only on the client, and ensure the deadline string includes
the explicit timezone (+09:00) to guarantee consistent end time across locales.
- Line 9: The countdown target is parsed as UTC because the string
'2026-02-28T23:59:59' has no timezone; update the call in LandingChecklist (the
useCountdown invocation) to use an explicit KST offset like
'2026-02-28T23:59:59+09:00' or alternatively update the useCountdown hook to
accept a timezone param or treat naive ISO strings as KST (convert/adjust the
parsed Date by +9 hours) so the countdown ends at the intended KST moment.

In @src/hooks/useCountdown.ts:
- Around line 3-9: The hook currently initializes timeLeft to zeros which causes
SSR hydration mismatch when the client immediately recalculates in useEffect;
change useCountdown so the initial useState uses a lazy initializer that
synchronously computes the remaining time from the provided targetDate (e.g.,
via a helper like calculateTimeLeft or getTimeLeft that parses targetDate and
returns {days,hours,minutes,seconds}) and reuse that same helper inside the
interval callback and cleanup logic; ensure you reference useCountdown,
setTimeLeft, and the new calculateTimeLeft/getTimeLeft helper so the first
render already reflects the computed countdown instead of all zeros.
- Line 12: The code uses new Date(targetDate).getTime() which parses
timezone-less strings in the local timezone causing inconsistent countdowns;
update useCountdown (the target constant) to parse or normalize the input to an
explicit timezone/UTC: either require callers to pass an ISO string with offset
(e.g., '2026-02-28T23:59:59+09:00') or convert the received targetDate to a UTC
timestamp using a timezone-aware parser (e.g., parse as UTC or append '+00:00'
or '+09:00' as appropriate) before calling getTime(), and validate/throw if the
string is ambiguous so target in useCountdown is always deterministic.
🧹 Nitpick comments (1)
src/app/_components/landing/LandingChecklist.tsx (1)

26-40: 동적 카운트다운 구현 확인

카운트다운 로직이 올바르게 동작하지만, 몇 가지 개선 사항이 있습니다:

  1. Key prop: Line 33에서 key={index} 사용은 권장되지 않습니다. 배열 순서가 안정적이긴 하지만, 더 명확한 key를 사용하는 것이 좋습니다.
♻️ 개선 제안
       {[
         { value: timeLeft.days, label: '일' },
         { value: timeLeft.hours, label: '시간' },
         { value: timeLeft.minutes, label: '분' },
         { value: timeLeft.seconds, label: '초' },
       ].map((item, index) => (
         <div
-          key={index}
+          key={item.label}
           className="ds-heading flex h-[86px] w-[120px] items-center justify-center rounded-lg bg-gray-900 py-10 font-semibold text-white"
         >

또는 배열을 컴포넌트 외부로 분리하여 재생성 방지:

+const TIME_UNITS = [
+  { key: 'days', label: '일' },
+  { key: 'hours', label: '시간' },
+  { key: 'minutes', label: '분' },
+  { key: 'seconds', label: '초' },
+] as const;
+
 const LandingChecklist = () => {
   const router = useRouter();
   const timeLeft = useCountdown('2026-02-28T23:59:59+09:00');

   return (
     // ...
-      {[
-        { value: timeLeft.days, label: '일' },
-        { value: timeLeft.hours, label: '시간' },
-        { value: timeLeft.minutes, label: '분' },
-        { value: timeLeft.seconds, label: '초' },
-      ].map((item, index) => (
+      {TIME_UNITS.map((unit) => (
         <div
-          key={index}
+          key={unit.key}
           className="ds-heading flex h-[86px] w-[120px] items-center justify-center rounded-lg bg-gray-900 py-10 font-semibold text-white"
         >
-          {item.value}
-          {item.label}
+          {timeLeft[unit.key]}
+          {unit.label}
         </div>
       ))}
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 60ac4cd and 0d2d769.

📒 Files selected for processing (2)
  • src/app/_components/landing/LandingChecklist.tsx
  • src/hooks/useCountdown.ts
🧰 Additional context used
🧬 Code graph analysis (1)
src/app/_components/landing/LandingChecklist.tsx (1)
src/hooks/useCountdown.ts (1)
  • useCountdown (3-37)
🔇 Additional comments (1)
src/hooks/useCountdown.ts (1)

30-34: 정리 로직이 올바르게 구현되었습니다

clearInterval을 사용한 cleanup 함수가 정확하며, targetDate가 변경될 때 이전 interval이 올바르게 정리됩니다. 메모리 누수 우려가 없습니다.

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

🤖 Fix all issues with AI agents
In @src/hooks/useCountdown.ts:
- Around line 30-43: The updateTimer function duplicates the time-difference
logic already implemented in calculateTimeLeft; replace the inlined computation
inside updateTimer with a single call to calculateTimeLeft (passing the same
target value or eliminating the redundant local target if calculateTimeLeft
closes over it) and call setTimeLeft with the result, removing the duplicated
block so all time calculation lives in calculateTimeLeft and updateTimer only
invokes it and updates state.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0d2d769 and 26c4dc0.

📒 Files selected for processing (1)
  • src/hooks/useCountdown.ts

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.

확인했씁니다 !! 수고하셨습니당

@Chasyuss Chasyuss merged commit 1f6961a into develop Jan 7, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ FEAT 새로운 기능 구현

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants