๋ฉ”์ธ ์ฝ˜ํ…์ธ ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ
pnpm sonamu test ๋ช…๋ น์–ด๋Š” ์‹คํ–‰ ์ค‘์ธ dev ์„œ๋ฒ„์˜ Vitest ์ธ์Šคํ„ด์Šค๋ฅผ ํ†ตํ•ด ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. dev ์„œ๋ฒ„๊ฐ€ ์ด๋ฏธ ๋กœ๋“œํ•œ ๋ชจ๋“ˆ์„ ์žฌ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ๋งค๋ฒˆ ์ดˆ๊ธฐํ™”ํ•˜๋Š” pnpm test๋ณด๋‹ค ๋น ๋ฅด๊ฒŒ ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ „์ œ์กฐ๊ฑด

์ด ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋‘ ๊ฐ€์ง€๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค:
  1. sonamu.config.ts์—์„œ devRunner ํ™œ์„ฑํ™”
  2. pnpm dev๋กœ dev ์„œ๋ฒ„๊ฐ€ ์‹คํ–‰ ์ค‘

sonamu.config.ts ์„ค์ •

api/src/sonamu.config.ts
export default defineConfig({
  // ... ๋‹ค๋ฅธ ์„ค์ •
  test: {
    devRunner: {
      enabled: true,
      routePrefix: "/__test__",            // ์„ ํƒ, ๊ธฐ๋ณธ๊ฐ’
      vitestConfigPath: "vitest.config.ts", // ์„ ํƒ, api-root ์ƒ๋Œ€๊ฒฝ๋กœ
    },
  },
});

์„ค์ • ์˜ต์…˜

์˜ต์…˜ํƒ€์ž…๊ธฐ๋ณธ๊ฐ’์„ค๋ช…
enabledbooleanfalseDevRunner ํ™œ์„ฑํ™” ์—ฌ๋ถ€
routePrefixstring"/__test__"ํ…Œ์ŠคํŠธ ์—”๋“œํฌ์ธํŠธ ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ
vitestConfigPathstring-vitest.config.ts ๊ฒฝ๋กœ (api-root ์ƒ๋Œ€๊ฒฝ๋กœ)

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

# ์ „์ฒด ํ…Œ์ŠคํŠธ ์‹คํ–‰
pnpm sonamu test

# ํŠน์ • ํŒŒ์ผ ์‹คํ–‰
pnpm sonamu test src/application/user/user.test.ts

# ์ด๋ฆ„ ํŒจํ„ด์œผ๋กœ ํ•„ํ„ฐ๋ง
pnpm sonamu test --pattern "findMany"

# ํŒŒ์ผ + ํŒจํ„ด ์กฐํ•ฉ
pnpm sonamu test src/application/user/user.test.ts --pattern "findById"

์˜ต์…˜

์˜ต์…˜๋‹จ์ถ•์„ค๋ช…
--pattern <์ด๋ฆ„>-p <์ด๋ฆ„>ํ…Œ์ŠคํŠธ ์ด๋ฆ„ ํŒจํ„ด์œผ๋กœ ํ•„ํ„ฐ๋ง
ํŒŒ์ผ ๊ฒฝ๋กœ๋Š” ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
pnpm sonamu test src/application/user/user.test.ts src/application/post/post.test.ts

๋™์ž‘ ์›๋ฆฌ

pnpm sonamu test๋Š” dev ์„œ๋ฒ„ ๋‚ด๋ถ€์— ์ƒ์ฃผํ•˜๋Š” Vitest ์ธ์Šคํ„ด์Šค๋ฅผ HTTP ์š”์ฒญ์œผ๋กœ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
  1. CLI๊ฐ€ dev ์„œ๋ฒ„์˜ /__test__/run ์—”๋“œํฌ์ธํŠธ์— POST ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
  2. dev ์„œ๋ฒ„์˜ DevVitestManager๊ฐ€ ์ƒ์ฃผ Vitest ์ธ์Šคํ„ด์Šค๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  3. ๊ฒฐ๊ณผ๋ฅผ JSON์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋ฉด CLI๊ฐ€ ์š”์•ฝ์„ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

pnpm test์™€์˜ ๋น„๊ต

pnpm testpnpm sonamu test
์„œ๋ฒ„ ํ•„์š”๋ถˆํ•„์š”pnpm dev ์‹คํ–‰ ์ค‘ ํ•„์š”
์‹คํ–‰ ์†๋„๋งค๋ฒˆ ์ดˆ๊ธฐํ™”Vitest ์ธ์Šคํ„ด์Šค ์žฌ์‚ฌ์šฉ (๋น ๋ฆ„)
HMR ์—ฐ๋™์—†์Œ์ฝ”๋“œ ๋ณ€๊ฒฝ ์ฆ‰์‹œ ๋ฐ˜์˜
์šฉ๋„CI, ์ „์ฒด ํ…Œ์ŠคํŠธ๊ฐœ๋ฐœ ์ค‘ ๋น ๋ฅธ ํ”ผ๋“œ๋ฐฑ
์–ธ์ œ ์–ด๋–ค ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋‚˜์š”?
  • ๊ฐœ๋ฐœ ์ค‘: pnpm sonamu test๋กœ ๋น ๋ฅด๊ฒŒ ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ›์œผ์„ธ์š”. ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ๋ฐ”๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • CI/CD: pnpm test๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. ๋…๋ฆฝ์ ์ธ ํ™˜๊ฒฝ์—์„œ ์ „์ฒด ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์ƒํƒœ ํ™•์ธ

dev ์„œ๋ฒ„์˜ DevRunner ์ƒํƒœ๋ฅผ ํ™•์ธํ•˜๋ ค๋ฉด /__test__/status ์—”๋“œํฌ์ธํŠธ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:
curl http://localhost:3000/__test__/status
{
  "ready": true,
  "running": false,
  "lastRunAt": "2026-02-23T10:30:00.000Z"
}
ํ•„๋“œ์„ค๋ช…
readyVitest ์ธ์Šคํ„ด์Šค๊ฐ€ ์ค€๋น„๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€
runningํ˜„์žฌ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํ–‰ ์ค‘์ธ์ง€ ์—ฌ๋ถ€
lastRunAt๋งˆ์ง€๋ง‰ ํ…Œ์ŠคํŠธ ์‹คํ–‰ ์‹œ๊ฐ

๋ฌธ์ œ ํ•ด๊ฒฐ

dev ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ

dev ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. sonamu dev๊ฐ€ ์‹คํ–‰ ์ค‘์ธ์ง€ ํ™•์ธํ•˜์„ธ์š”
ํ•ด๊ฒฐ: pnpm dev๋กœ dev ์„œ๋ฒ„๋ฅผ ๋จผ์ € ์‹œ์ž‘ํ•˜์„ธ์š”.

devRunner๊ฐ€ ํ™œ์„ฑํ™”๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ

devRunner๊ฐ€ ํ™œ์„ฑํ™”๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. sonamu.config.ts์—์„œ test.devRunner.enabled: true ์„ค์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค
ํ•ด๊ฒฐ: sonamu.config.ts์˜ test.devRunner.enabled๋ฅผ true๋กœ ์„ค์ •ํ•˜๊ณ  dev ์„œ๋ฒ„๋ฅผ ์žฌ์‹œ์ž‘ํ•˜์„ธ์š”.

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