stats.takjakim.kr 개발기 (4): 배포
stats.takjakim.kr 개발기 (4): 배포
Method 개발기 시리즈 (4/4)
| ← 이전: 개발 | 목차 |
개요

이 파트에서는 배포 및 운영을 다룹니다:
- Vercel 배포
- CI/CD 파이프라인
- 커스텀 도메인
- 모니터링
1. Vercel 배포
1.1 왜 Vercel인가?
| 기능 | Vercel | 다른 옵션 |
|---|---|---|
| Next.js 최적화 | 공식 지원 (만든 회사) | 추가 설정 필요 |
| 무료 티어 | 충분함 | 제한적 |
| 자동 CI/CD | Git push로 끝 | 별도 설정 |
| Edge Functions | 기본 지원 | 제한적 |
| Preview 배포 | PR마다 자동 | 수동 설정 |
1.2 배포 프로세스
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ Code │────▶│ Push │────▶│ Build │────▶│ Deploy │
│ Edit │ │ GitHub │ │ Vercel │ │ Edge │
└─────────┘ └─────────┘ └─────────┘ └─────────┘
│ │ │
│ │ ▼
│ │ ┌─────────┐
│ │ │ Live │
│ │ │ Site │
│ │ └─────────┘
│ │
│ ▼
│ ┌─────────┐
└────────▶│ Preview │ (PR 생성 시)
│ URL │
└─────────┘
1.3 초기 설정
# 1. Vercel CLI 설치
npm i -g vercel
# 2. 로그인
vercel login
# 3. 프로젝트 연결
vercel link
# 4. 환경변수 설정
vercel env add DATABASE_URL
vercel env add NEXTAUTH_SECRET
vercel env add GOOGLE_CLIENT_ID
vercel env add GOOGLE_CLIENT_SECRET
vercel env add NEXTAUTH_URL
# 5. 프로덕션 배포
vercel --prod
1.4 vercel.json 설정
{
"framework": "nextjs",
"regions": ["icn1"],
"functions": {
"app/api/**/*": {
"maxDuration": 30
}
},
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "X-Content-Type-Options",
"value": "nosniff"
},
{
"key": "X-Frame-Options",
"value": "DENY"
}
]
}
]
}
2. CI/CD 파이프라인
2.1 자동 배포 흐름
┌──────────────────────────────────────────────────────────────┐
│ GitHub Repository │
├──────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────────┐ │
│ │ main │──── push ────────────────────▶│ Production │ │
│ │ branch │ │ Deploy │ │
│ └─────────┘ └─────────────┘ │
│ ▲ │
│ │ merge │
│ ┌─────────┐ ┌─────────────┐ │
│ │ feature │──── PR 생성 ─────────────────▶│ Preview │ │
│ │ branch │ │ Deploy │ │
│ └─────────┘ └─────────────┘ │
│ │
└──────────────────────────────────────────────────────────────┘
2.2 브랜치 전략
| 브랜치 | 용도 | 배포 환경 |
|---|---|---|
main |
프로덕션 코드 | Production |
feature/* |
기능 개발 | Preview |
fix/* |
버그 수정 | Preview |
2.3 Preview 배포
PR 생성 시 자동으로 Preview URL 생성:
https://method-git-feature-login-takjakim.vercel.app
- PR 코멘트에 자동으로 URL 추가
- 코드 리뷰 시 실제 동작 확인 가능
- PR 닫으면 자동 삭제
3. 환경변수 관리
3.1 환경별 변수
| 환경 | 용도 | 설정 위치 |
|---|---|---|
| Development | 로컬 개발 | .env.local |
| Preview | PR 테스트 | Vercel Dashboard |
| Production | 실서비스 | Vercel Dashboard |
3.2 필수 환경변수
# Database (Supabase)
DATABASE_URL="postgresql://postgres:password@db.xxx.supabase.co:5432/postgres"
# NextAuth.js
NEXTAUTH_SECRET="your-secret-key-here"
NEXTAUTH_URL="https://stats.takjakim.kr"
# Google OAuth
GOOGLE_CLIENT_ID="xxx.apps.googleusercontent.com"
GOOGLE_CLIENT_SECRET="GOCSPX-xxx"
3.3 비밀값 관리
# Vercel CLI로 환경변수 추가 (암호화 저장)
vercel env add DATABASE_URL production
# 입력 프롬프트
? What's the value of DATABASE_URL? [hidden]
4. 커스텀 도메인
4.1 도메인 설정
┌──────────────────────────────────────────────────────────────┐
│ DNS 설정 │
├──────────────────────────────────────────────────────────────┤
│ │
│ stats.takjakim.kr ──── CNAME ────▶ cname.vercel-dns.com │
│ │
└──────────────────────────────────────────────────────────────┘
4.2 설정 단계
- Vercel Dashboard → Settings → Domains
-
stats.takjakim.kr입력 - DNS 레코드 안내 확인
-
도메인 레지스트라에서 CNAME 추가:
- Host:
stats - Value:
cname.vercel-dns.com
- Host:
- SSL 인증서 자동 발급 (Let’s Encrypt)
4.3 리다이렉트 설정
// next.config.js
module.exports = {
async redirects() {
return [
{
source: '/',
destination: '/ko',
permanent: false,
},
];
},
};
5. 모니터링
5.1 Vercel Analytics
┌──────────────────────────────────────────────────────────────┐
│ Vercel Analytics │
├──────────────────────────────────────────────────────────────┤
│ │
│ Page Views ████████████████████ 12,345 │
│ Unique Visitors ██████████████ 8,234 │
│ Bounce Rate ████████ 32% │
│ │
│ Top Pages: │
│ 1. /ko/learn/descriptive-statistics/mean 2,345 views │
│ 2. /ko 1,890 views │
│ 3. /ko/learn 1,456 views │
│ │
└──────────────────────────────────────────────────────────────┘
// app/layout.tsx
import { Analytics } from '@vercel/analytics/react';
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<Analytics />
</body>
</html>
);
}
5.2 Speed Insights
import { SpeedInsights } from '@vercel/speed-insights/next';
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<SpeedInsights />
</body>
</html>
);
}
5.3 Web Vitals
| 메트릭 | 타겟 | 현재 |
|---|---|---|
| LCP (Largest Contentful Paint) | < 2.5s | 1.8s |
| FID (First Input Delay) | < 100ms | 45ms |
| CLS (Cumulative Layout Shift) | < 0.1 | 0.05 |
| TTFB (Time to First Byte) | < 800ms | 320ms |
5.4 Error Tracking (예정)
// Sentry 설정 (예정)
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.SENTRY_DSN,
tracesSampleRate: 1.0,
});
6. 성능 최적화
6.1 이미지 최적화
import Image from 'next/image';
// 자동 최적화
<Image
src="/images/hero.png"
alt="Hero"
width={1200}
height={630}
priority // LCP 이미지
/>
6.2 폰트 최적화
// app/layout.tsx
import { Noto_Sans_KR } from 'next/font/google';
const notoSansKr = Noto_Sans_KR({
subsets: ['latin'],
weight: ['400', '500', '700'],
display: 'swap', // FOIT 방지
});
6.3 번들 분석
# 번들 사이즈 분석
ANALYZE=true npm run build
7. 배포 체크리스트
배포 전
-
npm run build성공 -
npm run lint경고 없음 - 환경변수 모두 설정
- 데이터베이스 마이그레이션 완료
배포 후
- 메인 페이지 로드 확인
- 로그인/로그아웃 동작 확인
- 레슨 페이지 Python 실행 확인
- 모바일 반응형 확인
- 진도 저장 동작 확인
결론 및 향후 계획
배운 점
- Vercel + Next.js: 배포가 놀라울 정도로 간단
- Preview 배포: PR 리뷰 효율 크게 향상
- Edge Functions: 한국 리전(icn1) 선택으로 지연시간 최소화
향후 계획
- Sentry 연동 - 에러 트래킹
- PWA - 오프라인 지원
- WebR - R 언어 지원
- AI 튜터 - Claude 연동
- 커뮤니티 - 댓글, 질문 기능
마무리
4개의 파트에 걸쳐 Method 프로젝트의 기획부터 배포까지 전 과정을 살펴보았습니다.
핵심 요약:
- 기획: 환경 설정 없이 바로 통계 실습
- 설계: Next.js 15 + Pyodide + Supabase
- 개발: InteractiveCode, MDX, 인증
- 배포: Vercel 자동 CI/CD
이 프로젝트가 통계를 배우는 분들께 도움이 되길 바랍니다.
Links
- Live: stats.takjakim.kr
- GitHub: github.com/takjakim/stat-method
- Developer: 김재현 (takjakim.kr)
| ← 이전: 개발 | 목차 |
2026년 2월 작성