Skip to content

[Refactor] WTH-243 : 랜딩 페이지 수정사항 적용#35

Open
nabbang6 wants to merge 15 commits intodevelopfrom
fix/WTH-243-랜딩-수정사항-적용

Hidden character warning

The head ref may contain hidden characters: "fix/WTH-243-\ub79c\ub529-\uc218\uc815\uc0ac\ud56d-\uc801\uc6a9"
Open

[Refactor] WTH-243 : 랜딩 페이지 수정사항 적용#35
nabbang6 wants to merge 15 commits intodevelopfrom
fix/WTH-243-랜딩-수정사항-적용

Conversation

@nabbang6
Copy link
Copy Markdown
Collaborator

@nabbang6 nabbang6 commented Apr 2, 2026

✅ PR 유형

어떤 변경 사항이 있었나요?

  • 새로운 기능 추가
  • 버그 수정
  • 코드에 영향을 주지 않는 변경사항(오타 수정, 탭 사이즈 변경, 변수명 변경)
  • 코드 리팩토링
  • 주석 추가 및 수정
  • 문서 수정
  • 빌드 부분 혹은 패키지 매니저 수정
  • 파일 혹은 폴더명 수정
  • 파일 혹은 폴더 삭제

📌 관련 이슈번호

  • Closed #243

✅ Key Changes

  • 서비스 섹션 동영상 적용: 동영상(mp4) 파일 추가, 활성 카드만 재생/비활성 카드는 일시정지하는 최적화 적용
  • 히어로 섹션 카드 변경: 기존 히어로 이미지를 Weeth 브랜드 카드 디자인으로 교체
  • 무료로 시작하기 제거: 히어로 섹션 및 CTA 섹션에서 "무료로 시작하기" 버튼 제거
  • 가입 문의 모달 추가: CTA 섹션에 InquiryDialog 추가, 이메일/문의사항 입력 후 API 전송
  • 문의하기 API 연결: lib/apis/inquiry.ts 추가하여 /api/v4/users/inquiries 엔드포인트 연동
  • 런칭 전 경로 차단: proxy.ts에 PRE_LAUNCH 플래그 추가, /landing 외 경로 접근 시 리다이렉트 및 토스트 안내
  • 철학 섹션 카드 이미지 교체: placeholder 색상 블록을 실제 SVG 카드 이미지로 교체
  • 행동 분석 툴 추가: instrumentation-client.ts 추가
image

📸 스크린샷 or 실행영상

/landing 페이지에서 확인 가능합니다!


🎸 기타 사항 or 추가 코멘트

  • HeroSection의 "무료로 시작하기" 링크는 주석 처리된 상태 -> 런칭 시 복원 또는 삭제 결정 필요
  • PublicHeader의 showAuthButtons prop도 TODO로 남겨둔 상태

현재 서비스 섹션에서 마지막 카드를 제외하고 드래그 시 description 영역이 화면에 노출되지 않는 문제가 있습니당...
수정하려고 하니 스크롤/애니메이션 쪽 충돌이 많이 나서 예상보다 시간이 오래 걸릴 것 같아... 우선은 현 상태로 pr 올려두엇습니다... ㅜ__ㅜ

Summary by CodeRabbit

  • 새로운 기능

    • 문의 양식 대화상자 추가: 랜딩에서 이메일/문의 제출 가능
    • 방문 차단 알림 추가: 차단 시 안내 토스트 후 랜딩으로 리다이렉트
  • 개선사항

    • 서비스 섹션: 동영상 재생 지원 및 주요 키워드 강조 표시
    • 헤로·CTA 재설계: 히어로 콘텐츠 및 CTA 동작 변경
    • 철학 섹션: 카드 이미지 교체 및 개선된 레이아웃
  • 기타

    • 웹 분석(태그 매니저·Clarity·PostHog) 통합 및 환경설정·무시 규칙 업데이트

@nabbang6 nabbang6 added the 🔨 Refactor 코드 리팩토링 label Apr 2, 2026
@nabbang6 nabbang6 self-assigned this Apr 2, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 2, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bf3c8e79-d47d-4938-a485-ddac5c625bc4

📥 Commits

Reviewing files that changed from the base of the PR and between 4a1c7be and c94add7.

📒 Files selected for processing (5)
  • instrumentation-client.ts
  • src/app/(public)/landing/page.tsx
  • src/components/landing/CTASection.tsx
  • src/components/landing/InquiryDialog.tsx
  • src/lib/apis/inquiry.ts
✅ Files skipped from review due to trivial changes (1)
  • instrumentation-client.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/lib/apis/inquiry.ts
  • src/components/landing/InquiryDialog.tsx

📝 Walkthrough

Walkthrough

프리런칭 미들웨어 리다이렉트, PostHog 및 GTM/Clarity 스크립트 추가, 랜딩용 BlockedToast·InquiryDialog 컴포넌트 및 API 추가, 서비스 섹션에 비디오·강조 키워드 도입과 랜딩 자산/상수 업데이트가 포함됩니다.

Changes

