๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Project

[ํ”„๋กœ์ ํŠธ ๊ธฐ๋ณธ ์„ธํŒ…] Swagger, Response Model, ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์„ธํŒ…

ํ”„๋กœ์ ํŠธ ๊ธฐ๋ณธ ์„ธํŒ…

2. [๋ฐฑ์—”๋“œ] Swagger, Response Model, ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์„ธํŒ…


Swagger Setting

๋ฐฑ์—”๋“œ ์ดˆ๊ธฐ ์„ธํŒ… ๋•Œ build.gradle์— ์„ค์ •ํ–ˆ๋˜ Swagger๋ฅผ ์„ธํŒ…ํ–ˆ๋‹ค.

Swagger์— ๋Œ€ํ•œ ๊ธฐ๋ณธ ์„ธํŒ…์„ ํ•ด์ฃผ๋Š” SwaggerConfig.java๋ฅผ ๋งŒ๋“ค๊ณ , Security์—์„œ๋„ web.ignoring() ์„ค์ •์„ ํ•ด์ฃผ์—ˆ๋‹ค.

SwaggerConfig.java


package com.portfolio.backend.config.swagger;

// import ์ƒ๋žต

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket swaggerApi() {
        return new Docket(DocumentationType.SWAGGER_2).apiInfo(swaggerInfo()).select()
                .apis(RequestHandlerSelectors.basePackage("com.portfolio.backend"))
                .paths(PathSelectors.any())
                .build()
                .useDefaultResponseMessages(false);
    }

    private ApiInfo swaggerInfo() {
        return new ApiInfoBuilder().title("Portfolio For Developers API Documentation")
                .description("๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ ํฌํŠธํด๋ฆฌ์˜ค ํ”„๋กœ์ ํŠธ API ์—ฐ๋™ ๋ฌธ์„œ")
                .license("vividswan").licenseUrl("https://vividswan.github.io/").version("1").build();
    }

} 

SecurityConfig.java

package com.portfolio.backend.config.security;

// import ์ƒ๋žต

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override // ignore check swagger resource
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers("/v2/api-docs", "/swagger-resources/**",
                "/swagger-ui.html", "/webjars/**", "/swagger/**");

    }

} 

Api Response Model Setting

Response ํ˜•์‹์„ ํ†ต์ผํ•˜๊ธฐ ์œ„ํ•ด Response Model ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

Response์˜ ์„ฑ๊ณต ์—ฌ๋ถ€, ์ฝ”๋“œ๋ฒˆํ˜ธ, ๋ฉ”์‹œ์ง€๋ฅผ ๋‹ด๋Š” CommonResponse์™€ ์ด๋ฅผ ์ƒ์†ํ•˜์—ฌ ๋‹จ์ผ Data๋ฅผ Return ํ•˜๋Š” SingleResponse<T>์™€ ๋ฆฌ์ŠคํŠธ Data๋ฅผ Return ํ•˜๋Š” ListResponse<T> ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

์ด๋ฅผ ์ƒํ™ฉ์— ๋งž๊ฒŒ Return ํ•ด์ค„ ์ˆ˜ ์žˆ๋Š” ResponseService๋ผ๋Š” Service ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

CommonResponse.java

package com.portfolio.backend.model.response;

// import ์ƒ๋žต

@Getter
@Setter
public class CommonResponse {

    @ApiModelProperty(value = "Response ์„ฑ๊ณต ์—ฌ๋ถ€")
    private boolean isSuccess;

    @ApiModelProperty(value = "Response ์ฝ”๋“œ ๋ฒˆํ˜ธ")
    private int code;

    @ApiModelProperty(value = "Response Message")
    private String message;

    public CommonResponse(){}
    public CommonResponse(String msg){
        this.message = msg;
    };

} 

SingleResponse.java

package com.portfolio.backend.model.response;

// import ์ƒ๋žต

@Setter
@Getter
public class SingleResponse<T> extends CommonResponse{

    @ApiModelProperty(value = "Single Response Data")
    private T data;

}

ListResponse.java

package com.portfolio.backend.model.response;

// import ์ƒ๋žต

import java.util.List;

@Getter
@Setter
public class ListResponse<T> extends CommonResponse{

    @ApiModelProperty(value = "Response Data List")
    private List<T> list;

}

ResponseService.java

package com.portfolio.backend.model.response;

// import ์ƒ๋žต

@Service
public class ResponseService {

    public <T> SingleResponse<T> getSingleResponse(T data){
        SingleResponse<T> res = new SingleResponse<>();
        res.setData(data);
        res.setCode(0);
        res.setMessage("Success");
        res.setSuccess(true);
        return res;
    }

    public <T> ListResponse<T> getListResponse(List<T> list){
        ListResponse<T> res = new ListResponse<>();
        res.setList(list);
        res.setCode(0);
        res.setMessage("Success");
        res.setSuccess(true);
        return res;
    }

    public CommonResponse getSuccessResponse(){
        CommonResponse res = new CommonResponse();
        res.setSuccess(true);
        res.setCode(0);
        res.setMessage("Success");
        return res;
    }

    public CommonResponse getFailResponse(String msg){
        CommonResponse res = new CommonResponse(msg);
        res.setSuccess(false);
        res.setCode(-1);
        res.setMessage(msg);
        return res;
    }

}

Exception Handler Setting

์šฐ์„  ๋‘ ๊ฐ€์ง€ ์˜ˆ์™ธ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.


๊ทธ ํ›„ ์ „์—ญ์œผ๋กœ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ์ปจํŠธ๋กค(@RestControllerAdvice ์–ด๋…ธํ…Œ์ด์…˜) ํ•  ์ˆ˜ ์žˆ๋Š” ExceptionAdvice์„ ์„ ์–ธํ•˜์—ฌ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๊ณ ๋„ํ™”๋ฅผ ํ•ด์ค€๋‹ค.

CustomValidationException

package com.portfolio.backend.config.advice.exception;

public class CustomValidationException extends RuntimeException{
    public CustomValidationException() {
        super();
    }

    public CustomValidationException(String message) {
        super(message);
    }

    public CustomValidationException(String message, Throwable cause) {
        super(message, cause);
    }
}

CustomUserNotFoundException

package com.portfolio.backend.config.advice.exception;

public class CustomUserNotFoundException extends  RuntimeException{
    public CustomUserNotFoundException() {
        super();
    }

    public CustomUserNotFoundException(String message) {
        super(message);
    }

    public CustomUserNotFoundException(String message, Throwable cause) {
        super(message, cause);
    }
}

ExceptionAdvice

package com.portfolio.backend.config.advice;

// import ์ƒ๋žต

@RequiredArgsConstructor
@RestControllerAdvice
public class ExceptionAdvice {

    private final ResponseService responseService;

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    protected CommonResponse defaultException(HttpServletRequest request, Exception e) {
        return responseService.getFailResponse("Default Error");
    }

    @ExceptionHandler(CustomUserNotFoundException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    protected CommonResponse userNotfoundException(HttpServletRequest req, CustomUserNotFoundException e){
        return responseService.getFailResponse("์ž˜ ๋ชป ๋œ User ์ •๋ณด ์ž…๋‹ˆ๋‹ค.");
    }

    @ExceptionHandler(CustomValidationException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    protected CommonResponse validationException(HttpServletRequest req, CustomValidationException e){
        return responseService.getFailResponse("์ž˜ ๋ชป ๋œ ์ž…๋ ฅ ๊ฐ’์ž…๋‹ˆ๋‹ค.");
    }
}