๋ฉ”์ธ ์ฝ˜ํ…์ธ ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ
pnpm build ๋ช…๋ น์–ด๋Š” ํ”„๋กœ์ ํŠธ๋ฅผ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์— ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์ตœ์ ํ™”๋œ ์ฝ”๋“œ๋กœ ๋นŒ๋“œํ•ฉ๋‹ˆ๋‹ค. TypeScript๋ฅผ JavaScript๋กœ ์ปดํŒŒ์ผํ•˜๊ณ , ๋ถˆํ•„์š”ํ•œ ์ฝ”๋“œ๋ฅผ ์ œ๊ฑฐํ•˜์—ฌ ์‹คํ–‰ ์†๋„๋ฅผ ๋†’์ž…๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

pnpm build
๋นŒ๋“œ๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด dist ๋””๋ ‰ํ† ๋ฆฌ์— ์ตœ์ ํ™”๋œ JavaScript ํŒŒ์ผ์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
๐Ÿ“my-project/
๐Ÿ“dist/ - ๋นŒ๋“œ ๊ฒฐ๊ณผ๋ฌผ
๐Ÿ“„JSindex.js
๐Ÿ“models/
๐Ÿ“api/
๐Ÿ“src/ - ์›๋ณธ ์†Œ์Šค
๐Ÿ“„JSONpackage.json

๋นŒ๋“œ ๊ณผ์ •

๋นŒ๋“œ๋Š” ๋‹ค์Œ ๋‹จ๊ณ„๋กœ ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค:

1. ๊ธฐ์กด ๋นŒ๋“œ ๊ฒฐ๊ณผ๋ฌผ ์ œ๊ฑฐ

์ด์ „ ๋นŒ๋“œ์˜ ์ž”์—ฌ ํŒŒ์ผ์„ ๊นจ๋—ํ•˜๊ฒŒ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
โœ“ Build artifacts removed successfully.
์ œ๊ฑฐ๋˜๋Š” ๋””๋ ‰ํ† ๋ฆฌ:
  • dist/ - API ๋นŒ๋“œ ๊ฒฐ๊ณผ๋ฌผ
  • web/dist/ - Web ๋นŒ๋“œ ๊ฒฐ๊ณผ๋ฌผ
  • web-build/ - ๋ณต์‚ฌ๋œ Web ๊ฒฐ๊ณผ๋ฌผ

2. SWC ์„ค์ • ํŒŒ์ผ ์ค€๋น„

๋นŒ๋“œ์— ์‚ฌ์šฉํ•  SWC ์„ค์ • ํŒŒ์ผ์„ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
// ์šฐ์„ ์ˆœ์œ„
// 1. ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ์˜ .swcrc (์ปค์Šคํ…€ ์„ค์ •)
// 2. Sonamu ๊ธฐ๋ณธ .swcrc (์—†์„ ๊ฒฝ์šฐ)
์ปค์Šคํ…€ ์„ค์ • ์‚ฌ์šฉ:
# ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ์— .swcrc ์ƒ์„ฑ
touch .swcrc
๊ธฐ๋ณธ ์„ค์ • ์‚ฌ์šฉ:
Using default .swcrc from sonamu package...

3. API ํ”„๋กœ์ ํŠธ ๋นŒ๋“œ

TypeScript๋ฅผ JavaScript๋กœ ์ปดํŒŒ์ผํ•ฉ๋‹ˆ๋‹ค.
1

๋นŒ๋“œ ์‹œ์ž‘

๐Ÿ“ฆ API Server
Building production-ready API
/path/to/project
2

์ปดํŒŒ์ผ ์‹คํ–‰

swc src -d dist --config-file .swcrc
๋นŒ๋“œ ๋„๊ตฌ: SWC - Rust ๊ธฐ๋ฐ˜ ์ดˆ๊ณ ์† TypeScript ์ปดํŒŒ์ผ๋Ÿฌ
3

์™„๋ฃŒ

โœ“ build completed (2.5s)
โœ“ API build completed in 2.5s

4. Web ํ”„๋กœ์ ํŠธ ๋นŒ๋“œ (์„ ํƒ)

Web ํ”„๋กœ์ ํŠธ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ๋นŒ๋“œํ•˜๊ณ  API ํ”„๋กœ์ ํŠธ๋กœ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.
1

๋นŒ๋“œ ์‹œ์ž‘

๐ŸŒ Web Application
Building static web assets
/path/to/project/web
2

