ⓦeb ⓢtory/web service

[스크랩] REST 알아보기 - 1부, 연동의 역사

뚱땡이 우주인 2011. 8. 30. 16:09
원본 : http://dreamgoer.net/199

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의 약자로 주로 유닉스에서 사용되었었습니다. 하지만 이놈은 보안에도 문제가 좀 있었고, 네트웍 자원 활용이나 함수를 동적으로 사용하는데 있어서도 제약이 있었습니다. (프로그래밍 안해보신 분들은 아래그림보고 그냥 이런게 있구나 하고 넘어가시면 되겠습니다)

(출처: http://www2.cs.uregina.ca)

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

(출처: http://img.zdnet.com)

그런데 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같은 거라고 이해하시면 됩니다)라는 놈에 등록해서 외부에서 발견할 수 있게 하는 구조였습니다.

(출처: http://nuwanbando.com)

그러다가, 서비스지향으로 바라보기 보다는 리소스기반(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의 대명사가 되었는지를 설명하도록 하겠습니다.