Spring Boot에 Swagger 적용하기

PEPPERMINT100·2021년 3월 3일
0

서론

최근에 처음으로 팀으로서 프로젝트를 진행해보았다. 프로젝트 기획 및 프론트엔드 개발 역할로 프로젝트를 진행하였는데, 기획 및 커뮤니케이션 부분에서 많이 부족했고 또 많이 배울 수 있는 시간이었다.

디자인을 맡은 팀원과 백엔드 개발을 맡은 팀원과 동시에 커뮤니케이션을 해야할 일이 정말 잦았는데, 프로젝트 진행 방법을 구글링을 해보니 대부분 모든 디자인과 API 기획이 끝난 후에 프론트엔드 구조를 설계하는 방식이 많다고 한다.

하지만 처음 진행했던터라 부족한 부분이 많았고 크게 문제는 없었지만 백엔드 개발의 API 구조에 관한 소통을 할 일이 많았다.

프로젝트 진행에 있어서 API 설계는 그냥 공유된 노션을 통해 API를 문서화하였는데,

UserController("/user")

1. 연결확인
@GET("/check-connection")
input =>({})
output =>({ 
		success: boolean, 
		msg: String 
})

2. 회원가입
@POST("/signup")
input => ({
	"email": String,
	"password": String,
	"passwordConfirm": String,
	"name": String
})
output => ({
		"success": boolean,
		"msg": String
})

3. 로그인
@POST("/signin")
input => ( {
		"email":String, 
		"password":String 
})
output => ({
    "success": boolean,
    "msg": String,
    "token": String
})

4. 로그인 유지
@GET("/me")
input => ({token})
output => ({
	"success": boolean,
	"msg": String,
	"userId": Long,
	"email": String,
	"name": String,
	"userImage" : String
})

5. 임시비밀번호 생성 및 메일전송
@POST("/sendMailPassword")
input => ({
	"name": String,
	"email": String,
})
output => ({
		"success": boolean,
		"msg": String
})

6. 회원정보 변경
@PUT("/updateUserInfo/{userId}")
input => ({
	"passwordBefore": String,  //현재비밀번호
	"password": String,        //바꿀비밀번호
	"passwordConfirm": String, //바꿀비밀번호 확인
	"name": String
	"userImage" : MultipartFile 
})
output => ({
		"success": boolean,
		"msg": String
})

이렇게 직접 하나하나 적어서 진행을 했다. 이렇게 하면 사실 API 문서의 구조를 서로 소통한 뒤에 진행하기 때문에 더 알아보기 쉽다는 장점이 있었다. 하지만 몇 가지 단점을 발견할 수 있었다.

하나는 JSON 데이터의 키 단어 선택이 문제였다. 여행 계획 플래너가 프로젝트의 주제였는데, accomodation 이나 transportation과 같은 긴 단어에서 오타가 발생하는 경우가 많았다. 물론 이 단어를을 static String의 형태로 잘 저장해두고 약속해두었으면 해결될 문제 였는데 처음으로 협업을 진행한터라 미리 기획해놓지 못했고 덕분에 서로 계속해서 코드를 고치는 경우가 발생하였다.

또 하나는 업데이트 문제였다. 만약 API 설계과정에서 문제가 생겼을 경우 input, output을 조정하는데 그러면 다시 이 문서로 들어와서 찾아서 고쳐놔야 하는, 즉 일을 두 번씩하게 되는 문제가 발생하였다.

그래서 프로젝트 진행 도중 Postman을 사용하는 방식으로 변경하였다.

이런 방식으로 input, output 결과를 미리 저장해놓고 이 결과를 파일화시켜서 서로 주고 받으며 API 설계를 해나갔다. 이 방식은 API 테스트에 있어서는 굉장히 유용했지만 역시 위 두 문제를 완벽히 해결해주는 방법은 아니었다.

그리고 최근 Spring Boot와 Spring Security를 사용하고 Cors 처리도 하다보면 API 테스트할때와 React App과 통신할때 계속 설정을 다르게 해주어야 해서 더 귀찮은 일이 생기기도 했다.

하지만 역시 이러한 일도 쉽게 처리를 해주는 방법이 있었다. Swagger라는 패키지를 적용하면 매 업데이트마다 알아서 컨트롤러에 들어가고 나오는 input, output을 분석해준다. 그리고 Swagger UI를 사용하면 쉽게 알아볼 수 있고 심지어 API 테스트까지 가능한 html 파일을 생성할 수 도 있다. 지금부터 Spring Boot 프로젝트에 Swagger를 입히는 방법을 알아보도록 하겠다.

패키지 적용(Maven)

pom.xml에 아래와 같은 패키지를 적용시켜준다.

<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger2</artifactId>
	<version>3.0.0</version>
</dependency>
<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger-ui</artifactId>
   <version>3.0.0</version>
</dependency>
<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-boot-starter</artifactId>
	<version>3.0.0</version>
</dependency>

설정

먼저 SwaggerConfig라는 클래스를 생성하고 아래와 같이 작성해준다.

package io.peppermint100.server.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;

@Configuration
public class SwaggerConfig {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build();
    }
}

Swagger는 도커 빈을 통해 설정을 할 수 있는데 여기서 스웨거에 대한 세부 설정을 할 수 있다. 여기에서 세부 설정하는 방법을 볼 수 있다.

그리고 메인 클래스 파일에

@SpringBootApplication
@EnableSwagger2
public class ServerApplication {

위처럼 @EnableSwagger2 어노테이션을 추가해준다. 이 설정만으로 포스트맨에서 Get 방식으로 localhost:8080/v2(혹은 v3)/api-docs를 가져오면 우리가 만든 API의 상세 내용을 볼 수 있다. 하지만 이 방식은 굉장히 보기 불편하다. 따라서 즉 위에서 말한 Swagger UI를 적용하면 되는데 이미 다운로드를 받았으므로localhost:8080/swagger-ui/index.html로 접속해주면 우리가 생성한 컨트롤러 별로 input, output을 확인할 수 있으며 심지어 그 안에서 API 테스트도 할 수 있다는것을 확인할 수 있다.

Spring Security와 Swagger

만약 스프링 부트 프로젝트가 Spring Security를 사용한다면 추가적으로 해야할 설정이 있다. 왜냐하면 기본적으로 Security에 예외 처리되지 않은 URL 매핑들은 필터를 거치지 않으면 통과시키지 않기 때문이다.

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
                .authorizeRequests()
                .antMatchers("/user/signup", "/user/login", "/exception/**","/item/**", "/v2/api-docs", "/configuration/**", "/swagger*/**", "/webjars/**")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .exceptionHandling().authenticationEntryPoint(new AuthenticationExceptionHandler())
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
    }

antMatcher"/v2/api-docs", "/configuration/**", "/swagger*/**", "/webjars/**" 이 부분을 추가시켜주면 된다. 그러면 포스트맨에서 Swagger를 JSON 방식으로 확인할 수도 있고 Swagger UI로 생성된 API 문서를 html로 확인할 수도 있다.

직접 Swagger를 설정하고 테스트 해본 결과 Cors는 신경을 안써도 되는것으로 확인이 되었는데, 공식 문서를 확인해보니 Swagger 를 적용한 서버와 API 엔드포인트 서버가 동일하다면 따로 적용을 해주지 않아도 된다고 한다.

하지만 Swagger 서버를 따로 운영해야 하는 경우에는 여기에서 Swaggercors 설정 방법을 확인할 수 있었다.

profile
기억하기 위해 혹은 잊어버리기 위해 글을 씁니다.

0개의 댓글