API(Application Programming Interface)는 애플리케이션과 시스템 간의 경계를 가리키는 용어이다. 프로그램 개발자 입장에서 애플리케이션의 코드는 라이브러리의 함수나 클래스 라이브러리를 이용한다. 따라서 개발자의 입장에서 보면 API는 함수나 클래스의 사양이다.
웹 API가 상정하는 시스템은 웹 서비스이다. 웹 서비스를 이용하는 애플리케이션은 이 둘 사이의 작업을 HTTP를 통해 수행한다. 애플리케이션은 웹 서비스에 HTTP요청을 던지고 응답을 받는다. 이때의 통신 규약이 웹 API이다.
SOAP(Simple Object Access Protocol)
HTTP를 RPC로 사용하는 시도가 있다. RPC는 프로세스간 통신을 위해 사용하는 IPC(Inter Process Communication)의 한 종류이다. 원격지의 프로세스에 접근해 프로시저 또는 함수를 호출해 사용한다. 통상적으로 프로세스는 사진 주소공간 안에 존재하는 함수만 호출해 실행한다. 하지만 RPC를 사용하면 다른 주소공간에서 동작하는 프로세스의 함수를 실행할 수 있다.
*프로시저와 함수는 둘 다 코드 블록이긴 하지만 프로지저는 값을 반환하지 않고 함수는 한개 이상의 값을 반환한다.
SOAP는 XML기반의 메시지를 컴퓨터 네트워크 상에서 교환하는 프로토콜이다. SOAP는 웹 서비스에서 기본적인 메시지를 전달하는 기반이 된다. SOAP는 통상적으로 RPC를 사용해 클라이언트에서 서버로 메시지를 요청하고 서버는 메시지를 응답하게 된다.
SOAP는 파라미터를 작성하는데 XML을 사용한다. SOAP는 XML로 명령을 작성하는 RPC이다. SOAP와 웹 서비스의 주변에는 대량의 규격이 존재한다. 이 중 WSDL은 인터페이스 정의 기술 언어이다. SOAP가 RCP 호출용 규격이라면 RPC의 형식(파라미터, 반환값)을 기술하는 것이 WSDL의 역할이다. UDDI는 WSDL을 발경하기 위해 디렉터리의 역할을 하는 작성 언어이다.
REST(Representational State Transfer)
REST는 원래 웹API와는 관련 없이 탄생된 용어이다. REST는 특정 기술을 가리키는 용어가 아니라 웹이라는 아키텍처를 분석하는 중에 웹을 특징 짓는 분산 시스템 패턴을 가리키는 용어로 만들어졌다. 웹이라는 실존하는 시스템이 먼저 탄생했고 웹이 어떻게 스케일할 수 있을지를 분석하던 중 그런 패턴을 REST라 명명한거다. 따라서 웹은 REST 패턴에 따른 분산 시스템이기 때문에 확장 가능하다는 결론이 내려졌다.
REST는 분산 시스템상의 대상을 리소스라 한다. 그리고 리소스는 URI로 접근하면 어떤 특정 형태로 실체화 된다. 즉, 클라이언트에서 서버로 접근하면 서버에서 관리되는 데이터가 JSON등의 특정 포맷으로 클라이언트로 반환된다. 리소스는 HTTP 요청 메서드를 활용해 CRUD를 할 수 있다.
REST는 원격 조작을 리소스의 객신에만 한정한다. 그에 반해 REST이전까지 분산 시스템의 주류였던 RPC는 분산 시스템 상의 함수 호출 또는 원격 객체에 대한 메서드 호출을 축으로 한다.
REST의 주축은 리소스이다. 오직 리소스의 CRUD만을 허용한다. 이는 큰 제약이지만 이 제약이 아키텍쳐를 결정짓는다. REST가 처음 등장한 로이필딩의 논문인 Architectural Styles and the Design of Network-based Software Architectures에서는 이런 REST의 제약이 웹의 확장성을 유지하고 있다고 결론짓는다.
SOAP와 REST
SOAP는 RPC적인 사상으로 원격함수를 호출한다. 따라서 HTTP에 싣는 XML은 명령이다. REST에서는 그에 반해 HTTP상에서 데이터를 보낸다. 서버상의 리소스나 문서를 갱신하기 위해 갱신 정보를 HTTP로 넘긴다. 명령은 요청 메서드로 표시한다.
SOAP와 REST의 차이는 URL의 명명 스타일에서도 나타난다. SOAP의 URL은 조작과 대응되기 때문에 동사 형태를 취한다. 그에 반해 REST의 URL은 리소스에 대응되기 때문에 명사 형태를 취하고 있다. 대신 행위(동사)를 요청 메서드로 나타낸다.
API키
일부 웹 서버는 웹 API를 활용하기 위해 API키를 발급하고 해당 웹 API 사용시 키 제출을 강제한다. API 키의 주된 역할을 다음과 같다.
1. 이용 제한
2. 과금
API 키를 비밀로 해야 하는가는 클라이언트 JS에서 중요한 의미를 가진다. 클라이언트 JS에서 API 키를 사용하는 경우 원리상 API키를 비밀로 할 수 없기 때문이다.
사용자 인증과 허가
만약 웹 API에서 문서를 갱신하거나 접근 제한을 두어야 한다면 사용자 인증을 사용해야 한다. HTTP 통신은 stateless이기 때문에 어떤 사용자에게서 온 요청인지를 판별하기 위해서는 세션을 관리할 필요가 있다. 세션은 웹 애플리케이션 측에서 사용자마다 유지하는 상태이다.
쿠키와 세션 관리
쿠키의 실체는 Cookie라는 이름의 HTTP헤더이다. 쿠키 헤더가 다른 요청 헤더와 다른 점은 웹 브라우저가 쿠키 헤더의 값을 로컬에 기억한다는 것이다.
웹 브라우저는 서버에서 받은 쿠키 값을 기억하고 같은 서버로 요청할 때는 기억하고 있는 쿠키 값을 요청에 싣는다. 웹 애플리케이션은 받은 쿠키 헤더의 값을 참조해서 해당 요청이 어느 웹 브라우저에서 온 것인지 판별한다.
쿠키로 구별할 수 있는 것은 같은 웹 브라우저인지 여부이기 때문에 다른 사용자가 같은 웹 브라우저를 사용하면 사용자를 구별할 수 없다. 따라서 불특정 다수가 사용하는 PC의 경우 보안 위험이 발생한다. 쿠키 헤더의 값이 개인 식별을 위해서 사용된다면 비밀번호 이상의 중요도를 갖는다. 하지만 보통의 웹 브라우저는 로컬에서 기억하는 쿠키 값에 엄중한 방어 기능을 갖고 있지 않다.
이런 위험을 예방하기 위해 통상적으로 쿠키에 세션 ID를 사용한다. 세션 ID는 난수를 기본으로 생성되기 때문에 값 자체에는 의미가 없다. 사용자가 로그아웃을 하거나 일정 시간 이상 응답이 없으면 웹 애플리케이션 측에서 세션을 지운다. 웹 애플리케이션 측에서 세션 ID의 유효기간을 한정하는 것을 통해 쿠키 값, 세션 ID를 도난 당하는 것을 방지한다. 이런 유효 기간을 세션 타임 아웃 값이라 한다.
쿠키의 유효 기간
유효 기간을 명시하지 않은 쿠키의 유효 기간은 웹 브라우저 프로세스가 살아 있는 동안이다. 즉, 웹 프라우저를 완전히 종료하면 쿠키가 뮤효화 된다. 이런 쿠키를 세션 쿠키라 한다. 하지만 쿠키의 유효 기간을 명시한 경우 웹 브라우저 측의 로컬 디스크에 남아 웹 브라우저를 재가동한 후에도 쿠키가 유효한 상태로 존재한다.
쿠키와 세션을 이용한 사용자 인증 과정
서버사이드의 웹 API 호출과 권한
서버 사이드에서 웹 API를 호출하는 경우 cross-origin 제한이 업기 때문에 비교적 구현하기가 쉽다. 클라이언트 사시드에서의 웹 API 호출과 비교하면 사용자의 웹 API 호출을 서버가 중단하는 형식이 된다. 그때문에 응답이 사라질 위험이 존재한다. 또 한 웹 API의 처리사 서버에 집중되서 성능상 병목 현상이 발생할 수 도 있다. 하지만 같은 웹 API 호출 결과를 추소하거나 호출 자체를 집약할 수 있는 이점 역시 존재한다.
서버 사이드에서 웹 API를 호출하는 것의 문제는 누구의 권한으로 API를 호출하냐는 것이다. 이상적으로는 사용자가 서비스 제공자상에 가진 계정의 권한으로 웹 API를 호출해야 한다. 하지만 쿠키는 발행한 서버 이외에는 송신되지 않는다는 문제가 발생한다. 이 문제를 해결하기 위해 OAuth라는 권한 위임 프로토콜을 사용한다. 이를 사용하면 사용자로 부터 권한을 위임받은 서드파티 애플리케이션이 사용자의 권한으로 서비스 제공자의 웹 API를 호출할 수 있다.
클라이언트 사이드의 웹 API 호출과 권한
클라이언트 사이드에서 웹 API를 호출한 경우 서버사이드 처럼 권한 문제가 발생하지만 조금 다른 형태의 권한 문제가 발생한다. 클라이언트 사이드에서 웹 API호출은 웹 브라우저에서 서빗 제공자로의 HTTP요청이다. 서버 사이드의 웹 API 호출과는 달리 이 요청에는 사용자의 서비스 제공자상의 로그인 상태와 관련된 쿠키가 실린다. 이는 CSRF(Cross Site Request Forgery)문제를 야기한다. CSRF는 웹 애플애플리케이션의 취약점 중 하나로 사용자가 자신의 의지와는 무관하게 공격자가 사용자의 권한을 도용해 공격자가 원하는 행위를 특정 웹사이트에 요청하게 만드는 공격이다.
인증(authentication)과 인가(authorization)
명칭 | 설명 |
인증 | 신원을 판단하기 위해 개인이나 프로세스가 게시하는 자격 정보 검증. 웹에서는 통상적으로 로그인을 의미한다. |
인가 | 어떤 행위를 하는, 어떤 장소에 접근하기 위해 권한을 개인에게 주는 일. ex).인증을 통과하면 할 수 있는 어떤 일 |
위에서 말했던거 처럼 웹 API를 사용할 때는 서비스 제공자, 서드파티 애플리케이션, 사용자라는 세 주체가 존재한다. 각 주체 간의 인증과 인가에는 권한 위임 같은 별도의 구조가 필요하다. 이런 구조를 분산 인증 시스템/프로토콜 또는 분산 인가 시스템/프로토콜이라 한다.
분산 인증의 예로는 openID가 있고 분산 인가의 예로는 OAuth가 있다. 웹 API에서는 분산 인가 시스템의 역할이 커지고 있다.
OAuth
OAuth는 인가 전달 프로토콜이다. 즉, 서비스 A에서 인가된 것을 서비스 B에 전달하기 위한 프로토콜 규격이다. 이는 웹 API에서 서비스 제공자상의 사용자 권한을 서드파티 애플리케이션에 위임하기 위해 사용된다. 이때 사용자와 서비스 제공자 간의 비밀 정보(비밀번호, 세션 ID의 쿠키값)를 서드파티 애플리케이션에 넘기지 않고 권한위임을 할 수 있다.
일반적으로 OAuth라고 하면 위에서 설명한 '서버사이드의 웹 API 호출과 권한' 설명한거 처럼 서드파티 애플리케이션이 사용자의 권한으로 서비스 제공자의 웹 API를 사용하는 것이 기본 시나리오다. OAuth 2.0에서는 클라이언트 사이드 js에서도 사용할 수 있는 사용자 에이전트 플로가 추가됐다.
OAuth 2.0의 서버 사이드 플로우
OAuth 2.0의 사용자 에이전트 플로우
사용자 에이전트 플로우의 경우 서드파티 애플리케이션(서버 사이드)과 서비스 제공자는 교류가 없다. 사용자와 서비스 제공자 간의 HTTP 통신은 로그인 상태면 쿠키가 실려 세션이 관리된다.