Cohort / File(s) Summary
Analytics & Instrumentation
instrumentation-client.ts, package.json, src/app/layout.tsx
PostHog 초기화 모듈(환경변수 기반) 추가, posthog-js 의존성 추가, 레이아웃에 Google Tag Manager·Microsoft Clarity 스크립트 및 noscript 삽입
Landing UI — 새로운 컴포넌트
src/components/landing/BlockedToast.tsx, src/components/landing/InquiryDialog.tsx, src/components/landing/index.ts
쿼리 기반 리다이렉트/토스트 처리용 BlockedToast 추가, 문의 제출용 InquiryDialog 추가 및 인덱스에 재수출
Landing UI — 섹션 변경
src/components/landing/CTASection.tsx, src/components/landing/HeroSection.tsx, src/components/landing/PhilosophySection.tsx, src/components/landing/ServiceSection.tsx
CTA 링크를 다이얼로그로 전환, 히어로 이미지/CTA 제거 및 SVG 인라인화, 철학 섹션에 정적 이미지 컴포넌트 적용, 서비스 섹션에 비디오 지원·highlightKeyword 로직 추가 및 레이아웃 조정
Assets & Constants
src/assets/icons/index.ts, src/assets/image/landing/card/index.ts, src/constants/landing/landing.ts
로고 초기 아이콘 재수출 추가, 랜딩 카드 SVG 인덱스 파일 추가, 기능 목록 항목을 이미지에서 비디오·highlightKeyword 필드로 변경
API surface
src/lib/apis/inquiry.ts, src/lib/apis/index.ts
문의 POST API 모듈(inquiryApi.create) 추가 및 API 인덱스에 re-export 추가
Middleware / Routing
src/proxy.ts
PRE_LAUNCH = true 설정으로 비-랜딩 경로를 /landing?blocked=true로 리다이렉트하도록 로직 추가; config.matcher/videos 예외 추가
Config & Ignore
.claude/settings.json, .claude/settings.local.json, .gitignore
MCP 서버 API URL 업데이트, 로컬 설정에 PostHog 검색 명령 허용 추가, .env.local을 .gitignore에 추가
Landing page usage
src/app/(public)/landing/page.tsx
BlockedToastSuspense로 래핑하여 렌더링, PublicHeader에서 showAuthButtons prop 제거

Sequence Diagram(s)

sequenceDiagram
  participant B as Browser
  participant M as Middleware (proxy.ts)
  participant S as Server/App
  participant C as Client (BlockedToast)

  B->>M: HTTP request (any pathname)
  alt PRE_LAUNCH = true and pathname != /landing and not excluded
    M->>B: 302 Redirect to /landing?blocked=true
    B->>S: Request /landing?blocked=true
    S->>B: Serve landing page (includes scripts + BlockedToast)
    B->>C: Client loads BlockedToast
    C->>C: detect blocked=true -> show toast, router.replace('/landing')
  else normal flow
    M->>S: proxy/request forwarded
    S->>B: normal response
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

✨ Feature, 📬 API

Suggested reviewers

  • dalzzy
  • woneeeee
  • JIN921

Poem

🐰 햇살 속에 작게 뛰놀며,
버튼 대신 창을 열고 속삭여요.
비디오는 춤추고, 토스트는 소곤대며,
미들웨어는 잠깐 길을 바꾸었네.
토끼가 응원해요 — 출시까지 파이팅! 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경 사항인 '랜딩 페이지 수정사항'을 명확하게 요약하고 있으며, 이슈번호(WTH-243)도 포함되어 있습니다.
Description check ✅ Passed PR 설명이 템플릿 요구사항을 대부분 충족하고 있으며, PR 유형 선택, 이슈번호, 상세한 Key Changes, 스크린샷이 포함되어 있습니다.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/WTH-243-랜딩-수정사항-적용

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.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

🤖 Claude 테스트 제안

모델: claude-sonnet-4-6 | 토큰: 0 입력 / 0 출력

변경된 컴포넌트에 대해 Claude가 생성한 테스트 코드입니다. 검토 후 적합한 부분만 사용하세요.

src/app/(public)/landing/page.tsx

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


src/app/layout.tsx

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


src/components/landing/BlockedToast.tsx

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


src/components/landing/CTASection.tsx

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


src/components/landing/HeroSection.tsx

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


이 코멘트는 Claude API를 통해 자동 생성되었습니다. 반드시 검토 후 사용하세요.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

PR 테스트 결과

Jest: 통과

🎉 모든 테스트를 통과했습니다!

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

PR 검증 결과

TypeScript: 통과
ESLint: 통과
Prettier: 실패
Build: 통과

⚠️ 일부 검증에 실패했습니다. 확인 후 수정해주세요.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

구현한 기능 Preview: https://weeth-kjy0pgvrx-weethsite-4975s-projects.vercel.app

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

🤖 Claude 테스트 제안

모델: claude-sonnet-4-6 | 토큰: 0 입력 / 0 출력

변경된 컴포넌트에 대해 Claude가 생성한 테스트 코드입니다. 검토 후 적합한 부분만 사용하세요.

src/app/(public)/landing/page.tsx

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


src/app/layout.tsx

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


src/components/landing/BlockedToast.tsx

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


src/components/landing/CTASection.tsx

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


src/components/landing/HeroSection.tsx

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


이 코멘트는 Claude API를 통해 자동 생성되었습니다. 반드시 검토 후 사용하세요.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

PR 테스트 결과

Jest: 통과

🎉 모든 테스트를 통과했습니다!

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

PR 검증 결과

TypeScript: 통과
ESLint: 통과
Prettier: 통과
Build: 통과

🎉 모든 검증을 통과했습니다!

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

구현한 기능 Preview: https://weeth-hxxwew8zm-weethsite-4975s-projects.vercel.app

Copy link
Copy Markdown

@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: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/landing/ServiceSection.tsx (1)

59-81: ⚠️ Potential issue | 🟠 Major

첫 번째/마지막 비디오가 섹션 밖에서도 계속 재생됩니다.

autoPlay={i === 0} 때문에 이 섹션이 화면 밖에 있어도 첫 비디오가 바로 재생되고, ScrollTrigger에는 onLeave/onLeaveBack pause가 없어서 섹션을 벗어난 뒤에는 마지막 active 비디오가 계속 돕니다. 지금 구현은 “active 카드만 재생” 목표와 다르게 offscreen 재생이 남아 있어서, 진입 시에만 활성 카드 재생 + 이탈 시 전체 pause로 맞춰주는 게 좋겠습니다.

