2012년 5월 15일 화요일

Rest 알아보기 1,2부

출처 : http://www.rcy.co.kr/xeb/411


2000년대 후반부터 웹에서 OPEN API하면 REST가 항상 언급됩니다. 그리고 제가 WOT(Web of things) 소개하면서 쓴 글("왜 WOT인가? - 1부", 클릭)에도, REST가 핵심이라고 했습니다. 그래서 오늘은 웹기반 Open API의 표준 연동방식처럼 회자되는 REST라는 놈에 대해 정리를 해보고자 합니다. 

우선 REST는 무엇일까요? REST(Representaional State Transfer의 약자)는 웹프로토콜(HTTP)을 활용하여, Resource 중심으로 연동 인터페이스 구조를 제안한 것입니다. 그런데 리소스 중심이라는 얘기나, HTTP라는 얘기 모두 감이 잘 오지 않을 것입니다. 일단은 웹서비스를 Open API로 연동하는 데 있어서, 어떻게 HTTP를 사용하면 좋다는 스타일 가이드라고만 해두고 REST가 나오기까지의 히스토리를 좀 짚어보겠습니다. 왜냐하면 웹세상 이전으로 돌아가서, 고전적인 시스템(클라이언트-서버)간 연동 문제가 어떻게 해결되어 왔는지 그 실타래를 따라가다보면 REST가 어떻게 Open API의 강자가 되었는지를 저절로 이해하게 되기 때문입니다. 



[프로그램간 연동 - 고민의 시작]

개발의 기본은 무엇인가요? 라이브러리화(쉽게 말해 함수화하는 것)입니다. 그렇게 함으로써 소스코드를 쉽게 재활용할 수 있게 하고, 특히 라이브러리를 공유함으로 나혼자가 아니라, 다른 사람들도 이어서 개발을 할 수 있는 기반이 됩니다. 그런데, 이렇게 하는 것도 하나의 컴퓨터에서나 가능할 뿐, 네트웍을 넘어갈 순 없었습니다. 즉 A컴퓨터에서 B의 컴퓨터에 있는 라이브러리를 호출할 수는 없다는 것이었습니다. 

그래서 B의 컴에 네트웍을 통해 호출받을 수 있도록 좀 작업을 하기 시작합니다. 그게 소위 RPC 데몬이라는 놈인데, Remote Procedure Call의 약자로 주로 유닉스에서 사용되었었습니다. 하지만 이놈은 보안에도 문제가 좀 있었고, 네트웍 자원 활용이나 함수를 동적으로 사용하는데 있어서도 제약이 있었습니다. (프로그래밍 안해보신 분들은 아래그림보고 그냥 이런게 있구나 하고 넘어가시면 되겠습니다)


그래서, 이 문제를 해결하는 김에, 아예 프로그램언어, OS와도 무관하게 해결해보자는 시도가 있게됩니다. 바로 그게 CORBA였습니다. CORBA는 A컴에 있는 C++ 프로그램이, B컴에 있는 자바 서버의 함수도 호출할 수 있게 한다는 뭐 그런 취지였습니다. 원리는 대강 이렇습니다. IIOP라는 프로토콜을 통해서, 프로그램 언어에 상관없이 인터페이스를 정의(IDL)하고, 그걸 기반으로 각 언어에서 CORBA 플랫폼을 통해 개발하면 C++로 짜놓은 함수도, 자바에서 호출할 수 있게 되는 것이었습니다. 


그런데 CORBA는 무겁고 비쌌습니다. (참고로 많이는 아니지만, Iona의 Orbix와 볼랜드의 Visibroker라는 대표적인 Corba 플랫폼을 다 만져볼 기회가 있었습니다.) 클라이언트는 무료였지만, 서버쪽 CORBA 플랫폼은 2000년 초반가격으로도 1억이 넘었습니다. 게다가 연동오버헤드도 무거운 편이어서, 개발해보면 서버쪽 HW도 어느정도 빠방해야 했지요. 결국 프로그램간 연동을 쉽고 경제적으로 하기 위해 나온 놈이 비싸고 쉽지 않았던 겁니다. 