Vite ๋นŒ๋“œ

vite build
์ •์  ์—์…‹์„ ์ตœ์ ํ™”ํ•˜๊ณ  ๋ฒˆ๋“ค๋งํ•ฉ๋‹ˆ๋‹ค.
3

ํŒŒ์ผ ๋ณต์‚ฌ

web/dist โ†’ web-build
API ์„œ๋ฒ„์—์„œ ์„œ๋น™ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.
4

์™„๋ฃŒ

โœ“ build completed (8.2s)
โœ“ copy completed (0.1s)
โœ“ Web build completed in 8.3s
Web ๋นŒ๋“œ ๊ฒฐ๊ณผ๋ฌผ:
  • web/dist/ - ์›๋ณธ ๋นŒ๋“œ ๊ฒฐ๊ณผ
  • web-build/ - API ์„œ๋ฒ„์—์„œ ์„œ๋น™ํ•  ๋ณต์‚ฌ๋ณธ

๋นŒ๋“œ ์„ค์ •

SWC ์„ค์ • ์ปค์Šคํ„ฐ๋งˆ์ด์ง•

ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ์— .swcrc ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์—ฌ ๋นŒ๋“œ๋ฅผ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
.swcrc
{
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": false,
      "decorators": true
    },
    "target": "es2022",
    "loose": false,
    "externalHelpers": false,
    "keepClassNames": true,
    "transform": {
      "legacyDecorator": true,
      "decoratorMetadata": true
    }
  },
  "module": {
    "type": "es6"
  },
  "sourceMaps": true
}
์ฃผ์š” ์˜ต์…˜:
์˜ต์…˜์„ค๋ช…๊ธฐ๋ณธ๊ฐ’
target์ปดํŒŒ์ผ ํƒ€๊ฒŸes2022
decorators๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ์ง€์›true
sourceMaps์†Œ์Šค๋งต ์ƒ์„ฑtrue
keepClassNamesํด๋ž˜์Šค๋ช… ๋ณด์กดtrue
.swcrc ํŒŒ์ผ์ด ์—†์œผ๋ฉด Sonamu๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ตœ์ ํ™”๋œ ๊ธฐ๋ณธ ์„ค์ •์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋นŒ๋“œ ๊ฒฐ๊ณผ๋ฌผ

API ๋นŒ๋“œ ๊ฒฐ๊ณผ

๐Ÿ“dist/
๐Ÿ“„JSindex.js - ์—”ํŠธ๋ฆฌํฌ์ธํŠธ
๐Ÿ“models/ - Model ํŒŒ์ผ๋“ค
๐Ÿ“„JSuser.model.js
๐Ÿ“„JSpost.model.js
๐Ÿ“api/ - API ๋กœ์ง
๐Ÿ“„JSsonamu.js
๐Ÿ“entities/ - Entity ์ •์˜
๐Ÿ“„JSentities.js
๐Ÿ“practices/ - Practice ์Šคํฌ๋ฆฝํŠธ
๐Ÿ“„JSp1-test.js
ํŠน์ง•:
  • TypeScript โ†’ JavaScript ๋ณ€ํ™˜
  • ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ๋ณ€ํ™˜ ์™„๋ฃŒ
  • ์†Œ์Šค๋งต ํฌํ•จ (.js.map)
  • Import ๊ฒฝ๋กœ ํ•ด์„ ์™„๋ฃŒ

Web ๋นŒ๋“œ ๊ฒฐ๊ณผ (์„ ํƒ)

๐Ÿ“web-build/
๐Ÿ“„HTMLindex.html - HTML ์—”ํŠธ๋ฆฌ
๐Ÿ“assets/ - ์ตœ์ ํ™”๋œ ์—์…‹
๐Ÿ“„JSindex-abc123.js
๐Ÿ“„CSSindex-def456.css
๐Ÿ“„ICOfavicon.ico
ํŠน์ง•:
  • ์ฝ”๋“œ ์••์ถ• (minification)
  • ์—์…‹ ํ•ด์‹ฑ (cache busting)
  • Tree shaking (์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ฝ”๋“œ ์ œ๊ฑฐ)

๋นŒ๋“œ ์ตœ์ ํ™”

1. ํƒ€์ž… ์ฒดํฌ ๋ถ„๋ฆฌ

