메인 μ½˜ν…μΈ λ‘œ κ±΄λ„ˆλ›°κΈ°
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

개발 μ„œλ²„ μžμ„Ένžˆ μ•Œμ•„λ³΄κΈ°