그래서 Java 진영에서는 RMI (RPC의 자바버전)를 소개합니다. 제가 NMS 개발하면서 사용해보았는데, 쉽고 아주 편했습니다. 하지만 이 놈도 사내 네트웍에서는 연동이 쉬웠지만 방화벽에서는 늘 상 걸리곤 했습니다. 방화벽은 기본적으로 HTTP만 열어주지요. 





[HTTP - 웹서비스 화두를 열다]

그래서 HTTP로 무엇인가 연동하는 방안을 고민했었고, 그게 바로 XML과 HTTP를 결합한 SOAP기반의 웹서비스였습니다. 일단 SOAP은HTTP를 활용할 수 있므로, 방화벽문제는 어느정도 해결했습니다. 그런데 문제는 여전히 좀 어려웠다는 겁니다. SOAP기반 웹서비스는 근본적으로 서비스지향 구조(Service-Oriented Architecture)로써, SOA라고 불리는데요. 서비스를 자유자재로 정의할 수 있다는 게 매력인 동시에 그만큼 복잡해질 수도 있다는 게 문제였습니다. 

즉 서비스를 정의하는 것 자체도, WSDL이란 놈을 만들어 함수명부터 시작해서 매개변수, 결과값까지 세부적인 사항 하나하나를 정의합니다. 그리고 이를 UDDI(인터넷에서 DNS같은 거라고 이해하시면 됩니다)라는 놈에 등록해서 외부에서 발견할 수 있게 하는 구조였습니다.


그러다가, 서비스지향으로 바라보기 보다는 리소스기반(Resource-Oriented Architecture: ROA)으로 정의하면 어떻겠느냐는 아이디어가 나옵니다. 잘 아시듯, 웹이라는 놈 자체가 리소스기반입니다. 웹에서는 모든 문서, 객체(URI를 통해 가져올 페이지를 표시하지요)를 대상으로 해서, HTTP Get하는 게 기본 조작입니다. 그래서 자원관점으로 보면, 웹에서 사용하는 HTTP Primitive (GET, PUT, POST, DELETE)를 그대로 쓸 수 있지 않겠냐는 생각을 하게 된거죠. 바로 그게 REST인겁니다. 

결국 REST는 SOAP기반의 웹서비스인 SOA(Service-Oriented Architecture)와 대비되는 자원기반의 ROA(Resource-oriented Architecture) 연동방식인 것입니다. 참고로 ROA는 더 확장해서 WOA 즉 Web Oriented Architecture로까지 발전됩니다. 아래 그림은 ROA의 대표격인 REST를 포함해서, 이를 더 넓게 그린 WOA를 보여줍니다. 


참고로 저는 SOAP시대까지만 프로그램에 손을 대었는지라, REST로 직접 개발을 해본 경험은 없습니다. 대신 REST 책은 한권 읽어보았고, 그걸 기반으로 아는체 하고 있는 겁니다. 따라서 REST 개발자분들께서 댓글을 달아주시면 저와 읽는 분들 모두 다 행복해지겠지요.


[ROA - 생각해보면 그럴싸하다]

SOA에서는 WSDL에 호출할 함수명을 마음대로 정의할 수 있습니다. 즉 id로 이름을 가져오는 웹서비스를 만든다고 할때, getName, retrieveName, findName 모두 사용할 수 있습니다. 그런데 과연 이런 자유도가 중요할까요? 알고보면 이름은 거기서 다 거기인 셈입니다. 

REST는 모든 것을 리소스기반으로 보기때문에, 위의 함수(getName, retrieveName, findName)를 만드는데 사용하는 함수명은 HTTP의 Get임이 자명합니다. 그리고 특정 ID로 이름을 입력하려면 HTTP POST, 갱신하려면 HTTP PUT, 삭제하려면 HTTP Delete를 사용하면 될 것입니다. 바로 이 부분에서만 해도, REST는 개발상 굉장히 직관적인 셈입니다. 

리소스 관점으로 보는 대표적인 예가 DB입니다. DB안에 있는 것은 모두 리소스입니다. 그러면 DB를 조작하는 데 사용하는 SQL의 Primitive는 무엇이 있습니까? 아래 그림 가운데 있는 insert, select, update, delete입니다. 