๋นŒ๋“œ ์†๋„๋ฅผ ๋†’์ด๋ ค๋ฉด ํƒ€์ž… ์ฒดํฌ๋ฅผ ๋ณ„๋„๋กœ ์ˆ˜ํ–‰ํ•˜์„ธ์š”.
# ํƒ€์ž… ์ฒดํฌ๋งŒ ์ˆ˜ํ–‰ (๋น ๋ฆ„)
pnpm tsc --noEmit

# ๋นŒ๋“œ๋งŒ ์ˆ˜ํ–‰ (ํƒ€์ž… ์ฒดํฌ ์—†์Œ)
pnpm build

2. ์ฆ๋ถ„ ๋นŒ๋“œ

๋ณ€๊ฒฝ๋œ ํŒŒ์ผ๋งŒ ์žฌ๋นŒ๋“œํ•˜๋ ค๋ฉด ๊ฐœ๋ฐœ ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.
# ์ „์ฒด ๋นŒ๋“œ (๋А๋ฆผ)
pnpm build

# HMR ๊ฐœ๋ฐœ ์„œ๋ฒ„ (๋น ๋ฆ„)
pnpm dev

3. ์บ์‹œ ํ™œ์šฉ

SWC๋Š” ์ž๋™์œผ๋กœ ๋นŒ๋“œ ์บ์‹œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
# ์ฒซ ๋นŒ๋“œ (๋А๋ฆผ)
pnpm build  # 5์ดˆ

# ๋‘ ๋ฒˆ์งธ ๋นŒ๋“œ (๋น ๋ฆ„)
pnpm build  # 2์ดˆ

๋ฌธ์ œ ํ•ด๊ฒฐ

๋นŒ๋“œ ์‹คํŒจ

๋ฌธ์ œ: TypeScript ์—๋Ÿฌ๋กœ ๋นŒ๋“œ ์‹คํŒจ
Error: Cannot find module 'some-module'
ํ•ด๊ฒฐ:
# 1. ํƒ€์ž… ์ฒดํฌ
pnpm tsc --noEmit

# 2. ์˜์กด์„ฑ ํ™•์ธ
pnpm install

# 3. node_modules ์žฌ์„ค์น˜
rm -rf node_modules
pnpm install

SWC ์„ค์ • ์—๋Ÿฌ

๋ฌธ์ œ: .swcrc ์„ค์ • ์˜ค๋ฅ˜
Error: Invalid .swcrc configuration
ํ•ด๊ฒฐ:
# ๊ธฐ๋ณธ ์„ค์ •์œผ๋กœ ๋ณต๊ตฌ
rm .swcrc
pnpm build

Web ๋นŒ๋“œ ์‹คํŒจ

๋ฌธ์ œ: Vite ๋นŒ๋“œ ์—๋Ÿฌ
Error: Could not resolve './some-file'
ํ•ด๊ฒฐ:
# Web ํ”„๋กœ์ ํŠธ ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์ด๋™
cd web

# ์˜์กด์„ฑ ํ™•์ธ
pnpm install

# Web๋งŒ ๋นŒ๋“œ ํ…Œ์ŠคํŠธ
pnpm build

# ๋ฃจํŠธ๋กœ ๋Œ์•„์™€ ์ „์ฒด ๋นŒ๋“œ
cd ..
pnpm build

๋นŒ๋“œ ํ›„ ์‹คํ–‰

๋นŒ๋“œ๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด start ๋ช…๋ น์–ด๋กœ ํ”„๋กœ๋•์…˜ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
# ๋นŒ๋“œ
pnpm build

# ์‹คํ–‰
pnpm start
ํ”„๋กœ๋•์…˜ ์‹คํ–‰์˜ ํŠน์ง•:
  • ๋น ๋ฅธ ์‹œ์ž‘: ์ปดํŒŒ์ผ์ด ์™„๋ฃŒ๋œ JavaScript ์‹คํ–‰
  • ๋‚ฎ์€ ๋ฉ”๋ชจ๋ฆฌ: TypeScript ๋ณ€ํ™˜ ์˜ค๋ฒ„ํ—ค๋“œ ์—†์Œ
  • ์†Œ์Šค๋งต ์ง€์›: ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ์›๋ณธ ํŒŒ์ผ ์œ„์น˜ ํ‘œ์‹œ

์ง์ ‘ ์‹คํ–‰

