REST 방식으로 웹 서비스 구축하기Roger L. Costello, 이대엽 옮김
먼저 REST에 대해서 간략한 소개를 한 다음 REST 방식으로 웹 서비스를
구축할 수 있는 방법에 대해설명해 보도록 하겠습니다.
REST란 무엇입니까?
REST는 Roy Fielding의 박사학위 논문에서 [1] 만들어진 용어로서
네트워크로 연결된 시스템을 서술하는 아키텍처 스타일의 하나입니다.
REST는 Representational State Transfer를 나타내는 약어입니다.
Representational State Transfer로 불리는 이유는 무엇입니까?
웹은 여러 리소스로 구성되어 있습니다. 리소스는 의미 있는 모든 항목을
말합니다. 예를 들면 Boeing Aircraft Corp에서는 747을 리소스로
지정할 수도 있습니다. 클라이언트(Client)는 그러한 리소스에 다음과
같은 URL로 접근할 수 있습니다:
http://www.boeing.com/aircraft/747
레프리젠테이션(representation)은 반환되는 리소스입니다
(예, Boeing747.html). 레프리젠테이션은 클라이언트 애플리케이션을
어떤 상태(state)에 놓이게 합니다. 클라이언트가 Boeing747.html 문서에
포함되어 있는 하이퍼링크를 탐색한 결과가 또 다른 리소스에 접근하는
것이 됩니다. 새로운 레프리젠테이션이 클라이언트 애플리케이션을
다른 상태에 이르게 합니다. 따라서 클라이언트 애플리케이션이
각 리소스 레프리젠테이션의 상태에 변화(transfer; 전이)를 주게
되므로 Representational State Transfer가 됩니다.
아래는 이러한 Representational State Transfer의 의미에 대한
Roy Fielding의 설명입니다:
“Representational State Transfer는 잘 설계된 웹 애플리케이션이
행동하는 방식에 대한 형상을 재현하기 위한 의도로 만들어진 것입니다.
즉, 웹 페이지의 네트워크(가상 상태기계, virtual state-machine)는
사용자가 링크를 선택함으로써 애플리케이션의 작업을 진행하게 하며,
그 결과로 다음 페이지(애플리케이션의 다음 상태를 표현하는)가
사용자에게 전달되고 사용자가 사용할 수 있는 형태로나타내어지게 됩니다.”
왜 REST를 사용해야 합니까?
REST를 사용해야 하는 이유는 웹을 성공하게 만들어준 웹의
고유한 특성을 포착했기 때문이었습니다.그 후 이러한 특성들은
웹이 진화하는 방향으로 안내해주는 데 이용되었습니다.
REST – 표준이 아닌 아키텍처 스타일
REST는 표준이 아닙니다. 여러분은 W3C가 REST 스펙을 발표할
것을 볼 수 없을 것입니다. 게다가 여러분은 IBM이나 Microsoft 혹은 Sun에서 REST 개발 툴킷을 판매하는 것도 볼 수 없을 것입니다. 왜일까요? REST는
단순히 아키텍처 스타일에 지나지 않기 때문입니다.
여러분은 그러한 스타일을 감출 수없습니다. 여러분은 그것을 이해하고
여러분의 웹 서비스를 그러한 스타일로 설계할 수 있을 뿐입니다.
이러한 면은 클라이언트-서버 아키텍처 스타일이 있을 뿐이며
클라이언트-서버 표준이 없다는 것과 일맥상통합니다.
REST는 표준은 아니지만 다음의 표준 기술을 사용합니다:
· HTTP
· URL
· XML/HTML/GIF/JPEG/etc (Resource Representations)
· text/xml, text/html, image/gif, image/jpeg, etc (MIME 형식)
전통적인 REST 시스템
웹은 REST 시스템입니다! 여러분이 수 년 동안 사용해 왔던 무수히 많은
웹 서비스들-도서 주문 서비스, 검색 서비스, 온라인 사전 서비스, 등-은
REST기반의 웹 서비스들입니다. 가엾게도 여러분은 지금까지 REST를
사용하고 REST 서비스를 구축해 왔지만 정작
여러분은 그러한 사실을 몰랐던 것입니다.
REST는 웹의 “큰 그림”에 관심이 있습니다. REST는 상세한 구현내용
(예를 들면, 웹 서비스를 구현하기 위해 Java 서블릿이나 CGI를
사용하는 것)을 다루지는 않습니다.
그러므로REST의 “큰 그림” 관점으로부터 웹 서비스를 만들어보는 예제를
하나 살펴보도록 합시다.
Parts Depot 웹 서비스
Parts Depot, Inc(가상 회사임)는 고객이 다음과 같은 것들을 할 수 있도록
해주는 웹 서비스를 배포하였습니다:
· 부품목록 가져오기
· 특정 부품에 관한 상세정보 가져오기
· 구입 주문(purchase order; PO) 전송하기
이번에는 이러한 각 서비스들이 RESTful 방식으로 어떻게 구현되는지
알아보도록 합시다.
부품 목록 가져오기
웹 서비스는 URL을 통해 부품 목록 자원에 접근할 수 있도록 해줍니다.
예를 들어, 클라이언트는 다음의 URL을 이용하여 부품 목록을 획득할 수
있을 것입니다:
http://www.parts-depot.com/parts
한 가지 알아두어야 할 것은 웹 서비스가 “어떻게” 부품 목록을 생성하는지는
클라이언트에 대하여 완전히 투명하다는 것입니다. 모든 클라이언트는
사용자가 위의 URL을 전송할 경우 부품 목록이 담긴 문서가 반환된다는
것을 알고 있습니다. 구현이 클라이언트에 대해 투명하기 때문에
Parts Depot은 이러한리소스에 대하여 클라이언트에 아무런 영향을 주지
않고도 자유로이 내부 구현을 변경할 수 있습니다.
이것이 loose coupling입니다.
다음은 클라이언트가 받게 되는 문서입니다:
<?xml version="1.0"?>
<p:Parts xmlns:p="http://www.parts-depot.com"
xmlns:xlink="http://www.w3.org/1999/xlink">
<Part id="00345"
xlink:href="http://www.parts-depot.com/parts/00345"/>
<Part id="00346"
xlink:href="http://www.parts-depot.com/parts/00346"/>
<Part id="00347"
xlink:href="http://www.parts-depot.com/parts/00347"/>
<Part id="00348"
xlink:href="http://www.parts-depot.com/parts/00348"/>
</p:Parts>
[여기에서는 컨텐츠 협상을 통해 서비스가 클라이언트 측에서 표현수단으로
XML(machine-to-machine 처리를 위해)을 사용하기를 원하는 것으로
가정합니다.] 위의 부품 목록은 각각의 부품에 관하여 상세 정보를
획득할 수 있는 링크를 갖고 있음을 알아두십시오.
이는 REST의 핵심 기능입니다. 클라이언트는 응답 문서에 포함되어
있는 대체 URL을 검사하고 선택하여 한 상태에서 다음 상태로
옮겨가게 됩니다.
상세 부품 정보 획득하기
웹 서비스는 URL을 통해 각 부품 자원에 접근할 수 있도록 해줍니다.
가령 다음은 클라이언트가 00345번 부품을 요청하는 방법을 보여줍니다:
http://www.parts-depot.com/parts/00345
다음은 클라이언트가 받게 되는 문서입니다:
<?xml version="1.0"?>
<p:Part xmlns:p="http://www.parts-depot.com"
xmlns:xlink="http://www.w3.org/1999/xlink">
<Part-ID>00345</Part-ID>
<Name>Widget-A</Name>
<Description>This part is used within the frap assembly
</Description>
<Specification xlink:href="http://www.parts-depot.com/parts/00345/specification"/>
<UnitCost currency="USD">0.10</UnitCost>
<Quantity>10</Quantity>
</p:Part>
다시 한번 이 데이터가 어떠한 방식으로 훨씬 많은 데이터에 링크되는지
눈여겨봐주십시오. 이 부분에대한 구현은 하이퍼링크를 탐색하여
알 수도 있습니다. 각각의 응답 문서는 클라이언트가 좀 더 상세한정보로
드릴다운할 수 있도록 해줍니다.
구입주문(PO) 전송하기
웹 서비스는 URL을 통해 구입 주문(이하 PO)을 전송할 수 있도록 해줍니다.
클라이언트는 Parts Depot에서 설계한(그리고 WSDL 문서로 공표한)
PO 스키마를 준수하는 PO 인스턴스 문서를 작성합니다.
그런 다음 클라이언트는 앞서 작성한 PO.xml을 HTTP POST의
payload로 전송합니다.
PO 서비스는 PO가 전송된 URL에 대한 HTTP POST에 응답합니다.
그러므로 클라이언트는 그 후 언제든지 PO를 (업데이트나 편집하기 위해) 검색
할 수 있습니다.
이제 PO는 클라이언트와 서버간에 공유된정보의 일부가 됩니다.
공유 정보(PO)는 서버에 의해 주어진 주소(URL)이며 웹 서비스로서
외부로 노출됩니다.
논리적 URL vs. 물리적 URL
리소스는 개념적인 개체입니다. 레프리젠테이션은 그러한 리소스에 대한
구체적인 표시입니다. 다음의URL은:
http://www.parts-depot.com/parts/00345
논리적인 URL이며, 물리적인 URL은 아닙니다. 그러므로 예를 들면 각 부품에
대한 정적 HTML 페이지가 따로 존재할 필요가 없어집니다.
사실, 백 만개의 부품이 있기 때문에 백 만개의 정적 HTML 페이지가 있어야
한다면 그것은 그리 매력적인 설계는 아닐 것입니다.
[상세 구현: Parts Depot은 특정 부품에 관한 상세 데이터를 가져오는
서비스를 Java Servlet을 이용하여 다음과 같이 구현할 수도 있는데,
즉 호스트명 다음의 문자열을 파싱한 다음, 부품 번호를 사용하여 부품
데이터베이스에 질의를 하고,
쿼리 결과를 XML문서로 변환한 다음 XML 문서를 HTTP 응답의payload로
반환하게 하는 것입니다.]
스타일이야 어찌됐건 간에 URL은 사용된 구현 기법을 드러내지 말아야 합니다.
여러분은 클라이언트나URL이 오도되지 않은 채로 구현내용을 자유로이
변경할 필요가 있습니다.
REST 웹 서비스의 특징
다음은 REST의 특징들입니다:
· 클라이언트-서버: pull기반의 상호작용 스타일:
레프리젠테이션을 pull하는 컴포넌트들을 소비(consuming).
· 비상태유지(Stateless): 클라이언트로부터 서버로의
각 요청은 요청을 이해하는데 필요한 모든 정보들을
포함해야 하며, 서버에 저장되어 있는
어떠한 문맥 정보도 이용할수 없음.
· 캐시(Cache): 네트워크 효율을 재고하기 위해 각 응답은
캐싱 가능이나 캐싱 불가로식별될 수 있어야 함.
· 표준 인터페이스: 모든 리소스는 일반적인 인터페이스
(예, HTTP GET, POST, PUT, DELETE)를 통해 접근됨.
· 명기된 리소스(Named resourecs): 시스템은 URL을
이용하여 명기된 리소스로 구성됨.
· 상호연결된 리소스 레프리젠테이션
(Interconnected resource representations) –리소스에
대한 레프리젠테이션은 URL을 이용하여 상호 연결되어 있으며,
그 때문에 클라이언트는 한 상태에서 다른 상태로 진행할 수 있음.
· 계층화된 컴포넌트(Layered components) – 퍼포먼스나
보안 등과 같은 것들을 지원하기 위하여 프록시 서버, 캐시 서버,
게이트웨이 등과 같은 매개체(intermediaries)가 클라이언트와
리소스간에 삽입될 수 있음.
REST 웹 서비스 설계 원칙
1. REST 네트워크(예를 들면, 웹과 같은)로 웹 서비스를 구축하는데 있어
가장 중요한 것은 여러분이서비스로 노출하고자 하는 모든 개념적인
개체들을 식별하는 것입니다. 위에서 우리는 부품 목록, 상세부품 데이터,
구입 주문과 같은 리소스의 예를 살펴보았습니다.
2. 각 리소스에 대한 URL을 만드십시오. 리소스는 동사가 아닌 명사이어야
합니다. 예를 들면 다음과같이 사용하지 마십시오:
http://www.parts-depot.com/parts/getPart?id=00345
getPart는 동사임을 명심하십시오. 그렇게 하는 대신 다음과 같이 명사를
사용합니다:
http://www.parts-depot.com/parts/00345
3. 여러분의 리소스를 분류하는 데 있어, 클라이언트가 단순히 리소스에
대한 레프리젠테이션을 받을수 있게만 할지, 아니면 클라이언트가 리소스를
수정(추가)할 수 있게 할지에 따라 분류하십시오. 전자의 경우에는
HTTP GET을 이용하여 리소스에 접근할 수 있도록 만들어 줍니다.
후자의 경우에는 HTTP POST, PUT, 그리고(혹은) DELETE를 이용하여
리소스에 접근할 수 있도록 만들어 줍니다.
4. HTTP GET을 통해 접근 가능한 모든 리소스는 부작용이 없어야 합니다.
다시 말해 리소스는 해당 리소스에 대한 레프리젠테이션을 반환하기만 해야
합니다. 리소스에 대한 호출이 해당 리소스를 변경하게해서는 안됩니다.
5. 어느 누구도 혼자 살 수는 없습니다. 마찬가지로 어떠한 레프리젠테이션도
혼자일 수 없습니다. 바꾸어 말해 리소스 레프리젠테이션내에 하이퍼링크를
넣어 클라이언트가 좀 더 많은 정보를 드릴다운 하거나 혹은 관련 정보를
얻을 수 있도록 해주십시오.
6. 데이터를 점진적으로 드러내도록 설계하십시오. 한번의 응답 문서에
모든 것을 보여주지는 마십시오. 좀 더 상세한 내용을 얻을 수 있는
하이퍼링크를 제공하십시오.
7. 스키마(DTD, W3C Schema, RelaxNG, Schematron)를 이용하여
응답 데이터의 형식을 지정하십시오. POST나 PUT을 필요로 하는
서비스에 대해서는 응답 형식을 지정하는 스키마도 제공해 주십시오.
8. 여러분의 서비스가 WSDL 문서나 혹은 단순 HTML 문서를 이용하여
어떻게 호출될지 설명해 주십시오.
요약
이 기사에서는 REST를 아키텍처 스타일의 하나로 설명하였습니다.
사실, REST는 웹의 아키텍처 스타일입니다. REST는 무엇이 웹을
잘 동작하게 하는지를 설명합니다. REST의 원칙에 충실하게 되면
여러분의 서비스는 웹 환경에서 매우 잘 동작할 것입니다.
향후에 쓸 기사에는 REST 원칙을 이용하는 웹의 진화에 관해 쓸 것입니다.
감사의 말
이 문서를 작성하는데 매우 유익한 조언을 해주신 Robert Leftwich와
Philip Eskelin에게 감사드립니다.
참고문헌
[1] http://www.ebuilt.com/fielding/pubs/dissertation/top.htm