Go to file
Mina Choi d22ef5eadc build(docker): .env 을 build context 에 포함
서버에 .env 만들어도 .dockerignore 의 .env* 패턴에 막혀 빌드에 안 들어가던 문제 해결.
.env.local 같은 개인 파일은 여전히 제외.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 13:06:33 +09:00
e2e test: Playwright e2e 셋업 + test-prefill-flow 스펙 2026-05-20 11:51:32 +09:00
public/fonts chore: 프론트엔드 마이그레이션 + 아키텍처 정의 2026-05-13 11:38:07 +09:00
src feat(dev): VITE_ENABLE_DEV_ROUTES 로 비-로컬호스트에서도 /dev/*·/test 허용 2026-05-20 11:59:32 +09:00
.dockerignore build(docker): .env 을 build context 에 포함 2026-05-20 13:06:33 +09:00
.env.example feat(dev): VITE_ENABLE_DEV_ROUTES 로 비-로컬호스트에서도 /dev/*·/test 허용 2026-05-20 11:59:32 +09:00
.gitignore test: Playwright e2e 셋업 + test-prefill-flow 스펙 2026-05-20 11:51:32 +09:00
Dockerfile build(docker): VITE_ENABLE_DEV_ROUTES 빌드 ARG 기본 true 로 주입 2026-05-20 13:03:51 +09:00
Dockerfile.dev chore: 프론트엔드 마이그레이션 + 아키텍처 정의 2026-05-13 11:38:07 +09:00
README.md chore: 프론트엔드 마이그레이션 + 아키텍처 정의 2026-05-13 11:38:07 +09:00
components.json chore: 프론트엔드 마이그레이션 + 아키텍처 정의 2026-05-13 11:38:07 +09:00
docker-compose.yml chore: 프론트엔드 마이그레이션 + 아키텍처 정의 2026-05-13 11:38:07 +09:00
index.html chore: 프론트엔드 마이그레이션 + 아키텍처 정의 2026-05-13 11:38:07 +09:00
nginx.conf chore: 프론트엔드 마이그레이션 + 아키텍처 정의 2026-05-13 11:38:07 +09:00
orval.config.ts feat: 백엔드 신스키마 (PlanOutput / 신규 analysis 라우트) 반영 + 화면·환경 적응 2026-05-18 15:19:48 +09:00
package-lock.json test: Playwright e2e 셋업 + test-prefill-flow 스펙 2026-05-20 11:51:32 +09:00
package.json test: Playwright e2e 셋업 + test-prefill-flow 스펙 2026-05-20 11:51:32 +09:00
playwright.config.ts test: Playwright e2e 셋업 + test-prefill-flow 스펙 2026-05-20 11:51:32 +09:00
tsconfig.json feat: 클리닉 전용 페이지 추가, PageContainer 도입, 불필요한 ui 주석처리 2026-05-14 11:53:29 +09:00
vite.config.ts fix: orval mutator의 import.meta cjs 경고 제거 2026-05-18 09:55:37 +09:00

README.md

o2o-infinith-frontend

INFINITH 마케팅 분석 플랫폼의 프론트엔드. React 19 + Vite + Tailwind v4 + TanStack Query.

기술 스펙

영역 라이브러리 / 도구 비고
언어 TypeScript ~5.8
빌드 Vite 6 @vitejs/plugin-react
UI 프레임워크 React 19
스타일 Tailwind CSS v4 CSS-first 방식 (config 파일 없음)
컴포넌트 shadcn/ui Radix + Tailwind 조합, src/shared/ui/ 에 복사해 사용
아이콘 lucide-react, 커스텀 (src/shared/icons/)
애니메이션 motion (Framer Motion 후속), tw-animate-css
라우팅 react-router 7
데이터 페칭 TanStack Query 5
HTTP 클라이언트 ky customFetcher 의 베이스
API SDK 생성 orval 7 OpenAPI → React Query 훅
클라이언트 상태 zustand 5
PDF 출력 jspdf, html2canvas-pro
폰트 Pretendard Variable (self-host), Playfair Display

시작하기

로컬 (Node)

npm install
npm run dev        # localhost:3000
npm run build      # 프로덕션 빌드
npm run lint       # tsc --noEmit
npm run api:gen    # SDK 재생성 (orval)

Docker (개발)

Dockerfile.dev + docker-compose.yml — Vite dev 서버를 컨테이너에서 돌리고 호스트 소스 변경을 HMR로 반영.

docker compose up           # 시작
docker compose up --build   # 의존성 바뀐 경우
docker compose down         # 종료

프로젝트 구조

src/
├── app/              # 라우터 / 프로바이더 / 진입점 셋업
├── config/           # 앱 전역 설정
├── features/         # 도메인별 모듈 (페이지 + 훅 + 컴포넌트 + 데이터)
│   ├── admin/        # 관리자 (API 대시보드 등)
│   ├── auth/         # 인증
│   ├── channels/     # 채널 검증 / enrichment
│   ├── clinics/      # 병원 프로필
│   ├── dev/          # 개발용 페이지
│   ├── distribution/ # 콘텐츠 배포
│   ├── landing/      # 랜딩
│   ├── performance/  # 성과 대시보드
│   ├── plan/         # 마케팅 플랜
│   ├── pricing/      # 요금제
│   ├── report/       # 분석 리포트 (로딩/뷰어)
│   └── studio/       # 콘텐츠 스튜디오
├── shared/
│   ├── api/          # orval-generated SDK + HTTP 어댑터
│   │   ├── api.ts        # customFetcher (ky 기반 mutator)
│   │   ├── generated/    # ⚠️ orval 자동생성 (직접 수정 금지)
│   │   └── model/        # ⚠️ orval 자동생성 타입
│   ├── constants/    # 전역 상수
│   ├── hooks/        # 범용 훅
│   ├── icons/        # 커스텀 아이콘
│   ├── layouts/      # 공통 레이아웃
│   ├── lib/          # 유틸 헬퍼
│   ├── types/        # 공통 타입
│   ├── ui/           # shadcn 기반 공용 컴포넌트
│   └── utils/        # 유틸 함수
├── styles/
│   └── index.css     # ★ Tailwind + 디자인 토큰 (브랜드 색 / 폰트 / radius)
└── assets/           # 정적 자산 (폰트, 이미지 등)

기능 모듈 내부 컨벤션:

features/<name>/
├── pages/        # 라우트에 매핑되는 페이지 컴포넌트
├── components/   # 해당 기능 전용 컴포넌트
├── hooks/        # 기능 전용 훅 (use<Feature>.ts)
├── lib/          # transform / parser 등 순수 로직
├── data/         # mock / 시드 상수
├── types/        # 기능 전용 타입
└── routes.tsx    # 라우트 정의

디자인 토큰

전부 src/styles/index.css에서 관리. Tailwind v4의 CSS-first 방식이라 별도 tailwind.config.js 파일이 없다.

블록 위치 용도
:root { --brand-* } 상단 브랜드 색 원본 (purple / navy / rose / earth …)
:root { --status-* } 중간 semantic 상태 색 (critical / warning / good / info)
:root { --background, --primary, … } shadcn 영역 shadcn 토큰 → 브랜드 색 매핑
.dark { … } 다크모드 다크 모드 오버라이드
@theme inline { --color-*, --font-* } 하단 Tailwind 유틸리티로 노출 (bg-brand-purple, text-status-critical-text 등)

새 색을 만들고 싶다면 :root--brand-xxx 추가 → @theme inline--color-brand-xxx: var(--brand-xxx) 추가 → bg-brand-xxx 유틸로 사용.

tailwind.config.js 가 없나요? Tailwind v4 부터 설정을 JS 파일이 아닌 CSS의 @theme 블록에서 한다. 폰트, 색, radius, breakpoint 같은 모든 토큰을 src/styles/index.css 하나에서 관리한다.

커스텀 클래스 / CSS

위치 내용
src/styles/custom.css 커스텀 유틸 클래스(.text-gradient, .glass-card, .gradient-bg, .soft-gradient) + @keyframes + 애니메이션 유틸(.animate-blob, .animation-delay-*)
src/styles/index.css @layer base 전역 element 스타일 (body, h1~h6 등)

새 유틸 클래스는 custom.css 에 추가. 컴포넌트 단위 스타일은 Tailwind 유틸리티로 JSX에서 직접 작성하는 게 기본.

폰트 변경

Google Fonts로 가져오는 방식. 두 곳만 수정하면 된다.

  1. index.html — Google Fonts <link>family= 파라미터에 원하는 폰트 추가/교체
    <link href="https://fonts.googleapis.com/css2?family=원하는폰트:wght@400;700&display=swap" rel="stylesheet">
    
  2. src/styles/index.css@theme inline 에서 --font-sans (본문) 또는 --font-serif (제목) 의 첫 항목을 새 폰트 이름으로 교체

백엔드 API / orval

OpenAPI 스펙을 가져와 SDK(React Query 훅 포함)를 자동생성한다.

  • 입력: orval.config.tsinput 필드 (예: http://localhost:8001/openapi.json)
  • 출력: src/shared/api/generated/ (함수 + 훅) + src/shared/api/model/ (타입)
  • HTTP 어댑터: src/shared/api/api.ts — ky 기반 customFetcher. 4xx/5xx도 throw하지 않고 { status, data, headers }로 반환.

사용 예

// 쿼리 훅
import { useGetReport } from '@/shared/api/generated/reports/reports'
const { data, isLoading } = useGetReport(id, { query: { enabled: !!id } })

// 뮤테이션 훅
import { useStartAnalysis } from '@/shared/api/generated/analyses/analyses'
const { mutateAsync } = useStartAnalysis()
await mutateAsync({ data: { url: '...' } })

// imperative 호출(폴링 등)
import { getAnalysisStatus } from '@/shared/api/generated/analyses/analyses'
const res = await getAnalysisStatus(runId)

재생성

백엔드 스펙이 바뀌면:

npm run api:gen

clean: truegenerated/, model/ 폴더는 매번 비워지고 새로 생성된다. 직접 수정 금지.

API 프록시 (개발)

vite.config.ts 에서 /api/* 요청을 백엔드로 프록시한다.

  • 기본 타겟: http://localhost:8001
  • 도커 안에서 dev 서버 돌 때: http://host.docker.internal:8001 (CHOKIDAR_USEPOLLING=true 일 때 자동)
  • 오버라이드: VITE_API_TARGET=http://40.82.133.44:8001 환경변수

shadcn/ui

ui.shadcn.com 컴포넌트는 패키지가 아니라 소스 복사 방식으로 사용한다. 추가/수정한 컴포넌트는 src/shared/ui/ 에 위치하며, Tailwind 토큰(--background, --primary 등)을 통해 디자인 시스템과 연결된다.

새 컴포넌트 추가:

npx shadcn@latest add button