pnpm start ๋Œ€์‹  Node.js๋กœ ์ง์ ‘ ์‹คํ–‰ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค:
node --enable-source-maps dist/index.js
์˜ต์…˜ ์„ค๋ช…:
  • --enable-source-maps: ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ์›๋ณธ TypeScript ํŒŒ์ผ ์œ„์น˜ ํ‘œ์‹œ
  • dist/index.js: ๋นŒ๋“œ๋œ ์—”ํŠธ๋ฆฌํฌ์ธํŠธ

ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๋กœ๋“œ

ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ:
# dotenv๋กœ .env ํŒŒ์ผ ๋กœ๋“œ
node -r dotenv/config --enable-source-maps dist/index.js

# ๋˜๋Š” ์ง์ ‘ ์ง€์ •
NODE_ENV=production PORT=3000 node --enable-source-maps dist/index.js

CI/CD ์„ค์ •

CI/CD ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์„ฑํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ํ‘ธ์‹œํ•  ๋•Œ๋งˆ๋‹ค ์ž๋™์œผ๋กœ ๋นŒ๋“œํ•˜๊ณ  ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. GitHub Actions, GitLab CI, Jenkins ๋“ฑ ๋‹ค์–‘ํ•œ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์™œ CI/CD๊ฐ€ ํ•„์š”ํ•œ๊ฐ€?

์ด์ ์„ค๋ช…
์ž๋™ํ™”์ˆ˜๋™ ๋นŒ๋“œ/๋ฐฐํฌ ์ž‘์—… ์ œ๊ฑฐ
์ผ๊ด€์„ฑํ•ญ์ƒ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋นŒ๋“œ
๋น ๋ฅธ ํ”ผ๋“œ๋ฐฑ๋นŒ๋“œ ์‹คํŒจ๋ฅผ ์ฆ‰์‹œ ํ™•์ธ
์•ˆ์ „์„ฑํ…Œ์ŠคํŠธ ํ†ต๊ณผ ํ›„์—๋งŒ ๋ฐฐํฌ
์ถ”์ ์„ฑ๋ชจ๋“  ๋ฐฐํฌ ๊ธฐ๋ก ๋ณด์กด

GitHub Actions

GitHub Actions๋Š” GitHub์— ํ†ตํ•ฉ๋œ CI/CD ํ”Œ๋žซํผ์ž…๋‹ˆ๋‹ค. .github/workflows/ ๋””๋ ‰ํ† ๋ฆฌ์— YAML ํŒŒ์ผ์„ ์ž‘์„ฑํ•˜์—ฌ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
.github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches: [main]  # main ๋ธŒ๋žœ์น˜์— ํ‘ธ์‹œํ•  ๋•Œ ์‹คํ–‰

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
      # 1. ์ฝ”๋“œ ์ฒดํฌ์•„์›ƒ
      - uses: actions/checkout@v3
      
      # 2. pnpm ์„ค์น˜
      - uses: pnpm/action-setup@v2
        with:
          version: 8
      
      # 3. Node.js ์„ค์ • (pnpm ์บ์‹œ ํ™œ์„ฑํ™”)
      - uses: actions/setup-node@v3
        with:
          node-version: 20
          cache: 'pnpm'
      
      # 4. ์˜์กด์„ฑ ์„ค์น˜
      - run: pnpm install
      
      # 5. ๋นŒ๋“œ
      - run: pnpm build
      
      # 6. ๋ฐฐํฌ
      - name: Deploy
        run: |
          # rsync๋กœ ๋นŒ๋“œ ๊ฒฐ๊ณผ๋ฌผ ์—…๋กœ๋“œ
          rsync -avz dist/ server:/app/
์ฃผ์š” ๋‹จ๊ณ„ ์„ค๋ช…:
1

์ฝ”๋“œ ์ฒดํฌ์•„์›ƒ

actions/checkout@v3์„ ์‚ฌ์šฉํ•˜์—ฌ ์ €์žฅ์†Œ ์ฝ”๋“œ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
2

pnpm ์„ค์น˜

pnpm/action-setup@v2๋กœ pnpm ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ €๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.
3

Node.js ์„ค์ •

actions/setup-node@v3์œผ๋กœ Node.js๋ฅผ ์„ค์น˜ํ•˜๊ณ  pnpm ์บ์‹œ๋ฅผ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. ์บ์‹œ ๋•๋ถ„์— ์˜์กด์„ฑ ์„ค์น˜๊ฐ€ ํ›จ์”ฌ ๋น ๋ฆ…๋‹ˆ๋‹ค.
4

์˜์กด์„ฑ ์„ค์น˜