Also applies to: 174-186

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/landing/ServiceSection.tsx` around lines 59 - 81, The
first/last videos are autoplaying offscreen because of the autoPlay={i === 0}
prop and the ScrollTrigger only handles onUpdate; remove the JSX autoPlay
control (stop unconditional autoplay) and instead control playback via the
ScrollTrigger lifecycle: in the ScrollTrigger.create block (the one calling
ScrollTrigger.create / onUpdate / setActiveIndex / videoRefs), add onEnter and
onEnterBack handlers that play only the currently active video (use
setActiveIndex/index from onUpdate or compute index from self.progress) and add
onLeave and onLeaveBack handlers that pause all videos via
videoRefs.current.forEach(...); keep the existing onUpdate logic that plays the
new active index and pauses others, but ensure initial page load/play is only
triggered via onEnter so offscreen cards don’t auto-play.
🧹 Nitpick comments (5)
.gitignore (1)

37-48: 중복 ignore 규칙은 정리하는 편이 좋습니다.

Line 37의 .env*가 이미 Line 48의 .env.local을 포함하므로, Line 48은 제거해도 동작은 동일합니다.

정리 예시
- .env.local
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.gitignore around lines 37 - 48, Remove the redundant .env.local entry from
.gitignore because the existing broader rule `.env*` already covers it; locate
the `.env*` and `.env.local` lines and delete the `.env.local` line so the
ignore rules are deduplicated while preserving existing behavior.
src/components/landing/HeroSection.tsx (1)

4-7: 주석 처리된 CTA 관련 코드 정리를 권장합니다.

현재는 기능이 제거된 상태라 주석 import/JSX를 유지하기보다 제거하고, 필요 시 이슈 링크나 feature flag로 복구 경로를 남기는 편이 관리에 더 안전합니다.

Also applies to: 196-205

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/landing/HeroSection.tsx` around lines 4 - 7, Remove the
dead/commented CTA imports and JSX in HeroSection.tsx: delete the commented
imports (Link, Image, buttonVariants) at the top and remove the commented CTA
JSX block around lines where the CTA was rendered (the commented section noted
at ~196-205); if you want to keep a recovery path, replace the removed comments
with a single-line TODO referencing an issue ID or add a feature-flag reminder
(e.g., TODO: restore CTA when FEATURE_CTA enabled or link to issue) so the
codebase stays clean and reversible.
src/app/(public)/landing/page.tsx (1)

24-25: PublicHeader 의도를 코드에 명시해 두는 편이 좋습니다.

현재 TODO만 남아 있어 정책이 불명확해 보입니다. 숨김이 의도라면 showAuthButtons={false}를 명시하거나 TODO를 정리해 주세요.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/`(public)/landing/page.tsx around lines 24 - 25, The intent for
PublicHeader is unclear — either explicitly hide the auth buttons by passing the
prop (e.g., set showAuthButtons={false} on the PublicHeader component) or remove
the TODO and make the intended behavior explicit (e.g., document/show in a
comment or set showAuthButtons={true} if they should be visible); update the JSX
where PublicHeader is rendered to include the explicit prop so the policy is
clear.
src/components/landing/ServiceSection.tsx (2)

199-200: 새로 추가한 강조 색상은 토큰 클래스로 맞추는 편이 좋습니다.

text-[#000]는 이 PR에서 새로 들어온 하드코딩 색상이라 테마 변경 시 추적이 어렵습니다. 이미 text-brand-primary, text-text-* 토큰을 쓰고 있으니 같은 방식으로 통일해 주세요. As per coding guidelines src/**/*.{ts,tsx}: Always use design token classes first (text-, bg-, typo-, p-, gap-*) — no hardcoded values; ask before adding new tokens.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/landing/ServiceSection.tsx` around lines 199 - 200, The span
in ServiceSection rendering (around f.highlightKeyword) uses a hardcoded color
class text-[`#000`]; replace it with the appropriate design token class (e.g.,
text-brand-primary or one of the text-text-* tokens used elsewhere) so it
follows the project's token-first rule; update the JSX in ServiceSection (where
f.highlightKeyword is rendered) to use the chosen token class and ensure it
matches existing theme semantics rather than introducing a new hardcoded value.

14-21: cardTitle가 더 이상 렌더링되지 않아 타입과 실제 UI가 어긋납니다.

Feature에서는 아직 필수 필드인데 JSX는 description만 사용합니다. 현재처럼 둘 다 constants에서 계속 관리하면 어떤 문구가 실제 노출되는지 헷갈리기 쉬우니, 의도적으로 없앤 거면 타입/데이터에서 제거하고 아니라면 렌더링을 복원해 주세요.

