[Web] JAX-RS

2022. 10. 26. 23:56·Programming/Web
728x90

JAX-RS

REST 서비스를 제공하기 위해서는 여러 HTTP Method(GET, POST, PUT 등)를 지원하면서 다양한 URI 요청을 처리할 수 있는 서버 프로그램 구조가 필요하다. 단순히 서블릿만 이용해도 어느 정도 REST 형태의 서비스를 개발할 수 있지만 여러 URI 요청을 구조적으로 손쉽게 처리하려면 규격이 필요하다. 이에 따라 자바에서는 JAX-RS라고 하는 표준 규격을 만들었다.

JAX-RS(Java API for RESTful Web Services)는 REST 원칙을 사용하는 개발 메커니즘을 제공하는 자바 표준 API다. 즉 JAX-RS는 서비스 측 REST 애플리케이션 개발을 단순화하는 인터페이스 및 Java 애너테이션의 집합체라고 볼 수 있다.

스프링 프레임워크의 경우 RestController라고 하는 자체 규격을 제공하며 필요에 따라 JAX-RS를 사용할 수 있다. 시스템 자체가 스프링 기반이라고 한다면 JAX-RS를 사용하는 것보다는 스프링의 RestController가 좀 더 편리하다.

 

구현체가 필요한 JAX-RS

JDBC와 유사하게 JAX-RS 역시 표준 규격만 인터페이스 형태로 JDK에 포함되어 있고 실제 사용을 위해서는 구현체가 필요하다. 대표적으로 아파치 Jersey, JBoss RESTEasy 등이 있으나 오라클이 Java EE를 이클립스 재단으로 이관하면서 패키지명이나 명칭에 대한 부분이 변경되는 과정에서 관련 자료들이 혼재해 있는 상태다. Java EE 9 버전에서부터 JAX-RS는 Restful WS 3.0이라는 명칭을 사용하고 아파치 Jersey는 Eclipse Jersey로 명칭이 변경되었고 완전히 정착하기 전까지는 2.x 버전 사용을 권장한다. 또한 새로운 버전에서는 관련 패키지가 javax.ws.rs에서 org.glassfish.jersey로 변경되니 참고한다.

JAX-RS 사용 과정

API 서비스 등록

먼저 제공하려고 하는 API 서비스에 대한 정보를 컨테이너에 전달해야 한다. @Application 애너테이션을 사용해 어떤 시작 url을 사용할지 지정해야 하며 해당 요청에 대한 구현 클래스의 패키지를 등록해주어야 한다.

서블릿이나 JSP의 경우에도 콘텍스트 루트라고 해서 시작 경로가 정해져 있다. 다음 코드는 모든 REST API 요청이 /api로 시작하도록 지정하고 있다.

@ApplicationPath("/api")
public class RestConfig extends Application {
    public Map<String, Object> getProperties() {
        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put("jersey.config.server.provider.packages", "ch12");
        return properties;
    }
}

주의할 점은 RestConfig 클래스에서 속성으로 저장하는 패키지에 대해서만 REST API 클래스로 사용할 수 있다는 점이다. 패키지 이외에도 개별 클래스를 등록하는 방법도 있다. 자세한 사항은 관련 문서를 참고한다.

※ JAX-RS 공식 문서: https://eclipse-ee4j.github.io/jersey.github.io/documentation/latest/index.html ※

API 클래스 구현

API 클래스는 서블릿과 달리 별도의 클래스 상속 없이 일반 자바 클래스로 구현된다. 클래스 앞부분에 @Path 애너테이션으로 하위 URI 시작점을 지정하고(선택 사항) 각각의 요청에 대한 처리를 담당하는 메서드를 구현하면 된다.

 

REST API 클래스 구현에 필요한 구성요소는 다음과 같다.

  • 메서드: GET, POST, PUT, DELETE 등 어떤 HTTP 메서드 요청을 처리할 것인지 지정한다.
  • 요청 경로: 어떤 URI 요청에 동작할 것인지 지정한다.
  • 응답 콘텐트 타입 : 어떤 콘텐트 타입(예: text, html, json, xml 등)으로 응답 메시지를 구성할 것인지 지정한다.
  • 파라미터: 클라이언트 요청 파라미터 및 경로 파라미터 값을 메서드에 전달한다.

REST API를 구성한다는 것은 어떤 HTTP 메서드로 요청되는 특정 URI에 동작할 메서드를 구현하고 요청 파라미터를 메서드에서 사용해 프로그램을 구현한 다음 처리 결과를 어떤 형태로 전달할지 정의한다고 이해하면 된다.