위에 보시는 것처럼, 각각은 알고보면 HTTP의 기본동사(Primitive)와도 1:1 대응이 됩니다. 그리고 프로그램할때, 특정 변수에 대해 생각해볼 기본조작 함수인 CRUD(Create, Read, Update, Delete)도 알고보면 HTTP 기본동사(Primitive)에 대응이 되는 셈입니다. 즉 REST는 나름 우리가 표준적으로 사용하는 프로그래밍 패러다임과 쉽게 매핑이 된다는 얘기입니다. 

※ SDK를 보신 분들이라면, 메쏘드 이름을 떠올려보세요. 객체지향 프로그램을 하는 분들은 다 공감하실 것이, 객체를 생성하거나, 삭제하는 것을 제외하면, 대부분 함수는 Getter와 Setter로 구성된다는 겁니다. 즉 GetXXX, SetXXX식의 함수가 되버리죠. 물론 Go, run, doIt 같은 함수들도 돌리지만, 그게 알고보면 Create, Delete, GetXXX, SetXXX로 구성될 수 있는 것들입니다. 


[그러면 매개변수와 결과값은 어떻게 전달해주나요?]

아마 누군가가 벌써 질문하고 있을 겁니다. 기존프로그램에서는 함수라는 게 알고보면 함수명만 있는 게 아니고 매개변수고 있고, 결과값도 있는데 그게 어떻게 처리되냐고 말입니다. 일반적인 함수의 형식은 이렇지요. 
  • NameType GetName(String id);

위에서 말한 것처럼, GetName에 해당하는 부분은 HTTP의 GET인 셈입니다. 그리고 Name이라는 부분은 URI를 통해서 이뤄지는데, 아마도 http://abc.com/employee/name?id="ooo" 같은 식으로 HTTP-Request의 GET에서 충분히 표현이 될 것입니다. 그리고 그 결과값(위에서는 NameType)은 형식만 정의하면(보통 XML이나 JSON으로 정의합니다) HTTP response로도 정리가 될 것이구요. 

특히 HTTP는 RESPONSE W3C에서 표준 코드로 인터넷에서 발생할 수 있는 상황을 모두 고려하여 정리되어 있습니다. 즉 결과값에서 200OK뿐만 아니라, 다음과 같은 상태 코드들이 나올 수 있고, 그에 대한 대응도 대부분의 브라우저는 다 알고 있습니다. 다시말해 웹개발을 해본 사람들은 누구나 쉽게 이해할 수 있으며, 이에 맞게 대응할 수 있다는 얘기입니다. (아래는 Status code 일부만 표시해본 것입니다)
  • 301 Moved permanently
  • 302 Found
  • 303 See Other
  • 403 Forbidden
  • 404 Not Found
상기의 HTTP-response 코드는 단순해보이지만, Loosely coupled 된 웹을 지켜주는 오랜 경험의 산물입니다. 실상 이 코드에 따라 IE나 파폭, 크롬, 사파리같은 웹브라우저는 알지도 못하는 아프리카의 한 웹사이트에서 오는 가끔 에러를 발생시키는 검증안된 웹 response에도 걸맞게 대응할 수 있는 것입니다. 

REST에서는 힘하나 안들이고, 상기의 HTTP 프로토콜에서 제공해주는 메커니즘을 그대로 활용하고 있는 셈입니다.

※ 물론 연동방식을 결정하실때 REST로 하자고만 하면 다 해결되는 것은 아닙니다. REST는 RESTful approach, 즉 하나의 방식이라는 표현을 사용하고 있는데 그 이유는 REST가 HTTP Primitive + URI를 사용하여, HTTP-request를 날리고, HTTP-response를 통해 응답결과를 주고받으라는 방식을 지정했을 뿐, 실제 결과 데이타의 표현형식은 개발자가 알아서 정해야 하기 때문입니다.(보통 XML이나 JSON으로 정합니다) 이 점에서 REST는 나름 꽤 열려있지만, 그만큼 REST 이름만 빌릴 뿐 RESTful하지 않은 OpenAPI가 마구 나올 수 있다는 얘기가 됩니다.