Also applies to: 191-206

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/landing/ServiceSection.tsx` around lines 14 - 21, The Feature
interface declares cardTitle as required but the ServiceSection JSX only renders
description (so types and UI diverge); either restore rendering of cardTitle in
the component or remove cardTitle from the Feature type and from the feature
constants. Concretely: in ServiceSection (and the feature data constants
referenced around the other occurrence at 191-206) either add the cardTitle
element back into the mapped JSX where features are rendered (use the
Feature.cardTitle value with the same styling as before), or update the Feature
interface to make cardTitle optional and remove/adjust any cardTitle values in
the constants so types match rendered output; ensure you update both the Feature
type declaration and the feature constants used by the ServiceSection component.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/settings.json:
- Line 8: The OPENAPI_SPEC_PATH setting currently points to the Swagger UI HTML
page which causes MCP parsing to fail; update the OPENAPI_SPEC_PATH value (the
JSON key OPENAPI_SPEC_PATH in .claude/settings.json) to the actual OpenAPI JSON
endpoint (replace the current
"https://api-dev.v4.weeth.kr/swagger-ui/index.html#/" with
"https://api-dev.v4.weeth.kr/v3/api-docs") so openapi-mcp-server can fetch the
spec.

In @.claude/settings.local.json:
- Line 19: The path string "Bash(grep -r \"POSTHOG\\|PostHog\"
D:projectweeth-client/.env*)" is missing the path separator after the Windows
drive letter and will fail to find files; update the path segment to include the
separator (e.g., add a slash after "D:" like "D:/projectweeth-client/.env*" or
"D:\\projectweeth-client\\.env*") and ensure any backslashes are properly
escaped for JSON; replace the original string in .claude/settings.local.json
with the corrected, properly escaped path variant so the grep command can locate
the .env files.

In `@instrumentation-client.ts`:
- Around line 3-6: The code uses a non-null assertion on
process.env.NEXT_PUBLIC_POSTHOG_KEY when calling posthog.init which can crash at
runtime if the env var is missing; update the initialization in
instrumentation-client.ts to first check that NEXT_PUBLIC_POSTHOG_KEY (and
optionally NEXT_PUBLIC_POSTHOG_HOST) is defined and only call posthog.init when
present, otherwise skip initialization or log/throw a clear error; reference the
posthog.init call and the environment variables NEXT_PUBLIC_POSTHOG_KEY and
NEXT_PUBLIC_POSTHOG_HOST when making the guard so the fix is easy to locate.

In `@src/components/landing/CTASection.tsx`:
- Line 9: CTASection imports InquiryDialog via the barrel export
'@/components/landing', causing a circular dependency because CTASection itself
is exported from that barrel; change the import in CTASection.tsx to reference
InquiryDialog's direct file path (the component file that defines InquiryDialog)
instead of the barrel, e.g., replace import { InquiryDialog } from
'@/components/landing' with a relative import to the InquiryDialog module so the
module initialization order no longer depends on barrel export ordering.

In `@src/components/landing/InquiryDialog.tsx`:
- Around line 29-30: The current validation uses isValid = email.trim().length >
0 && message.trim().length > 0 which allows invalid emails and the labels aren’t
associated with inputs; change the component to use a proper <form> with a
submit handler (instead of manual button enable/disable), set the email input to
type="email" with required and an id, link its <label htmlFor="..."> to that id,
do the same for the message textarea (required + id + label htmlFor), and rely
on the browser’s built-in validation in the submit handler (preventDefault only
when needed and check form.checkValidity() or let the browser show errors);
update the isValid logic/remove it or use it only for non-blocking UI state, and
apply the same pattern to the other similar blocks mentioned (lines 37-43,
71-88, 99-105) so accessibility and email format validation are enforced.
- Around line 31-35: The dialog allows closing via multiple paths that bypass
the submission state, causing stale request results to surface; centralize all
close logic into a single handler (e.g., replace raw onOpenChange prop and any
individual close callbacks with a unified handleClose/handleRequestClose used by
Dialog, cancel/X buttons, and overlay/ESC) and inside that handler either
prevent closing when isSubmitting is true or cancel the in-flight request before
closing; update references to onOpenChange, the cancel/X button click handlers,
and any direct setEmail/setMessage resets to use this unified handler so all
close paths respect isSubmitting and properly reset state or abort the
submission.

In `@src/lib/apis/inquiry.ts`:
- Around line 10-11: create in src/lib/apis/inquiry.ts calls axios.post with
BASE_URL without validating it; add a guard at the start of the exported create
function (the create: (body: InquiryBody) => ...) to check that BASE_URL is a
non-empty string and throw a clear Error or return a rejected Promise if
missing, so callers fail fast instead of sending a malformed request; include
BASE_URL and a short context in the error message to aid debugging.

In `@src/proxy.ts`:
- Line 8: PRE_LAUNCH 상수가 true로 하드코딩되어 있어 운영 리스크가 큽니다; PRE_LAUNCH를 환경변수 기반으로 변경해
배포 없이 토글할 수 있도록 수정하세요: proxy.ts의 PRE_LAUNCH 선언을 제거하고 process.env 기반(예:
process.env.PRE_LAUNCH 또는 PRE_LAUNCH_MODE)으로 읽되 기본값을 안전한 값(false)으로 설정하고 문자열을
불리언으로 파싱하여 사용하세요; 또한 PRE_LAUNCH를 사용하는 함수/조건들이 새 env 기반 플래그를 참조하는지 확인하고 관련 문서나
.env 샘플을 업데이트하세요.
- Around line 13-19: The PRE_LAUNCH early-return currently redirects all
non-/landing requests before the whitelist check, preventing /kakao/* routes
from ever being reached; update the PRE_LAUNCH condition in the proxy middleware
to exclude the kakao path (e.g., add && !pathname.startsWith('/kakao/')) or move
the pathname.startsWith('/kakao/') check ahead of the PRE_LAUNCH block so that
the OAuth callback handlers (routes matched by pathname.startsWith('/kakao/'))
are allowed through before NextResponse.redirect is returned.

---

Outside diff comments:
In `@src/components/landing/ServiceSection.tsx`:
- Around line 59-81: The first/last videos are autoplaying offscreen because of
the autoPlay={i === 0} prop and the ScrollTrigger only handles onUpdate; remove
the JSX autoPlay control (stop unconditional autoplay) and instead control
playback via the ScrollTrigger lifecycle: in the ScrollTrigger.create block (the
one calling ScrollTrigger.create / onUpdate / setActiveIndex / videoRefs), add
onEnter and onEnterBack handlers that play only the currently active video (use
setActiveIndex/index from onUpdate or compute index from self.progress) and add
onLeave and onLeaveBack handlers that pause all videos via
videoRefs.current.forEach(...); keep the existing onUpdate logic that plays the
new active index and pauses others, but ensure initial page load/play is only
triggered via onEnter so offscreen cards don’t auto-play.

---

Nitpick comments:
In @.gitignore:
- Around line 37-48: Remove the redundant .env.local entry from .gitignore
because the existing broader rule `.env*` already covers it; locate the `.env*`
and `.env.local` lines and delete the `.env.local` line so the ignore rules are
deduplicated while preserving existing behavior.

In `@src/app/`(public)/landing/page.tsx:
- Around line 24-25: The intent for PublicHeader is unclear — either explicitly
hide the auth buttons by passing the prop (e.g., set showAuthButtons={false} on
the PublicHeader component) or remove the TODO and make the intended behavior
explicit (e.g., document/show in a comment or set showAuthButtons={true} if they
should be visible); update the JSX where PublicHeader is rendered to include the
explicit prop so the policy is clear.

In `@src/components/landing/HeroSection.tsx`:
- Around line 4-7: Remove the dead/commented CTA imports and JSX in
HeroSection.tsx: delete the commented imports (Link, Image, buttonVariants) at
the top and remove the commented CTA JSX block around lines where the CTA was
rendered (the commented section noted at ~196-205); if you want to keep a
recovery path, replace the removed comments with a single-line TODO referencing
an issue ID or add a feature-flag reminder (e.g., TODO: restore CTA when
FEATURE_CTA enabled or link to issue) so the codebase stays clean and
reversible.

In `@src/components/landing/ServiceSection.tsx`:
- Around line 199-200: The span in ServiceSection rendering (around
f.highlightKeyword) uses a hardcoded color class text-[`#000`]; replace it with
the appropriate design token class (e.g., text-brand-primary or one of the
text-text-* tokens used elsewhere) so it follows the project's token-first rule;
update the JSX in ServiceSection (where f.highlightKeyword is rendered) to use
the chosen token class and ensure it matches existing theme semantics rather
than introducing a new hardcoded value.
- Around line 14-21: The Feature interface declares cardTitle as required but
the ServiceSection JSX only renders description (so types and UI diverge);
either restore rendering of cardTitle in the component or remove cardTitle from
the Feature type and from the feature constants. Concretely: in ServiceSection
(and the feature data constants referenced around the other occurrence at
191-206) either add the cardTitle element back into the mapped JSX where
features are rendered (use the Feature.cardTitle value with the same styling as
before), or update the Feature interface to make cardTitle optional and
remove/adjust any cardTitle values in the constants so types match rendered
output; ensure you update both the Feature type declaration and the feature
constants used by the ServiceSection component.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 125914c6-bbae-4c37-ab3e-ba34af7b3028