예를 들어 /api/addrbook/list 요청을 처리하는 API 클래스는 다음과 같이 구현할 수 있다.

@Path("/addrbook")
public class AddrbookApiService {

    Logger logger = Logger.getLoeger("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") : 클래스부에 선언된 애너테이션의 경우 현재 클래스에서 처리할 서브 경로를 지정한다. 즉 /api/addrbook 요청에 응답한다.
  • @GET : GET 요청을 처리한다.
  • @Path("list") : /api/addrbook/list 요청에 응답한다.
  • @Produces(MediaType.APPLICATION_JSON) : 메서드 처리 후 생성되는 데이터 타입으로, 여기서는 JSON 형식을 리턴하게 된다는 의미다. 내부적으로 List 타입이 JSON으로 변경된다.

REST API 설계 원칙

REST API를 구현하는 과정은 비교적 단순하지만 프로그램 문법과 같이 정해진 규칙이 있는 것이 아니기 때문에 잘 설계하기 위해서는 많은 경험과 노력이 필요하다.

Swagger(https://swagger.io)와 같은 도구를 사용하면 Open API 규격의 API를 손 쉽게 설계하고 문서화할 수 있다.

일반적인 REST API 설계 원칙은 다음과 같다.

동사 대신 명사 사용

예를 들어 전체 상품 목록을 제공하는 API의 경우 getProductList, getAll, getProducts와 같은 동사 형태보다는 products와 같은 명사 형태가 적합하다.

/getProductList → /products
/getAllStudent → /students

상태 변경 시 GET 메서드와 쿼리 파라미터 사용 금지

수정, 삭제와 같이 데이터의 상태를 변경하는 경우 파라미터 형태가 아닌 HTTP 메서드와 경로 파라미터로 처리하는 것이 좋다.

GET /api/products?action=delete&id=1021 → DELETE /api/products/1021

복수 명사 사용

집합형 데이터를 다루는 API의 경우 단수형보다는 복수형을 사용하는 것이 좋다.

GET /product → GET /products
GET /studentAll → GET /students

관계 형태 표현에 하위 리소스 사용

예를 들어 컴퓨터공학과 학생들 중 홍길동 학생을 찾는 경우 다음과 같이 작성한다.

GET /depts/CE/students/홍길동

에러 정보 제공

에러 발생 시 단순히 서버 에러 500만 표시하는 것이 아니라 여러 HTTP 상태 코드를 활용해야 하며, 별도의 에러 정보를 응답 메시지 구조에 포함할 수 있어야 한다.

{
    "errors": [
        {
            "userMessage": "요청 데이터를 찾을 수 없습니다.",
            "internalMessage": "데이터베이스 검색 오류", "code": 211,
            "more info": "http://abc.def.com/api/v1/errors/12345"
        }
    ]
}

 

'Programming > Web' 카테고리의 다른 글

[Web] 스프링 프레임워크와 스프링 부트  (0) 2022.10.27
[Web] REST 클라이언트  (0) 2022.10.27
[Web] REST API  (0) 2022.10.26
[Web] 필터(Filter)  (0) 2022.10.26
[Web] 리스너(Listener)  (0) 2022.10.26
'Programming/Web' 카테고리의 다른 글
  • [Web] 스프링 프레임워크와 스프링 부트
  • [Web] REST 클라이언트
  • [Web] REST API
  • [Web] 필터(Filter)
arajo
arajo
  • arajo
    아라 메모장
    arajo
  • 전체
    오늘
    어제
    • 분류 전체보기 (509)
      • Language (298)
        • HTML (55)
        • CSS (11)
        • JavaScript (70)
        • TypeScript (8)
        • Python (33)
        • Java (119)
        • C (0)
        • C# (2)
      • Programming (92)
        • Programming (14)
        • Web (51)
        • Apache (1)
        • MySQL (23)
        • AWS (3)
      • Framework | Library (26)
        • Framework | Library (3)
        • Vue.js (2)
        • React.js (5)
        • React Native (4)
        • Node.js (1)
        • Ajax (1)
        • Bootstrap (8)
        • Spring (1)
        • Flutter (1)
      • etc (2)
      • 휴식 (19)
        • 책 (13)
        • 일기 (5)
        • 게임 일기 (1)
      • A (71)
        • 공부 (18)
        • 기타 (6)
        • 일 (47)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    HTML
    타입스크립트
    리액트
    변수
    MySQL
    객체
    react
    JavaScript
    파이썬
    array
    object
    Python
    TypeScript
    자바스크립트
    event
    web
    Java
    next.js
    제어문
    CSS
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
arajo
[Web] JAX-RS
상단으로

티스토리툴바