Skip to content

[Refactor/#132] 온보딩 디자인 및 애니메이션 개선, AuthLayout 개선 - #136

Merged
Seojegyeong merged 20 commits into
developfrom
refactor/#132
Mar 26, 2026
Merged

[Refactor/#132] 온보딩 디자인 및 애니메이션 개선, AuthLayout 개선#136
Seojegyeong merged 20 commits into
developfrom
refactor/#132

Conversation

@Seojegyeong

@Seojegyeong Seojegyeong commented Mar 25, 2026

Copy link
Copy Markdown
Collaborator

🚨 관련 이슈

#132

✨ 변경사항

  • 🐞 BugFix Something isn't working
  • 💻 CrossBrowsing Browser compatibility
  • 🌏 Deploy Deploy
  • 🎨 Design Markup & styling
  • 📃 Docs Documentation writing and editing (README.md, etc.)
  • ✨ Feature Feature
  • 🔨 Refactor Code refactoring
  • ⚙️ Setting Development environment setup
  • ✅ Test Test related (storybook, jest, etc.)

✏️ 작업 내용

  1. 온보딩: 서비스명 추가 및 접근성 개선
  2. 디자인 시스템 / 공통 토큰 정리: 미사용 토큰 정리 및 카드 호버 공통 적요
  3. Auth / Signup 레이아웃: 중복 레이아웃 정의 제거 + 불필요한 패딩 제거
  4. 모달 & Drawer & 온보딩 애니메이션 개선 상세
  • Modal 닫힘 애니메이션 추가
  • Drawer easing 수정: 슬라이드 진입 시 빠르게 즉각적인 반응감 확보함
  • Button: active-scale 조건부 적용. 접근성 개선
  • 온보딩 슬라이드 전환 애니메이션: 슬라이드 페이드 속도 개선

😅 미완성 작업

N/A

📢 논의 사항 및 참고 사항

N/A

💬 리뷰어 가이드 (P-Rules)
P1: 필수 반영 (Critical) - 버그 가능성, 컨벤션 위반. 해결 전 머지 불가.
P2: 적극 권장 (Recommended) - 더 나은 대안 제시. 가급적 반영 권장.
P3: 제안 (Suggestion) - 아이디어 공유. 반영 여부는 드라이버 자율.
P4: 단순 확인/칭찬 (Nit) - 사소한 오타, 칭찬 등 피드백.

Summary by CodeRabbit

릴리스 노트

  • 스타일

    • 모달 닫힘 애니메이션이 부드러워졌습니다.
    • 온보딩 슬라이드가 더 빠르게 전환됩니다.
    • UI 컴포넌트의 섀도우와 라운드 처리가 개선되었습니다.
    • 애니메이션 타이밍과 전환 효과가 최적화되었습니다.
  • 버그 수정

    • 비활성화되거나 로딩 중인 버튼의 활성화 애니메이션이 제대로 작동합니다.

@Seojegyeong
Seojegyeong requested review from YermIm and jjjsun March 25, 2026 06:47
@Seojegyeong Seojegyeong self-assigned this Mar 25, 2026
@Seojegyeong Seojegyeong linked an issue Mar 25, 2026 that may be closed by this pull request
3 tasks
@coderabbitai

coderabbitai Bot commented Mar 25, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

인증·온보딩 관련 컴포넌트들의 full-screen 중앙정렬 래퍼를 제거하고 인트로 애니메이션·유틸 CSS를 정리했으며, 공통 UI 컴포넌트에 디자인 토큰 클래스와 모달 종료 애니메이션 지연 언마운트 로직을 도입했습니다.

Changes

Cohort / File(s) Summary
Auth flow 레이아웃 정리
src/components/auth/common/PasswordForm.tsx, src/components/auth/flows/find-email/..., src/components/auth/flows/reset-password/EmailVerificationStep.tsx, src/components/auth/flows/signup/..., src/components/auth/flows/signup/ProfileSetupStep.tsx
전체 화면(min-h-screen) 및 flex 중앙정렬 래퍼 제거; 내부 w-full max-w-130 px-6 pb-12 컨테이너를 최상위로 올려 컴포넌트 계층을 단순화. 로직(폼 제출/검증)은 변경 없음.
Intro / onboarding 애니메이션 및 마크업 조정
src/components/auth/intro/AiTalkBubble.tsx, src/components/auth/intro/IntroAIAnalytics.tsx, src/components/auth/intro/IntroAdManagement.tsx, src/components/auth/intro/IntroLogo.tsx, src/components/auth/intro/OnboardingIntro.tsx
인트로 전반 애니메이션 시간 단축 및 pointer-events-none 추가, 애니메이션 재생 제어(애니메이션 재생상태/paused), AiTalkBubble 삼각 포인터를 CSS → SVG로 변경, 일부 레이아웃/타이포그래피 조정.
Skeleton / 페이지 레이아웃 조정
src/components/auth/skeleton/*, src/pages/auth/Login.tsx, src/pages/auth/Signup.tsx
스켈레톤 및 페이지 컨테이너의 전체 화면 래퍼 제거, padding/width 조정(pt-30 pb-12py-12, max-w-90max-w-130 등), 일부 타이포그래피 경미 변경.
공통 컴포넌트 스타일 토큰화
src/components/common/button/Button.tsx, src/components/common/card/Card.tsx, src/components/common/card/StatCard.tsx, src/components/common/card/InfoCard.tsx, src/components/common/drawer/Drawer.tsx
하드코딩된 rounding/shadow 제거 후 rounded-component-lg, shadow-card, shadow-card-hover 등 디자인 토큰 클래스 적용. Button은 active-scale를 disabled/isLoading일 때 비활성화하도록 조건부 적용. Drawer 애니메이션 easing 조정(ease-in-out→ease-out).
Modal 종료 애니메이션 & 언마운트 분리
src/components/common/modal/Modal.tsx, src/index.css
isOpen 즉시 언마운트에서 shouldRender/isClosing 도입으로 닫힐 때 out 애니메이션 재생 후 언마운트(CLOSE_DURATION)하도록 변경. focus/scroll lock을 isVisible 기반으로 처리하고 out 애니메이션 클래스 추가. CSS에 모달 out keyframes/유틸 추가.
글로벌 CSS·유틸 업데이트
src/index.css
사용하지 않는 spacing 변수 제거, .transition-smooth/.transition-fast의 transition-property 명시화, .shadow-card/.shadow-card-hover 및 모달/슬라이드/버블 관련 애니메이션(keyframes·유틸) 추가, .animate-scroll 속도 단축(50s→30s), prefers-reduced-motion 보강.
레이아웃 조정
src/layout/auth/AuthLayout.tsx, src/layout/main/MainLayout.tsx, src/pages/dashboard/overview/OverviewDashboard.tsx
Auth onboarding 패널 너비 55%→45%, 오른쪽 컨텐츠를 scrollable로 변경(최상단 max-width 제거), MainLayout의 wrapper px-20px-lg(spacing token 변경), 버튼 폰트웨이트 조정.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant User as User
    participant Page as Page (opens Modal)
    participant Modal as Modal Component
    participant RemoveScroll as RemoveScroll (scroll lock)
    participant FocusMgr as Focus manager

    User->>Page: click open
    Page->>Modal: set isOpen = true
    Modal->>RemoveScroll: enabled = true (isVisible)
    Modal->>FocusMgr: set focus to modal
    Note right of Modal: Modal renders overlay + content\nwith "in" animation

    User->>Modal: click close / backdrop
    Modal->>Modal: set isOpen = false
    Modal->>Modal: isClosing = true (start CLOSE_DURATION)
    Modal->>RemoveScroll: keep enabled = true (isVisible)
    Modal->>Modal: apply animate-modal-*-out classes
    Note right of Modal: closing animation plays (~CLOSE_DURATION)

    Modal->>RemoveScroll: enabled = false (after closing)
    Modal->>FocusMgr: restore focus to previous element
    Modal->>Page: set shouldRender = false (unmount)
Loading

(시각 요소 애니메이션 클래스는 isVisible/isClosing 상태로 전환됨. 다채로운 박스는 애니메이션 상태 표시 목적.)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

🎨 Html&css, 🐞 BugFix

Suggested reviewers

  • YermIm
  • jjjsun
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.55% 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 제목이 주요 변경사항인 온보딩 디자인 및 애니메이션 개선, AuthLayout 개선을 명확하게 요약하고 있으며, 관련 이슈 번호(#132)도 포함되어 있어 변경 의도가 명확합니다.
Description check ✅ Passed PR 설명이 템플릿을 따르고 있으며, 관련 이슈, 변경사항(BugFix와 Refactor 체크), 상세한 작업 내용 4가지, 미완성 작업 상태를 모두 명확하게 기술하고 있습니다.

✏️ 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 refactor/#132

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

github-actions Bot commented Mar 25, 2026

Copy link
Copy Markdown

📚 Storybook 배포 완료

항목 링크
📖 Storybook https://69a147b60a56365d9e2185ef-bcyeowtkjv.chromatic.com/
🔍 Chromatic https://www.chromatic.com/build?appId=69a147b60a56365d9e2185ef&number=152

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🧹 Nitpick comments (1)
src/components/auth/flows/signup/ProfileSetupStep.tsx (1)

97-115: 동의 영역 클릭 처리에 키보드 접근성을 보강하는 게 좋겠습니다.

현재 onClickdiv에 걸려 있어서 “전체 행 클릭” 인터랙션은 포인터 중심입니다. 전체 영역을 액션 영역으로 유지하려면 role="button", tabIndex, onKeyDown(Enter/Space)를 추가하거나, 클릭 책임을 실제 button으로 모으는 쪽이 더 안전합니다.

As per coding guidelines, src/**: 7. 접근성: 시맨틱 HTML, ARIA 속성 사용 확인.

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

In `@src/components/auth/flows/signup/ProfileSetupStep.tsx` around lines 97 - 115,
The clickable consent row uses a non-semantic div with an onClick handler; make
it keyboard-accessible by replacing the div with a semantic button (preserve the
className and onClick) or, if you must keep a div, add role="button",
tabIndex={0} and an onKeyDown handler that triggers the same logic on
Enter/Space; ensure type="button" when using a button and keep the existing
modal-opening logic that calls openModal(MODAL_TYPES.PRIVACY) and uses
watch("terms")/watch("marketing") and setValue("marketing")/setValue("terms",
..., { shouldValidate:true }) so keyboard activation behaves identically to
pointer activation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/auth/flows/find-email/EnterPhoneStep.tsx`:
- Around line 164-178: The verification input and submit path allow calling
verifySMSMutate before a code was sent; update EnterPhoneStep.tsx to disable the
code field and block submission until sendCode is true: make the CommonAuthInput
disabled when !sendCode (in addition to existing isExpired logic) and add a
guard at the start of the onSubmit handler (e.g., if (!sendCode) return or show
a user-facing message) so verifySMSMutate is only invoked after a code was
actually sent; ensure references include the sendCode flag, the CommonAuthInput
usage (register("code")), and the verifySMSMutate call in onSubmit.

In `@src/components/auth/flows/signup/EnterEmailStep.tsx`:
- Around line 77-87: The disabled logic for the verification input in
EnterEmailStep.tsx is too permissive (disabled={isExpired}), allowing typing
before a code is sent; update the CommonAuthInput disabled prop to match the
other flow by using disabled={!sendCode || isExpired} so the field is disabled
until sendCode is true or when the timer expires—locate the CommonAuthInput
invocation where register("code") is spread and change the disabled expression
accordingly to keep behavior consistent with EmailVerificationStep.

In `@src/components/auth/intro/IntroAdManagement.tsx`:
- Line 29: The carousel currently duplicates PLATFORMS only twice (const
CAROUSEL_ITEMS = [...PLATFORMS, ...PLATFORMS]) which can make the looping
boundary visible when the track is shorter than the container; change this to
dynamically build CAROUSEL_ITEMS inside the IntroAdManagement component: measure
the carousel container width (or use window.innerWidth) and an item width, then
append PLATFORMS repeatedly until the computed track width exceeds the container
width plus a safety buffer (or at least twice the container width) to avoid gaps
at translateX(-50%); implement this logic in a useEffect and store the result in
state (e.g., carouselItems state) instead of a module-level const so it runs
client-side and reflows correctly.

In `@src/components/auth/intro/IntroAIAnalytics.tsx`:
- Around line 83-93: The inline transition styles on the bubble in
IntroAIAnalytics.tsx (the element using className with showBubble) prevent the
existing prefers-reduced-motion CSS from disabling animations; move the inline
style block (transitionProperty, transitionDuration, transitionTimingFunction)
into a named CSS utility/class (e.g., .ai-analytics-bubble-transition) defined
in your global CSS where the existing prefers-reduced-motion rule can override
it (set transition: none inside the media query). Then remove the inline style
and add that utility class to the element’s className so the showBubble toggles
still control visibility via classes but reduced-motion users get transitions
suppressed by CSS.

In `@src/components/auth/intro/IntroLogo.tsx`:
- Around line 6-8: The IntroLogo component's root element uses only visual
hiding (opacity/pointer-events) so screen readers still expose inactive panel
content; update the root element (the element with the className string that
uses isActive) to add aria-hidden={!isActive} so the accessibility tree is
updated when isActive is false; locate the className usage in the IntroLogo
component and add the aria-hidden attribute bound to the isActive prop.

In `@src/components/auth/intro/OnboardingIntro.tsx`:
- Around line 41-43: The indicator's width change (w-8 ↔ w-2.5) in
OnboardingIntro.tsx is not being animated because the current transition class
(transition-smooth) does not include width; update the indicator element's
className (the element that uses getIndicatorColor(index)) to use a transition
that covers width (e.g., replace or extend transition-smooth with a utility that
includes width like transition-all or a custom transition-width class) or adjust
the transition-smooth definition to include width so the width change from
getIndicatorColor is animated smoothly.

In `@src/components/common/modal/Modal.tsx`:
- Around line 43-59: The close animation currently keeps DOM via shouldRender
but still releases focus and RemoveScroll because those side effects depend only
on isOpen; change effects that control scroll lock/RemoveScroll and focus
restoration to use the combined rendering state (isOpen || isClosing) instead of
isOpen so they remain active during the CLOSE_DURATION; keep the existing
useEffect that toggles shouldRender/isClosing (with CLOSE_DURATION) to delay
unmounting, and update any focus-restore effect and RemoveScroll usage to read
(isOpen || isClosing) so focus/scroll are only released after the closing
animation completes.

In `@src/layout/main/MainLayout.tsx`:
- Line 27: The div in MainLayout.tsx uses the CSS token class "px-component-xl"
which appears missing from the theme, causing horizontal padding to be lost;
update the code by either (A) replacing "px-component-xl" in the className on
the div inside MainLayout.tsx with an existing, defined padding token (e.g.,
"px-component" or another valid token from your theme), or (B) add a matching
"component-xl" padding token to your theme/CSS (src/index.css `@theme`) so the
"px-component-xl" utility is generated—ensure the class name in MainLayout.tsx
and the token name in src/index.css match exactly.

In `@src/pages/auth/Login.tsx`:
- Around line 76-79: The login button currently allows duplicate submissions;
wire the useLogin.isPending state into the Button in Login.tsx so that when
useLogin.isPending is true the Button is disabled and shows a loading indicator,
and ensure the form's submit handler (e.g., the function using useLogin or
handleSubmit) respects that state to prevent re-entry; update the Button props
(disabled and a loading/aria-busy flag or variant) to reflect useLogin.isPending
and guard the submit handler to return early if isPending.

---

Nitpick comments:
In `@src/components/auth/flows/signup/ProfileSetupStep.tsx`:
- Around line 97-115: The clickable consent row uses a non-semantic div with an
onClick handler; make it keyboard-accessible by replacing the div with a
semantic button (preserve the className and onClick) or, if you must keep a div,
add role="button", tabIndex={0} and an onKeyDown handler that triggers the same
logic on Enter/Space; ensure type="button" when using a button and keep the
existing modal-opening logic that calls openModal(MODAL_TYPES.PRIVACY) and uses
watch("terms")/watch("marketing") and setValue("marketing")/setValue("terms",
..., { shouldValidate:true }) so keyboard activation behaves identically to
pointer activation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9c57ad1b-6e94-4a42-a800-5c8b09431912

📥 Commits

Reviewing files that changed from the base of the PR and between 3e90ee3 and efc623b.

⛔ Files ignored due to path filters (2)
  • .gitignore is excluded by none and included by none
  • ai-button-preview.html is excluded by none and included by none
📒 Files selected for processing (26)
  • src/components/auth/common/PasswordForm.tsx
  • src/components/auth/flows/find-email/EnterPhoneStep.tsx
  • src/components/auth/flows/find-email/ShowEmailResultStep.tsx
  • src/components/auth/flows/reset-password/EmailVerificationStep.tsx
  • src/components/auth/flows/signup/EnterEmailStep.tsx
  • src/components/auth/flows/signup/ProfileSetupStep.tsx
  • src/components/auth/intro/AiTalkBubble.tsx
  • src/components/auth/intro/IntroAIAnalytics.tsx
  • src/components/auth/intro/IntroAdManagement.tsx
  • src/components/auth/intro/IntroLogo.tsx
  • src/components/auth/intro/OnboardingIntro.tsx
  • src/components/auth/skeleton/LoginPageSkeleton.tsx
  • src/components/auth/skeleton/SignupEmailStepSkeleton.tsx
  • src/components/auth/skeleton/SignupPageSkeleton.tsx
  • src/components/common/button/Button.tsx
  • src/components/common/card/Card.tsx
  • src/components/common/card/InfoCard.tsx
  • src/components/common/card/StatCard.tsx
  • src/components/common/drawer/Drawer.tsx
  • src/components/common/modal/Modal.tsx
  • src/index.css
  • src/layout/auth/AuthLayout.tsx
  • src/layout/main/MainLayout.tsx
  • src/pages/auth/Login.tsx
  • src/pages/auth/Signup.tsx
  • src/pages/dashboard/overview/OverviewDashboard.tsx
💤 Files with no reviewable changes (1)
  • src/components/common/card/InfoCard.tsx

Comment thread src/components/auth/flows/find-email/EnterPhoneStep.tsx
Comment thread src/components/auth/flows/signup/EnterEmailStep.tsx
Comment thread src/components/auth/intro/IntroAdManagement.tsx
Comment thread src/components/auth/intro/IntroAIAnalytics.tsx Outdated
Comment thread src/components/auth/intro/IntroLogo.tsx
Comment thread src/components/auth/intro/OnboardingIntro.tsx Outdated
Comment thread src/components/common/modal/Modal.tsx
Comment thread src/layout/main/MainLayout.tsx Outdated
Comment thread src/pages/auth/Login.tsx

@jjjsun jjjsun left a comment

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.

P4: 확인했습니다! 고생하셨어요!

@YermIm

YermIm commented Mar 25, 2026

Copy link
Copy Markdown
Collaborator

P4: 확인했습니다 수고하셨습니다!!

@YermIm

YermIm commented Mar 25, 2026

Copy link
Copy Markdown
Collaborator

P3: 패딩이 사라진 것 같은데 확인 부탁드립니다!
스크린샷 2026-03-26 오전 2 21 22

@Seojegyeong Seojegyeong added the 🔨 Refactor 코드 리팩토링 label Mar 26, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/auth/intro/IntroAIAnalytics.tsx`:
- Around line 32-35: The slide wrapper in IntroAIAnalytics (the div using
isActive to toggle classes) only hides visually and via pointer-events but is
still exposed to assistive tech; update the div that uses isActive to also set
aria-hidden={!isActive} (or aria-hidden={isActive ? "false" : "true"} if JSX
string values are preferred) so inactive slides are hidden from screen readers,
and ensure any interactive children are not focusable when isActive is false
(e.g., rely on existing pointer-events-none/opacity logic plus aria-hidden to
prevent duplicate announcements).

In `@src/components/common/modal/Modal.tsx`:
- Around line 43-45: The focus effect runs too early because isVisible becomes
true before the modal DOM mounts (shouldRender is still false), causing
modalRef.current to be null and focus to remain on the background; also the
first effect triggers close logic when isOpen is false. Fix by changing the
render/focus logic so focus is applied only after the modal is actually mounted:
ensure shouldRender is set to true immediately when isOpen becomes true (so the
DOM mounts before the focus effect runs) and move/guard the focus-setting effect
to run when shouldRender && modalRef.current are truthy (instead of just
isVisible), and also guard the closing effect so it only runs when transitioning
from open→closed (e.g., check previous isOpen or isClosing) to avoid unnecessary
close logic; update references in Modal.tsx to the shouldRender, isClosing,
isVisible states and modalRef so the focus and close effects run at the correct
times.

In `@src/index.css`:
- Around line 487-500: The reduced-motion override is being trumped by the later
default animation; move the `@media` (prefers-reduced-motion: reduce) block that
defines the reduced keyframes and the .animate-fade-in-up rule (and/or the
`@keyframes` fade-in-up-reduced) so it appears after the default `@keyframes`
fade-in-up and the default .animate-fade-in-up definition in the file; ensure
the media-query contains the .animate-fade-in-up rule that uses
fade-in-up-reduced so the reduced-motion preference takes precedence.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6e36bbbe-7cec-4c39-b071-cceb205d6816

📥 Commits

Reviewing files that changed from the base of the PR and between efc623b and 20639f9.

📒 Files selected for processing (8)
  • src/components/auth/flows/find-email/EnterPhoneStep.tsx
  • src/components/auth/flows/signup/EnterEmailStep.tsx
  • src/components/auth/intro/IntroAIAnalytics.tsx
  • src/components/auth/intro/IntroLogo.tsx
  • src/components/auth/intro/OnboardingIntro.tsx
  • src/components/common/modal/Modal.tsx
  • src/index.css
  • src/layout/main/MainLayout.tsx
✅ Files skipped from review due to trivial changes (2)
  • src/components/auth/intro/OnboardingIntro.tsx
  • src/layout/main/MainLayout.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/components/auth/intro/IntroLogo.tsx
  • src/components/auth/flows/find-email/EnterPhoneStep.tsx
  • src/components/auth/flows/signup/EnterEmailStep.tsx

Comment thread src/components/auth/intro/IntroAIAnalytics.tsx
Comment thread src/components/common/modal/Modal.tsx
Comment thread src/index.css
@Seojegyeong
Seojegyeong merged commit 8174c7f into develop Mar 26, 2026
3 checks passed
@Seojegyeong
Seojegyeong deleted the refactor/#132 branch March 26, 2026 05:51
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.

♻️ [Refactor] OnboardingIntro 디자인 개선

3 participants