티스토리 뷰

지난번에 했던건 그저 API 호출을 하면 Hello,World를 뱉어내는 아주 단순한 API를 만들어냈다.

사실 어떤 웹서비스를 만들고 그 서비스를 이용하기 위해서는 꽤 많은 양의 API들이 필요하고 그 API를 정리하는데에 시간을 소모하게 된다.

내가 만약 아주 단순한 서비스를 만든다고 가정했을 때(아직 OAuth를 배우진 않았으니까 OAuth가 없다고 가정하고) 일반적으로 예상할 수 있는 API의 종류는 아래와 같을 것이다.


  • 이메일 중복확인
  • 회원가입
  • 로그인
  • 개인정보 수정
  • 패스워드 수정(개인정보 수정에 포함 가능)
  • 회원 탈퇴
  • 파일 업로드
  • 파일 다운로드(다운로드 관련 기능이 별도로 필요하다면)
  • 글 쓰기
  • 글 수정하기
  • 글 삭제하기
  • 글 목록 가져오기
  • 글 읽기

이 정도 기능이면 아주아주 단순한 게시판 하나 달랑있는 사이트를 만들어 낼 수 있다.

아, 위 기능은 서버에서 처리할 API 종류에 대한 이야기다. 최소한의 기능들의 목록이며 나머지 사이트들의 경우 이 기능들에서 살을 덧붙여 만들거나 위 기능의 반복 수준에서 소규모에서 중규모 사이트까지 만들어 낼 수 있다.

물론 이런 기본 기능 외에 다른 특수한 기능들을 제공 받기를 원할 수 있는데 이것은 대부분 Frontend 단에서 적용이 가능하거나 Backend의 기능 확장이 필요한 경우가 있을 수 있다. 내가 여기에서 이야기하고 싶은 부분은 저 위의 기능은 사이트를 구성하는 아주 아주 최소한의 기능뿐이라는 거다.

그리고 관리자 기능은 넣지도 않았다. 관리자 기능을 넣으면 회원관리기능이라던지 게시물 관리기능 정도가 붙겠지만 사실 위 기능의 확장이거나 응용이 전부라는 점에서 큰 이슈사항이 없을것이라고 생각한다. 물론 통계라던지 태그를 이용한 검색이라던지 하는 특수한 기능들도 있겠지만 내가 하려는건 어디까지나 "단순한" 사이트니까.


일단 이 정도의 기능으로 사이트를 만들고 그 뒤에 추가 기능을 덧붙인다고 생각하고 진행한다.

오늘은 저번에 만든 프로젝트에 Swagger라는 기능을 붙일 생각인데 이 기능이 무엇이냐하면 Controller에서 API를 만들면 이것을 문서화하는 일이 굉장히 귀찮다. 뭐 엑셀로 할지, 혹은 워드로 정리할지 문서화하는 일은 중요하지만 귀찮은 일임에는 틀림이 없다. 그래서 그걸 대신작업을 해주는 녀석이 이 Swagger라는 라이브러리다.

이 라이브러리는 서버가 올라갈때 자동으로 RestController어노테이션을 읽어서 내부의 API를 분석하고 HTML 문서를 작성해 서비스를 제공해준다. 셋팅작업을 진행해보자.


일단 https://swagger.io/ 사이트에 가본다.



이런 페이지가 나온다. 세상에서 가장 유명한 API 툴이라며 광고를 했다. 이것은 Open Source고 무료로 적용할 수 있다. 내용을 읽어보니 뭐 좋은 내용들이다. 무료고 오픈소스고 라이센스가 어떻고 디자인이나 빌드나 Document도 어떻고...

그런데 문제는 이걸 어떻게 우리 프로젝트에 적용해야 하는가에 대한 것은 어디있느냐는 거다.


그래서 구글링을 좀 했더니 http://www.baeldung.com/swagger-2-documentation-for-spring-rest-api 사이트에 설명이 잘 되어 있는 것을 확인했다.

Maven Dependency를 통해 생성하는 것부터 잘 따라서 작업해보자.



<dependency>
    <groupid>io.springfox</groupid>
    <artifactid>springfox-swagger2</artifactid>
    <version>2.7.0</version>
