이 글은 스프링부트
, Gradle
환경에서 API 문서 Swagger를 설정
하는 방법에 대해 다룹니다.
build.gradle
파일에 아래 코드를 추가합니다.
// Swagger
implementation 'io.springfox:springfox-boot-starter:3.0.0'
implementation 'io.springfox:springfox-swagger-ui:3.0.0'
package example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
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.OAS_30)
.useDefaultResponseMessages(true) // Swagger 에서 제공해주는 기본 응답 코드를 표시할 것이면 true
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("example.src")) // Controller가 들어있는 패키지. 이 경로의 하위에 있는 api만 표시됨.
.paths(PathSelectors.any()) // 위 패키지 안의 api 중 지정된 path만 보여줌. (any()로 설정 시 모든 api가 보여짐)
.build();
}
public ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("SpringBoot Rest API Documentation")
.description("3rd UMC Server: BAEMIN Clone coding - ?조")
.version("0.1")
.build();
}
}
api()
함수는 스웨거 설정을 위해 필요하고, apiInfo()
는 설정해주지 않아도 된다.
api가 들어있는 Controller의 이름을 꼭 ~~~Controller.java
로 설정해 주어야 한다.
http://localhost:8080/swagger-ui/index.html 로 접속하였을 때, Swagger의 API 시트에 본인이 만든 api가 보여야 한다.
하지만... 더 자세한 설명을 써 줄 필요가 있겠죠?
swagger 어노테이션을 통해 세부 사항들을 자세하게 작성할 수 있다.
@Api(tags="태그 이름")
@Api(tags = "test")
Controller 파일에 붙여주면, 이런 식으로 정리가 된다.
@ApiOperation(value="사용 목적", notes="설명")
@ApiOperation(
value = "마이페이지 회원 정보 조회",
notes = "로그인한 유저의 페이지에서, 회원 정보에 해당하는 부분을 불러오는 API")
Controller 안의 특정 api에 작성하면 된다.
api 설명이 추가되었다.
@ApiImplicitParam
@ApiImplicitParam(
name = "userIdx",
value = "유저 인덱스 번호",
required = true,
dataType = "int",
paramType = "path",
defaultValue = "None"
)
이것도, Controller 안의 특정 api에 작성한다.
parameter의 세부적인 특징까지 볼 수 있다.
@ApiResponse(code="코드", message="상태 메시지"), @ApiResponses
_@ApiResponse(code = 200, message = "성공입니다.")
여러 개를 작성하고 싶을 때는,
@ApiResponses({
@ApiResponse(code=200, message="성공"),
@ApiResponse(code=401, message="접근 권한이 없습니다.")
})
이렇게 작성한다.
200, 401 응답에 대한 내용이 추가되었다.
@ApiModel(value="설명")
이 설정을 해 주지 않으면, API 아래 Schema를 볼 수 있는 부분에
모델들이 서버에서 설정한 이름 그대로 나타나게 된다.
프론트 입장에서는 이해하기 어려울 수 있으므로, 이에 대한 설명을 작성해 보자.
@ApiModel(value = "마이페이지 회원 정보 조회 응답")
이렇게 바뀌었다.
@ApiModelProperty(value="설명", example="예시", required=true/false)
@ApiModelProperty(value="유저 인덱스 번호", example = "7", required = true)
private int userIdx;
@ApiModelProperty(value="유저 이름", example = "서당개", required = true)
private String userName;
이 어노테이션을 모델 안의 각 변수들에 하나씩 지정해주면,
이렇게 예시를 띄워준다!
Schemas
에서도 자세하게 볼 수 있다.
TestController.java
package example.src.test;
import example.config.BaseException;
import example.config.BaseResponse;
import example.src.test.model.GetMypageProfileRes;
import example.utils.JwtService;
import io.swagger.annotations.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import static example.config.BaseResponseStatus.*;
@RestController
@Api(tags = "test")
@RequestMapping("/test")
public class TestController {
final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private final TestProvider testProvider;
@Autowired
private final TestService testService;
@Autowired
private final JwtService jwtService;
public TestController(TestProvider testProvider, TestService testService, JwtService jwtService){
this.testProvider = testProvider;
this.testService = testService;
this.jwtService = jwtService;
}
/**
* 1.1 마이페이지 회원 정보 조회 API
* [GET] /test/info/{userIdx}
* @param userIdx
* @return GetMypageProfileRes
* @throws BaseException
*/
@ApiOperation(
value = "마이페이지 회원 정보 조회",
notes = "로그인한 유저의 페이지에서, 회원 정보에 해당하는 부분을 불러오는 API")
@ApiImplicitParam(
name = "userIdx",
value = "유저 인덱스 번호",
required = true,
dataType = "int",
paramType = "path",
defaultValue = "None"
)
@ApiResponses({
@ApiResponse(code=200, message="성공"),
@ApiResponse(code=401, message="접근 권한이 없습니다.")
})
@GetMapping("/info/{userIdx}")
public BaseResponse<GetMypageProfileRes> mypageProfile(@PathVariable ("userIdx") int userIdx) throws BaseException {
// 헤더로 받은 JWT를 통해 유저의 인덱스를 추출합니다.
int userIdxByJwt = jwtService.getUserIdx();
// JWT로 추출한 유저 인덱스와, 파라미터로 받은 유저 인덱스가 일치하는지 확인합니다(validation 처리용 - 만약 일치하지 않는다면, 큰 문제가 되겠죠??)
if(userIdx != userIdxByJwt){
throw new BaseException(INVALID_JWT);
}
GetMypageProfileRes getMypageProfileRes = testService.mypageProfile(userIdx);
return new BaseResponse<>(getMypageProfileRes);
}
}
GetMypageProfileRes.java
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
@ApiModel(value = "마이페이지 회원 정보 조회 응답")
@Getter
@Setter
@AllArgsConstructor
public class GetMypageProfileRes {
@ApiModelProperty(value="유저 인덱스 번호", example = "7", required = true)
private int userIdx;
@ApiModelProperty(value="유저 인스타 아이디", example = "kijrary", required = true)
private String userID;
@ApiModelProperty(value="유저 이름", example = "서당개", required = true)
private String userName;
@ApiModelProperty(value="유저 소개글", example = "안녕하세요", required = true)
private String userIntro;
@ApiModelProperty(value="유저 소개 웹사이트", example = "https://velog.io/@kijrary", required = true)
private String userWebsite;
@ApiModelProperty(value="유저 프로필 이미지", example = "profileimg.jpg", required = true)
private String userProfileImg;
@ApiModelProperty(value="작성한 게시물 수", example = "6", required = true)
private int postNum;
@ApiModelProperty(value="유저를 팔로우하고 있는 사람 수", example = "47", required = true)
private int followerNum;
@ApiModelProperty(value="유저가 팔로우하고 있는 사람 수", example = "50", required = true)
private int followingNum;
}