오늘은 Spring 프로젝트에 Swagger와 OpenAPI를 적용하는 방법과 이를 효과적으로 활용하기 위한 베스트 프랙티스에 대해 알아보겠습니다. RESTful API를 설계하고 문서화하는 과정에서 Swagger의 도구들을 활용하면 개발 효율성을 향상시킬 수 있습니다. 이번에는 Swagger를 Spring 프로젝트에 통합하는 단계별 과정과 함께 실무에서 유용한 팁들을 공유하고자 합니다.
1. Swagger(OpenAPI)란?
Swagger는 OpenAPI의 구현체 중 하나로, API의 설계와 문서화를 쉽게 할 수 있도록 다양한 도구와 프레임워크를 제공합니다. Spring 프로젝트에 Swagger를 통합하면 API 명세를 자동으로 생성하고, 인터랙티브한 문서를 제공하여 개발자 간 협업을 원활하게 할 수 있습니다.
2. Spring Boot 프로젝트에 Swagger 통합하기
2.1. 프로젝트 설정
먼저, Spring Boot 프로젝트에 Swagger를 통합하기 위해 필요한 의존성을 추가해야 합니다. Springfox 라이브러리를 사용하면 손쉽게 Swagger를 설정할 수 있습니다.
build.gradle
plugins {
id 'org.springframework.boot' version '3.0.0'
id 'io.spring.dependency-management' version '1.1.0'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
// Swagger 관련 의존성 추가
implementation 'io.springfox:springfox-boot-starter:3.0.0'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
test {
useJUnitPlatform()
}
2.2. Swagger 설정 클래스 작성
Swagger를 설정하기 위해 별도의 설정 클래스를 작성합니다. 이 클래스에서는 Swagger의 기본 설정과 API 문서의 기본 정보를 정의합니다.
SwaggerConfig.java
package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.demo.controller"))
.paths(PathSelectors.any())
.build();
}
}
2.3. 컨트롤러에 Swagger 어노테이션 추가
API 문서화를 위해 컨트롤러와 엔드포인트에 Swagger 어노테이션을 추가합니다. 예를 들어, 간단한 사용자 관리 API를 만들어보겠습니다.
UserController.java
package com.example.demo.controller;
import com.example.demo.model.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController
@RequestMapping("/users")
@Api(value = "User Management System", description = "Operations pertaining to user in User Management System")
public class UserController {
private Map<Integer, User> userDB = new HashMap<>();
@ApiOperation(value = "View a list of available users", response = List.class)
@GetMapping
public ResponseEntity<List<User>> getAllUsers() {
return ResponseEntity.ok(new ArrayList<>(userDB.values()));
}
@ApiOperation(value = "Get a user by Id")
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Integer id) {
User user = userDB.get(id);
if (user != null) {
return ResponseEntity.ok(user);
}
return ResponseEntity.notFound().build();
}
@ApiOperation(value = "Add a user")
@PostMapping
public ResponseEntity<User> addUser(@RequestBody User user) {
userDB.put(user.getId(), user);
return ResponseEntity.ok(user);
}
@ApiOperation(value = "Delete a user")
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Integer id) {
userDB.remove(id);
return ResponseEntity.noContent().build();
}
}
User.java
public class User {
private Integer id;
private String name;
private String email;
public User() {}
public User(Integer id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
2.4. Swagger UI 확인
프로젝트를 실행한 후, 브라우저에서 http://localhost:8080/swagger-ui/
에 접속하면 Swagger UI를 통해 API 문서를 확인할 수 있습니다. 여기서 API 엔드포인트를 테스트해보고, 요청과 응답을 시각적으로 확인할 수 있습니다.
3. 베스트 프랙티스
3.1. 명확한 API 설계
API의 모든 엔드포인트, 요청 및 응답 형식을 명확하게 정의하는 것이 중요합니다. Swagger의 어노테이션을 활용하여 각 엔드포인트의 목적과 동작을 명확히 설명하는것이 좋습니다.
3.2. 일관된 네이밍 컨벤션
엔드포인트와 모델 클래스의 네이밍을 일관되게 유지해야 합니다. 예를 들어, 복수형과 단수형을 혼용하지 않고 일관된 형식을 사용합니다.
3.3. 버전 관리
API 버전을 명시적으로 관리하여, 기존 클라이언트가 영향을 받지 않도록 합니다. 예를 들어, /api/v1/users
와 같이 버전을 URL에 포함시킬 수 있습니다.
3.4. 보안 설정
Swagger를 통해 공개된 API 문서에 민감한 정보가 노출되지 않도록 주의해야 합니다. 인증이 필요한 엔드포인트는 적절한 인증 메커니즘을 적용하고, Swagger 설정에서도 이를 반영하는 것이 좋습니다.
SwaggerConfig.java
(Bearer Token 인증 추가)
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.demo.controller"))
.paths(PathSelectors.any())
.build()
.securitySchemes(Collections.singletonList(apiKey()));
}
private ApiKey apiKey() {
return new ApiKey("JWT", "Authorization", "header");
}
3.5. 자동화 도구 활용
Swagger Codegen이나 Swagger Editor와 같은 도구를 활용하여 API 문서화와 코드 생성을 자동화하면 개발 효율성을 높일 수 있습니다. 이를 통해 일관된 코드베이스를 유지하고, 반복적인 작업을 줄일 수 있습니다.
3.6. 문서 유지보수
API가 변경될 때마다 Swagger 문서도 함께 업데이트하여 항상 최신 상태를 유지해야 합니다. CI/CD 파이프라인에 Swagger 문서 생성을 포함시키면 자동으로 문서가 업데이트되도록 설정할 수 있습니다.
4. 실무 적용 예제
4.1. CI/CD 파이프라인에 Swagger 통합
Jenkins나 GitHub Actions와 같은 CI/CD 도구를 사용하여, 코드가 변경될 때마다 Swagger 문서를 자동으로 생성하고 배포할 수 있습니다. 예를 들어, GitHub Actions을 사용하여 Swagger 문서를 빌드하고 GitHub Pages에 배포하는 워크플로우를 설정할 수 있습니다.
.github/workflows/swagger.yml
name: Deploy Swagger UI
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up JDK 17
uses: actions/setup-java@v2
with:
java-version: '17'
- name: Build project
run: ./gradlew build
- name: Deploy Swagger UI to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./build/swagger-ui
4.2. 클라이언트 코드 자동 생성
Swagger Codegen을 사용하여 클라이언트 SDK를 자동으로 생성할 수 있습니다. 이를 통해 다양한 언어의 클라이언트 코드를 쉽게 생성하고, API 변경 시 클라이언트 코드를 자동으로 업데이트할 수 있습니다.
명령어 예시
swagger-codegen generate -i http://localhost:8080/v2/api-docs -l java -o ./generated-client
5. TIP & 정리
▶ TIP
1. 초기 설계 단계에서 사양 정의
- API 개발의 초기 단계에서 OpenAPI 사양을 명확히 정의하는 것이 좋다고 생각합니다. 이를 통해 개발 방향을 명확히 설정하고, 팀원 간의 이해를 도울 수 있습니다.
2. 자동화 도구 적극 활용
- Swagger Editor, Swagger UI, Swagger Codegen과 같은 도구를 활용하여 API 문서화와 코드 생성을 자동화하여 반복적인 작업을 줄이고, 일관된 코드베이스를 유지할 수 있습니다.
3. 일관된 네이밍 컨벤션 유지
- 엔드포인트와 모델 클래스의 네이밍을 일관되게 유지하는 것이 좋습니다. 예를 들어, 복수형과 단수형을 혼용하지 않고 일관된 형식을 사용하면 코드의 가독성과 유지보수성이 향상됩니다.
4. 버전 관리 철저
- API의 버전을 명시적으로 관리하여, 기존 클라이언트가 영향을 받지 않도록 합니다. 예를 들어, URL에 /api/v1/과 같이 버전을 포함시키는 방법이 있습니다.
5. 보안 설정 강화
- Swagger를 통해 공개된 API 문서에 민감한 정보가 노출되지 않도록 주의하는 것이 중요하다고 생각합니다. 인증이 필요한 엔드포인트는 적절한 인증 메커니즘을 적용하고, Swagger 설정에서도 이를 반영해야 합니다.
6. CI/CD 파이프라인에 문서 통합
- Jenkins, GitHub Actions와 같은 CI/CD 도구를 사용하여 코드 변경 시 Swagger 문서가 자동으로 생성되고 배포되도록 설정하는 것이 최신 문서 유지에 좋다고 생각합니다.
7. 클라이언트 코드 자동 생성 활용
- Swagger Codegen을 사용하여 다양한 언어의 클라이언트 SDK를 자동으로 생성하면 클라이언트와 서버 간의 일관성을 유지하고, API 변경 시 클라이언트 코드를 쉽게 업데이트할 수 있습니다.
▶ 정리
OpenAPI와 Swagger는 RESTful API의 설계, 문서화, 테스트, 코드 생성을 효율적으로 지원하는 강력한 도구입니다. 특히, Spring 프로젝트와의 통합을 통해 API 개발 과정을 자동화하고, 일관성을 유지하며, 팀 간 협업을 원활하게 할 수 있습니다. 다음과 같은 베스트 프랙티스를 통해 Swagger와 OpenAPI를 더욱 효과적으로 활용할 수 있습니다.
- 명확한 사양 정의 : API의 모든 세부 사항을 명확하게 정의하여 오해나 오류를 방지합니다.
- 자동화 도구 활용 : Swagger의 다양한 도구를 활용하여 문서화와 코드 생성을 자동화합니다.
- 일관된 네이밍과 버전 관리 : 일관된 네이밍 컨벤션과 철저한 버전 관리를 통해 API의 유지보수성을 높입니다.
- 보안 강화 : API 문서에 민감한 정보가 노출되지 않도록 보안 설정을 철저히 합니다.
- CI/CD 통합 : 지속적인 통합과 배포 파이프라인에 Swagger 문서 생성을 포함시켜 항상 최신의 문서를 유지합니다.
6. 결론
Spring 프로젝트에 Swagger(OpenAPI)를 통합하면 API 설계와 문서화가 훨씬 수월해집니다. 자동화 도구를 적극 활용하고, 베스트 프랙티스를 준수함으로써 일관성 있고 유지보수하기 쉬운 API를 구축할 수 있습니다.
'Spring' 카테고리의 다른 글
(Spring) Swagger와 OpenAPI 유사 도구들 개념 정리 (1) | 2024.12.13 |
---|---|
(Spring) RESTful에 대한 이해 (0) | 2024.11.11 |
(Spring) 데이터베이스 개념 및 MySQL 개요 (0) | 2024.11.04 |
(Spring) HTTP 데이터 객체 처리 및 CRUD 구현하기 (0) | 2024.10.30 |
(Spring) Path Variable & Request Param 차이점 (0) | 2024.10.29 |