pnpm install๋กœ ํ”„๋กœ์ ํŠธ ์˜์กด์„ฑ์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.
5

๋นŒ๋“œ

pnpm build๋กœ ํ”„๋กœ๋•์…˜ ๋นŒ๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
6

๋ฐฐํฌ

๋นŒ๋“œ ๊ฒฐ๊ณผ๋ฌผ์„ ์„œ๋ฒ„๋กœ ์—…๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค. rsync, scp, FTP ๋“ฑ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ• ์‚ฌ์šฉ ๊ฐ€๋Šฅ.

ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€

๋ฐฐํฌ ์ „์— ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ๋ฒ„๊ทธ๋ฅผ ์กฐ๊ธฐ์— ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
.github/workflows/deploy.yml
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: pnpm/action-setup@v2
        with:
          version: 8
      - uses: actions/setup-node@v3
        with:
          node-version: 20
          cache: 'pnpm'
      - run: pnpm install
      - run: pnpm test  # ํ…Œ์ŠคํŠธ ์‹คํ–‰
  
  build:
    needs: test  # ํ…Œ์ŠคํŠธ ํ†ต๊ณผ ํ›„์—๋งŒ ๋นŒ๋“œ
    runs-on: ubuntu-latest
    steps:
      # ... ๋นŒ๋“œ ์Šคํ…

ํ™˜๊ฒฝ๋ณ„ ๋ฐฐํฌ

Staging๊ณผ Production ํ™˜๊ฒฝ์„ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
on:
  push:
    branches:
      - develop    # Staging์œผ๋กœ ๋ฐฐํฌ
      - main       # Production์œผ๋กœ ๋ฐฐํฌ

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      # ... ๋นŒ๋“œ ์Šคํ…
      
      - name: Deploy to Staging
        if: github.ref == 'refs/heads/develop'
        run: |
          rsync -avz dist/ staging-server:/app/
      
      - name: Deploy to Production
        if: github.ref == 'refs/heads/main'
        run: |
          rsync -avz dist/ prod-server:/app/

Docker

Docker๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ผ๊ด€๋œ ์‹คํ–‰ ํ™˜๊ฒฝ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ, ์Šคํ…Œ์ด์ง•, ํ”„๋กœ๋•์…˜ ๋ชจ๋‘ ๊ฐ™์€ ํ™˜๊ฒฝ์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
Dockerfile
# Stage 1: ๋นŒ๋“œ ์Šคํ…Œ์ด์ง€
FROM node:20-alpine AS builder

WORKDIR /app

# pnpm ์„ค์น˜
RUN npm install -g pnpm

# ์˜์กด์„ฑ ์„ค์น˜ (package.json๋งŒ ๋จผ์ € ๋ณต์‚ฌํ•˜์—ฌ ์บ์‹œ ํ™œ์šฉ)
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile

# ์†Œ์Šค ์ฝ”๋“œ ๋ณต์‚ฌ
COPY . .

# ๋นŒ๋“œ
RUN pnpm build

# Stage 2: ํ”„๋กœ๋•์…˜ ์Šคํ…Œ์ด์ง€
FROM node:20-alpine

WORKDIR /app

# pnpm ์„ค์น˜
RUN npm install -g pnpm

# ํ”„๋กœ๋•์…˜ ์˜์กด์„ฑ๋งŒ ์„ค์น˜
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --prod --frozen-lockfile

# ๋นŒ๋“œ ๊ฒฐ๊ณผ๋ฌผ ๋ณต์‚ฌ
COPY --from=builder /app/dist ./dist

# ํ™˜๊ฒฝ ๋ณ€์ˆ˜
ENV NODE_ENV=production

# ํฌํŠธ ๋…ธ์ถœ
EXPOSE 3000

# ์‹คํ–‰
CMD ["pnpm", "start"]
๋ฉ€ํ‹ฐ์Šคํ…Œ์ด์ง€ ๋นŒ๋“œ์˜ ์žฅ์ :
์žฅ์ ์„ค๋ช…
์ž‘์€ ์ด๋ฏธ์ง€ ํฌ๊ธฐ๋นŒ๋“œ ๋„๊ตฌ๋ฅผ ์ตœ์ข… ์ด๋ฏธ์ง€์—์„œ ์ œ์™ธ
๋น ๋ฅธ ๋ฐฐํฌ์ž‘์€ ์ด๋ฏธ์ง€๋Š” pull/push๊ฐ€ ๋น ๋ฆ„
๋ณด์•ˆ๋ถˆํ•„์š”ํ•œ ๊ฐœ๋ฐœ ๋„๊ตฌ ์ œ๊ฑฐ
๋ ˆ์ด์–ด ์บ์‹ฑ์˜์กด์„ฑ์ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์œผ๋ฉด ์žฌ์‚ฌ์šฉ