📥 Commits

Reviewing files that changed from the base of the PR and between 51407c2 and da50486.

⛔ Files ignored due to path filters (16)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • public/videos/landing/admin_attendance.mp4 is excluded by !**/*.mp4
  • public/videos/landing/admin_board.mp4 is excluded by !**/*.mp4
  • public/videos/landing/admin_member.mp4 is excluded by !**/*.mp4
  • public/videos/landing/admin_schedule.mp4 is excluded by !**/*.mp4
  • public/videos/landing/user_board.mp4 is excluded by !**/*.mp4
  • public/videos/landing/user_home.mp4 is excluded by !**/*.mp4
  • src/assets/image/landing/card/landing_card_1.svg is excluded by !**/*.svg
  • src/assets/image/landing/card/landing_card_2.svg is excluded by !**/*.svg
  • src/assets/image/landing/card/landing_card_3.svg is excluded by !**/*.svg
  • src/assets/image/landing/card/landing_card_4.svg is excluded by !**/*.svg
  • src/assets/image/landing/card/landing_card_5.svg is excluded by !**/*.svg
  • src/assets/image/landing/card/landing_card_6.svg is excluded by !**/*.svg
  • src/assets/image/landing/card/landing_card_7.svg is excluded by !**/*.svg
  • src/assets/image/landing/card/landing_card_8.svg is excluded by !**/*.svg
  • src/assets/image/landing/card/landing_hero_card.svg is excluded by !**/*.svg
📒 Files selected for processing (20)
  • .claude/settings.json
  • .claude/settings.local.json
  • .gitignore
  • instrumentation-client.ts
  • package.json
  • src/app/(public)/landing/page.tsx
  • src/app/layout.tsx
  • src/assets/icons/index.ts
  • src/assets/image/landing/card/index.ts
  • src/components/landing/BlockedToast.tsx
  • src/components/landing/CTASection.tsx
  • src/components/landing/HeroSection.tsx
  • src/components/landing/InquiryDialog.tsx
  • src/components/landing/PhilosophySection.tsx
  • src/components/landing/ServiceSection.tsx
  • src/components/landing/index.ts
  • src/constants/landing/landing.ts
  • src/lib/apis/index.ts
  • src/lib/apis/inquiry.ts
  • src/proxy.ts

"API_BASE_URL": "https://13.124.170.169.nip.io",
"OPENAPI_SPEC_PATH": "https://13.124.170.169.nip.io/v3/api-docs"
"API_BASE_URL": "https://api-dev.v4.weeth.kr",
"OPENAPI_SPEC_PATH": "https://api-dev.v4.weeth.kr/swagger-ui/index.html#/"
Copy link
Copy Markdown

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:

#!/bin/bash
set -euo pipefail

UI_URL='https://api-dev.v4.weeth.kr/swagger-ui/index.html#/'
SPEC_URL='https://api-dev.v4.weeth.kr/v3/api-docs'

echo '[1] 현재 설정된 URL의 헤더(HTML 여부 확인)'
curl -sSI "$UI_URL" | sed -n '1,10p'

echo '[2] 현재 설정된 URL 바디 앞부분'
curl -sS "$UI_URL" | head -n 5

echo '[3] OpenAPI JSON 후보 URL 헤더'
curl -sSI "$SPEC_URL" | sed -n '1,10p'

echo '[4] OpenAPI JSON 핵심 키 확인(openapi/info/paths)'
curl -sS "$SPEC_URL" | python - <<'PY'
import json, sys
obj = json.load(sys.stdin)
print("has_openapi:", "openapi" in obj)
print("has_info:", "info" in obj)
print("has_paths:", "paths" in obj)
PY

Repository: Team-Weeth/weeth-client

Length of output: 1733


OPENAPI_SPEC_PATH가 Swagger UI HTML 페이지를 가리키고 있어 MCP 파싱이 실패합니다.

현재 설정(https://api-dev.v4.weeth.kr/swagger-ui/index.html#/)은 HTML 페이지를 반환하지만, openapi-mcp-server는 OpenAPI 스펙 문서(JSON)를 필요로 합니다.

올바른 스펙 엔드포인트인 https://api-dev.v4.weeth.kr/v3/api-docs로 변경하세요.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/settings.json at line 8, The OPENAPI_SPEC_PATH setting currently
points to the Swagger UI HTML page which causes MCP parsing to fail; update the
OPENAPI_SPEC_PATH value (the JSON key OPENAPI_SPEC_PATH in
.claude/settings.json) to the actual OpenAPI JSON endpoint (replace the current
"https://api-dev.v4.weeth.kr/swagger-ui/index.html#/" with
"https://api-dev.v4.weeth.kr/v3/api-docs") so openapi-mcp-server can fetch the
spec.

"Bash(find D:projectweeth-clientsrccomponentsui -type f \\\\\\(-name *.tsx -o -name *.ts \\\\\\))",
"Bash(find D:/project/weeth-client/src/constants -name *.ts)"
"Bash(find D:/project/weeth-client/src/constants -name *.ts)",
"Bash(grep -r \"POSTHOG\\\\|PostHog\" D:projectweeth-client/.env*)"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

경로 문자열 형식이 깨져 명령이 실패할 수 있습니다.

Line 19의 D:projectweeth-client/.env*는 드라이브 경로 구분자가 빠져 있어 대상 파일을 찾지 못할 가능성이 큽니다.

수정 예시
-      "Bash(grep -r \"POSTHOG\\\\|PostHog\" D:projectweeth-client/.env*)"
+      "Bash(grep -r \"POSTHOG\\\\|PostHog\" D:/project/weeth-client/.env*)"
📝 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
"Bash(grep -r \"POSTHOG\\\\|PostHog\" D:projectweeth-client/.env*)"
"Bash(grep -r \"POSTHOG\\\\|PostHog\" D:/project/weeth-client/.env*)"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/settings.local.json at line 19, The path string "Bash(grep -r
\"POSTHOG\\|PostHog\" D:projectweeth-client/.env*)" is missing the path
separator after the Windows drive letter and will fail to find files; update the
path segment to include the separator (e.g., add a slash after "D:" like
"D:/projectweeth-client/.env*" or "D:\\projectweeth-client\\.env*") and ensure
any backslashes are properly escaped for JSON; replace the original string in
.claude/settings.local.json with the corrected, properly escaped path variant so
the grep command can locate the .env files.

Comment on lines +10 to +11
create: (body: InquiryBody) =>
axios.post(`${BASE_URL}/api/v4/users/inquiries`, body),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

BASE_URL 미설정 케이스를 방어해야 합니다.

Line 11은 BASE_URL이 비어 있을 때 잘못된 URL로 요청이 나가므로, 호출 전에 명시적으로 검증해 실패를 빠르게 드러내는 것이 안전합니다.

방어 코드 예시
 export const inquiryApi = {
-  create: (body: InquiryBody) =>
-    axios.post(`${BASE_URL}/api/v4/users/inquiries`, body),
+  create: (body: InquiryBody) => {
+    if (!BASE_URL) {
+      throw new Error('NEXT_PUBLIC_API_URL is not set');
+    }
+    return axios.post(new URL('/api/v4/users/inquiries', BASE_URL).toString(), body);
+  },
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/apis/inquiry.ts` around lines 10 - 11, create in
src/lib/apis/inquiry.ts calls axios.post with BASE_URL without validating it;
add a guard at the start of the exported create function (the create: (body:
InquiryBody) => ...) to check that BASE_URL is a non-empty string and throw a
clear Error or return a rejected Promise if missing, so callers fail fast
instead of sending a malformed request; include BASE_URL and a short context in
the error message to aid debugging.

const PUBLIC_PATHS = ['/', '/login', '/terms', '/hub', '/landing'];

// TODO: 런칭 후 PRE_LAUNCH 플래그 및 관련 분기 제거
const PRE_LAUNCH = true;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

PRE_LAUNCH 하드코딩은 운영 차단 리스크가 큽니다.

현재 값이 true로 고정되어 있어 런칭 이후에도 전체 경로가 계속 막힐 수 있습니다. 환경변수 기반으로 전환해 배포 없이 제어 가능하게 두는 게 안전합니다.

🔧 제안 수정안
-const PRE_LAUNCH = true;
+const PRE_LAUNCH = process.env.PRE_LAUNCH === '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.

Suggested change
const PRE_LAUNCH = true;
const PRE_LAUNCH = process.env.PRE_LAUNCH === 'true';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/proxy.ts` at line 8, PRE_LAUNCH 상수가 true로 하드코딩되어 있어 운영 리스크가 큽니다;
PRE_LAUNCH를 환경변수 기반으로 변경해 배포 없이 토글할 수 있도록 수정하세요: proxy.ts의 PRE_LAUNCH 선언을 제거하고
process.env 기반(예: process.env.PRE_LAUNCH 또는 PRE_LAUNCH_MODE)으로 읽되 기본값을 안전한
값(false)으로 설정하고 문자열을 불리언으로 파싱하여 사용하세요; 또한 PRE_LAUNCH를 사용하는 함수/조건들이 새 env 기반 플래그를
참조하는지 확인하고 관련 문서나 .env 샘플을 업데이트하세요.

Comment on lines +13 to +19
// 런칭 전: /landing 외 모든 경로 차단
if (PRE_LAUNCH && pathname !== '/landing') {
const url = request.nextUrl.clone();
url.pathname = '/landing';
url.searchParams.set('blocked', 'true');
return NextResponse.redirect(url);
}
Copy link
Copy Markdown

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:

#!/bin/bash
set -euo pipefail

# pre-launch 차단 분기와 kakao allow 분기 위치 확인
rg -n "PRE_LAUNCH|pathname.startsWith\\('/kakao/'\\)" src/proxy.ts

# 실제 kakao oauth 라우트 존재 확인
fd -i "route.ts" src/app | rg -n "kakao/oauth/route.ts"

Repository: Team-Weeth/weeth-client

Length of output: 263


🏁 Script executed:

wc -l src/proxy.ts

Repository: Team-Weeth/weeth-client

Length of output: 82


🏁 Script executed:

cat -n src/proxy.ts

Repository: Team-Weeth/weeth-client

Length of output: 2704


PRE_LAUNCH 블록의 조기 반환으로 인해 /kakao/ 경로 허용-목록이 도달 불가능합니다.

Lines 14-19에서 PRE_LAUNCH && pathname !== '/landing' 조건이 참이면 즉시 반환되므로, Lines 50-53의 pathname.startsWith('/kakao/') 조건은 절대 실행되지 않습니다.

OAuth 콜백(예: /kakao/oauth)을 pre-launch 중에 허용하려면 다음 중 하나로 수정이 필요합니다:

  • Line 14 조건을 if (PRE_LAUNCH && pathname !== '/landing' && !pathname.startsWith('/kakao/')) 로 변경하거나
  • /kakao/ 체크를 PRE_LAUNCH 블록 이전으로 이동
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/proxy.ts` around lines 13 - 19, The PRE_LAUNCH early-return currently
redirects all non-/landing requests before the whitelist check, preventing
/kakao/* routes from ever being reached; update the PRE_LAUNCH condition in the
proxy middleware to exclude the kakao path (e.g., add &&
!pathname.startsWith('/kakao/')) or move the pathname.startsWith('/kakao/')
check ahead of the PRE_LAUNCH block so that the OAuth callback handlers (routes
matched by pathname.startsWith('/kakao/')) are allowed through before
NextResponse.redirect is returned.

Copy link
Copy Markdown
Collaborator

@JIN921 JIN921 left a comment

Choose a reason for hiding this comment

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

image 여기 스크롤시 축소 되는 효과가 사라진.. 거 같습니다.. 어디갓지..

그리고 캡션 부분 효과 이상한 거... 제 노트북으로 봣을 때는 또 멀쩡해서 냅둿는데 맥북으로 보니까 또 이상하네요..?? 머지 진짜ㅜ 아 그리구 description 안 보이는 게 어떤 건지 알려주실 수 잇으신가요..? 먼지 모르겟어요.....

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

이게 이렇게 기울어진 채로 추가돼서.. 제가 일단.. 구현을 햇어요... 예진님한테 이거 다시 받아서 교체하는 게 나을까요...!?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

비율을 90퍼로 해야 애니메이션이 보이네염

Copy link
Copy Markdown

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/landing/ServiceSection.tsx (1)

59-80: ⚠️ Potential issue | 🟠 Major

섹션 밖에서도 영상이 재생될 수 있으며, 섹션 이탈 시 계속 재생됩니다.

autoPlay={i === 0}로 인해 이 섹션이 viewport 아래에 있어도 첫 번째 영상이 DOM 렌더링되자마자 자동재생됩니다. 더 심각한 문제는 비디오 제어가 onUpdate 콜백에만 의존한다는 점입니다. 스크롤을 멈추면 콜백이 호출되지 않아 마지막 활성 영상이 계속 재생되며, 같은 인덱스에서도 play()가 반복 호출됩니다. 성능에 직접 영향을 미치는 부분이므로:

  1. autoPlay={i === 0} 제거
  2. ScrollTrigger의 onEnter/onLeave 콜백 추가 또는 Intersection Observer 활용하여 섹션 진입/이탈 시에만 비디오 상태를 동기화
관련 코드 구간
ScrollTrigger.create({
  // ...
  onUpdate: (self) => {
    const index = Math.round(self.progress * (features.length - 1));
    setActiveIndex(index);
    videoRefs.current.forEach((video, idx) => {
      if (!video) return;
      if (idx === index) {
        video.play();
      } else {
        video.pause();
      }
    });
  },
});
<video
  ref={(el) => {
    videoRefs.current[i] = el;
  }}
  src={f.video}
  autoPlay={i === 0}
  loop
  muted
  playsInline
  preload="metadata"
  className="h-full w-full object-cover"
/>

Also applies to: 174-185

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/landing/ServiceSection.tsx` around lines 59 - 80, Remove the
initial autoPlay prop from the video elements (remove autoPlay={i === 0}) and
stop relying solely on ScrollTrigger.create's onUpdate to control play/pause;
instead add ScrollTrigger callbacks (onEnter, onEnterBack, onLeave, onLeaveBack)
or an IntersectionObserver to synchronize video state only when the
section/slide actually enters or leaves the viewport: use the same
videoRefs.current array and setActiveIndex logic but invoke
video.play()/video.pause() in onEnter/onEnterBack (play the target index) and
onLeave/onLeaveBack (pause the leaving index) so videos won't auto-play when
off-screen and won't keep playing after scrolling stops; update any existing
onUpdate usage to only setActiveIndex (not repeatedly call play()) or remove
redundant play() calls there.
🧹 Nitpick comments (2)
src/components/landing/ServiceSection.tsx (2)

116-116: 새로 추가한 임의값 클래스는 토큰 클래스로 치환해 주세요.

이번 변경에서 min-h-[1227px], pt-[86px], pl-[306px], mb-[86px], w-[1123px], rounded-[30px], px-[93px], pt-[91px], text-[#909599], text-[#000] 같은 arbitrary value가 다시 들어왔습니다. 이 경로는 토큰 우선 규칙 대상이라 기존 spacing/text/bg 토큰으로 치환하거나, 없으면 토큰을 먼저 추가한 뒤 사용하는 쪽이 맞습니다. As per coding guidelines "Always use design token classes first (text-, bg-, typo-, p-, gap-*) — no hardcoded values; ask before adding new tokens".

Also applies to: 136-136, 170-171, 191-199

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/landing/ServiceSection.tsx` at line 116, The class string in
ServiceSection.tsx currently uses arbitrary value classes like min-h-[1227px],
pt-[86px], pl-[306px], mb-[86px], w-[1123px], rounded-[30px], px-[93px],
pt-[91px], text-[`#909599`], and text-[`#000`]; replace each arbitrary token in the
className (the sticky top-0 h-screen ... string and similar occurrences at the
referenced locations) with the appropriate design token utility
(spacing/text/bg/typo tokens) according to the token-first rule, and if a
matching token does not exist, add a new design token entry and then use that
token class instead of the hardcoded value (apply this fix to the className in
the component and the other occurrences mentioned).

14-21: Feature 타입이 현재 렌더링 규칙을 보장하지 못합니다.

지금 정의로는 imagevideo가 둘 다 optional이라 잘못된 데이터가 들어와도 Line 187-189처럼 빈 카드가 조용히 렌더링됩니다. 반대로 비디오 카드에서 쓰이지 않는 bgColor와 더 이상 렌더링하지 않는 cardTitle은 계속 필수라서 data contract도 어긋나 있습니다. export 중인 타입인 만큼 image | video를 강제하는 union으로 좁히고, 사용하지 않는 필드는 같이 정리해 두는 편이 안전합니다.

Also applies to: 171-189

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/landing/ServiceSection.tsx` around lines 14 - 21, The Feature
interface in ServiceSection.tsx should be replaced with a discriminated union to
guarantee either an image or a video and remove fields not used by the other
variant: define export type Feature = ImageFeature | VideoFeature where
ImageFeature = { kind: 'image'; image: StaticImageData; chipLabel: string;
cardTitle: string; description: string; bgColor: string; highlightKeyword?:
string } and VideoFeature = { kind: 'video'; video: string; chipLabel: string;
description: string; highlightKeyword?: string } (omit bgColor/cardTitle from
the video variant), then update the ServiceSection render/map logic that
consumes Feature (the part that previously rendered empty cards) to switch on
feature.kind and render the image card for kind==='image' and the video card for
kind==='video' so no empty cards can appear and the exported type contract
matches actual usage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/components/landing/ServiceSection.tsx`:
- Around line 59-80: Remove the initial autoPlay prop from the video elements
(remove autoPlay={i === 0}) and stop relying solely on ScrollTrigger.create's
onUpdate to control play/pause; instead add ScrollTrigger callbacks (onEnter,
onEnterBack, onLeave, onLeaveBack) or an IntersectionObserver to synchronize
video state only when the section/slide actually enters or leaves the viewport:
use the same videoRefs.current array and setActiveIndex logic but invoke
video.play()/video.pause() in onEnter/onEnterBack (play the target index) and
onLeave/onLeaveBack (pause the leaving index) so videos won't auto-play when
off-screen and won't keep playing after scrolling stops; update any existing
onUpdate usage to only setActiveIndex (not repeatedly call play()) or remove
redundant play() calls there.

---

Nitpick comments:
In `@src/components/landing/ServiceSection.tsx`:
- Line 116: The class string in ServiceSection.tsx currently uses arbitrary
value classes like min-h-[1227px], pt-[86px], pl-[306px], mb-[86px], w-[1123px],
rounded-[30px], px-[93px], pt-[91px], text-[`#909599`], and text-[`#000`]; replace
each arbitrary token in the className (the sticky top-0 h-screen ... string and
similar occurrences at the referenced locations) with the appropriate design
token utility (spacing/text/bg/typo tokens) according to the token-first rule,
and if a matching token does not exist, add a new design token entry and then
use that token class instead of the hardcoded value (apply this fix to the
className in the component and the other occurrences mentioned).
- Around line 14-21: The Feature interface in ServiceSection.tsx should be
replaced with a discriminated union to guarantee either an image or a video and
remove fields not used by the other variant: define export type Feature =
ImageFeature | VideoFeature where ImageFeature = { kind: 'image'; image:
StaticImageData; chipLabel: string; cardTitle: string; description: string;
bgColor: string; highlightKeyword?: string } and VideoFeature = { kind: 'video';
video: string; chipLabel: string; description: string; highlightKeyword?: string
} (omit bgColor/cardTitle from the video variant), then update the
ServiceSection render/map logic that consumes Feature (the part that previously
rendered empty cards) to switch on feature.kind and render the image card for
kind==='image' and the video card for kind==='video' so no empty cards can
appear and the exported type contract matches actual usage.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 60690d9a-6444-478c-bb02-088bf83aaddd

📥 Commits

Reviewing files that changed from the base of the PR and between da50486 and 4a1c7be.

📒 Files selected for processing (2)
  • src/components/landing/ServiceSection.tsx
  • src/lib/apis/inquiry.ts
✅ Files skipped from review due to trivial changes (1)
  • src/lib/apis/inquiry.ts

@nabbang6
Copy link
Copy Markdown
Collaborator Author

nabbang6 commented Apr 2, 2026

image 여기 스크롤시 축소 되는 효과가 사라진.. 거 같습니다.. 어디갓지..
그리고 캡션 부분 효과 이상한 거... 제 노트북으로 봣을 때는 또 멀쩡해서 냅둿는데 맥북으로 보니까 또 이상하네요..?? 머지 진짜ㅜ 아 그리구 description 안 보이는 게 어떤 건지 알려주실 수 잇으신가요..? 먼지 모르겟어요.....

제 화면에선 스크롤 시 축소/확대되는 효과 잘 적용되고 잇긴 한데... 머...머지... 한 번 확인해보겠습니다!

글고 description 쪽 문제는,, 서비스 섹션에서 각 카드마다 description이 아래 이미지처럼 존재하는데, 이게 뷰 포트 height를 벗어나는 위치에 잇어서 그런지 잘려서 보이지 않는 문제가 있습니다... 카드 + description 전부 한 화면에 노출하려면 카드 크기나 간격 조절이 필요할 것 같은데,,, 예진님께 함 여쭤볼게용.... ㅠ ㅠ

image

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

🤖 Claude 테스트 제안

모델: claude-sonnet-4-6 | 토큰: 0 입력 / 0 출력

변경된 컴포넌트에 대해 Claude가 생성한 테스트 코드입니다. 검토 후 적합한 부분만 사용하세요.

src/app/(public)/landing/page.tsx

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


src/app/layout.tsx

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


src/components/landing/BlockedToast.tsx

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


src/components/landing/CTASection.tsx

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


src/components/landing/HeroSection.tsx

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


이 코멘트는 Claude API를 통해 자동 생성되었습니다. 반드시 검토 후 사용하세요.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

PR 테스트 결과

Jest: 통과

🎉 모든 테스트를 통과했습니다!

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

PR 검증 결과

TypeScript: 통과
ESLint: 통과
Prettier: 실패
Build: 통과

⚠️ 일부 검증에 실패했습니다. 확인 후 수정해주세요.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

구현한 기능 Preview: https://weeth-65azwb7ha-weethsite-4975s-projects.vercel.app

Copy link
Copy Markdown
Member

@dalzzy dalzzy left a comment

Choose a reason for hiding this comment

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

수고하셨습니다!!!!! 당신은 최고의 프론트,,

스크롤 시 축소되는 건,, 저도 확인해봣는데 어쩔 때는 잘되고 어쩔때는 안되고 그러는 것 같아요.. 왜징

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Image

footer 쪽에 여백이 많이 생겨서 찾아보니 DialogContent는 고정 높이 + flex column 구조인데, 내부 form이 남는 높이를 차지하지 않아서 footer 아래 여백이 생기는 것 같네욤..

한번 확인 부탁드릴게요!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔨 Refactor 코드 리팩토링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants