muno-claude-plugin 1.7.0 → 1.9.0

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.
@@ -0,0 +1,666 @@
1
+ # [서비스 이름] API 문서
2
+
3
+ > Generated from Swagger/OpenAPI
4
+ > Version: [version]
5
+ > Generated Date: [YYYY-MM-DD]
6
+
7
+ ---
8
+
9
+ ## 📋 목차
10
+
11
+ - [개요](#개요)
12
+ - [서버 정보](#서버-정보)
13
+ - [인증](#인증)
14
+ - [API 엔드포인트](#api-엔드포인트)
15
+ - [데이터 모델](#데이터-모델)
16
+ - [에러 코드](#에러-코드)
17
+
18
+ ---
19
+
20
+ ## 개요
21
+
22
+ **서비스명**: [Service Title]
23
+ **버전**: [version]
24
+ **설명**: [description]
25
+
26
+ ### 주요 기능
27
+
28
+ - 기능 1
29
+ - 기능 2
30
+ - 기능 3
31
+
32
+ ---
33
+
34
+ ## 서버 정보
35
+
36
+ ### Base URLs
37
+
38
+ | 환경 | URL | 설명 |
39
+ |------|-----|------|
40
+ | Local | `http://localhost:8080` | 로컬 개발 서버 |
41
+ | Development | `https://dev-api.example.com` | 개발 환경 |
42
+ | Staging | `https://staging-api.example.com` | 스테이징 환경 |
43
+ | Production | `https://api.example.com` | 프로덕션 환경 |
44
+
45
+ ### Contact
46
+
47
+ - **Email**: [contact email]
48
+ - **License**: [license name]
49
+
50
+ ---
51
+
52
+ ## 인증
53
+
54
+ ### Bearer Token
55
+
56
+ 이 API는 Bearer Token 인증을 사용합니다.
57
+
58
+ **Header**:
59
+ ```
60
+ Authorization: Bearer {token}
61
+ ```
62
+
63
+ **토큰 획득 방법**:
64
+ 1. `/auth/login` 엔드포인트로 로그인
65
+ 2. 응답에서 `accessToken` 획득
66
+ 3. 모든 요청의 Authorization 헤더에 포함
67
+
68
+ **Example**:
69
+ ```bash
70
+ curl -X GET "https://api.example.com/api/users" \
71
+ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
72
+ ```
73
+
74
+ ---
75
+
76
+ ## API 엔드포인트
77
+
78
+ ### 👤 User
79
+
80
+ 사용자 관리 관련 API
81
+
82
+ ---
83
+
84
+ #### `GET /api/users`
85
+
86
+ 사용자 목록을 조회합니다.
87
+
88
+ **Parameters**:
89
+
90
+ | Name | In | Type | Required | Description | Default |
91
+ |------|-----|------|----------|-------------|---------|
92
+ | page | query | integer | ❌ | Page number | 1 |
93
+ | size | query | integer | ❌ | Page size | 20 |
94
+ | sort | query | string | ❌ | Sort field | createdAt |
95
+ | order | query | string | ❌ | Sort order (asc/desc) | desc |
96
+
97
+ **Request Example**:
98
+
99
+ ```bash
100
+ curl -X GET "http://localhost:8080/api/users?page=1&size=20" \
101
+ -H "Authorization: Bearer {token}"
102
+ ```
103
+
104
+ **Response**:
105
+
106
+ - **200 OK**
107
+
108
+ ```json
109
+ {
110
+ "data": [
111
+ {
112
+ "id": 1,
113
+ "name": "John Doe",
114
+ "email": "john@example.com",
115
+ "role": "USER",
116
+ "createdAt": "2025-01-01T00:00:00Z"
117
+ }
118
+ ],
119
+ "pagination": {
120
+ "page": 1,
121
+ "size": 20,
122
+ "totalElements": 100,
123
+ "totalPages": 5
124
+ }
125
+ }
126
+ ```
127
+
128
+ - **401 Unauthorized**
129
+
130
+ ```json
131
+ {
132
+ "error": "UNAUTHORIZED",
133
+ "message": "Invalid or missing authentication token"
134
+ }
135
+ ```
136
+
137
+ **Code Examples**:
138
+
139
+ <details>
140
+ <summary>JavaScript (fetch)</summary>
141
+
142
+ ```javascript
143
+ const response = await fetch('http://localhost:8080/api/users?page=1&size=20', {
144
+ method: 'GET',
145
+ headers: {
146
+ 'Authorization': `Bearer ${token}`,
147
+ 'Content-Type': 'application/json'
148
+ }
149
+ });
150
+ const data = await response.json();
151
+ console.log(data);
152
+ ```
153
+ </details>
154
+
155
+ <details>
156
+ <summary>Python (requests)</summary>
157
+
158
+ ```python
159
+ import requests
160
+
161
+ headers = {
162
+ 'Authorization': f'Bearer {token}',
163
+ 'Content-Type': 'application/json'
164
+ }
165
+ response = requests.get(
166
+ 'http://localhost:8080/api/users',
167
+ headers=headers,
168
+ params={'page': 1, 'size': 20}
169
+ )
170
+ print(response.json())
171
+ ```
172
+ </details>
173
+
174
+ <details>
175
+ <summary>Java (Spring WebClient)</summary>
176
+
177
+ ```java
178
+ WebClient client = WebClient.create("http://localhost:8080");
179
+ UserListResponse response = client.get()
180
+ .uri(uriBuilder -> uriBuilder
181
+ .path("/api/users")
182
+ .queryParam("page", 1)
183
+ .queryParam("size", 20)
184
+ .build())
185
+ .header("Authorization", "Bearer " + token)
186
+ .retrieve()
187
+ .bodyToMono(UserListResponse.class)
188
+ .block();
189
+ ```
190
+ </details>
191
+
192
+ <details>
193
+ <summary>Kotlin (Spring WebClient)</summary>
194
+
195
+ ```kotlin
196
+ val client = WebClient.create("http://localhost:8080")
197
+ val response = client.get()
198
+ .uri { uriBuilder ->
199
+ uriBuilder
200
+ .path("/api/users")
201
+ .queryParam("page", 1)
202
+ .queryParam("size", 20)
203
+ .build()
204
+ }
205
+ .header("Authorization", "Bearer $token")
206
+ .retrieve()
207
+ .awaitBody<UserListResponse>()
208
+ ```
209
+ </details>
210
+
211
+ ---
212
+
213
+ #### `GET /api/users/{id}`
214
+
215
+ 특정 사용자의 상세 정보를 조회합니다.
216
+
217
+ **Parameters**:
218
+
219
+ | Name | In | Type | Required | Description |
220
+ |------|-----|------|----------|-------------|
221
+ | id | path | integer | ✅ | User ID |
222
+
223
+ **Request Example**:
224
+
225
+ ```bash
226
+ curl -X GET "http://localhost:8080/api/users/1" \
227
+ -H "Authorization: Bearer {token}"
228
+ ```
229
+
230
+ **Response**:
231
+
232
+ - **200 OK**
233
+
234
+ ```json
235
+ {
236
+ "id": 1,
237
+ "name": "John Doe",
238
+ "email": "john@example.com",
239
+ "role": "USER",
240
+ "profile": {
241
+ "avatar": "https://example.com/avatar.jpg",
242
+ "bio": "Software Engineer"
243
+ },
244
+ "createdAt": "2025-01-01T00:00:00Z",
245
+ "updatedAt": "2025-01-01T00:00:00Z"
246
+ }
247
+ ```
248
+
249
+ - **404 Not Found**
250
+
251
+ ```json
252
+ {
253
+ "error": "NOT_FOUND",
254
+ "message": "User not found with id: 1"
255
+ }
256
+ ```
257
+
258
+ ---
259
+
260
+ #### `POST /api/users`
261
+
262
+ 새로운 사용자를 생성합니다.
263
+
264
+ **Request Body**:
265
+
266
+ ```json
267
+ {
268
+ "name": "string",
269
+ "email": "string",
270
+ "password": "string",
271
+ "role": "USER"
272
+ }
273
+ ```
274
+
275
+ **Request Example**:
276
+
277
+ ```bash
278
+ curl -X POST "http://localhost:8080/api/users" \
279
+ -H "Authorization: Bearer {token}" \
280
+ -H "Content-Type: application/json" \
281
+ -d '{
282
+ "name": "Jane Doe",
283
+ "email": "jane@example.com",
284
+ "password": "securePassword123",
285
+ "role": "USER"
286
+ }'
287
+ ```
288
+
289
+ **Response**:
290
+
291
+ - **201 Created**
292
+
293
+ ```json
294
+ {
295
+ "id": 2,
296
+ "name": "Jane Doe",
297
+ "email": "jane@example.com",
298
+ "role": "USER",
299
+ "createdAt": "2025-01-01T00:00:00Z"
300
+ }
301
+ ```
302
+
303
+ - **400 Bad Request**
304
+
305
+ ```json
306
+ {
307
+ "error": "VALIDATION_ERROR",
308
+ "message": "Invalid input",
309
+ "details": [
310
+ {
311
+ "field": "email",
312
+ "message": "Email already exists"
313
+ }
314
+ ]
315
+ }
316
+ ```
317
+
318
+ ---
319
+
320
+ #### `PUT /api/users/{id}`
321
+
322
+ 사용자 정보를 수정합니다.
323
+
324
+ **Parameters**:
325
+
326
+ | Name | In | Type | Required | Description |
327
+ |------|-----|------|----------|-------------|
328
+ | id | path | integer | ✅ | User ID |
329
+
330
+ **Request Body**:
331
+
332
+ ```json
333
+ {
334
+ "name": "string",
335
+ "email": "string",
336
+ "role": "USER"
337
+ }
338
+ ```
339
+
340
+ **Request Example**:
341
+
342
+ ```bash
343
+ curl -X PUT "http://localhost:8080/api/users/1" \
344
+ -H "Authorization: Bearer {token}" \
345
+ -H "Content-Type: application/json" \
346
+ -d '{
347
+ "name": "John Updated",
348
+ "email": "john.updated@example.com"
349
+ }'
350
+ ```
351
+
352
+ **Response**:
353
+
354
+ - **200 OK**
355
+
356
+ ```json
357
+ {
358
+ "id": 1,
359
+ "name": "John Updated",
360
+ "email": "john.updated@example.com",
361
+ "role": "USER",
362
+ "updatedAt": "2025-01-01T12:00:00Z"
363
+ }
364
+ ```
365
+
366
+ - **404 Not Found**
367
+
368
+ ```json
369
+ {
370
+ "error": "NOT_FOUND",
371
+ "message": "User not found with id: 1"
372
+ }
373
+ ```
374
+
375
+ ---
376
+
377
+ #### `DELETE /api/users/{id}`
378
+
379
+ 사용자를 삭제합니다.
380
+
381
+ **Parameters**:
382
+
383
+ | Name | In | Type | Required | Description |
384
+ |------|-----|------|----------|-------------|
385
+ | id | path | integer | ✅ | User ID |
386
+
387
+ **Request Example**:
388
+
389
+ ```bash
390
+ curl -X DELETE "http://localhost:8080/api/users/1" \
391
+ -H "Authorization: Bearer {token}"
392
+ ```
393
+
394
+ **Response**:
395
+
396
+ - **204 No Content**
397
+
398
+ 성공적으로 삭제됨 (본문 없음)
399
+
400
+ - **404 Not Found**
401
+
402
+ ```json
403
+ {
404
+ "error": "NOT_FOUND",
405
+ "message": "User not found with id: 1"
406
+ }
407
+ ```
408
+
409
+ ---
410
+
411
+ ### 🔐 Authentication
412
+
413
+ 인증 관련 API
414
+
415
+ ---
416
+
417
+ #### `POST /auth/login`
418
+
419
+ 사용자 로그인
420
+
421
+ **Request Body**:
422
+
423
+ ```json
424
+ {
425
+ "email": "string",
426
+ "password": "string"
427
+ }
428
+ ```
429
+
430
+ **Request Example**:
431
+
432
+ ```bash
433
+ curl -X POST "http://localhost:8080/auth/login" \
434
+ -H "Content-Type: application/json" \
435
+ -d '{
436
+ "email": "john@example.com",
437
+ "password": "password123"
438
+ }'
439
+ ```
440
+
441
+ **Response**:
442
+
443
+ - **200 OK**
444
+
445
+ ```json
446
+ {
447
+ "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
448
+ "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
449
+ "tokenType": "Bearer",
450
+ "expiresIn": 3600,
451
+ "user": {
452
+ "id": 1,
453
+ "name": "John Doe",
454
+ "email": "john@example.com",
455
+ "role": "USER"
456
+ }
457
+ }
458
+ ```
459
+
460
+ - **401 Unauthorized**
461
+
462
+ ```json
463
+ {
464
+ "error": "INVALID_CREDENTIALS",
465
+ "message": "Invalid email or password"
466
+ }
467
+ ```
468
+
469
+ ---
470
+
471
+ #### `POST /auth/refresh`
472
+
473
+ Access Token 갱신
474
+
475
+ **Request Body**:
476
+
477
+ ```json
478
+ {
479
+ "refreshToken": "string"
480
+ }
481
+ ```
482
+
483
+ **Response**:
484
+
485
+ - **200 OK**
486
+
487
+ ```json
488
+ {
489
+ "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
490
+ "tokenType": "Bearer",
491
+ "expiresIn": 3600
492
+ }
493
+ ```
494
+
495
+ - **401 Unauthorized**
496
+
497
+ ```json
498
+ {
499
+ "error": "INVALID_TOKEN",
500
+ "message": "Refresh token is invalid or expired"
501
+ }
502
+ ```
503
+
504
+ ---
505
+
506
+ ## 데이터 모델
507
+
508
+ ### User
509
+
510
+ 사용자 정보
511
+
512
+ ```json
513
+ {
514
+ "id": "integer",
515
+ "name": "string",
516
+ "email": "string",
517
+ "role": "string",
518
+ "profile": "UserProfile",
519
+ "createdAt": "string (date-time)",
520
+ "updatedAt": "string (date-time)"
521
+ }
522
+ ```
523
+
524
+ **Properties**:
525
+
526
+ | Field | Type | Required | Description | Constraints |
527
+ |-------|------|----------|-------------|-------------|
528
+ | id | integer | ✅ | User ID | Auto-generated |
529
+ | name | string | ✅ | User name | 2-50 characters |
530
+ | email | string | ✅ | User email | Valid email format |
531
+ | role | string | ✅ | User role | Enum: USER, ADMIN |
532
+ | profile | UserProfile | ❌ | User profile | - |
533
+ | createdAt | string | ✅ | Created timestamp | ISO 8601 format |
534
+ | updatedAt | string | ✅ | Updated timestamp | ISO 8601 format |
535
+
536
+ ---
537
+
538
+ ### UserProfile
539
+
540
+ 사용자 프로필 정보
541
+
542
+ ```json
543
+ {
544
+ "avatar": "string",
545
+ "bio": "string",
546
+ "phone": "string"
547
+ }
548
+ ```
549
+
550
+ **Properties**:
551
+
552
+ | Field | Type | Required | Description | Constraints |
553
+ |-------|------|----------|-------------|-------------|
554
+ | avatar | string | ❌ | Avatar URL | Valid URL |
555
+ | bio | string | ❌ | User bio | Max 200 characters |
556
+ | phone | string | ❌ | Phone number | E.164 format |
557
+
558
+ ---
559
+
560
+ ### PaginationResponse
561
+
562
+ 페이지네이션 정보
563
+
564
+ ```json
565
+ {
566
+ "page": "integer",
567
+ "size": "integer",
568
+ "totalElements": "integer",
569
+ "totalPages": "integer"
570
+ }
571
+ ```
572
+
573
+ **Properties**:
574
+
575
+ | Field | Type | Description |
576
+ |-------|------|-------------|
577
+ | page | integer | Current page number (1-indexed) |
578
+ | size | integer | Page size |
579
+ | totalElements | integer | Total number of elements |
580
+ | totalPages | integer | Total number of pages |
581
+
582
+ ---
583
+
584
+ ### ErrorResponse
585
+
586
+ 에러 응답 형식
587
+
588
+ ```json
589
+ {
590
+ "error": "string",
591
+ "message": "string",
592
+ "details": "array"
593
+ }
594
+ ```
595
+
596
+ **Properties**:
597
+
598
+ | Field | Type | Description |
599
+ |-------|------|-------------|
600
+ | error | string | Error code |
601
+ | message | string | Human-readable error message |
602
+ | details | array | Additional error details (optional) |
603
+
604
+ ---
605
+
606
+ ## 에러 코드
607
+
608
+ ### HTTP Status Codes
609
+
610
+ | Code | Name | Description |
611
+ |------|------|-------------|
612
+ | 200 | OK | Request succeeded |
613
+ | 201 | Created | Resource created successfully |
614
+ | 204 | No Content | Request succeeded with no response body |
615
+ | 400 | Bad Request | Invalid request parameters |
616
+ | 401 | Unauthorized | Missing or invalid authentication |
617
+ | 403 | Forbidden | Insufficient permissions |
618
+ | 404 | Not Found | Resource not found |
619
+ | 409 | Conflict | Resource conflict (e.g., duplicate email) |
620
+ | 422 | Unprocessable Entity | Validation error |
621
+ | 500 | Internal Server Error | Server error |
622
+ | 503 | Service Unavailable | Service temporarily unavailable |
623
+
624
+ ### Application Error Codes
625
+
626
+ | Code | HTTP Status | Description |
627
+ |------|-------------|-------------|
628
+ | VALIDATION_ERROR | 400 | Input validation failed |
629
+ | INVALID_CREDENTIALS | 401 | Invalid email or password |
630
+ | UNAUTHORIZED | 401 | Missing or invalid token |
631
+ | FORBIDDEN | 403 | Insufficient permissions |
632
+ | NOT_FOUND | 404 | Resource not found |
633
+ | DUPLICATE_EMAIL | 409 | Email already exists |
634
+ | INTERNAL_ERROR | 500 | Internal server error |
635
+
636
+ ---
637
+
638
+ ## 부록
639
+
640
+ ### Rate Limiting
641
+
642
+ - **제한**: 100 requests per minute per user
643
+ - **Header**:
644
+ - `X-RateLimit-Limit`: 최대 요청 수
645
+ - `X-RateLimit-Remaining`: 남은 요청 수
646
+ - `X-RateLimit-Reset`: 제한 초기화 시각 (Unix timestamp)
647
+
648
+ ### Changelog
649
+
650
+ #### Version 1.0.0 (2025-01-01)
651
+ - Initial release
652
+ - User CRUD operations
653
+ - Authentication (JWT)
654
+
655
+ ---
656
+
657
+ ## 링크
658
+
659
+ - **Swagger UI**: http://localhost:8080/swagger-ui.html
660
+ - **API Docs JSON**: http://localhost:8080/v3/api-docs
661
+ - **Postman Collection**: [Download](./postman-collection.json)
662
+
663
+ ---
664
+
665
+ > 📝 이 문서는 Swagger/OpenAPI 명세로부터 자동 생성되었습니다.
666
+ > 마지막 업데이트: [YYYY-MM-DD HH:mm:ss]