728x90

실무에서 협업을 할 때 API에 대한 문서를 요청받은 적이 있었다. 메모장에 필요한 것만 적어서 전달하였는데 Swagger에 존재를 알았다면 덜 고생했을 것이다. 지금이라도 적용해서 사용 중인 Swagger 환경 세팅과 사용법에 대해 간단하게 알아보자.


목차

     

    Swagger란?

    Swagger란 보통 백엔드에서 개발한 API들의 명세서이며 이것을 통해 프론트엔드는 지속적으로 공유되는 API들을 확인해서 개발할 수 있다. Swagger는 화면에서 테스트도 지원한다.

     

    SpringFox와 SpringDoc

    Swagger를 사용하기 위해서는 오픈소스 라이브러리인 SpringFox와 SpringDoc이 있는데 SpringFox는 2020년 이후로 업데이트가 중단되었다고 한다. 지속적으로 관리가 되지 않기 때문에 사용을 지양해야한다. 반면에 SpringDoc은 SpringFox가 중단된 이후에 나온 버전이다. 지속적으로 불편한 점을 개선하고 있기 때문에 Swagger를 사용할 계획이라면 SpringDoc을 사용하는 것이 좋다.

     

    설치방법

    (https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-ui) → 여기로 접속한다.

    1.7.0을 클릭한다.

    필자는 Gradle을 사용하고 있기 때문에 Gradle을 복붙해서 빌드한다.

     

    1
    2
    3
    4
    5
    6
    springdoc:
      default-consumes-media-type: application/json
      default-produces-media-type: application/json
      swagger-ui:
        path: /v3/swagger-ui.html
        disable-swagger-default-url: true
    cs

    이후에는 위 문법을 application.yml에 작성한다.(application.properties에는 문법만 바꿔서 작성해도됌)

    http://localhost:8080/v3/swagger-ui.html → 접속하면 API를 볼 수 있다.

     

    Controller에서 Swagger 사용 예제

    많이 사용하는 Swagger 어노테이션 목록이다.

    • @Tag
    • @Parameters
    • @Parameter(hidden = true) or @Operation(hidden = true) or @Hidden
    • @Schema(accessMode = READ_ONLY)
    • @Operation(summary = "foo", description = "bar")
    • @ApiResponse(responseCode = "404", description = "foo")

    개인적으로 @Parameters 사용은 권장하지 않는다. 파라미터 UI가 깔끔하지 않기 때문에 가독성이 떨어진다고 느껴 사용하지 않았다. 대신 Request Body에서 Example Value 우측에 Schema를 사용하였다. 아래 예제를 보면 @Schma안에 implementation = LoginParam.class를 작성하면 훨씬 깔끔하고 가독성 있는 문서를 작성할 수 있다.

    LoginController.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    @RestController
    @RequiredArgsConstructor
    @RequestMapping("/")
    @Tag(name = "LoginController", description = "유저 API")
    public class LoginController {
     
        private final LoginService loginService;
        private final JwtUtils jwtUtils;
     
        @Operation(summary = "로그인한다.",
            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                description = "로그인 요청 예제", required = true,
                content = @Content(
                    mediaType = "application/json",
                    schema = @Schema(implementation = LoginParam.class),
                    examples = {
                        @ExampleObject(
                            name = "기본 예제",
                            value = "{" +
                                "\"loginId\":\"admin\"," +
                                "\"userPw\":\"1234\"," +
                                "\"accessToken\":null," +
                                "\"refreshToken\":null," +
                                "\"loginDevice\":\"WEB\"," +
                                "\"deviceBrowser\":\"Chrome\"," +
                                "\"userId\":0," +
                                "\"authRole\":\"USER\"" +
                            "}"
                        )
                    }
                )
            ),
            responses = {
                @ApiResponse(
                    responseCode = "200",
                    description = "API 요청 성공",
                    content = @Content(
                        schema = @Schema(
                            example = "{" +
                                "\"header\": {" +
                                    "\"requestUrl\":\"/login\"," +
                                    "\"method\":\"POST\"," +
                                    "\"message\":\"메인화면으로 이동합니다\"," +
                                    "\"resultCode\":\"ok\"" +
                                "}," +
                                "\"data\": {" +
                                    "\"userId\": 1," +
                                    "\"loginId\":\"admin\"," +
                                    "\"authId\": 5," +
                                    "\"authNm\":\"사용자\"," +
                                    "\"authVal\":\"USER\"," +
                                    "\"authRole\":\"USER\"," +
                                    "\"userNm\":\"관리자\"," +
                                    "\"telNo\":\"01011112222\"," +
                                    "\"pwInitYn\":\"Y\"," +
                                    "\"loginFailCnt\": 0," +
                                    "\"lastLoginLabel\":\"2023-09-11 10:09:13\"" +
                                "}" +
                            "}"
                        )
                    )
                ),
            }
        )
        @PostMapping("/login")
        public ResponseEntity<Map<String,Object>> login (
    @RequestBody LoginParam loginParam, HttpServletRequest httpServletRequest
    )
            throws Exception {
     
            return new ResponseEntity<>(responseMap, status);
        }
    }
     
    cs

     

    LoginParam.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @ToString(callSuper = true)
    @EqualsAndHashCode()
    public class LoginParam {
     
        @Schema(description = "아이디")
        public String loginId;
     
        @Schema(description = "패스워드")
        public String userPw;
     
        @Schema(description = "억세스토큰")
        public String accessToken;
     
        @Schema(description = "리프레시토큰")
        public String refreshToken;
     
        @Schema(description = "접속디바이스")
        public String loginDevice;
     
        @Schema(description = "디바이스 브라우저")
        public String deviceBrowser;
     
        @Schema(description = "사용자 아이디")
        public long userId;
     
        @Schema(description = "권한구분")
        public String authRole;
     
    }
     
    cs

     

    728x90
    TOP