</dependency>
<dependency>
    <groupid>io.springfox</groupid>
    <artifactid>springfox-swagger-ui</artifactid>
    <version>2.7.0</version>
</dependency>


먼저 swagger2 라이브러리를 pom.xml의 dependency 쪽에 추가하자.


그리고 SwaggerConfig라는 클래스를 만든다. 나는 config 패키지를 하나 추가해서 거기에 SwaggerConfig 클래스를 만들었다.



이렇게 했으면 몇가지 코드를 추가하는데 아래와 같이 준비한다.



package com.example.sample.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;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

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


이렇게 작성하면 일단 Swagger 설정은 마쳤다. 

이렇게 하고 서버를 시작해보자.



이러면 위 사진처럼 Swagger관련 API들이 로그에 찍힌 것을 확인할 수 있다.

조금 더 설정 정보를 추가할 수 있다.



package com.example.sample.config;

import java.util.Collections;

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.service.ApiInfo;
import springfox.documentation.service.Contact;
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.SWAGGER_2)  
          .select()                                  
          .apis(RequestHandlerSelectors.basePackage("com.example.sample.controller") )              
          .paths(PathSelectors.any())                          
          .build()
          .apiInfo(apiInfo());
    }
    
    private ApiInfo apiInfo() {
        return new ApiInfo(
          "Hello REST API", 
          "Some custom description of API.", 
          "API TOS", 
          "Terms of service", 
          new Contact("야훔", "www.example.com", "myeaddress@company.com"), 
          "License of API", "API license URL", Collections.emptyList());
   }
}


이렇게 작업을 해 놓고 http://localhost:8080/swagger-ui.html 페이지를 한번 확인해보자.


요런 화면이 나오고  우리가 만든 hello API가 자동으로 확인되어 화면에 표시해준다.


그리고 API 주소를 클릭하면 조금 더 상세 정보를 확인할 수 있고 "Try it out!" 버튼을 클릭하면 XHR로 API를 호출한 결과를 알려준다.


Controller에 아래와 같이 주석처리를 하면 Swagger UI에 설명을 추가해 넣을 수 있다.



HelloController.java

package com.example.sample.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@RestController
@Api(value = "HelloController", description = "헬로 에이피아이")
public class HelloController {

	@RequestMapping(value="/hello", method= RequestMethod.GET)
	@ApiOperation(value="hello, World API", notes="hello, World를 반환하는 API, Ajax 통신 확인용.")
	public String helloWorld() {
		return "hello, World";
	}
}


SwaggerConfig.java

package com.example.sample.config;

import java.util.ArrayList;
import java.util.Collections;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMethod;

import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.ResponseMessageBuilder;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.ResponseMessage;
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.SWAGGER_2)  
          .select()                                  
          .apis(RequestHandlerSelectors.basePackage("com.example.sample.controller") )              
          .paths(PathSelectors.any())
          .build()
          .apiInfo(apiInfo())
          .useDefaultResponseMessages(false)                                   
          .globalResponseMessage(RequestMethod.GET, getArrayList());
        
    }
    
    private ArrayList<ResponseMessage> getArrayList(){
    	ArrayList<ResponseMessage> lists = new ArrayList<ResponseMessage>();
    	
    	lists.add(new ResponseMessageBuilder().code(500).message("서버에러").responseModel(new ModelRef("Error")).build());
    	lists.add(new ResponseMessageBuilder().code(403).message("권한없음").responseModel(new ModelRef("Forbbiden")).build());
    	
    	return lists;
    }
    
    private ApiInfo apiInfo() {
        return new ApiInfo(
          "Hello REST API", 
          "Some custom description of API.", 
          "API TOS", 
          "Terms of service", 
          new Contact("야훔", "www.example.com", "myeaddress@company.com"), 
          "License of API", "API license URL", Collections.emptyList());
   }
}


코드가 좀 길어지긴 했는데 위와 같이 수정을 하고 서버를 재시작하면 아래와 같은 화면을 볼 수 있다.



이런식으로 Swagger를 적용시켜서 작업하면 나중에 API 문서를 따로 준비하느라 고생할 필요가 없겠지.


다음시간엔 처음에 이야기한 기능들을 위해 DB를 셋팅하고 QueryDSL을 설정하는 시간을 갖도록 하자.


오늘은 여기까지!

댓글
댓글쓰기 폼