snp-batch-validation/SWAGGER_GUIDE.md

518 lines
15 KiB
Markdown
Raw Normal View 히스토리

2025-10-22 13:50:04 +09:00
# Swagger API 문서화 가이드
**작성일**: 2025-10-16
**버전**: 1.0.0
**프로젝트**: SNP Batch - Spring Batch 기반 데이터 통합 시스템
---
## 📋 Swagger 설정 완료 사항
### ✅ 수정 완료 파일
1. **BaseController.java** - 공통 CRUD Controller 추상 클래스
- Java import alias 오류 수정 (`as SwaggerApiResponse` 제거)
- `@Operation` 어노테이션 내 `responses` 속성으로 통합
- 전체 경로로 어노테이션 사용: `@io.swagger.v3.oas.annotations.responses.ApiResponse`
2. **ProductWebController.java** - 샘플 제품 API Controller
- Java import alias 오류 수정
- 커스텀 엔드포인트 Swagger 어노테이션 수정
3. **SwaggerConfig.java** - Swagger/OpenAPI 3.0 설정
- 서버 포트 동적 설정 (`@Value("${server.port:8081}")`)
- 상세한 API 문서 설명 추가
- Markdown 형식 설명 추가
4. **BatchController.java** - 배치 관리 API (이미 올바르게 구현됨)
---
## 🌐 Swagger UI 접속 정보
### 접속 URL
```
Swagger UI: http://localhost:8081/swagger-ui/index.html
API 문서 (JSON): http://localhost:8081/v3/api-docs
API 문서 (YAML): http://localhost:8081/v3/api-docs.yaml
```
### 제공되는 API 그룹
> **참고**: BaseController는 추상 클래스이므로 별도의 API 그룹으로 표시되지 않습니다.
> 상속받는 Controller(예: ProductWebController)의 `@Tag`로 모든 CRUD 엔드포인트가 그룹화됩니다.
#### 1. **Batch Management API** (`/api/batch`)
배치 작업 실행 및 스케줄 관리
**엔드포인트**:
- `POST /api/batch/jobs/{jobName}/execute` - 배치 작업 실행
- `GET /api/batch/jobs` - 배치 작업 목록 조회
- `GET /api/batch/jobs/{jobName}/executions` - 실행 이력 조회
- `POST /api/batch/executions/{executionId}/stop` - 실행 중지
- `GET /api/batch/schedules` - 스케줄 목록 조회
- `POST /api/batch/schedules` - 스케줄 생성
- `PUT /api/batch/schedules/{jobName}` - 스케줄 수정
- `DELETE /api/batch/schedules/{jobName}` - 스케줄 삭제
- `PATCH /api/batch/schedules/{jobName}/toggle` - 스케줄 활성화/비활성화
- `GET /api/batch/dashboard` - 대시보드 데이터
- `GET /api/batch/timeline` - 타임라인 데이터
#### 2. **Product API** (`/api/products`)
샘플 제품 데이터 CRUD (BaseController 상속)
**모든 엔드포인트가 "Product API" 그룹으로 통합 표시됩니다.**
**공통 CRUD 엔드포인트** (BaseController에서 상속):
- `POST /api/products` - 제품 생성
- `GET /api/products/{id}` - 제품 조회 (ID)
- `GET /api/products` - 전체 제품 조회
- `GET /api/products/page?offset=0&limit=20` - 페이징 조회
- `PUT /api/products/{id}` - 제품 수정
- `DELETE /api/products/{id}` - 제품 삭제
- `GET /api/products/{id}/exists` - 존재 여부 확인
**커스텀 엔드포인트**:
- `GET /api/products/by-product-id/{productId}` - 제품 코드로 조회
- `GET /api/products/stats/active-count` - 활성 제품 개수
---
## 🛠️ 애플리케이션 실행 및 테스트
### 1. 애플리케이션 빌드 및 실행
```bash
# Maven 빌드 (IntelliJ IDEA에서)
mvn clean package -DskipTests
# 애플리케이션 실행
mvn spring-boot:run
```
또는 IntelliJ IDEA에서:
1. `SnpBatchApplication.java` 파일 열기
2. 메인 메서드 왼쪽의 ▶ 아이콘 클릭
3. "Run 'SnpBatchApplication'" 선택
### 2. Swagger UI 접속
브라우저에서 다음 URL 접속:
```
http://localhost:8081/swagger-ui/index.html
```
### 3. API 테스트 예시
#### 예시 1: 배치 작업 목록 조회
```http
GET http://localhost:8081/api/batch/jobs
```
**예상 응답**:
```json
[
"sampleProductImportJob",
"shipDataImportJob"
]
```
#### 예시 2: 배치 작업 실행
```http
POST http://localhost:8081/api/batch/jobs/sampleProductImportJob/execute
```
**예상 응답**:
```json
{
"success": true,
"message": "Job started successfully",
"executionId": 1
}
```
#### 예시 3: 제품 생성 (샘플)
```http
POST http://localhost:8081/api/products
Content-Type: application/json
{
"productId": "TEST-001",
"productName": "테스트 제품",
"category": "Electronics",
"price": 99.99,
"stockQuantity": 50,
"isActive": true,
"rating": 4.5
}
```
**예상 응답**:
```json
{
"success": true,
"message": "Product created successfully",
"data": {
"id": 1,
"productId": "TEST-001",
"productName": "테스트 제품",
"category": "Electronics",
"price": 99.99,
"stockQuantity": 50,
"isActive": true,
"rating": 4.5,
"createdAt": "2025-10-16T10:30:00",
"updatedAt": "2025-10-16T10:30:00"
}
}
```
#### 예시 4: 페이징 조회
```http
GET http://localhost:8081/api/products/page?offset=0&limit=10
```
**예상 응답**:
```json
{
"success": true,
"message": "Retrieved 10 items (total: 100)",
"data": [
{ "id": 1, "productName": "Product 1", ... },
{ "id": 2, "productName": "Product 2", ... },
...
]
}
```
---
## 📚 Swagger 어노테이션 가이드
### BaseController에서 사용된 패턴
#### ❌ 잘못된 사용법 (Java에서는 불가능)
```java
// Kotlin의 import alias는 Java에서 지원되지 않음
import io.swagger.v3.oas.annotations.responses.ApiResponse as SwaggerApiResponse;
@ApiResponses(value = {
@SwaggerApiResponse(responseCode = "200", description = "성공")
})
```
#### ✅ 올바른 사용법 (수정 완료)
```java
// import alias 제거
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@Operation(
summary = "리소스 생성",
description = "새로운 리소스를 생성합니다",
responses = {
@io.swagger.v3.oas.annotations.responses.ApiResponse(
responseCode = "200",
description = "생성 성공"
),
@io.swagger.v3.oas.annotations.responses.ApiResponse(
responseCode = "500",
description = "서버 오류"
)
}
)
@PostMapping
public ResponseEntity<ApiResponse<D>> create(
@Parameter(description = "생성할 리소스 데이터", required = true)
@RequestBody D dto) {
// ...
}
```
### 주요 어노테이션 설명
#### 1. `@Tag` - API 그룹화
```java
@Tag(name = "Product API", description = "제품 관리 API")
public class ProductWebController extends BaseController<ProductWebDto, Long> {
// ...
}
```
#### 2. `@Operation` - 엔드포인트 문서화
```java
@Operation(
summary = "짧은 설명 (목록에 표시)",
description = "상세 설명 (확장 시 표시)",
responses = { /* 응답 정의 */ }
)
```
#### 3. `@Parameter` - 파라미터 설명
```java
@Parameter(
description = "파라미터 설명",
required = true,
example = "예시 값"
)
@PathVariable String id
```
#### 4. `@io.swagger.v3.oas.annotations.responses.ApiResponse` - 응답 정의
```java
@io.swagger.v3.oas.annotations.responses.ApiResponse(
responseCode = "200",
description = "성공 메시지",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ProductDto.class)
)
)
```
---
## 🎯 신규 Controller 개발 시 Swagger 적용 가이드
### 1. BaseController를 상속하는 경우
```java
@RestController
@RequestMapping("/api/myresource")
@RequiredArgsConstructor
@Tag(name = "My Resource API", description = "나의 리소스 관리 API")
public class MyResourceController extends BaseController<MyResourceDto, Long> {
private final MyResourceService myResourceService;
@Override
protected BaseService<?, MyResourceDto, Long> getService() {
return myResourceService;
}
@Override
protected String getResourceName() {
return "MyResource";
}
// BaseController가 제공하는 CRUD 엔드포인트 자동 생성:
// POST /api/myresource
// GET /api/myresource/{id}
// GET /api/myresource
// GET /api/myresource/page
// PUT /api/myresource/{id}
// DELETE /api/myresource/{id}
// GET /api/myresource/{id}/exists
// 커스텀 엔드포인트 추가 시:
@Operation(
summary = "커스텀 조회",
description = "특정 조건으로 리소스를 조회합니다",
responses = {
@io.swagger.v3.oas.annotations.responses.ApiResponse(
responseCode = "200",
description = "조회 성공"
)
}
)
@GetMapping("/custom/{key}")
public ResponseEntity<ApiResponse<MyResourceDto>> customEndpoint(
@Parameter(description = "커스텀 키", required = true)
@PathVariable String key) {
// 구현...
}
}
```
### 2. 독립적인 Controller를 작성하는 경우
```java
@RestController
@RequestMapping("/api/custom")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "Custom API", description = "커스텀 API")
public class CustomController {
@Operation(
summary = "커스텀 작업",
description = "특정 작업을 수행합니다",
responses = {
@io.swagger.v3.oas.annotations.responses.ApiResponse(
responseCode = "200",
description = "작업 성공"
),
@io.swagger.v3.oas.annotations.responses.ApiResponse(
responseCode = "500",
description = "서버 오류"
)
}
)
@PostMapping("/action")
public ResponseEntity<Map<String, Object>> customAction(
@Parameter(description = "액션 파라미터", required = true)
@RequestBody Map<String, String> params) {
// 구현...
}
}
```
---
## 🔍 Swagger UI 화면 구성
### 메인 화면
```
┌─────────────────────────────────────────────────┐
│ SNP Batch REST API │
│ Version: v1.0.0 │
│ Spring Batch 기반 데이터 통합 시스템 REST API │
├─────────────────────────────────────────────────┤
│ Servers: │
│ ▼ http://localhost:8081 (로컬 개발 서버) │
├─────────────────────────────────────────────────┤
│ │
│ ▼ Batch Management API │
│ POST /api/batch/jobs/{jobName}/execute │
│ GET /api/batch/jobs │
│ ... │
│ │
│ ▼ Product API (9개 엔드포인트 통합 표시) │
│ POST /api/products │
│ GET /api/products/{id} │
│ GET /api/products │
│ GET /api/products/page │
│ PUT /api/products/{id} │
│ DELETE /api/products/{id} │
│ GET /api/products/{id}/exists │
│ GET /api/products/by-product-id/{...} │
│ GET /api/products/stats/active-count │
│ │
│ (Base API 그룹은 표시되지 않음) │
│ │
└─────────────────────────────────────────────────┘
```
### API 실행 화면 예시
각 엔드포인트 클릭 시:
- **Parameters**: 파라미터 입력 필드
- **Request body**: JSON 요청 본문 에디터
- **Try it out**: 실제 API 호출 버튼
- **Responses**: 응답 코드 및 예시
- **Curl**: curl 명령어 생성
---
## ⚠️ 문제 해결
### 1. Swagger UI 접속 불가
**증상**: `http://localhost:8081/swagger-ui/index.html` 접속 시 404 오류
**해결**:
1. 애플리케이션이 실행 중인지 확인
2. 포트 번호 확인 (`application.yml`의 `server.port`)
3. 다음 URL 시도:
- `http://localhost:8081/swagger-ui.html`
- `http://localhost:8081/swagger-ui/`
### 2. API 실행 시 401/403 오류
**증상**: "Try it out" 클릭 시 인증 오류
**해결**:
- 현재 인증이 설정되지 않음 (기본 허용)
- Spring Security 추가 시 Swagger 경로 허용 필요:
```java
.authorizeHttpRequests(auth -> auth
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
.anyRequest().authenticated()
)
```
### 3. 특정 엔드포인트가 보이지 않음
**증상**: Controller는 작성했지만 Swagger UI에 표시되지 않음
**해결**:
1. `@RestController` 어노테이션 확인
2. `@RequestMapping` 경로 확인
3. Controller가 `com.snp.batch` 패키지 하위에 있는지 확인
4. 애플리케이션 재시작
---
## 📊 설정 파일
### application.yml (Swagger 관련 설정)
```yaml
server:
port: 8081 # Swagger UI 접속 포트
# Springdoc OpenAPI 설정 (필요 시 추가)
springdoc:
api-docs:
path: /v3/api-docs # OpenAPI JSON 경로
swagger-ui:
path: /swagger-ui.html # Swagger UI 경로
enabled: true
operations-sorter: alpha # 엔드포인트 정렬 (alpha, method)
tags-sorter: alpha # 태그 정렬
```
---
## 🎓 추가 학습 자료
### Swagger 어노테이션 공식 문서
- [OpenAPI 3.0 Annotations](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Annotations)
- [Springdoc OpenAPI](https://springdoc.org/)
### 관련 파일 위치
```
src/main/java/com/snp/batch/
├── common/web/controller/BaseController.java # 공통 CRUD Base
├── global/config/SwaggerConfig.java # Swagger 설정
├── global/controller/BatchController.java # Batch API
└── jobs/sample/web/controller/ProductWebController.java # Product API
```
---
## ✅ 체크리스트
애플리케이션 실행 전 확인:
- [ ] Maven 빌드 성공
- [ ] `application.yml` 설정 확인
- [ ] PostgreSQL 데이터베이스 연결 확인
- [ ] 포트 8081 사용 가능 여부 확인
Swagger 테스트 확인:
- [ ] Swagger UI 접속 성공
- [ ] Batch Management API 표시 확인
- [ ] Product API 표시 확인
- [ ] "Try it out" 기능 동작 확인
- [ ] API 응답 정상 확인
---
## 📚 관련 문서
### 핵심 문서
- **[README.md](README.md)** - 프로젝트 개요 및 빠른 시작 가이드
- **[DEVELOPMENT_GUIDE.md](DEVELOPMENT_GUIDE.md)** - 신규 Job 개발 가이드 및 Base 클래스 사용법
- **[CLAUDE.md](CLAUDE.md)** - 프로젝트 형상관리 문서 (세션 연속성)
### 아키텍처 문서
- **[docs/architecture/ARCHITECTURE.md](docs/architecture/ARCHITECTURE.md)** - 프로젝트 아키텍처 상세 설계
- **[docs/architecture/PROJECT_STRUCTURE.md](docs/architecture/PROJECT_STRUCTURE.md)** - Job 중심 패키지 구조 가이드
### 구현 가이드
- **[docs/guides/PROXY_SERVICE_GUIDE.md](docs/guides/PROXY_SERVICE_GUIDE.md)** - 외부 API 프록시 패턴 구현 가이드
- **[docs/guides/SHIP_API_EXAMPLE.md](docs/guides/SHIP_API_EXAMPLE.md)** - Maritime API 연동 실전 예제
### 보안 문서
- **[docs/security/README.md](docs/security/README.md)** - 보안 전략 개요 (계획 단계)
---
**최종 업데이트**: 2025-10-16
**작성자**: Claude Code
**버전**: 1.1.0