프로그래밍/Java

API를 Restful 하게 작성하기 위해 고려해 볼 만한 5가지 디자인

미냐님 2024. 4. 17. 13:45
728x90

" beyondj2ee "글을 참고하여 정리하였습니다.


“100% RESTful 아키텍쳐링“을 다 지킬수는 없지만
최소한 아래에 “언급하는 5가지 디자인“에 대해서는 인식할 필요가 있습니다.

1. API의Endpoint가 오직 한개인가?

실제 경험한 사례로써 한번은 어떤 시스템의 연동 문서를 보니 “오직 한개의 URL로 fix” 되어 있었습니다.


예를 들어서 URL은 “http://example.com/rest” 이며, 모든 request는 해당 URL로 통합니다.

실제 자원에 대한 정보, 호출 서비스 정보, 파라미터 정보 등은 “XML 형태의 Body 데이터“로
전송 하도록 되어 있었습니다.

 

REST의 매우 중요한 구성 요소중 하나는 “Resource” 입니다.

“Resource”의 의미는 말 그대로 서비스를 제공 하는 시스템의 자원을 말합니다.

 

예를 들어서 “영화 예매 시스템“일 경우 “고객“, “예약번호“, “좌석번호“, “영화정보” 같은 것이며
대부분 명사(noun) 형태의 특성을 갖습니다.


또한 각 “Resource“는 “URL로 표시가 되며, 유일한 식별자“로써 표현 됩니다.

2. 모든 요청을 POST 방식으로만 요청 하는가?

“RESTful“에서 위에서 언급한 “Resource“를 핸드링하기 위해서 “HTTP의 전송 메서드” 를 사용합니다.자원의 생성은 “POST“, 수정은 “PUT“, 조회는 “GET“, 삭제는 “DELETE” 메서드를 사용합니다.


예를 들면
예약 생성 : POST /reservation/2013012500001
예약 수정 : PUT /reservation/2013012500001
예약 조회 : GET /reservation/2013012500001
예약취소 : DELETE /reservation/2013012500001

 

하지만 실제 실무에서 이런 부분에 대해서 오해를 잘못해서
아래와 비슷한 방식으로 표현을 했었습니다.

 

예약 생성 : POST /reservation/2013012500001?cmd=insert
예약 수정 : POST /reservation/2013012500001?cmd=update
예약 조회 : POST /reservation/2013012500001?cmd=select
예약취소 : POST /reservation/2013012500001?cmd=delete

 

이와 같은 표현은 “RESTful“한 설계라고 할수 없습니다.

3. 응답에 대한 메타데이터를 Body에 포함 하는가?

“RESTful” 한 설계에서 “Request/Response“에 대한 메타 데이터는 최대한 HTTP 프로토콜의 방식을 준수 합니다.

클라이언트에서 요청 후 “처리 결과 값이 성공“일 경우 해당 시스템은 처리 결과를 “Body”에 포함하는 것이 아니고,

HTTP Status의 값으로써 표현을 합니다.

 

저 같은 경우는 최대한 “Pure한 HTTP Status” 코드를 사용하고,

추가되는 부분은 별도로 “사용자 정의” 코드로 관리 합니다.


사용자 정보가 없을 경우는 : 404 (Not Found)
요청 정보가 정확하지 않을 경우 : 400 (Bad Request)
인증 실패 : 401 (UNAUTHORIZED)

 

즉, 이러한 전송에 대한 메타 데이터(결과 값, 세션 키)는 최대한 HTTP 헤더로
선언하고 실제 “Body 데이터“는 위에서 언급한 “Resource의 순수한 데이터”
만을 전송 해야 합니다.

4. URL에 동사(Verb)가 포함 되어 있는가?

위에서 언급 했듯이 “RESTful“한 API 설계에서 시스템에서 제공하는 것들은 “Resource“라고 말하며

“URL“로 표기 한다라고 말씀을 드렸습니다.


또한 이러한 “Resource“들은 “명사(noun)“적 특성을 같습니다.

만약 “URL“로 표기할때 동사(Verb)가 포함이 되면 혼돈이 올수 있습니다.
행위적 표현이기때문에 RPC(메서드)를 의미하는지 “Resource“를 하는지 구분이 모호해 집니다.

 