[정리하자면...]

REST는 네트웍상에서 원격에 있는 서버의 서비스(API)를 사용할 수 있게, 그것도 방화벽이라는 제약을 넘어서 가능하게 하자는 취지에서 나왔습니다. 이런 시도는 서비스지향의 SOAP기반의 웹서비스도 있었으나 REST는 좀더 실용적인 접근을 했고, 그 실용성, 이해하기 쉬움, HTTP의 Verb, request, response를 그대로 사용한다는 특징덕에 현재는 가장 각광받는 Open API 방식이 되었습니다. 

2부에서는 상기 이유외에도, 아니 상기 이유를 좀 더 구체적으로 명기하여 왜 REST가 OpenAPI의 대명사가 되었는지를 설명하도록 하겠습니다. 

 
---- 1부 끝 ----
 
이 글은 REST에 대해 정리하는 두편의 글중 두번째 글입니다. 따라서 1부("REST 알아보기 - 1부, 연동의 역사", 클릭)를 읽지 않으신 분은 먼저 1부부터 보시고 본 글을 읽어주시길 바랍니다. 1부 글은 왠만하면 반복하지 않을테니까 말입니다. 


[1부를 아주 간단히 요약해버리자면]

REST도 네트웍에 물려있는 서비스 자원들간의 연동이라는 이슈에서 나온 것으로써, 1부에서 네트웍에서 연동의 역사를 한번 나름대로 짚어보았습니다. RPC - CORBA - RMI - SOAP - REST에 이르기까지, 그 기술들이 진화하며 해결한 부분들을 파악했습니다. 

REST는 "Representaional State Transfer"의 약자로써, 웹프로토콜(HTTP)을 활용하여, Resource 중심으로 연동 인터페이스를 정의하고 사용하는 방법을 제안한 것입니다. 한마디로 웹(HTTP) 프로토콜을 최대한 그대로 사용하여, Open API를 만드는 스타일가이드라고 할 수 있습니다. 

그러나, 이런 개념적인 얘기로는 개발자가 아니신 분들이라면 잘 이해가 가지 않을 것입니다. 그래서 오늘은 좀 더 명확하게 이해할 수 있도록 REST가 좋은 이유를 구체적으로 설명하도록 하겠습니다. 
 


[REST는 뭐가 그리 좋은가?]

1. 웹친화적이다.
이미 웹 친화적이라는 말씀은 서두에서 드렸으므로, 더이상 설명할 필요는 없을 것 같습니다. 요새는 방화벽을 넘어서 연동해야 하는 경우가 허다합니다. 그럴때 SOAP이나 REST를 제외한 다른 연동프로토콜들을 대부분 방화벽에서 문제를 야기합니다. 


2. 웹서버로 해결이 가능하다
REST는 HTTP 동사를 그대로 사용합니다. 앞서서 얘기했듯이 HTTP request, response 전부 재활용합니다. 심지어 Error 상태 code까지도 말입니다. 게다가 결과를 주고받는 것도 웹브라우저에서 지원되는 XML 또는 JSON입니다. (JSON은 자바스크립트에서 XML보다 데이타를 쉽게 전달하는 방법이지요) 따라서 대부분의 서버프로그램을 제외하면 REST를 운용할 수 있는환경이 웹서버하나로 해결되는 셈입니다. (참고로 요새 공유기, IP전화기, 각종 셋탑 등 모든 IP장비는 웹을 통해 설정을 할 수 있게 되어 있습니다. 그 얘기는 그런 장비들에 웹서버들이 모두 들어간다는 것입니다.)

3. 캐슁(Caching)도 된다
REST 방식을 제대로 적용한다면, 즉 ReSTful하게 잘 만든다면, 웹에서 캐쉬기능도 그대로 활용할 수 있습니다. 아시다시피, 웹에서는 동일한 내용을 계속조회할때 중간노드에서 프락시를 사용하여 트래픽을 줄이기도 합니다. (IE 브라우저 옵션에 보시면 HTTP-Proxy 설정부분이 있는데 바로 그 부분을 말합니다) 그런데, 웹서비스도 알고보면 업데이트보다는 조회가 훨씬 많다는 것이고, 그 조회의 대답은 앞단에서 Proxy가 캐쉬한 값을 전달해서 처리할 수도 있다는 얘기입니다. 잘 사용하면 서버 부하, Response time을 확 줄일 수 있겠죠. 


