๐ Next.js ์ฌํ 10์ฅ: Deployment & Infrastructure โ Vercel vs Docker vs Node.js ์๋ฒ
๐ ๊ฐ์
Vercel, Docker, Node.js ์๋ฒ ๊ฐ ๋ฐฐํฌ ๋ฐฉ์์ ์ฐจ์ด์ ์ธํ๋ผ ์ค๊ณ ๊ธฐ์ค์ ์์๋ด ๋๋ค.
๐ ๋ชฉ์ฐจ
- ๐ ์ด ๋ฌธ์๋ฅผ ์ฝ๊ธฐ ์ ์
- ๐ค ์ ์์์ผ ํ๋๊ฐ
- ๐๏ธ ๋น์ ๋ก ๋จผ์ ์ดํดํ๊ธฐ
- ๐งฉ ์ธ ๊ฐ์ง ๋ฐฐํฌ ์ ๋ต ๋น๊ต ๐ข
- ๐ Vercel ๋ฐฐํฌ โ ์ ๋ก ์ค์ ์ ๋ง๋ฒ ๐ก
- ๐ณ Docker ์ปจํ ์ด๋ ๋ฐฐํฌ โ ์ํฐํ๋ผ์ด์ฆ ํ์ค ๐ก
- ๐ฅ๏ธ Node.js ์๋ฒ ์ง์ ๋ฐฐํฌ ๐ก
- โ๏ธ ํ๊ฒฝ ๋ณ์์ ๋น๋ฐํค ๊ด๋ฆฌ ๐ด
- ๐ฅ ์๋ฌ ํด๊ฒฐ ์นดํ๋ก๊ทธ
- ๐ ์ด๋ฒ์ ๋ฐฐ์ด ๋ด์ฉ ์ด์ ๋ฆฌ
- ๐ ๋ง๋ฌด๋ฆฌ ํด์ฆ
- ๐ ๋ ์์๋ณด๊ธฐ
๐ ์ด ๋ฌธ์๋ฅผ ์ฝ๊ธฐ ์ ์
โฑ๏ธ ์์ ์ฝ๊ธฐ ์๊ฐ: 18๋ถ (์ ์ฒด) / ํต์ฌ ํํธ๋ง: 9๋ถ
๐บ๏ธ ์ด ๋ฌธ์์ ๋ฐฐ๊ฒฝ ์ธ๊ณ๊ด: '์์๋ค ์ปค๋ฎค๋ํฐ'
- ์์(PM): "์ด์ ์๋น์ค๋ฅผ ์ค์ ๋ก ๋ฐฐํฌํด์ผ ํด์. Vercel๋ก ๋น ๋ฅด๊ฒ ๋๊ฐ์ผ ํ๋์, ์๋๋ฉด ํ์ฌ ์๋ฒ(AWS EC2)์ Docker๋ก ์ฌ๋ ค์ผ ํ๋์? ์ฐจ์ด๊ฐ ๋ญ์ง ์๊ณ ๊ฒฐ์ ํ๊ณ ์ถ์ด์."
- ์ํธ(๋ฆฌ๋): "ํ ๊ท๋ชจ, ๋น์ฉ, ๊ธฐ์ ์ฑ์๋์ ๋ฐ๋ผ ๋ฌ๋ผ์. ์คํํธ์ ์ด๊ธฐ๋ผ๋ฉด Vercel์ด ์ต์ ์ด์์. ISR, Edge Functions, ํ๋ฆฌ๋ทฐ ๋ฐฐํฌ๊ฐ ๊ธฐ๋ณธ์ด๊ณ ์ธํ๋ผ ๊ฑฑ์ ์ ์์ ์ ํด๋ ๋๊ฑฐ๋ ์. ๋ฐ๋ฉด ๊ธฐ์ ๋ด๋ถ ์๋ฒ๋ ํน์ ๊ท์ (์ปดํ๋ผ์ด์ธ์ค)์ด ์์ผ๋ฉด Docker๋ก ์์ฒด ์๋ฒ์ ์ฌ๋ ค์ผ ํด์."
๐บ๏ธ ์ด ๋ฌธ์์ ํ๋ฆ
์ธ ๊ฐ์ง ์ ๋ต ๋น๊ต โ Vercel ๋ฐฐํฌ ์ค์ โ Docker ์ต์ Dockerfile โ Node.js ์๋ฒ ์ง์ ๋ฐฐํฌ โ ํ๊ฒฝ ๋ณ์ ๊ด๋ฆฌ
๐ฏ ์ด ๋ฌธ์๋ฅผ ๋ค ์ฝ์ผ๋ฉด ํ ์ ์๋ ๊ฒ
- ํ๊ณผ ์๋น์ค ์ํฉ์ ๋ง๋ ๋ฐฐํฌ ์ ๋ต์ ์ ํํ ์ ์๋ค
- Next.js ์ฑ์ ์ํ ์ต์ ํ๋
Dockerfile์ ์์ฑํ ์ ์๋ค - ๋น๋ฐํค๋ฅผ ์์ ํ๊ฒ ๊ด๋ฆฌํ๋ ํ๊ฒฝ ๋ณ์ ์์น์ ์งํฌ ์ ์๋ค
๐ค ์ ์์์ผ ํ๋๊ฐ
๋ก์ปฌ์์ ์ ๋์ํ๋ ์ฝ๋๊ฐ ๋ฐฐํฌ ํ ๊ฐ์๊ธฐ ์ ๋์ํ๊ฑฐ๋, ์๋ฒ ๋น์ฉ์ด ์์๋ณด๋ค 10๋ฐฐ ๋์ค๊ฑฐ๋, ํ๊ฒฝ ๋ณ์๊ฐ ํด๋ผ์ด์ธํธ์ ๋ ธ์ถ๋๋ ์ฌ๊ณ โ ๋ฐฐํฌ๋ฅผ ๋ชจ๋ฅด๋ฉด ์ด๋ฐ ์ผ์ด ์๊ฒจ.
๋ฐฐํฌ๋ "์ด๋ค ์ธํ๋ผ์์ ์ด๋ป๊ฒ ์คํํ ๊ฒ์ธ๊ฐ"์ ๋ํ ์ํคํ ์ฒ ๊ฒฐ์ ์ด์ผ. ์ฝ๋ฉ๋งํผ ์ค์ํ ์ ํ์ด์ผ.
๐๏ธ ๋น์ ๋ก ๋จผ์ ์ดํดํ๊ธฐ
๐ง 5์ด์๊ฒ ์ค๋ช ํ๋ค๋ฉด?
์์ ๋ฐฐ๋ฌ ๋ฐฉ์์ ๋น์ ํด๋ด:
- Vercel = ๋ฐฐ๋ฌ์๋ฏผ์กฑ ์ ์ . ์ฃผ๋ฐฉ๋ง ์์ผ๋ฉด ๋๊ณ , ๋ฐฐ๋ฌยท๊ฒฐ์ ยท๊ด๊ณ ๋ ํ๋ซํผ์ด ๋ค ํด์ค. ๋น ๋ฅธ ๋์ ์์๋ฃ(๋น์ฉ)๊ฐ ์๊ณ , ํ๋ซํผ ๊ท์น์ ๋ฐ๋ผ์ผ ํด.
- Docker = ์์์ ์ง์ ์ด์ + ๋ฐฐ๋ฌ ํธ๋ญ ๋ณด์ . ๋ชจ๋ ๊ฑธ ์ง์ ๊ด๋ฆฌํด์ผ ํ์ง๋ง ์์ ๋๊ฐ ์ต๊ณ ์ผ.
- Node.js ์ง์ ๋ฐฐํฌ = ์์์ ์ง์ ์ด์์ธ๋ฐ ๋ฐฐ๋ฌ ํธ๋ญ์ ์ธ๋๊ธฐ. Docker๋ณด๋ค ์กฐ๊ธ ๋ ๋จ์ํ์ง๋ง ๊ด๋ฆฌํ ๊ฒ ์ฌ์ ํ ๋ง์.
๐งฉ ์ธ ๊ฐ์ง ๋ฐฐํฌ ์ ๋ต ๋น๊ต ๐ข
๐ฏ ์ด ์น์ ์ ์ฝ๊ณ ๋๋ฉด:
- ์ธ ๊ฐ์ง ๋ฐฐํฌ ์ ๋ต์ ์ฅ๋จ์ ์ ์ ํํ ์๊ณ ์ํฉ์ ๋ง๋ ์ ํ์ ํ ์ ์๋ค
| ๊ธฐ์ค | Vercel | Docker (K8s ํฌํจ) | Node.js ์๋ฒ ์ง์ |
|---|---|---|---|
| ์ค์ ๋ณต์ก๋ | โญ ๊ฑฐ์ ์์ | ๐ด ๋์ | ๐ก ์ค๊ฐ |
| ๋น์ฉ ์์ธก์ฑ | ๐ก ํธ๋ํฝ ๋ฐ๋ผ ๋ณ๋ | โ ์์ธก ๊ฐ๋ฅ | โ ์์ธก ๊ฐ๋ฅ |
| ISR / Edge ์ง์ | โ ์๋ฒฝ ์ง์ | ๐ก ์ค์ ํ์ | ๐ก ์ ํ์ |
| ์์ฒด ์๋ฒ ํตํฉ | โ ์ด๋ ค์ | โ ์๋ฒฝ ํตํฉ | โ ๊ฐ๋ฅ |
| ์ปดํ๋ผ์ด์ธ์ค | ๐ก ๋ฐ์ดํฐ ๋ฏธ๊ตญ ์๋ฒ | โ ์์ฒด ์๋ฒ ์์ ์ ์ด | โ ์์ฒด ์ ์ด |
| ๊ฐ์ฅ ์ ํฉํ ์ํฉ | ์คํํธ์ , ์ฌ์ด๋ ํ๋ก์ ํธ, ๋น ๋ฅธ ์ถ์ | ๊ธฐ์ , ๋ง์ดํฌ๋ก์๋น์ค, ๊ณ ๊ฐ์ฉ์ฑ | ๊ธฐ์กด VM ๋ณด์ , ์ค์ ๊ท๋ชจ |
2026๋ ๊ธฐ์ค ์ ํ ๊ฐ์ด๋:
ํ ๊ท๋ชจ ์ + ๋น ๋ฅธ ์ถ์ + ๋น์ฉ ์ต์ํ โ Vercel
๋ฐ์ดํฐ ๊ตญ๋ด ์๋ฒ ํ์ + ๊ธฐ์
๋ณด์ ๊ท์ โ Docker (์ฌ๋ด K8s)
๊ธฐ์กด VM ๋ณด์ + ๋จ์ ๋ฐฐํฌ + ์์ธก ๋น์ฉ โ Node.js ์ง์ ๋ฐฐํฌ
๐ Vercel ๋ฐฐํฌ โ ์ ๋ก ์ค์ ์ ๋ง๋ฒ ๐ก
๐ฏ ์ด ์น์ ์ ์ฝ๊ณ ๋๋ฉด:
- Vercel์์ ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํ๊ณ ์ปค์คํ ๋๋ฉ์ธ์ ์ฐ๊ฒฐํ ์ ์๋ค
vercel.json์ผ๋ก ๋ฆฌ๋ค์ด๋ ํธ์ ํค๋๋ฅผ ์ค์ ํ ์ ์๋ค
Vercel ๋ฐฐํฌ ๊ณผ์ :
# 1. Vercel CLI ์ค์น
npm i -g vercel
# 2. ํ๋ก์ ํธ ์ฐ๊ฒฐ ๋ฐ ๋ฐฐํฌ
vercel
# 3. ํ๋ก๋์
๋ฐฐํฌ
vercel --prod๋๋ GitHub ์ฐ๋์ผ๋ก pushํ ๋๋ง๋ค ์๋ ๋ฐฐํฌ (๊ถ์ฅ).
vercel.json ์ค์ :
{
"framework": "nextjs",
"buildCommand": "npm run build",
"devCommand": "npm run dev",
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "X-Frame-Options", "value": "DENY" },
{ "key": "X-Content-Type-Options", "value": "nosniff" },
{ "key": "Strict-Transport-Security", "value": "max-age=31536000; includeSubDomains" }
]
}
],
"redirects": [
{ "source": "/old-blog/(.*)", "destination": "/posts/$1", "permanent": true }
]
}Vercel ํ๊ฒฝ ๋ณ์ ์ค์ :
Vercel Dashboard โ ํ๋ก์ ํธ โ Settings โ Environment Variables
๊ฐ๋ฐ: DATABASE_URL=postgresql://localhost:5432/dev
ํ๋ฆฌ๋ทฐ: DATABASE_URL=postgresql://preview-server/preview
ํ๋ก๋์
: DATABASE_URL=postgresql://prod-server/prod
โ ๏ธ NEXT_PUBLIC_ ์ ๋์ฌ๊ฐ ๋ถ์ ๋ณ์๋ง ํด๋ผ์ด์ธํธ์ ๋
ธ์ถ๋จ!
Vercel์ ํน๋ณ ๊ธฐ๋ฅ:
โ
Preview URL: PR๋ง๋ค ๊ณ ์ ํ ๋ฏธ๋ฆฌ๋ณด๊ธฐ URL ์๋ ์์ฑ
- https://my-app-pr-123-team.vercel.app
โ
ISR ์ง์: revalidate ์ค์ ์ฆ์ ๋์
โ
Edge Functions: middleware๊ฐ Vercel Edge์์ ์๋ ์คํ
โ
Analytics: Core Web Vitals ์ค์ ์ฌ์ฉ์ ๋ฐ์ดํฐ ์๋ ์์ง
๐ณ Docker ์ปจํ ์ด๋ ๋ฐฐํฌ โ ์ํฐํ๋ผ์ด์ฆ ํ์ค ๐ก
๐ฏ ์ด ์น์ ์ ์ฝ๊ณ ๋๋ฉด:
- Next.js ์ฑ์ ์ํ ์ต์ ํ๋ ๋ฉํฐ ์คํ ์ด์ง Dockerfile์ ์์ฑํ ์ ์๋ค
- ์ด๋ฏธ์ง ํฌ๊ธฐ๋ฅผ ์ต์ํํ๋ ๋น๋ ํจํด์ ์ ์ฉํ ์ ์๋ค
Next.js ๊ณต์ ๊ถ์ฅ ๋ฉํฐ ์คํ ์ด์ง Dockerfile:
# Dockerfile
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Stage 1: ์์กด์ฑ ์ค์น
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
FROM node:20-alpine AS deps
WORKDIR /app
# package.json๊ณผ lock ํ์ผ๋ง ๋จผ์ ๋ณต์ฌ (๋ ์ด์ด ์บ์ฑ ์ต์ ํ)
COPY package.json package-lock.json ./
RUN npm ci --only=production
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Stage 2: ๋น๋
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
FROM node:20-alpine AS builder
WORKDIR /app
# ๋น๋์ ํ์ํ ์ ์ฒด ์์กด์ฑ ์ค์น (devDependencies ํฌํจ)
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
# ๋น๋ ํ์ ํ๊ฒฝ ๋ณ์
ARG NEXT_PUBLIC_API_URL
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
# standalone ๋ชจ๋๋ก ๋น๋ (์๋ฒ์ ํ์ํ ํ์ผ๋ง ์ถ๋ ฅ)
RUN npm run build
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Stage 3: ์คํ ์ด๋ฏธ์ง (์ต์ ํฌ๊ธฐ)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
# ๋ณด์: ๋ฃจํธ ๊ถํ์ผ๋ก ์คํํ์ง ์๊ธฐ
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# standalone ๋น๋ ๊ฒฐ๊ณผ๋ฌผ๋ง ๋ณต์ฌ (์ต์ ํ์ผ)
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]// next.config.ts โ standalone ๋ชจ๋ ํ์ฑํ (Docker ํ์ ์ค์ )
const nextConfig = {
output: 'standalone', // ์๋ฒ์ ํ์ํ ์ต์ ํ์ผ๋ง .next/standalone์ ์ถ๋ ฅ
}# docker-compose.yml โ ๋ก์ปฌ ๊ฐ๋ฐ/์คํ
์ด์ง์ฉ
services:
app:
build:
context: .
args:
NEXT_PUBLIC_API_URL: https://api.youngsu.community
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://postgres:password@db:5432/youngsu
- SESSION_SECRET=your-secret-key-here
depends_on:
- db
db:
image: postgres:16
environment:
POSTGRES_DB: youngsu
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:# ์ด๋ฏธ์ง ๋น๋ ๋ฐ ์คํ
docker build -t youngsu-community .
docker run -p 3000:3000 --env-file .env.production youngsu-community
# ๋๋ compose๋ก
docker-compose up -d๐ฅ๏ธ Node.js ์๋ฒ ์ง์ ๋ฐฐํฌ ๐ก
๊ธฐ์กด EC2, NCP ๊ฐ์ VM์ ์ง์ ๋ฐฐํฌํ๋ ๋ฐฉ๋ฒ์ด์ผ.
# server.sh โ ์๋ฒ ๋ฐฐํฌ ์คํฌ๋ฆฝํธ
#!/bin/bash
set -e
echo "๐ฆ ์์กด์ฑ ์ค์น..."
npm ci
echo "๐จ ๋น๋..."
npm run build
echo "๐ ์๋ฒ ์ฌ์์ (PM2 ์ฌ์ฉ)..."
pm2 restart youngsu-community || pm2 start npm --name youngsu-community -- start
echo "โ
๋ฐฐํฌ ์๋ฃ!"// ecosystem.config.js โ PM2 ์ค์
module.exports = {
apps: [
{
name: 'youngsu-community',
script: 'npm',
args: 'start',
instances: 'max', // CPU ์ฝ์ด ์๋งํผ ํ๋ก์ธ์ค ์คํ
exec_mode: 'cluster',
env: {
NODE_ENV: 'production',
PORT: 3000,
},
},
],
}โ๏ธ ํ๊ฒฝ ๋ณ์์ ๋น๋ฐํค ๊ด๋ฆฌ ๐ด
๐ฏ ์ด ์น์ ์ ์ฝ๊ณ ๋๋ฉด:
NEXT_PUBLIC_์ ๋์ฌ์ ์๋ฏธ์ ์ํ์ฑ์ ์ดํดํ๋ค- ๋น๋ฐํค๊ฐ ํด๋ผ์ด์ธํธ ๋ฒ๋ค์ ํฌํจ๋๋ ์ฌ๊ณ ๋ฅผ ๋ฐฉ์งํ๋ ๊ท์น์ ์๋ค
๐ค ์ ๊น, ๋จผ์ ์๊ฐํด๋ด
NEXT_PUBLIC_DATABASE_URL=postgresql://...์ด๋ผ๊ณ ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํ๋ฉด ์ด๋ค ์ผ์ด ์๊ธธ๊น?
ํ๊ฒฝ ๋ณ์์ ๋ ์ข ๋ฅ:
NEXT_PUBLIC_ ์ ๋์ฌ ์์ โ ํด๋ผ์ด์ธํธ(๋ธ๋ผ์ฐ์ ) ๋ฒ๋ค์ ํฌํจ
โ ๋๊ตฌ๋ DevTools์์ ๋ณผ ์ ์์ โ ๏ธ
NEXT_PUBLIC_ ์ ๋์ฌ ์์ โ ์๋ฒ์์๋ง ์ ๊ทผ ๊ฐ๋ฅ
โ ๋ธ๋ผ์ฐ์ ์ ์ ๋ ๋
ธ์ถ ์ ๋จ โ
# .env.local (๋ก์ปฌ ์ ์ฉ โ .gitignore์ ๋ฐ๋์ ํฌํจ!)
DATABASE_URL=postgresql://localhost:5432/dev # ์๋ฒ ์ ์ฉ โ
SESSION_SECRET=dev-secret-key # ์๋ฒ ์ ์ฉ โ
NEXT_PUBLIC_API_URL=http://localhost:3000 # ํด๋ผ์ด์ธํธ ์ ๊ทผ ๊ฐ๋ฅ (๊ณต๊ฐ OK)
# โ ์ ๋ ๊ธ์ง!
NEXT_PUBLIC_DATABASE_URL=postgresql://... # DB ์ ์ ์ ๋ณด๊ฐ ๋ธ๋ผ์ฐ์ ์ ๋
ธ์ถ!
NEXT_PUBLIC_SESSION_SECRET=secret-key # ์ํธํ ํค๊ฐ ๋ธ๋ผ์ฐ์ ์ ๋
ธ์ถ!server-only ํจํค์ง๋ก ์ค์ ๋ฐฉ์ง:
// lib/db.ts โ ์๋ฒ์์๋ง ์คํ๋๋ ํ์ผ
import 'server-only'
import { PrismaClient } from '@prisma/client'
// ์ด ํ์ผ์ด ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์์ import๋๋ฉด ๋น๋ ์๋ฌ ๋ฐ์
// โ ์ค์๋ก DB ์ฐ๊ฒฐ ์ ๋ณด๊ฐ ํด๋ผ์ด์ธํธ์ ๋
ธ์ถ๋๋ ์ฌ๊ณ ๋ฐฉ์ง
export const db = new PrismaClient().env ํ์ผ ๊ณ์ธต:
.env โ ๊ธฐ๋ณธ๊ฐ (git ์ถ์ ๊ฐ๋ฅ, ๋ฏผ๊ฐ ์ ๋ณด ์์ด์ผ ํจ)
.env.local โ ๋ก์ปฌ ๊ฐ๋ฐ (git ์ ์ธ, ๊ฐ์ธ ์ค์ )
.env.development โ ๊ฐ๋ฐ ํ๊ฒฝ (git ์ถ์ ๊ฐ๋ฅ)
.env.production โ ํ๋ก๋์
(git ์ ์ธ! ๋๋ ๋น๋ฐ ๊ด๋ฆฌ ์๋น์ค๋ก)
๐ฅ ์๋ฌ ํด๊ฒฐ ์นดํ๋ก๊ทธ
โ Docker ๋น๋ ํ output: 'standalone' ๊ฒฐ๊ณผ๋ฌผ์ public ํ์ผ ์์
์์ธ: standalone ๋ชจ๋๋ public ํด๋๋ฅผ ์๋์ผ๋ก ํฌํจํ์ง ์์.
ํด๊ฒฐ์ฑ :
# Dockerfile์์ public ํด๋๋ฅผ ๋ช
์์ ์ผ๋ก ๋ณต์ฌ
COPY --from=builder /app/public ./publicโ ๋ฐฐํฌ ํ ํ๊ฒฝ ๋ณ์๋ฅผ ๋ชป ์ฝ์ (undefined)
์์ธ ์ฒดํฌ๋ฆฌ์คํธ:
.env.local์ ๋ก์ปฌ ์ ์ฉ. ์๋ฒ์์๋ ์์คํ ํ๊ฒฝ ๋ณ์ ๋๋.env.production์ฌ์ฉNEXT_PUBLIC_์๋ ๋ณ์๋ฅผ ํด๋ผ์ด์ธํธ ์ฝ๋์์ ์ฝ์ผ๋ ค ํ ๊ฒฝ์ฐ- Docker ์คํ ์
--env-file์ต์ ๋๋ฝ
โ Vercel ๋ฐฐํฌ ํ API Route๊ฐ 504 Timeout
์์ธ: Vercel์ ๋ฌด๋ฃ ํ๋์์ ํจ์ ์คํ ์๊ฐ ํ๋(10์ด) ์ด๊ณผ.
ํด๊ฒฐ์ฑ :
// vercel.json์์ ํน์ ๊ฒฝ๋ก ํ์์์ ์ฐ์ฅ (Pro ํ๋ ํ์)
{
"functions": {
"app/api/heavy-task/route.ts": {
"maxDuration": 60
}
}
}๐ ์ด๋ฒ์ ๋ฐฐ์ด ๋ด์ฉ ์ด์ ๋ฆฌ
๐ ๋ฐฐํฌ ์ ๋ต ์ ํ ๊ธฐ์ค
| ์ํฉ | ๊ถ์ฅ ๋ฐฐํฌ ์ ๋ต |
|---|---|
| ์คํํธ์ , ์ด๊ธฐ ์ถ์, ์๊ท๋ชจ ํ | Vercel |
| ๊ธฐ์ ๋ด๋ถ ์๋ฒ, ๋ฐ์ดํฐ ๊ตญ๋ด ๋ณด๊ด ํ์ | Docker + ์ฌ๋ด ์๋ฒ |
| ๊ธฐ์กด VM ๋ณด์ , ๋จ์ ๋ฐฐํฌ | Node.js ์ง์ (PM2) |
โ ๏ธ ์ ๋ ํ์ง ๋ง ๊ฒ
| ์ํฉ | โ ๋์ ์ | โ ์ข์ ์ |
|---|---|---|
| DB ์ฐ๊ฒฐ ๋ฌธ์์ด | NEXT_PUBLIC_DATABASE_URL | DATABASE_URL (์๋ฒ ์ ์ฉ) |
| ๋น๋ฐํค git ์ถ์ | .env.production git commit | Vercel ํ๊ฒฝ ๋ณ์ ๋๋ AWS Secrets Manager |
| Docker์์ root ์คํ | ๊ธฐ๋ณธ root user | USER nextjs ์ค์ |
๐ ๋ง๋ฌด๋ฆฌ ํด์ฆ
Q1. NEXT_PUBLIC_SESSION_SECRET=abc123 ์ผ๋ก ์ค์ ํ์ ๋ ๋ฐ์ํ๋ ๋ฌธ์ ๋?
- A) ์๋ฒ์์ ํ๊ฒฝ ๋ณ์๋ฅผ ์ฝ์ง ๋ชปํ๋ค
- B) ๋ธ๋ผ์ฐ์ DevTools์์ ์ด ๊ฐ์ ๋๊ตฌ๋ ๋ณผ ์ ์๋ค
- C) Next.js ๋น๋๊ฐ ์คํจํ๋ค
- D) ์ฟ ํค๊ฐ ์๋์ผ๋ก ์ด๊ธฐํ๋๋ค
โ ์ ๋ต: B
ํด์ค:
NEXT_PUBLIC_์ ๋์ฌ๋ ํด๋ผ์ด์ธํธ ๋ฒ๋ค์ ๊ฐ์ ํฌํจ์์ผ. ๋ธ๋ผ์ฐ์ ๊ฐ๋ฐ์ ๋๊ตฌ์์ ๋๊ตฌ๋ ํ์ธ ๊ฐ๋ฅํด. ์ธ์ ๋น๋ฐํค๊ฐ ๋ ธ์ถ๋๋ฉด ๋ชจ๋ JWT๋ฅผ ์์กฐํ ์ ์์ด.๐ ํต์ฌ ๊ธฐ์ต๋ฒ:
NEXT_PUBLIC_= "๊ณต๊ฐ ๋ฐฉ์ก". ๋น๋ฐํค์ ์ ๋ ๋ถ์ด์ง ๋ง.
Q2. Docker output: 'standalone'์ ์ฅ์ ์ผ๋ก ์ณ์ง ์์ ๊ฒ์?
- A) ๋ถํ์ํ node_modules๋ฅผ ํฌํจํ์ง ์์ ์ด๋ฏธ์ง ํฌ๊ธฐ๊ฐ ์์์ง๋ค
- B) ์คํ์ ํ์ํ ์ต์ ํ์ผ๋ง ํฌํจ๋๋ค
- C)
publicํด๋๊ฐ ์๋์ผ๋ก ํฌํจ๋๋ค - D) ๋ฉํฐ ์คํ ์ด์ง ๋น๋์ ํจ๊ป ์ฐ๋ฉด ์ด๋ฏธ์ง ํฌ๊ธฐ๋ฅผ ํฌ๊ฒ ์ค์ผ ์ ์๋ค
โ ์ ๋ต: C
ํด์ค:
standalone๋ชจ๋๋publicํด๋๋ฅผ ์๋์ผ๋ก ํฌํจํ์ง ์์. Dockerfile์์ ๋ช ์์ ์ผ๋กCOPY --from=builder /app/public ./public์ ํด์ค์ผ ํด.๐ ํต์ฌ ๊ธฐ์ต๋ฒ: standalone์ standalone์ด์ผ.
public์ ๋ณ๋๋ก ์ฑ๊ฒจ์ผ ํด.
Q3. ์น๊ตฌ์๊ฒ ์ค๋ช ํ๋ค๋ฉด?
์คํํธ์ ์ด๊ธฐ์ Vercel์ ์ ํํ๊ณ , ๋์ค์ Docker๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ๋ ์ด์ ๋ฅผ ์ค๋ช ํด๋ด.
์์ ๋ต๋ณ:
"Vercel์ ๋ฐฐ๋ฌ์๋ฏผ์กฑ ์ ์ ์ด์ผ. ์ฒ์์ ๋น ๋ฅด๊ณ ํธํด. ๊ทผ๋ฐ ํธ๋ํฝ์ด ๋๋ฉด ์์๋ฃ(๋น์ฉ)๊ฐ ๊ธฐํ๊ธ์์ ์ผ๋ก ๋์ด. ๊ทธ๋ฆฌ๊ณ '์ฐ๋ฆฌ ์๋ฒ์ ์ ์ฅํด์ผ ํ๋ค'๋ ๊ธฐ์ ๊ท์ ์ด ์๊ธฐ๋ฉด Vercel์ ๋ฏธ๊ตญ ์๋ฒ๋ผ ๋ถ๊ฐ๋ฅํด. ๊ทธ๋ Docker๋ก ์์ฒด ์๋ฒ์ ์ฎ๊ธฐ๋ ๊ฑฐ์ผ. ์ด๊ธฐ์ ์๋, ๋์ค์ ์ ์ด๊ถ์ด ๋ ์ค์ํด์ง๋ ์ฑ์ฅ ๋จ๊ณ์ ๋ฐ๋ฅธ ์ ๋ต ๋ณํ์ผ."
๐ฃ ์์ฒ ์ด์ ํด๊ทผ ์ผ๊ธฐ
์ค๋์ ์ ๋ง ๋ฅ์คํธ ์ฑ์ด ์ธ์์ผ๋ก ๋๊ฐ๋ ๊ด๋ฌธ์ธ 'Deployment & Infra' ๋ฅผ ๋ฐฐ์ฐ๋ฉด์ ๊ฐ์ด์ด ๋ฒ ์ฐจ์ฌ๋์ด! ๋จ์ํ ์ฝ๋๋ฅผ ์ง๋ ๊ฑธ ๋์ด, Docker์ ๋ฉํฐ ์คํ ์ด์ง ๋น๋๋ก ์ด๋ฏธ์ง๋ฅผ ๊น๊ณ Vercel๊ณผ ์์ฒด ์๋ฒ ์ฌ์ด์ ์ ๋ต์ ๊ณ ๋ฏผํ๋ ๊ณผ์ ์ด ์ ๋ง ํฅ๋ฏธ๋ก์ ์ด.
๐ก ์ค๋์ ๊ตํ: "๋ฐฐํฌ๋ ๋์ด ์๋๋ผ ์๋ก์ด ์์์ด๋ค. Vercel๋ก ๋น ๋ฅด๊ฒ ์ถ์ํ๊ณ , ์ฑ์ฅ ๋จ๊ณ์ ๋ง์ถฐ Docker์ ์์ฒด ์๋ฒ๋ก ํ์ฅํ๋ฉฐ ์ ์ธ๊ณ ์ ์ ์๊ฒ ์์ ์ ์ธ ์๋น์ค๋ฅผ ์ ๊ณตํ์!"
์ํธ ๋ฆฌ๋ ๋์ด ๋ฐฐ๋ฌ ์ฑ ๋น์ ๋ฅผ ๋ค์ด ์ค๋ช ํด ์ฃผ์ค ๋, ์ ์ํฉ์ ๋ง๋ ๋ฐฐํฌ ์ ๋ต์ด ์ค์ํ์ง ๋จ๋ฒ์ ์ดํด๊ฐ ๊ฐ๋๋ผ. ํนํ ํ๊ฒฝ ๋ณ์ ํ๋์ ์๋น์ค์ ์ด๋ช ์ด ๊ฐ๋ฆด ์ ์๋ค๋ ๋ง์์ ์ ์ ์ด ๋ฒ์ฉ ๋ค์์ด. ์ค๋ ๋๋ฌด ๊ธด์ฅํ๋ฉด์ ์๋ฒ ์ค์ ์ ๋ง์ก๋๋ ๋ฐฐ๊ฐ ์ถ์ถํ๋ค. ํด๊ทผ๊ธธ์ ๋ด๊ฐ ์ข์ํ๋ '๋ฐฐ๋ฌ ์์' ํ๋ ์์ผ์ ๋ง์๊ฒ ๋จน์ผ๋ฉด์ ์ค๋ ๋ฐฐ์ด ๋ฐฐํฌ ๋ก์ง์ ๋ณต์ตํด์ผ๊ฒ ์ด. ๋ด์ผ์ ๋ '์์ ์ ์ธ' ์๋น์ค๋ฅผ ์ด์ํ๋ ๊ฐ๋ฐ์๊ฐ ๋ ๊ฑฐ์ผ! ๐ฃ