예를 들어서 예약 상태 정보를 조회를 하기 위해서 “/reservation/001/activate” 라는 표현 보다

“/reservation/001/status” 라고 표현을 해야 합니다.

5. URL에 RPC 호출 메서드 명이 있는가?

다양한 시스템 연동 스펙을 보면 아래 와 같이 실제 비지니스 컴포넌트 메서드를

URL에 포함되서 호출하는 경우가 있습니다.

 

?action=createReservation
?action=modifyReservation
?action=findReservation
?action=removeReservation

 

또한 URL에 노출되지는 않지만 “Body“안에 “XML” 형태로 선언 하는 경우도 있습니다.

 

하지만 “RESTful” 설계의 컨셉은 “RPC (Remote Procedure Call)” 목적이 아니고
시스템에서 제공하는 “Resource“를 “bucket“화 하는 것입니다.


 

나의 생각

실제 실무에서 외부연동을 하면 “RESTful” 방식이라고 하지만 실제로는 위에서 언급한 5가지중

몇개를 지키지 않은 경우도 있고, 심지어 5개 모두 적용이 안되는 경우가 많습니다.

 

또한 HTTP/JSON/XML 통신만 하면 “RESTful” 하다고 생각들을 하는 것 같습니다.

개인적으로 아쉬운 부분은 약간의 시간을 내서 검토만 했었으면 어떨까 생각 듭니다.


그런데 필자도 말했지만 모든 연동 시스템이 반드시 “RESTful” 해야 하는 것인가? 에 대해서는

저는 약간 다른 생각을 합니다.

 

너무 유행이 되어 버려서 요새는 반드시 연동은 “RESTful“로 하려고 해서 오히려 시스템을 복잡하게 만들거나,

심지어 시스템 아키텍쳐가 흔들리는 경우도 있습니다.


2년전 제가 “일본 결제 시스템” 과 연동 한적이 있었습니다. 통신 방식은 “HTTP/XML” 이었습니다.

문서가 일본어로 되어 있어서 “번역기” 돌리고 추후에는 한글 번역본을 받아서 작업을 했는데

 

연동 항목에 “Data Type, Length, Header 선언부, Null 유무” 등 깔끔하고 심플하면서, 쉽게 구성이 되었습니다.

 

구현은 어렵지 않았고 “결제 GW 테스트” 서버로 연동 테스트를 했는데 이해하고,

연동 테스트 하는데 3일정도 소요가 되었던것 같습니다.

 

반면 국내 다른 업체 연동을 할때 “RESTful” 방식으로 한다고 했는데 전혀 “RESTful” 하지도 않고 항목도

불명확해서 완전하게 테스트하는데 무려 한달이란 시간이 소요 되었고,

그 한달이란 기간이 정말 스트레스 엄청 받았었습니다.

 

또한 모든걸 “JSON“포맷으로 통신하는 것도 문제가 있습니다.
단말 <-> 서버는 “JSON” 포맷이 가볍고 좋을 수 있지만, 실제 “Server to Server” 연동은 가볍고, 빠른게 중요한게 아니라,
데이터의 정합성이 키포인트 입니다.

 

그럴 경우는 패캣이 다소 무거울수 있더라도 “XML” 포맷으로 해서 보내야 서로 비교 문석하기가 수월 합니다.

대량의 요청을 처리하는 서버는 하나의 바이트도 빼야 한다면 “A,B,C” 같은 토큰 방식으로 정의해서

보내야 하는 경우도 있습니다.

 

이렇듯 “연동 아키텍쳐링“을 할때 명분 없이 단지 “대세”라는 모호한 논리로 맞지도 않은 것을

도입하면 안된다고 생각 합니다.


저희는 개발자이고 아키텍트이기 때문에 “현 Usecase”에 맞는 것인지 냉정한 판단이 필요합니다.

“RESTful” 아키텍쳐는 “외부 OpenAPI“에 매우 적합한 연동 아키텍쳐인것 같습니다.


마지막으로 “차니 블로그“님께서 “API Strategy & Strata 2013 Conference” 참관기에서
했던 말을 남기며 본 글을 마무리 하겠습니다.

 

"API 333 목표 : 3초만에 API를 이해하고, 30초만에 API 키를 발급 받아서,
3분안에 첫번째 요청이 오도록 해라"

 

728x90