@kood/claude-code 0.1.6 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +109 -216
- package/package.json +8 -2
- package/templates/hono/CLAUDE.md +59 -328
- package/templates/hono/docs/architecture/architecture.md +93 -747
- package/templates/hono/docs/deployment/cloudflare.md +59 -513
- package/templates/hono/docs/deployment/docker.md +41 -356
- package/templates/hono/docs/deployment/index.md +54 -190
- package/templates/hono/docs/deployment/railway.md +36 -306
- package/templates/hono/docs/deployment/vercel.md +49 -434
- package/templates/hono/docs/library/ai-sdk/index.md +53 -290
- package/templates/hono/docs/library/ai-sdk/openrouter.md +19 -387
- package/templates/hono/docs/library/ai-sdk/providers.md +28 -394
- package/templates/hono/docs/library/ai-sdk/streaming.md +52 -353
- package/templates/hono/docs/library/ai-sdk/structured-output.md +63 -395
- package/templates/hono/docs/library/ai-sdk/tools.md +62 -431
- package/templates/hono/docs/library/hono/env-setup.md +24 -313
- package/templates/hono/docs/library/hono/error-handling.md +34 -295
- package/templates/hono/docs/library/hono/index.md +29 -121
- package/templates/hono/docs/library/hono/middleware.md +21 -188
- package/templates/hono/docs/library/hono/rpc.md +40 -341
- package/templates/hono/docs/library/hono/validation.md +35 -195
- package/templates/hono/docs/library/pino/index.md +42 -333
- package/templates/hono/docs/library/prisma/cloudflare-d1.md +64 -367
- package/templates/hono/docs/library/prisma/config.md +19 -260
- package/templates/hono/docs/library/prisma/index.md +67 -320
- package/templates/hono/docs/library/zod/index.md +53 -257
- package/templates/npx/CLAUDE.md +62 -274
- package/templates/npx/docs/references/patterns.md +160 -0
- package/templates/tanstack-start/CLAUDE.md +100 -256
- package/templates/tanstack-start/docs/architecture/architecture.md +44 -589
- package/templates/tanstack-start/docs/deployment/cloudflare.md +37 -424
- package/templates/tanstack-start/docs/deployment/index.md +57 -286
- package/templates/tanstack-start/docs/deployment/nitro.md +36 -318
- package/templates/tanstack-start/docs/deployment/railway.md +40 -409
- package/templates/tanstack-start/docs/deployment/vercel.md +43 -465
- package/templates/tanstack-start/docs/design/components.md +77 -311
- package/templates/tanstack-start/docs/design/index.md +113 -69
- package/templates/tanstack-start/docs/design/safe-area.md +51 -250
- package/templates/tanstack-start/docs/design/tailwind-setup.md +45 -359
- package/templates/tanstack-start/docs/guides/conventions.md +103 -0
- package/templates/tanstack-start/docs/guides/env-setup.md +34 -340
- package/templates/tanstack-start/docs/guides/getting-started.md +22 -209
- package/templates/tanstack-start/docs/guides/hooks.md +166 -0
- package/templates/tanstack-start/docs/guides/routes.md +166 -0
- package/templates/tanstack-start/docs/guides/services.md +143 -0
- package/templates/tanstack-start/docs/library/better-auth/2fa.md +27 -115
- package/templates/tanstack-start/docs/library/better-auth/advanced.md +22 -105
- package/templates/tanstack-start/docs/library/better-auth/index.md +17 -66
- package/templates/tanstack-start/docs/library/better-auth/plugins.md +11 -88
- package/templates/tanstack-start/docs/library/better-auth/session.md +12 -92
- package/templates/tanstack-start/docs/library/better-auth/setup.md +9 -91
- package/templates/tanstack-start/docs/library/prisma/cloudflare-d1.md +30 -358
- package/templates/tanstack-start/docs/library/prisma/config.md +27 -327
- package/templates/tanstack-start/docs/library/prisma/crud.md +46 -174
- package/templates/tanstack-start/docs/library/prisma/index.md +23 -113
- package/templates/tanstack-start/docs/library/prisma/relations.md +31 -153
- package/templates/tanstack-start/docs/library/prisma/schema.md +40 -217
- package/templates/tanstack-start/docs/library/prisma/setup.md +12 -112
- package/templates/tanstack-start/docs/library/prisma/transactions.md +20 -110
- package/templates/tanstack-start/docs/library/tanstack-query/index.md +26 -97
- package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +28 -107
- package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +44 -146
- package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +33 -127
- package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +49 -149
- package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +19 -112
- package/templates/tanstack-start/docs/library/tanstack-start/index.md +33 -80
- package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +28 -106
- package/templates/tanstack-start/docs/library/tanstack-start/routing.md +21 -118
- package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +34 -246
- package/templates/tanstack-start/docs/library/tanstack-start/setup.md +6 -39
- package/templates/tanstack-start/docs/library/zod/complex-types.md +32 -156
- package/templates/tanstack-start/docs/library/zod/index.md +31 -144
- package/templates/tanstack-start/docs/library/zod/transforms.md +20 -129
- package/templates/tanstack-start/docs/library/zod/validation.md +39 -155
- package/templates/hono/docs/commands/git.md +0 -145
- package/templates/hono/docs/mcp/context7.md +0 -106
- package/templates/hono/docs/mcp/index.md +0 -176
- package/templates/hono/docs/mcp/sequential-thinking.md +0 -101
- package/templates/hono/docs/mcp/serena.md +0 -269
- package/templates/hono/docs/mcp/sgrep.md +0 -105
- package/templates/hono/docs/skills/gemini-review/SKILL.md +0 -220
- package/templates/hono/docs/skills/gemini-review/references/checklists.md +0 -136
- package/templates/hono/docs/skills/gemini-review/references/prompt-templates.md +0 -303
- package/templates/npx/docs/commands/git.md +0 -145
- package/templates/npx/docs/mcp/index.md +0 -60
- package/templates/npx/docs/skills/gemini-review/SKILL.md +0 -220
- package/templates/npx/docs/skills/gemini-review/references/checklists.md +0 -134
- package/templates/npx/docs/skills/gemini-review/references/prompt-templates.md +0 -301
- package/templates/tanstack-start/docs/commands/git.md +0 -145
- package/templates/tanstack-start/docs/design/accessibility.md +0 -433
- package/templates/tanstack-start/docs/design/color.md +0 -235
- package/templates/tanstack-start/docs/design/spacing.md +0 -341
- package/templates/tanstack-start/docs/design/typography.md +0 -324
- package/templates/tanstack-start/docs/guides/best-practices.md +0 -950
- package/templates/tanstack-start/docs/guides/husky-lint-staged.md +0 -303
- package/templates/tanstack-start/docs/guides/prettier.md +0 -189
- package/templates/tanstack-start/docs/guides/project-templates.md +0 -710
- package/templates/tanstack-start/docs/library/tanstack-query/setup.md +0 -107
- package/templates/tanstack-start/docs/library/zod/basic-types.md +0 -186
- package/templates/tanstack-start/docs/mcp/context7.md +0 -204
- package/templates/tanstack-start/docs/mcp/index.md +0 -177
- package/templates/tanstack-start/docs/mcp/sequential-thinking.md +0 -180
- package/templates/tanstack-start/docs/mcp/serena.md +0 -269
- package/templates/tanstack-start/docs/mcp/sgrep.md +0 -174
- package/templates/tanstack-start/docs/skills/gemini-review/SKILL.md +0 -220
- package/templates/tanstack-start/docs/skills/gemini-review/references/checklists.md +0 -144
- package/templates/tanstack-start/docs/skills/gemini-review/references/prompt-templates.md +0 -292
|
@@ -4,27 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## 왜 console.log 대신 Pino를 사용해야 하나요?
|
|
8
|
-
|
|
9
|
-
| 항목 | console.log | Pino |
|
|
10
|
-
|------|-------------|------|
|
|
11
|
-
| **출력 형식** | 비정형 텍스트 | 구조화된 JSON |
|
|
12
|
-
| **성능** | 느림 | 초고속 (30x 빠름) |
|
|
13
|
-
| **로그 레벨** | 없음 | debug, info, warn, error, fatal |
|
|
14
|
-
| **컨텍스트 추가** | 수동 문자열 연결 | 자동 객체 바인딩 |
|
|
15
|
-
| **프로덕션 분석** | 어려움 | JSON 파싱으로 쉬움 |
|
|
16
|
-
| **Child Logger** | 불가 | 요청별 컨텍스트 분리 |
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
7
|
## 설치
|
|
21
8
|
|
|
22
9
|
```bash
|
|
23
|
-
# pino + pino-pretty (개발용 포맷터)
|
|
24
10
|
npm install pino pino-pretty
|
|
25
|
-
|
|
26
|
-
# pino-http (HTTP 요청 로깅)
|
|
27
|
-
npm install pino-http
|
|
28
11
|
```
|
|
29
12
|
|
|
30
13
|
---
|
|
@@ -53,385 +36,111 @@ export const logger = pino({
|
|
|
53
36
|
})
|
|
54
37
|
```
|
|
55
38
|
|
|
56
|
-
### 환경별 출력
|
|
57
|
-
|
|
58
|
-
**개발 환경** (pino-pretty):
|
|
59
|
-
```
|
|
60
|
-
2024-01-15 10:30:45 INFO: User created successfully
|
|
61
|
-
userId: "user_123"
|
|
62
|
-
email: "user@example.com"
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
**프로덕션** (JSON):
|
|
66
|
-
```json
|
|
67
|
-
{"level":30,"time":1705312245000,"msg":"User created successfully","userId":"user_123","email":"user@example.com"}
|
|
68
|
-
```
|
|
69
|
-
|
|
70
39
|
---
|
|
71
40
|
|
|
72
|
-
##
|
|
73
|
-
|
|
74
|
-
### 방법 1: pino-http 미들웨어
|
|
41
|
+
## 로그 레벨
|
|
75
42
|
|
|
76
43
|
```typescript
|
|
77
|
-
//
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
Variables: {
|
|
84
|
-
log: pino.Logger
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export const loggerMiddleware = createMiddleware<Env>(async (c, next) => {
|
|
89
|
-
// Hono의 request-id를 pino-http에 전달
|
|
90
|
-
c.env.incoming.id = c.req.header('x-request-id') ?? crypto.randomUUID()
|
|
91
|
-
|
|
92
|
-
// pino-http 미들웨어 실행
|
|
93
|
-
await new Promise((resolve) =>
|
|
94
|
-
pinoHttp({ logger })(c.env.incoming, c.env.outgoing, () => resolve(undefined))
|
|
95
|
-
)
|
|
44
|
+
logger.debug({ data }, 'Debug message') // 10
|
|
45
|
+
logger.info({ userId }, 'User logged in') // 30
|
|
46
|
+
logger.warn({ attempt }, 'Rate limit') // 40
|
|
47
|
+
logger.error({ err }, 'Failed') // 50
|
|
48
|
+
logger.fatal({ err }, 'Crash') // 60
|
|
49
|
+
```
|
|
96
50
|
|
|
97
|
-
|
|
98
|
-
c.set('log', c.env.incoming.log)
|
|
51
|
+
---
|
|
99
52
|
|
|
100
|
-
|
|
101
|
-
})
|
|
102
|
-
```
|
|
53
|
+
## Hono 통합
|
|
103
54
|
|
|
104
|
-
###
|
|
55
|
+
### 미들웨어
|
|
105
56
|
|
|
106
57
|
```typescript
|
|
107
|
-
// middleware/logger.ts
|
|
108
58
|
import { createMiddleware } from 'hono/factory'
|
|
109
59
|
import { logger } from '@/lib/logger'
|
|
110
|
-
import type { Logger } from 'pino'
|
|
111
60
|
|
|
112
|
-
type Env = {
|
|
113
|
-
Variables: {
|
|
114
|
-
log: Logger
|
|
115
|
-
requestId: string
|
|
116
|
-
}
|
|
117
|
-
}
|
|
61
|
+
type Env = { Variables: { log: pino.Logger } }
|
|
118
62
|
|
|
119
63
|
export const loggerMiddleware = createMiddleware<Env>(async (c, next) => {
|
|
120
64
|
const requestId = c.req.header('x-request-id') ?? crypto.randomUUID()
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
// 요청별 child logger 생성
|
|
124
|
-
const log = logger.child({
|
|
125
|
-
requestId,
|
|
126
|
-
method: c.req.method,
|
|
127
|
-
path: c.req.path,
|
|
128
|
-
})
|
|
65
|
+
const log = logger.child({ requestId })
|
|
129
66
|
|
|
130
67
|
c.set('log', log)
|
|
131
|
-
c.set('requestId', requestId)
|
|
132
|
-
|
|
133
|
-
log.info('Request started')
|
|
134
68
|
|
|
69
|
+
const start = Date.now()
|
|
135
70
|
await next()
|
|
136
71
|
|
|
137
|
-
|
|
138
|
-
|
|
72
|
+
log.info({
|
|
73
|
+
method: c.req.method,
|
|
74
|
+
path: c.req.path,
|
|
75
|
+
status: c.res.status,
|
|
76
|
+
duration: Date.now() - start,
|
|
77
|
+
}, 'Request completed')
|
|
139
78
|
})
|
|
140
79
|
```
|
|
141
80
|
|
|
142
|
-
###
|
|
81
|
+
### 사용
|
|
143
82
|
|
|
144
83
|
```typescript
|
|
145
|
-
// index.ts
|
|
146
|
-
import { Hono } from 'hono'
|
|
147
|
-
import { loggerMiddleware } from '@/middleware/logger'
|
|
148
|
-
|
|
149
|
-
const app = new Hono()
|
|
150
|
-
|
|
151
|
-
// 모든 라우트에 로깅 미들웨어 적용
|
|
152
84
|
app.use(loggerMiddleware)
|
|
153
85
|
|
|
154
|
-
app.
|
|
155
|
-
const log = c.get('log')
|
|
156
|
-
const id = c.req.param('id')
|
|
157
|
-
|
|
158
|
-
log.info({ userId: id }, 'Fetching user')
|
|
159
|
-
|
|
160
|
-
const user = await prisma.user.findUnique({ where: { id } })
|
|
161
|
-
|
|
162
|
-
if (!user) {
|
|
163
|
-
log.warn({ userId: id }, 'User not found')
|
|
164
|
-
return c.json({ error: 'User not found' }, 404)
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
log.debug({ user }, 'User fetched')
|
|
168
|
-
return c.json({ user })
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
export default app
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
---
|
|
175
|
-
|
|
176
|
-
## 로그 레벨
|
|
177
|
-
|
|
178
|
-
```typescript
|
|
179
|
-
const log = c.get('log')
|
|
180
|
-
|
|
181
|
-
log.trace('매우 상세한 디버깅 정보') // level: 10
|
|
182
|
-
log.debug('디버깅 정보') // level: 20
|
|
183
|
-
log.info('일반 정보') // level: 30
|
|
184
|
-
log.warn('경고') // level: 40
|
|
185
|
-
log.error('에러') // level: 50
|
|
186
|
-
log.fatal('치명적 에러') // level: 60
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
### 레벨별 사용 가이드
|
|
190
|
-
|
|
191
|
-
| 레벨 | 용도 | 예시 |
|
|
192
|
-
|------|------|------|
|
|
193
|
-
| `trace` | 매우 상세한 흐름 추적 | 함수 진입/종료, 변수 값 |
|
|
194
|
-
| `debug` | 개발 중 디버깅 | 쿼리 결과, 중간 계산값 |
|
|
195
|
-
| `info` | 주요 이벤트 | 사용자 생성, 결제 완료 |
|
|
196
|
-
| `warn` | 주의 필요 | 재시도 발생, 느린 쿼리 |
|
|
197
|
-
| `error` | 에러 발생 | API 실패, 예외 처리 |
|
|
198
|
-
| `fatal` | 시스템 중단 | 서버 시작 실패 |
|
|
199
|
-
|
|
200
|
-
---
|
|
201
|
-
|
|
202
|
-
## 구조화된 로깅 패턴
|
|
203
|
-
|
|
204
|
-
### 객체와 메시지 함께 로깅
|
|
205
|
-
|
|
206
|
-
```typescript
|
|
207
|
-
// ✅ 올바른 패턴: 객체 먼저, 메시지 나중
|
|
208
|
-
log.info({ userId: '123', action: 'login' }, 'User logged in')
|
|
209
|
-
|
|
210
|
-
// ❌ 잘못된 패턴: 문자열 연결
|
|
211
|
-
log.info('User ' + userId + ' logged in') // 구조화되지 않음
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
### 에러 로깅
|
|
215
|
-
|
|
216
|
-
```typescript
|
|
217
|
-
app.get('/risky', async (c) => {
|
|
86
|
+
app.post('/users', async (c) => {
|
|
218
87
|
const log = c.get('log')
|
|
88
|
+
const data = c.req.valid('json')
|
|
219
89
|
|
|
220
|
-
try {
|
|
221
|
-
await riskyOperation()
|
|
222
|
-
} catch (error) {
|
|
223
|
-
// ✅ err 키로 에러 객체 전달 (스택 트레이스 자동 포함)
|
|
224
|
-
log.error({ err: error, context: 'riskyOperation' }, 'Operation failed')
|
|
225
|
-
throw error
|
|
226
|
-
}
|
|
227
|
-
})
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
**출력**:
|
|
231
|
-
```json
|
|
232
|
-
{
|
|
233
|
-
"level": 50,
|
|
234
|
-
"time": 1705312245000,
|
|
235
|
-
"requestId": "req_abc123",
|
|
236
|
-
"method": "GET",
|
|
237
|
-
"path": "/risky",
|
|
238
|
-
"err": {
|
|
239
|
-
"type": "Error",
|
|
240
|
-
"message": "Connection refused",
|
|
241
|
-
"stack": "Error: Connection refused\n at ..."
|
|
242
|
-
},
|
|
243
|
-
"context": "riskyOperation",
|
|
244
|
-
"msg": "Operation failed"
|
|
245
|
-
}
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
---
|
|
249
|
-
|
|
250
|
-
## 서비스 레이어에서 사용
|
|
251
|
-
|
|
252
|
-
### Child Logger 전달 패턴
|
|
253
|
-
|
|
254
|
-
```typescript
|
|
255
|
-
// services/user.ts
|
|
256
|
-
import type { Logger } from 'pino'
|
|
257
|
-
import { prisma } from '@/database/prisma'
|
|
258
|
-
|
|
259
|
-
export const createUser = async (
|
|
260
|
-
data: CreateUserInput,
|
|
261
|
-
log: Logger // child logger 전달받음
|
|
262
|
-
) => {
|
|
263
90
|
log.info({ email: data.email }, 'Creating user')
|
|
264
91
|
|
|
265
92
|
const user = await prisma.user.create({ data })
|
|
266
|
-
|
|
267
93
|
log.info({ userId: user.id }, 'User created')
|
|
268
|
-
return user
|
|
269
|
-
}
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
```typescript
|
|
273
|
-
// routes/users.ts
|
|
274
|
-
import { Hono } from 'hono'
|
|
275
|
-
import { zValidator } from '@hono/zod-validator'
|
|
276
|
-
import { createUser } from '@/services/user'
|
|
277
|
-
import { createUserSchema } from '@/validators/user'
|
|
278
|
-
|
|
279
|
-
const users = new Hono()
|
|
280
94
|
|
|
281
|
-
users.post('/', zValidator('json', createUserSchema), async (c) => {
|
|
282
|
-
const log = c.get('log')
|
|
283
|
-
const data = c.req.valid('json')
|
|
284
|
-
|
|
285
|
-
const user = await createUser(data, log)
|
|
286
95
|
return c.json({ user }, 201)
|
|
287
96
|
})
|
|
288
|
-
|
|
289
|
-
export { users }
|
|
290
97
|
```
|
|
291
98
|
|
|
292
99
|
---
|
|
293
100
|
|
|
294
|
-
##
|
|
295
|
-
|
|
296
|
-
### pino-pretty 전체 옵션
|
|
101
|
+
## Child Logger
|
|
297
102
|
|
|
298
103
|
```typescript
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
export const logger = pino({
|
|
303
|
-
level: process.env.LOG_LEVEL || 'info',
|
|
304
|
-
transport:
|
|
305
|
-
process.env.NODE_ENV === 'development'
|
|
306
|
-
? {
|
|
307
|
-
target: 'pino-pretty',
|
|
308
|
-
options: {
|
|
309
|
-
colorize: true,
|
|
310
|
-
translateTime: 'SYS:yyyy-mm-dd HH:MM:ss.l',
|
|
311
|
-
ignore: 'pid,hostname',
|
|
312
|
-
singleLine: false,
|
|
313
|
-
levelFirst: true,
|
|
314
|
-
messageFormat: '{levelLabel} - {msg}',
|
|
315
|
-
customColors: 'info:blue,warn:yellow,error:red,fatal:bgRed',
|
|
316
|
-
errorProps: 'stack,code,cause',
|
|
317
|
-
},
|
|
318
|
-
}
|
|
319
|
-
: undefined,
|
|
104
|
+
const log = logger.child({
|
|
105
|
+
requestId: 'abc-123',
|
|
106
|
+
userId: 'user-456',
|
|
320
107
|
})
|
|
321
|
-
```
|
|
322
|
-
|
|
323
|
-
### TypeScript 타입 강제
|
|
324
108
|
|
|
325
|
-
|
|
326
|
-
//
|
|
327
|
-
declare module 'pino' {
|
|
328
|
-
interface LogFnFields {
|
|
329
|
-
userId?: string
|
|
330
|
-
requestId?: string
|
|
331
|
-
action?: string
|
|
332
|
-
}
|
|
333
|
-
}
|
|
109
|
+
log.info('Message with context')
|
|
110
|
+
// {"requestId":"abc-123","userId":"user-456","msg":"Message with context"}
|
|
334
111
|
```
|
|
335
112
|
|
|
336
113
|
---
|
|
337
114
|
|
|
338
|
-
##
|
|
115
|
+
## 에러 로깅
|
|
339
116
|
|
|
340
117
|
```typescript
|
|
341
|
-
// index.ts
|
|
342
|
-
import { Hono } from 'hono'
|
|
343
|
-
import { HTTPException } from 'hono/http-exception'
|
|
344
|
-
import { logger } from '@/lib/logger'
|
|
345
|
-
|
|
346
|
-
const app = new Hono()
|
|
347
|
-
|
|
348
118
|
app.onError((err, c) => {
|
|
349
|
-
const log = c.get('log')
|
|
119
|
+
const log = c.get('log')
|
|
350
120
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
121
|
+
log.error({
|
|
122
|
+
err: {
|
|
123
|
+
message: err.message,
|
|
124
|
+
stack: err.stack,
|
|
125
|
+
name: err.name,
|
|
126
|
+
},
|
|
127
|
+
path: c.req.path,
|
|
128
|
+
}, 'Request failed')
|
|
355
129
|
|
|
356
|
-
log.error({ err }, 'Unhandled error')
|
|
357
130
|
return c.json({ error: 'Internal Server Error' }, 500)
|
|
358
131
|
})
|
|
359
132
|
```
|
|
360
133
|
|
|
361
134
|
---
|
|
362
135
|
|
|
363
|
-
## 프로덕션
|
|
136
|
+
## 프로덕션 출력
|
|
364
137
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
```bash
|
|
368
|
-
# .env
|
|
369
|
-
LOG_LEVEL=info # production
|
|
370
|
-
# LOG_LEVEL=debug # staging
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
### 멀티 스트림 (파일 + stdout)
|
|
374
|
-
|
|
375
|
-
```typescript
|
|
376
|
-
import pino from 'pino'
|
|
377
|
-
|
|
378
|
-
const streams = [
|
|
379
|
-
{ level: 'info', stream: process.stdout },
|
|
380
|
-
{ level: 'error', stream: pino.destination('./logs/error.log') },
|
|
381
|
-
]
|
|
382
|
-
|
|
383
|
-
export const logger = pino(
|
|
384
|
-
{ level: 'debug' },
|
|
385
|
-
pino.multistream(streams)
|
|
386
|
-
)
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
---
|
|
390
|
-
|
|
391
|
-
## Cloudflare Workers 주의사항
|
|
392
|
-
|
|
393
|
-
Cloudflare Workers에서는 `pino-pretty` transport를 사용할 수 없습니다. 대신 JSON 출력을 사용하세요:
|
|
394
|
-
|
|
395
|
-
```typescript
|
|
396
|
-
// lib/logger.ts (Cloudflare Workers)
|
|
397
|
-
import pino from 'pino'
|
|
398
|
-
|
|
399
|
-
export const logger = pino({
|
|
400
|
-
level: 'info',
|
|
401
|
-
// transport 옵션 제거 (Workers에서는 지원 안 됨)
|
|
402
|
-
})
|
|
403
|
-
```
|
|
404
|
-
|
|
405
|
-
로컬 개발 시 CLI에서 pino-pretty 사용:
|
|
406
|
-
|
|
407
|
-
```bash
|
|
408
|
-
wrangler dev | npx pino-pretty
|
|
409
|
-
```
|
|
410
|
-
|
|
411
|
-
---
|
|
412
|
-
|
|
413
|
-
## ❌ 하지 말아야 할 것
|
|
414
|
-
|
|
415
|
-
```typescript
|
|
416
|
-
// ❌ 민감한 정보 로깅 금지
|
|
417
|
-
log.info({ password: user.password }, 'User logged in')
|
|
418
|
-
|
|
419
|
-
// ❌ 문자열 연결 사용 금지
|
|
420
|
-
log.info('User ' + userId + ' created at ' + new Date())
|
|
421
|
-
|
|
422
|
-
// ❌ console.log 사용 금지 (pino 사용하세요)
|
|
423
|
-
console.log('Processing request') // ❌
|
|
424
|
-
log.info('Processing request') // ✅
|
|
425
|
-
|
|
426
|
-
// ❌ 로그 레벨 무시 금지
|
|
427
|
-
log.debug('중요한 에러 발생!') // ❌ error 레벨 사용해야 함
|
|
428
|
-
log.error('중요한 에러 발생!') // ✅
|
|
138
|
+
```json
|
|
139
|
+
{"level":30,"time":1705312245000,"requestId":"abc-123","msg":"Request completed","method":"POST","path":"/users","status":201,"duration":45}
|
|
429
140
|
```
|
|
430
141
|
|
|
431
142
|
---
|
|
432
143
|
|
|
433
144
|
## 관련 문서
|
|
434
145
|
|
|
435
|
-
- [미들웨어](../hono/middleware.md)
|
|
436
|
-
- [에러 처리](../hono/error-handling.md)
|
|
437
|
-
- [아키텍처](../../architecture/architecture.md)
|
|
146
|
+
- [Hono 미들웨어](../hono/middleware.md)
|