๋ฉ”์ธ ์ฝ˜ํ…์ธ ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ
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"

# trace ์ •๋ณด์™€ ํ•จ๊ป˜ ์ถœ๋ ฅ
pnpm sonamu test --traces

# DevRunner ์ƒํƒœ ํ™•์ธ
pnpm sonamu test --status

์˜ต์…˜

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

Trace ์ถœ๋ ฅ

--traces (-t) ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ํ…Œ์ŠคํŠธ ์‹คํ–‰ ์ค‘ Naite.t()๋กœ ์ˆ˜์ง‘๋œ trace ์ •๋ณด๋ฅผ ๊ฒฐ๊ณผ์™€ ํ•จ๊ป˜ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. ๊ฐ trace๋Š” ํ‚ค, ์†Œ์Šค ์œ„์น˜, ๊ฐ’์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
pnpm sonamu test --traces
Tests: 3 passed, 0 failed, 3 total
Duration: 245ms

Traces:
  UserModel.findMany
  user.test.ts

    [query] user.model.ts:42
    SELECT * FROM users WHERE ...

    [result] user.model.ts:45
    [{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]
ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ Naite.t()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ trace๋ฅผ ๊ธฐ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
import { Naite } from "sonamu";

// ํ…Œ์ŠคํŠธ ๋˜๋Š” ๋ชจ๋ธ ์ฝ”๋“œ ๋‚ด์—์„œ
Naite.t("query", sqlString);
Naite.t("result", rows);

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

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๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. ๋…๋ฆฝ์ ์ธ ํ™˜๊ฒฝ์—์„œ ์ „์ฒด ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

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

CLI์—์„œ --status ํ”Œ๋ž˜๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ HTTP ์—”๋“œํฌ์ธํŠธ์— ์ง์ ‘ ์š”์ฒญํ•˜์—ฌ DevRunner ์ƒํƒœ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
# CLI๋กœ ํ™•์ธ
pnpm sonamu test --status

# ๋˜๋Š” HTTP ์—”๋“œํฌ์ธํŠธ์— ์ง์ ‘ ์š”์ฒญ
curl http://localhost:3000/__test__/status
{
  "ready": true,
  "running": false,
  "lastRunAt": "2026-02-23T10:30:00.000Z",
  "sseAvailable": true
}
ํ•„๋“œ์„ค๋ช…
readyVitest ์ธ์Šคํ„ด์Šค๊ฐ€ ์ค€๋น„๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€
runningํ˜„์žฌ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํ–‰ ์ค‘์ธ์ง€ ์—ฌ๋ถ€
lastRunAt๋งˆ์ง€๋ง‰ ํ…Œ์ŠคํŠธ ์‹คํ–‰ ์‹œ๊ฐ
sseAvailableSSE(Server-Sent Events) ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ์ด ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ์ง€ ์—ฌ๋ถ€

๋ฌธ์ œ ํ•ด๊ฒฐ

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

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

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

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

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

ํ…Œ์ŠคํŠธ ๊ตฌ์กฐ

Vitest ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ ์‹œ์Šคํ…œ ์•Œ์•„๋ณด๊ธฐ

dev

๊ฐœ๋ฐœ ์„œ๋ฒ„ ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ธฐ