Docker Compose

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ํ•จ๊ป˜ ์‹คํ–‰ํ•˜๋ ค๋ฉด Docker Compose๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:
docker-compose.yml
version: '3.8'

services:
  api:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://postgres:password@db:5432/myapp
    depends_on:
      - db
  
  db:
    image: pgvector/pgvector:pg16
    environment:
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=myapp
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:
์‹คํ–‰:
# ๋นŒ๋“œ ๋ฐ ์‹คํ–‰
docker-compose up --build

# ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์‹คํ–‰
docker-compose up -d

# ์ค‘์ง€
docker-compose down

์„ฑ๋Šฅ ๋น„๊ต

ํ”„๋กœ๋•์…˜ ๋นŒ๋“œ๋Š” ๊ฐœ๋ฐœ ์„œ๋ฒ„๋ณด๋‹ค ํ›จ์”ฌ ๋น ๋ฅด๊ณ  ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.
์ธก์ • ํ•ญ๋ชฉ๊ฐœ๋ฐœ ์„œ๋ฒ„ํ”„๋กœ๋•์…˜ ๋นŒ๋“œ์ฐจ์ด
์‹œ์ž‘ ์‹œ๊ฐ„2-3์ดˆ0.5์ดˆ4-6๋ฐฐ ๋น ๋ฆ„
๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ200MB100MB50% ์ ˆ๊ฐ
์š”์ฒญ ์ฒ˜๋ฆฌ๋А๋ฆผ๋น ๋ฆ„2-3๋ฐฐ ๋น ๋ฆ„
ํŒŒ์ผ ํฌ๊ธฐ์›๋ณธ์••์ถ•๋จ30-50% ์ž‘์Œ
ํ”„๋กœ๋•์…˜์ด ๋น ๋ฅธ ์ด์œ :
  1. ๋ฏธ๋ฆฌ ์ปดํŒŒ์ผ๋จ: TypeScript๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ณ€ํ™˜ํ•˜์ง€ ์•Š์Œ
  2. ์ฝ”๋“œ ์ตœ์ ํ™”: ๋ถˆํ•„์š”ํ•œ ์ฝ”๋“œ ์ œ๊ฑฐ, ์••์ถ•
  3. HMR ์˜ค๋ฒ„ํ—ค๋“œ ์—†์Œ: ํŒŒ์ผ ๊ฐ์‹œ ๋ฐ ์žฌ๋กœ๋”ฉ ๋น„์šฉ ์—†์Œ
  4. ํ”„๋กœ๋•์…˜ ๋ชจ๋“œ: Node.js์™€ ์˜์กด์„ฑ๋“ค์ด ์ตœ์ ํ™” ๋ชจ๋“œ๋กœ ์‹คํ–‰

์‹ค์ œ ์„ฑ๋Šฅ ์ธก์ •

๊ฐœ๋ฐœ ์„œ๋ฒ„์™€ ํ”„๋กœ๋•์…˜ ๋นŒ๋“œ์˜ ์„ฑ๋Šฅ์„ ์ง์ ‘ ๋น„๊ตํ•ด๋ณด์„ธ์š”:
# ๊ฐœ๋ฐœ ์„œ๋ฒ„ ์‹œ์ž‘ ์‹œ๊ฐ„ ์ธก์ •
time pnpm dev

# ํ”„๋กœ๋•์…˜ ๋นŒ๋“œ + ์‹œ์ž‘ ์‹œ๊ฐ„ ์ธก์ •
time (pnpm build && pnpm start)
API ์‘๋‹ต ์‹œ๊ฐ„ ๋น„๊ต:
# ๊ฐœ๋ฐœ ์„œ๋ฒ„
curl -w "\n%{time_total}s\n" http://localhost:3000/api/users
# ์˜ˆ: 0.05์ดˆ

# ํ”„๋กœ๋•์…˜
curl -w "\n%{time_total}s\n" http://localhost:3000/api/users
# ์˜ˆ: 0.02์ดˆ

๋‹ค์Œ ๋‹จ๊ณ„