:: JAX-RS 기반 RESTful API 개발
RESTful Web Service
REST는 현재 HTTP와 JSON을 함께 사용하여 OPEN API를 구현하는 형태로 많이 사용되고 있으며 대부분의 OPEN API는 REST 아키텍처를 기반으로 만들어져 있습니다. 일반적으로 REST 원칙을 따르는 시스템을 RESTful 이라고 하며 웹 기반으로 구현된 서비스 이므로 RESTful 웹 서비스라고 이야기 합니다.
REST 란 ?
2000년 Roy Fielding의 박사 학위 논문에처 처음 제안된 방법으로 네트워크 상에서 클라이언트와 서버 사이의 통신을 구현하는 방법중 하나 입니다. 클라이언트가 서버로 요청을 보냈을 때 서버가 응답으로 보내주는 Resource 의 상태를 Representation 이라고 할 수 있으며 하나의 Resource 는 여러 행태의 Representation 에를 들면 json, xml, text, rss 등으로 전달할 수 있는 것을 말합니다.
URI (Uniform Resource Identifier)
REST는 모든 유일한 오브젝트에 대해 유일하고 직관적인 URI을 통해 접근하도록 합니다. Open API 는 일반적인 프로그램 언어에서 함수를 호출하는 것과 유사하에 URI 를 통해 정보를 요청하거나 전달한다고 볼 수 있습니다.
- /users, /products 등 직관적으로 어떤 정보를 제공하는지 알 수 있는 단어로 구성
- /products/smartphone/apple/xs 와 같이 계층적인 구조를 가지도록 구성
- 기본적인 CRUD 처리는 URI에 명시적으로 표현하여 URI만으로 직관적으로 어떤 기능을 제공하는지 알 수 있도록 함.
HTTP Method
REST는 HTTP에서 제공하는 GET, PUT, POST, DELETE 4개의 메소드(여기에 HEAD나 OPTION을 추가하는 경우도 있다)를 이용해서 서비스를 제공 합니다. 이는 결국 HTTP 4개 메소드가 DB의 CRUD와 같은 기능을 하기 때문에(C:POST, R:GET, U:PUT, D:DELETE), 이러한 유형으로 분류할 수 없는 작업에 대해서는 어떻게 처리해야 할 지가 조금 모호해지기도 하기 때문에 실제 서비스 구현에 있어서는 URI을 어떻게 정의할 것인가가 REST 설계에 있어 가장 어려운 부분입니다. 관련해서는 Swagger
와 같은 문서화 도구를 사용해 API를 설계하기도 한다. 단지 CRUD 와 같은 데이터베이스 서비스만 제공한다고 했을때 서비스별로 복잡해지는 URI 를 계속해서 생성해야 하는 문제점을 해결하기 위해 페이스북에서 개발한 GraphQL
등을 사용하기도 한다.
JAX-RS
JAX-RS(Java™ API for RESTful Web Services)는 REST(Representational State Transfer) 원칙을 사용하는 개발 서비스에 대한 메커니즘을 제공하는 자바 표준 API 입니다. JAX-RS는 서비스 측 REST 애플리케이션 개발을 단순화하는 인터페이스 및 Java 어노테이션의 집합체로 REST 애플리케이션은 다른 분산 시스템 유형에 비해 개발하기 쉽고, 이용하기 편하며 확장하기 편리해서 최근 개발에 널리 사용되고 있습니다.
기본 설정
Restful Web Service 기반의 open api 를 구현하기 위해서는 자바 표준인(JAX-RS: Java Api for RESTful Web Service) 를 사용하는 방법과 스프링 프레임워크의 RestController 등을 사용하는 방법이 있습니다. JAX-RS 의 경우 표준 규격만 제공하고 있으므로 구현체가 필요한데 여기서는 apache 의 Jersey 를 사용 합니다.
build.gradle
- 프로그램의 코딩이나 구조를 어떻게 가져갈 것이냐에 따라 필요한 라이브러리가 달라짐
- 여기서는 리턴 데이터를 json 으로 혹은 json 데이터가 서버로 전달되는 것을 자바 객체와 매핑을 자동으로 해주기 위해 jersey-media-json-jackson 라이브러리를 사용함.
// Apache Jersey dependencies, require all compile 'org.glassfish.jersey.containers:jersey-container-servlet:2.27' compile group: 'org.glassfish.jersey.inject', name: 'jersey-hk2', version: '2.27' compile group: 'javax.xml.bind', name: 'jaxb-api', version: '2.4.0-b180830.0359' compile group: 'org.glassfish.jersey.media', name: 'jersey-media-json-jackson', version: '2.27'
설정 클래스
- /api 로 rest api 서비스를 제공하도록 path 를 지정하고
- javaweb.rest.exam 패키지의 클래스에서 rest url 을 검색해 등록할 수 있도록 지정 함.
@ApplicationPath("/api")
public class ApplicationConfig extends Application {
@Override
public Map<String, Object> getProperties() {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("jersey.config.server.provider.packages", "javaweb.rest.exam");
return properties;
}
}
API 클래스
- API 클래스는 기본적으로 서블릿 형태로 동작하지만 REST 특성에 따라 여러 URL 요청을 하나의 클래스에처 처리 하도록 되어 있음.
- @GET, @POST , @Path 등의 애너테이션을 이용해 메서드가 호출되는 URL 요청을 기술함.
- 각각의 메서드는 패러미터와 리턴을 가질 수 있으며 자바 객체 타입을 리턴하거나 파라미터로 받으면 자동으로 json 과 매핑됨.
@Path("/addrbook")
public class RestApiService {
Logger logger = Logger.getLogger("RestApiService");
AddrBookDAO dao = new AddrBookH2DAO();
@GET
@Path("list")
@Produces(MediaType.APPLICATION_JSON)
public List<AddrBook> getList() {
List<AddrBook> datas = dao.getAll();
logger.info("API call: /list ");
return datas;
}
}
- @Path(“/addrbook”) : 현재 클래스에처 처리할 URL 의 진입점. 전체 경로는
context root/api/addrbook
이 됨. - @GET : 지정된 URL 요청을 GET 방식으로 호출했을때 동작 하도록 함.
- @Path(“list”) : 메서드가 실행될 URI 요청. 전체 경로는
context root/api/addrbook/list
이 됨. - @Produces(MediaType.APPLICATION_JSON) : 리턴되는 데이터를 JSON 형식으로 지정.
실행 및 테스트
- 실행은 톰캣 서버를 실행하는 것으로 애너테이션으로 지정된 URI 가 등록 됨.
- GET 요청으로 등록 했으므로 웹브라우저에서 직접 URL을 입력해도 되고 curl, postman 등의 REST 테스팅 도구를 사용할수도 있다.
- 웹브라우저에서 실행하는 경우 json 으로 출력되는 결과물이 보기 좋지 않으므로 chrome 의 JSONView - Chrome 웹 스토어 확장 프로그램을 설치하면 보기 좋게 출력할 수 있다.
http://localhost:8080/javaweb/api/addrbook/list
실행결과