hayu's 개발 일지

[TIL]240314 Swagger 본문

프레임워크/spring

[TIL]240314 Swagger

hayu00 2024. 3. 14. 21:48

Swagger 란?

- API의 스펙(spec)을 설명하고 관리할 수 있는 API문서이다.

- API 사용 방법을 이해관계자에게 알려주는 문서이다.

 

1. application.properties

server.forward-headers-strategy=FRAMEWORK
spring.mvc.pathmatch.matching-strategy=ant_path_matcher

url = "<https://petstore.swagger.io/v2/swagger.json>"
dom_id = "#swagger-ui"
validatorUrl = "<https://validator.swagger.io/validator>"

2. build.gradle

// Swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'

3. SwaggerConfig

3.1 Spring Security

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SwaggerConfig {

    @Bean
    public OpenAPI openAPI() {
        return new OpenAPI()
                .addSecurityItem(
                        new SecurityRequirement().addList("Bearer Authentication")
                )
                .components(
                        new Components()
                        .addSecuritySchemes("Bearer Authentication", createAPIKeyScheme())
                )
                .info(
                        new Info()
                                .title("스파르타 강의 사이트 서버 API 명세서")
                                .version("v1")
                                .description("스파르타 강의 사이트 서버 만들기")
                );
    }

    private SecurityScheme createAPIKeyScheme() {
        return new SecurityScheme().type(SecurityScheme.Type.HTTP)
                .bearerFormat("JWT")
                .scheme("bearer");
    }
}

3.2 JWT일 때 적용하는 파일 버전

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SwaggerConfig {

    @Bean
    public OpenAPI openAPI() {
        String jwt = "JWT";
        SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwt);
        Components components = new Components().addSecuritySchemes(jwt, new SecurityScheme()
                .name(jwt)
                .type(SecurityScheme.Type.HTTP)
                .scheme("bearer")
                .bearerFormat("JWT"));

        Info info = new Info()
                .title("관리자 서버 API 명세서")
                .description("HH99LV3 관리자 서버 만들기 (송유하,이주호)")
                .version("1.0.0");

        return new OpenAPI()
                .components(new Components())
                .info(info)
                .addSecurityItem(securityRequirement)
                .components(components);
    }
}

4. WebSecurityConfig

securityFilterChain 메서드 하단

String[] PUBLIC_URL = {"/v1/api-docs",
                "/swagger-resources/**",
                "/api/v1/**",
                "/v3/api-docs/**",
                "/swagger-ui/**",
                "/swagger-ui.html",
                "/v1/api-docs/**",
                "/api-docs/**",
                "api-docs" };
                
http.authorizeHttpRequests((authorizeHttpRequests) ->
                authorizeHttpRequests
                        .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() // resources 접근 허용 설정
                        .requestMatchers("/").permitAll() // 메인 페이지 요청 허가
                        .requestMatchers("/api/user/**").permitAll() // '/api/user/'로 시작하는 요청 모두 접근 허가
                        .requestMatchers(PUBLIC_URL).permitAll() // swagger 관련 요청 모두 접근 허가 
                        .anyRequest().authenticated() // 그 외 모든 요청 인증처리
        );

5. Controller

@Tag(name = "Comment API", description = "댓글과 관련된 API 정보를 담고 있습니다.")
@RequestMapping("/api/v1/lecture")

@Operation(summary = "댓글 등록 기능", description = "댓글을 등록할 수 있는 API")
@PostMapping
@ApiResponse(responseCode = "201", 
	description = "강의 등록 성공", 
	content = @Content(schema = @Schema(implementation = CreateLectureResponseDto.class)))

 

- schema가 API문서의 **필드값를 설명하는 주석** 역할을 한다.

- schema를 추가하지 않으면 단순히 필드에 대해 String, int 등 데이터타입만 나타나서 해당 필드가 어떤 것인지 한 눈에 파악하기 어려울 수 있다.

- @schema 예시 (설명, default값, 입력가능값, null 가능여부, 예시 등이 있다.) @Schema(description = "유형", defaultValue = "0", allowableValues = {"0", "1", "2"}, nullable = false, example = "abc@jiniworld.me")

@ApiResponse 설명

 

@ApiResponse 어노테이션은 특정 응답에 대한 설명을 제공합니다.

 

- responseCode = "201": 이 응답의 HTTP 상태 코드가 201(Created)임을 나타냅니다.

- description = "강의 등록 성공": 해당 응답의 설명으로 "강의 등록 성공"임을 나타냅니다.

- content = @Content(schema = @Schema(implementation = CreateLectureResponseDto.class)): 이 응답의 내용은 CreateLectureResponseDto 클래스의 객체임을 나타냅니다. @Schema 어노테이션은 이 객체가 어떤 구조를 가지고 있는지 설명하며, 여기서는 implementation 속성을 사용하여 해당 클래스의 구현을 제공합니다.

즉, 이 코드는 "강의 등록 성공" 응답을 특정 HTTP 상태 코드(201)로 정의하고, 이 응답의 내용은 CreateLectureResponseDto 클래스의 객체로 표현된다는 것을 나타냅니다.

6. RequestDto

@Schema(description = "제목", example = "어린왕자") // swagger 관련 설정
@NotBlank(message = "책 제목을 입력해주세요.") // 유효성검사(validation) 관련 설정
private String title; // 필드

7. http://localhost:8080/swagger-ui/index.html

- 스프링부트 서버를 시작한 뒤 상기 주소창으로 접속한다.

- 화면 중앙 제목 하단의 하이퍼링크 클릭 > JSON 화면 나오면 오른쪽 클릭 > 다른 이름으로 저장

8. https://editor.swagger.io/

- File > Import File > JSON파일 불러오기

- Generate Client > html2 HTML파일로 변환해 저장하기

 

 

회고

-  Swagger는 같은 팀원분의 설명으로 사용법을 잘 알게 되었다. 그 전에는 복잡하다고 생각하고 있었는데 이렇게 정리를 잘해주셔서 너무 감동이었다. 성장하는 사람은 나의 지식을 다른 사람에게 알려줌으로써 조금 더 잘 알아가는 사람이 아닐까.