다크 모드
Invite (Next.js)
truloop-web-invite는 모임 초대 및 비회원 등록을 위한 웹 애플리케이션입니다. 사용자가 초대 링크를 통해 모임 정보를 확인하고, 앱 설치 없이 비회원으로 참여할 수 있습니다.
핵심 기능
- 초대장 렌더링: 모임 정보(일시, 장소, 참여자, 사진) 표시
- 비회원 등록: 비회원이 이름, 전화번호, 가능한 날짜를 입력하여 참여
- 전화번호 인증: SMS OTP 기반 본인 인증
- 다국어 지원: 한국어, 영어, 일본어
- 앱 딥링크: Branch SDK를 통한 앱 연동
기술 스택
핵심 프레임워크
| 기술 | 버전 | 용도 |
|---|---|---|
| Next.js | 16.1.1 | React 프레임워크 (App Router) |
| React | 19.2.3 | UI 라이브러리 |
| TypeScript | 5 | 타입 안전성 (strict 모드) |
| Tailwind CSS | 4 | 유틸리티 우선 스타일링 |
UI 컴포넌트
| 라이브러리 | 용도 |
|---|---|
| shadcn/ui (base-vega 스타일) | 재사용 가능한 UI 컴포넌트 (Button, Input, Card, Calendar 등) |
| @base-ui/react | shadcn의 Base UI 구현체 |
| Lucide React | 아이콘 라이브러리 |
| class-variance-authority (CVA) | 컴포넌트 variant 정의 |
| clsx + tailwind-merge | 조건부 className 조합 (cn() 유틸리티) |
기능별 라이브러리
| 라이브러리 | 용도 |
|---|---|
| next-intl | 다국어 처리 (i18n) |
| Framer Motion | 애니메이션 (슬라이드 전환, AnimatePresence) |
| libphonenumber-js | 국제 전화번호 파싱/검증 |
| date-fns | 날짜 유틸리티 |
| react-day-picker | 달력 컴포넌트 |
| react-markdown | 마크다운 렌더링 (MarkdownViewer 컴포넌트) |
| DOMPurify | HTML 콘텐츠 XSS sanitization |
| tw-animate-css | Tailwind CSS 애니메이션 |
개발 도구
| 도구 | 용도 |
|---|---|
| pnpm | 패키지 매니저 |
| ESLint | 코드 린팅 |
| @tailwindcss/postcss | Tailwind CSS 빌드 |
프로젝트 구조
truloop-web-invite/
├── app/ # Next.js App Router
│ ├── layout.tsx # 루트 레이아웃 (폰트, NextIntlProvider)
│ ├── page.tsx # 루트 페이지
│ ├── globals.css # Tailwind + OKLch CSS 변수
│ ├── [token]/ # 동적 초대 페이지
│ │ ├── page.tsx # 메인 초대 페이지 (SSR)
│ │ └── guest/page.tsx # 비회원 페이지 (→ [token]으로 리다이렉트)
│ └── api/
│ ├── proxy/[...path]/ # CORS 프록시 (브라우저 → API)
│ └── branch/link/ # Branch 딥링크 생성
├── components/
│ ├── ui/ # shadcn/ui 컴포넌트
│ │ ├── button.tsx
│ │ ├── input.tsx
│ │ ├── phone-input.tsx # 국가 선택 + 전화번호 입력
│ │ ├── otp-input.tsx # OTP 인증번호 입력
│ │ ├── calendar.tsx
│ │ ├── card.tsx
│ │ ├── markdown-viewer.tsx # 마크다운 렌더러 (react-markdown)
│ │ ├── scroll-reveal.tsx # 스크롤 노출 애니메이션
│ │ └── ... # alert-dialog, badge, combobox, select 등
│ └── invite/ # 초대 페이지 전용 컴포넌트
│ ├── hero-section.tsx # 커버 이미지 + 호스트 정보
│ ├── tab-navigation.tsx # 탭 내비게이션
│ ├── notice-card.tsx # 공지 카드
│ ├── place-card.tsx # 장소 정보 (지도)
│ ├── photos-gallery.tsx # 사진 갤러리
│ ├── description-section.tsx # 룹 설명 렌더링 (마크다운/HTML 자동 감지, XSS 방어, 트렁케이션)
│ ├── comments-preview.tsx # 댓글 미리보기
│ ├── stories-preview.tsx # 리캡 미리보기
│ ├── members-section.tsx # 참여자 목록
│ ├── guest-registration-card.tsx # 비회원 등록 카드 (상태 분기 + 폼 래핑)
│ ├── guest-registration-form.tsx # 비회원 등록 폼 (멀티스텝)
│ ├── guest-registration-link.tsx # 비회원 등록 링크
│ ├── guest-registration-wrapper.tsx # 비회원 등록 래퍼
│ ├── verification-step.tsx # SMS 인증 단계
│ ├── top-banner.tsx # 앱 다운로드 배너
│ └── error-card.tsx # 에러 표시
├── hooks/
│ ├── use-phone-verification.ts # SMS 인증 상태 관리
│ └── use-parallax.ts # 패럴렉스 스크롤 효과
├── lib/
│ ├── api.ts # API 클라이언트 + 타입 정의
│ ├── utils.ts # cn() = clsx + tailwind-merge
│ ├── paths.ts # basePath 헬퍼 함수
│ ├── guest-storage.ts # localStorage 비회원 데이터 캐싱
│ ├── date-utils.ts # 날짜 범위 파싱/포맷
│ ├── countries.ts # 지원 국가 (KR, US, JP)
│ ├── locale-utils.ts # 로케일 유틸리티
│ └── branch.ts # Branch SDK 연동
├── i18n/
│ ├── config.ts # 로케일 설정 (en, ko, ja)
│ └── request.ts # 요청별 로케일 감지
├── messages/
│ ├── en.json # 영어 번역
│ ├── ko.json # 한국어 번역
│ └── ja.json # 일본어 번역
├── openspec/ # OpenAPI 스펙 관리
│ ├── config.yaml # 스펙 설정
│ ├── specs/ # API 스펙 파일
│ └── changes/ # 스펙 변경 로그
├── middleware.ts # Accept-Language → locale 쿠키
├── next.config.ts # Next.js 설정 (basePath: /invite)
├── components.json # shadcn/ui 설정
└── tsconfig.json # TypeScript 설정주요 설정
basePath
next.config.ts에서 basePath: '/invite'로 설정되어 있어 모든 경로가 /invite 접두사를 가집니다. URL 생성 시 반드시 lib/paths.ts의 헬퍼 함수를 사용해야 합니다.
typescript
import { apiPath, assetPath, canonicalUrl } from '@/lib/paths';이미지 최적화
Next.js Image 컴포넌트에서 외부 이미지를 사용하기 위해 다음 도메인이 허용되어 있습니다.
*.amazonaws.com(S3)*.cloudfront.net(CDN)maps.googleapis.com(Google Maps)media.truloop.app(미디어 CDN)assets.truloop.app(에셋 CDN)
개발 환경
bash
# 의존성 설치
pnpm install
# 개발 서버 (localhost:3000)
pnpm dev
# 프로덕션 빌드
pnpm build
# ESLint 실행
pnpm lint주의
타입 체크는 별도의 tsc --noEmit 대신 pnpm build로 수행합니다. Vercel 빌드 환경과 동일한 결과를 보장하기 위함입니다.
변경 이력
| 날짜 | 내용 |
|---|---|
| 2026-03-16 | react-markdown, DOMPurify 라이브러리 추가. markdown-viewer.tsx, description-section.tsx 프로젝트 구조 반영 |
| 2026-03-10 | 소스 코드 검증: Next.js/React 버전 정밀화, 프로젝트 구조에 openspec/, guest-registration-link/wrapper, scroll-reveal 등 누락 항목 추가 |