본문 바로가기
Today I Learned/Spring

[Spring] API 문서화

by 프로그래 밍구 2022. 9. 26.

API 문서화

 Controller는 클라이언트 쪽에서 HTTP request URL을 통해 클라이언트의 요청을 전달 받는다. 그런데 백엔드 애플리케이션은 REST API 방식의 애플리케이션이다. 따라서 API 문서화란 클라이언트가 REST API 백엔드 애플리케이션에 요청을 전송하기 위해서 알아야 되는 요청 정보(요청 URL(또는 URI), request body, query parameter 등)를 문서로 잘 정리하는 것을 의미한다.

API 문서 생성의 자동화

 API 사용을 위한 어떤 정보가 담겨 있는 문서를 API 문서 또는 API 스펙이라고 한다. API 문서는 개발자가 요청 URL 등의 API 정보를 직접 수기로 작성할 수도 있고, 애플리케이션 빌드를 통해 API 문서를 자동 생성할 수도 있다. 결론적으로 수기로 API 문서를 직접 작성하는 것은 너무나 비효율적이다. API 문서에 기능이 추가되거나 수정되면 API 문서 역시 함께 수정되어야 하는데, API 문서를 수기로 작성하면 API 문서에 추가된 기능을 빠뜨릴수도 있고, 클라이언트에게 제공된 API 정보와 수기로 작성한 API 문서의 정보가 다를수도 있다. 이러한 점들이 API 문서 생성의 자동화가 필요한 이유이다. 이제부터 API 문서 생성을 자동화 해주는 Swagger와 Spring Rest Docs을 알아보겠다.

Swagger의 문서화 방식

Java 기반의 애플리케이션에서는 전통적으로 Swagger라는 API 문서 자동화 오픈 소스를 많이 사용해 왔다. Swagger는 Postman처럼 API 요청 툴로써의 기능을 사용할 수 있다는 점이 대표적인 장점이다. 아래 코드에 Swagger가 어떤 방식으로 API 문서를 자동으로 생성해 주는지 간단하게 나타내었다.

 

@ApiOperation(value = "회원 정보 API", tags = {"Member Controller"})
@RestController
@RequestMapping("/v1/swagger/members")
@Validated
@Slf4j
public class MemberControllerSwaggerExample {
    private final MemberService memberService;
    private final MemberMapper mapper;
 
    public MemberControllerSwaggerExample(MemberService memberService, MemberMapper mapper) {
        this.memberService = memberService;
        this.mapper = mapper;
    }
 
    @ApiOperation(value = "회원 정보 등록", notes = "회원 정보를 등록합니다.")
 
    @ApiResponses(value = {
            @ApiResponse(code = 201, message = "회원 등록 완료"),
            @ApiResponse(code = 404, message = "Member not found")
    })
	//...
}

 

 Swagger을 사용하면 @ApiOperation@ApiResponses와 같이 API 문서를 만들기 위한 무수히 많은 애너테이션들이 애플리케이션 코드에 추가되어야 한다. 기능 구현과 상관 없는 애너테이션이 대량으로 추가되는건 개발자 입장에서 바람직하지 않다. 또한 Controller 클래스가 끝이 아니라 Request Body나 Response Body 같은 DTO 클래스에도 Swagger의 애너테이션을 추가해주어야한다는 단점이 있다. 이는 곧 가독성 및 유지 보수성을 떨어지게 하고,  API 문서와 API 코드 간의 정보 불일치 문제 발생을 유발할 수 있다.

Spring Rest Docs의 문서화 방식

 Spring Rest Docs은 Swagger의 방식과는 다르게 애플리케이션의 기능 구현과 관련된 코드에는 API 문서 생성을 위한 애너테이션 같은 어떠한 정보도 추가되지 않는다. 대신 슬라이스 테스트를 위한 Controller의 테스트 클래스에 API 문서를 위한 정보가 추가된다.
 다음 코드는 Controller의 테스트 코드에 Spring Rest Docs의 API 문서화 코드가 추가된 예시이다.

 

@WebMvcTest(MemberController.class)
@MockBean(JpaMetamodelMappingContext.class)
@AutoConfigureRestDocs
public class MemberControllerRestDocsTest {
    @Autowired
    private MockMvc mockMvc;
 
    @MockBean
    private MemberService memberService;
	//...
    
    @Test
    public void postMemberTest() throws Exception {
	//...
        actions
                .andExpect(status().isCreated())
                .andExpect(jsonPath("$.data.email").value(post.getEmail()))
                .andExpect(jsonPath("$.data.name").value(post.getName()))
                .andExpect(jsonPath("$.data.phone").value(post.getPhone()))
                .andDo(document("post-member",    // API 문서화 관련 코드 시작
                        getRequestPreProcessor(),
                        getResponsePreProcessor(),
                        requestFields(
                                List.of(
                                        fieldWithPath("email").type(JsonFieldType.STRING).description("이메일"),
                                        fieldWithPath("name").type(JsonFieldType.STRING).description("이름"),
                                        fieldWithPath("phone").type(JsonFieldType.STRING).description("휴대폰 번호")
                                )
                        ),
                        responseFields(
                                List.of(
                                        fieldWithPath("data").type(JsonFieldType.OBJECT).description("결과 데이터"),
                                        fieldWithPath("data.memberId").type(JsonFieldType.NUMBER).description("회원 식별자"),
                                        fieldWithPath("data.email").type(JsonFieldType.STRING).description("이메일"),
                                        fieldWithPath("data.name").type(JsonFieldType.STRING).description("이름"),
                                        fieldWithPath("data.phone").type(JsonFieldType.STRING).description("휴대폰 번호")
                                )
                        )
                ));   // API 문서화 관련 코드 끝
    }
}

 

 위 예시 코드처럼 Spring Rest Docs 방식은 테스트 코드 기반의 API 문서화 방식이다. 이때 테스트 케이스에서 전송하는 API 문서 정보와 Controller에서 구현한 Request Body, Response Body, Query Parmeter 등의 정보가 하나라도 일치하지 않으면 테스트 케이스의 실행 결과가 'failed' 되면서 API 문서가 정상적으로 생성이 되지 않는다. 즉, 테스트 케이스의 실행 결과를 'passed'로 만들지 않으면 API 문서 생성이 완료되지 않는다는 것이다. 따라서 애플리케이션에 정의되어 있는 API 스펙 정보와 API 문서 정보의 불일치로 인해 발생하는 문제를 방지할 수 있다.

 Spring Rest Docs의 단점은 Controller에 대한 모든 테스트 케이스를 'passed'로 만들어야 한다는 점이 될 수 있다. 또한 API 툴로써 기능을 제공하지 않는다는 점이 단점이 될 수 있다.

댓글