시작하기 앞서…
스웨거를 세팅하기 위해서는 springdoc, springfox라는 api 문서화를 도와주는 라이브러리 중 하나를 선택해서 dependency를 추가하게 된다.
이 중 springfox의 경우 2020년 이후로는 업데이트 되고 있지 않으며,
그에 비해 springdoc의 경우 현재까지 꾸준히 업데이트 되어 오고 있다.
따라서 이번에는 springdoc을 활욯해 swagger 기능을 구현해보려고 한다.
SpringDoc과 Swagger
springdoc은 api를 json 형태로 응답해준다.
이를 이용하여 swagger는 json문서를 ui형태로 읽기 쉽게 만들어주는 역할을 한다.
swagger 설정하는 방법
1. build.gradle에 swagger 관련 라이브러리를 가져올 수 있도록 설정한다.
//swagger
implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.5.0'
testImplementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-api', version: '2.5.0'
2. application.properties 혹은 application.yml에 swagger관련 설정을 해준다.
springdoc 최신 버전은 swagger.config 설정 부분을 application.properties로 이동시켰다.
#swagger
springdoc.swagger-ui.path=/swagger-ui.html //swagger ui, 즉 api에 대한 ui를 보기 위한 url이다.
springdoc.swagger-ui.enabled=true //swagger ui를 볼 수 있게 할지 말지 설정하는 것. 디폴트는 true이다.
springdoc.swagger-ui.tags-sorter=alpha //swagger 페이지에 tag를 alphabet 순으로 정렬하겠다는 뜻
springdoc.swagger-ui.operations-sorter=alpha //swagger 페이지에 operation을 alphabet 순으로 정렬하겠다는 뜻
springdoc.api-docs.path=/api-docs //swagger ui에 담길 정보들을 가져오는 url이다. swagger는 이 docs를 통해 ui를 형성한다.
springdoc.default-consumes-media-type=application/json;charset=UTF-8
springdoc.default-produces-media-type=application/json;charset=UTF-8
3. SwaggerConfig 생성
스프링 디렉터리 밑에 SwaggerConfig
클래스를 생성한다.
일반적으로 configuration 파일은 conf 폴더를 생성해 이 밑에 저장한다.
필자는 /swagger/conf/SwaggerConfig
경로로 생성하였다.
@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI openAPI() {
return new OpenAPI()
.components(new Components())
.info(apiInfo());
}
private Info apiInfo() {
return new Info()
.title("중간지점 찾기 api 명세서")
.description("중간 지점 api 명세서입니다.")
.version("1.0.0");
}
}
- title은 swagger ui 페이지의 제목이다.
- description은 swagger ui페이지 제목에 대한 설명이다.
- version은 이 swagger ui 페이지에 이 페이지에 대한 버전을 명시하는 것이다. 추후 페이지가 변경될 때마다 버전을 올리면 될 거 같다.
4. swagger ui 페이지 확인
스프링 프로젝트를 실행시키고 아래 경로를 입력해보자.
http://localhost:8080/swagger-ui.html //uri는 위에 properties에 명시한 경로를 입력하면 된다.
정상적으로 swagger 페이지가 뜨면 성공!
만약 에러가 난다면 아래 트러블 슈팅을 확인해보자.
트러블 슈팅 : swagger 페이지가 not found인 에러
swagger 설정을 마친 후 실행하였더니 swagger 페이지를 찾을 수 없다고 한다.
결론적으로 swagger 라이브러리 버전을 변경함으로써 해결했다.
원인은 springdoc 1.0 버전은 spring boot 2.0 버전까지만 지원하기 때문에
spring boot 3.0 버전을 사용하려면 springdoc을 2.0버전으로 바꿔줘야 했기 때문이었다.
변경 전
implementation 'org.springdoc:springdoc-openapi-ui:1.6.15'
implementation 'org.springdoc:springdoc-openapi-data-rest:1.6.15'
implementation 'org.springdoc:springdoc-openapi-security:1.6.15'
}
변경 후
dependencies {
implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.5.0'
testImplementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-api', version: '2.5.0'
}
트러블 슈팅 : springSecurity단에서 막히는 에러
스프링 시큐리티 단에서 요청 url에 대해 permit하지 않았기에 시큐리티단에서 막혀 swagger페이지가 띄워지지 않았다.
따라서 swagger 관련 url에 대해 허용을 해줘야 한다.
SecurityConfig
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable) // 세션을 사용안하므로 csrf 공격 없으므로 csrf 비활성화
.httpBasic(AbstractHttpConfigurer::disable) // 기본 인증 방식 비활성화
.cors(cors -> cors.configurationSource(ConfigurationSource))
.formLogin(AbstractHttpConfigurer::disable) //json을 이용하여 로그인을 하므로 기본 Login 비활성화
.authorizeHttpRequests((authorize) -> authorize // PERMIT_URLS만 바로 접근 가능, 나머지 URL은 인증 필요
.requestMatchers("/api-docs", "/swagger-ui.html", "/api-docs/**", "/swagger-ui/**").permitAll()
.anyRequest().authenticated()
)
.logout(LogoutConfigurer::permitAll)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 토큰을 사용하기 때문에 Session 사용 x
;
...
}
위는 시큐리티 필터 체인의 일부분이다.
.authorizeHttpRequests((authorize) -> authorize // PERMIT_URLS만 바로 접근 가능, 나머지 URL은 인증 필요
.requestMatchers("/api-docs", "/swagger-ui.html", "/api-docs/**", "/swagger-ui/**").permitAll()
.anyRequest().authenticated()
)
이 부분을 수정하면 된다.
위의 url에 대해 요청을 허용해준다.
swagger는 swagger-ui를 생성하기 위해 서버에 여러 요청을 하게 된다.
/api-docs/swagger-config
/swagger-ui/favicon-32x32.png
/api-docs
위와 같은 요청을 하게 되므로 /**
등의 패턴을 통해 모든 하위 디렉토리에 대한 요청도 열어줘야 한다.