4. 개발자에게 상당히 직관적이다. 
이것도 앞에서 말씀드렸던 내용인데, HTTP 동사를 그대로 사용하고, 예외코드도 그대로 사용하므로, 개발자 관점에서는 상당히 익숙하고 직관적으로 이해할 수 있습니다. 즉 REST로 OpenAPI를 제공하면, 매개변수와 URI에 집중하면 되고, 함수를 실제 호출하고 사용하는 방식에 있어서, 많은 부분 RESTful하다는 얘기로 설명이 된다는 부분입니다. 


5. 컨텐츠 협상(Negotiation)이 가능하다. 
아니 프로그램에서 웬 협상하실 겁니다. 그런데, Open API는 클라이언트 서버처럼 Tight couple된 관계가 아니라서, 어떤 놈이 HTTP-request를 날릴지 모르는 것이고, 그 놈이 서버에서 제공해주는 HTTP-response를 다 알아 먹을 수 있는지도 알 수 없다는 점입니다. 즉, Response가 기본 한글인데, 함수를 호출한 놈은 영문만 받아들 일 수 있다면, HTTP에서는 컨텐츠 협상을 통해, 이 요구에 대해서는 좀 다르게 응답을 할 수도 있는 것이지요. (아마 HTTP request를 할때, 본문에서 Accept-Language header를 활용하여 이런 협상을 하게되겠죠)

일반적으로 서버 프로그램하면서 이런 것까지 다 고려해서, 확장성을 확보하기는 사실 어렵습니다. 기껏 한다고 해봐야, if절이나 예외처리(Try catch) 몇개로 해결할 뿐이죠. 그런데 HTTP는 언어나 미디어타입(MIME)까지 기본적으로 협상할 수 있게 왁꾸가 되어 있는 것입니다. 제게는 이런 Feature가 참 아름다운데, 그렇지 않으신지요 ^^; 


6. 웹 기술은 다 써먹을 수 있다. 
데이타를 주고받는데 가장 확장성있는 방법은 누구나 인정하듯 XML입니다. 그래서 웹에서 XML은 엄청 널리 쓰이고 있습니다. REST에서는 결과값을 전달하는 데 있어서 복잡한 내용도, 구조적인 결과도 XML로 처리할 수 있는 것입니다. 

아울러 웹은 HTTP-response로 전달될 결과값이, 그리 복잡한 구조도 아니고, 아주 간편한 처리를 할 수 있도록 할 경우 JSON을 쓰기도 합니다. (JSON은 JavaScript에서 손쉽게 구조적인 값을 주고받는 방식이지요) REST에서도 이 방식도 그대로 사용할 수 있습니다. (JSON을 쓸경우, HTTP request의 헤더중에 "Accept: application/json"이 들어가게 되겠지요)

결국 REST에서는 널리 사용되는 웹기술(HTTP + URI + XHTML + XML + JSON ...)을 그대로 받아들여 OpenAPI를 아주 실용적인 관점에서 접근하게 해주는 셈입니다. 


[끝으로 한마디]

제가 설명한 것외에도 HTTP 프로토콜을 사용함으로 얻는 이점은 더 많이 있을 것입니다. HTTP를 아는 사람이라면 새로 배울 필요가 없다, 개발툴, 검증/테스트가 쉽다 등등 말입니다. 그래서 REST는 OpenAPI로 각광받는 것이며, 아울러 계속해서 발전 진화하고 있습니다. WOA(Web oriented architecture)나 WOT(Web of things)같은 게 그발전, 활용도의 극대화 예라고도 할 수 있겠습니다. 

아무쪼록 웹하시는 분들, 매쉬업 아이템을 기획하시는 분들은 REST의 기본개념은 알아두시기 바랍니다. 


---- 2부 끝 ----

댓글 없음:

댓글 쓰기