API 설계
프로그램끼리 서로를 부르는 접점을 어떤 모양으로 낼지 미리 정해 두는 일입니다. 한 번 낸 모양은 남이 이미 그 모양대로 부르고 있습니다. 그래서 무엇을 정하느냐는 물음의 답이 한 문장이 아니라 목록으로 열립니다.
쉽고 빠른 이해
프로그램끼리 서로를 부르는 접점을 어떤 모양으로 낼지 미리 정해 두는 자리입니다. 무엇을 하나의 대상으로 삼을지, 실패를 무엇으로 알릴지가 여기서 정해집니다.
정해 두지 않으면 부르는 쪽이 소스 코드를 읽거나 트래픽을 직접 관찰해야 짐작할 수 있습니다. 미리 정해 두면 그 짐작이 없어집니다.
한 문장 정의가 안 서는 까닭은 정할 것이 하나가 아니어서입니다. 무엇을 대상으로 삼을지 정하는 일과 실패를 알리는 일과 접근을 가리는 일은 서로 다른 결정이고, 하나를 정했다고 나머지가 같이 정해지지 않습니다.
이 구역 안은 대략 이렇게 갈립니다.
- 무엇을 하나의 대상으로 보고 어떤 동작에 어떤 이름을 붙일지
- 실패·재호출·접점의 변경을 어떻게 다룰지
- 한 번에 얼마나 주고받고 누가 부를 수 있는지
한 번 낸 모양은 남이 이미 그 모양대로 부르고 있어서, 정한 뒤에 되돌리기 어렵습니다. 그래서 다른 프로그램이 부르기 전에 미리 정합니다. 데이터를 담는 표의 모양을 정하는 일과는 다릅니다.
상세
API(Application Programming Interface, 응용 프로그램 인터페이스)는 프로그램이 다른 프로그램을 부르는 접점입니다. 이 문서에서 인터페이스와 접점은 같은 것을 가리킵니다. 설계는 그 접점의 모양을 미리 정해 두는 일입니다. 은행 창구의 접수 서식과 비슷합니다 — 어느 칸에 이름을 적고 어느 칸에 계좌번호를 적을지 미리 정해 두면, 손님은 그 서식만 보고 채워 냅니다. 부르는 쪽은 정해진 모양만 보고 부릅니다.
무엇이 이미 정해져 있는지는 규약 문서가 보여 줍니다. RFC 9110(Request for Comments, 의견 요청) 은 HTTP(HyperText Transfer Protocol, 하이퍼텍스트 전송 규약) 메시지가 그 메시지의 주된 목적을 적는 제어 데이터로 시작한다고 적습니다. 요청 메시지의 제어 데이터에는 요청 메서드와 요청 대상과 규약 버전이 들어갑니다. 자원은 요청이 겨냥하는 대상입니다 — RFC 9110 은 HTTP 요청의 대상을 자원이라 부릅니다. 응답 메시지의 제어 데이터에는 상태 코드와 선택적인 사유 구절과 규약 버전이 들어갑니다. 어느 칸에 무엇이 오는지는 규약이 정합니다. 그 칸에 무엇을 넣을지가 이 구역의 일입니다.
접점을 글로 기술하는 문서도 따로 있습니다. OpenAPI 명세는 자신을 HTTP API 를 위한 표준 인터페이스 기술(인터페이스가 무엇인지 글로 적어 둔 것이지, 인터페이스를 만드는 기술이 아닙니다)이라고 정의합니다. 프로그래밍 언어에 매이지 않는다고 덧붙입니다. 소스 코드나 추가 문서나 네트워크 트래픽 관찰 없이도 사람과 컴퓨터가 서비스의 능력을 발견해 이해할 수 있게 한다고 적습니다. 제대로 정의해 두면 소비자가 최소한의 구현 로직으로 원격 서비스를 이해해 상호작용할 수 있다고 밝힙니다. 같은 문서는 이것이 서비스를 호출할 때의 짐작을 없앤다고 적습니다. 접점을 미리 정해 두는 이유가 여기에 있습니다 — 안 정해 두면 부르는 쪽이 매번 소스 코드를 읽거나 트래픽을 관찰해 짐작해야 합니다.
미리 정해 두는 것에는 대가가 붙습니다. REST(Representational State Transfer, 표현 상태 전이)를 예로 들면 그 대가가 뚜렷합니다. 표현은 자원이 어느 시점에 담고 있는 값의 형태를 뜻합니다. Roy T. Fielding 의 학위논문 5장은 REST 의 중심 특징을 적습니다. 컴포넌트 사이의 통일된 인터페이스(어떤 컴포넌트를 상대하든 같은 방식으로 부르게 하는 것)를 강조하는 점이 REST 를 다른 네트워크 기반 스타일과 구별한다고 적습니다. 컴포넌트 인터페이스에 일반성의 원리(모든 컴포넌트를 한 가지 방식으로 다룬다는 원칙)를 적용하면 전체 구조가 단순해진다고 덧붙입니다. 상호작용의 가시성(오가는 상호작용을 다른 컴포넌트도 알아볼 수 있는 정도)도 나아진다고 밝힙니다. 다만 이렇게 미리 통일해 둔 대가로 트레이드오프가 붙는다고 곧바로 적습니다 — 정보가 애플리케이션의 필요에 맞춘 형태가 아니라 표준화된 형태로 오가서 효율이 떨어진다는 것입니다.
한 번 낸 모양은 되돌리기 어렵습니다. 그래서 이 정하는 일은 접점을 처음 내놓기 전, 아직 아무도 부르지 않을 때 합니다. Google 의 API 개선 제안 문서는 API 가 근본적으로 사용자와 맺는 계약이라고 적습니다. 사용자는 흔히 API 에 기대어 코드를 짠다고 밝힙니다. 그 코드를 프로덕션 서비스에 띄웁니다. API 가 안정성 수준(계속 안정적으로 동작하지는 않을 수 있다고 미리 밝혀 두는 표시)을 달리 걸어 두지 않는 한, 사용자는 그것이 계속 동작하리라 기대한다고 덧붙입니다.
그래서 답이 목록으로 열립니다. 이 구역에서 마주치는 물음들입니다.
| 정하는 자리 | 물음 |
|---|---|
| 자원 | 무엇을 하나의 자원으로 볼 것인가 |
| 동작 | 어떤 동작을 어떤 이름에 붙일 것인가 |
| 실패 | 실패를 무엇으로 알릴 것인가 |
| 양 | 한 번에 얼마나 줄 것인가 |
| 재호출 | 같은 요청이 두 번 와도 되는가 |
| 변경 | 접점이 바뀔 때 옛 호출자를 어떻게 할 것인가 |
| 접근 | 누가 부를 수 있는지를 어떻게 가릴 것인가 |
각 물음의 답과 그 답에 붙는 이름은 아래의 관련 항목이 갖습니다.
경계
데이터베이스 스키마를 정하는 일
데이터를 담는 표의 모양을 정하는 것도 이 구역인가. 아닙니다. Google 의 자원 지향 설계 문서는 저장 시스템과 API 사이에 개념적으로 맞닿는 데가 있다고 적습니다. 다만 자원 지향 API 를 가진 서비스가 반드시 데이터베이스인 것은 아니라고 적습니다. 자원과 메서드를 어떻게 해석할지에 엄청난 유연성이 있다고 적습니다. API 설계자는 자기 API 가 밑에 깔린 데이터베이스 스키마를 반영하리라 기대해서는 안 된다고 적습니다.
같은 문서는 밑에 깔린 데이터베이스 스키마와 동일한 API 가 실은 안티패턴(그럴듯해 보이지만 실제로는 문제를 낳는다고 알려진 설계 방식)이라고 적습니다. 표면을 밑의 시스템에 단단히 묶기 때문입니다. 두 자리는 같은 낱말을 쓸 수 있습니다. 서로 닮을 수도 있습니다. 그래도 한쪽을 정하는 것이 다른 쪽을 정하는 일이 되지는 않습니다.
이견
REST 라는 이름을 놓고 원전과 세상의 쓰임이 갈립니다. 다만 그 사이에 자기를 그 이름으로 부르지 않는 문서가 하나 있습니다.
원전은 Fielding 의 학위논문입니다. 5장은 REST 가 네 개의 인터페이스 제약으로 정의된다고 적습니다. 자원의 식별, 표현을 통한 자원의 조작, 자기 서술적 메시지, 그리고 애플리케이션 상태의 엔진으로서의 하이퍼미디어(다음에 무엇을 할 수 있는지 알려 주는 링크와 선택지의 뭉치)입니다. 통일된 인터페이스를 얻으려면 컴포넌트의 행동을 이끄는 여러 구조적 제약이 필요하다고 적습니다.
같은 사람이 2008년 자기 블로그에서 REST 를 폭넓게 쓰는 관행을 직접 겨눴습니다. HTTP 기반 인터페이스면 무엇이든 REST API 라 부르는 사람이 많아 답답해지고 있다고 적습니다. 그날 예로 든 어느 API 를 두고 그것은 RPC(Remote Procedure Call, 원격 프로시저 호출)라고 적습니다. 애플리케이션 상태의 엔진이 — 앞서 말한 하이퍼미디어를 여기서는 하이퍼텍스트라고 부릅니다 — 따라서 API 가 하이퍼텍스트로 굴러가지 않는다면 그것은 RESTful(REST 의 네 제약을 지킨다는 뜻)일 수 없다고 적습니다. REST API 일 수도 없다고 적습니다. REST API 는 사전 지식 없이 들어설 수 있어야 한다고 적습니다. 예외는 최초 URI(Uniform Resource Identifier, 통합 자원 식별자) 하나와 의도한 독자가 이해하리라 기대되는 표준화된 미디어 타입 묶음뿐이라고 적습니다. 그 지점부터는 모든 애플리케이션 상태 전이가, 받은 표현 안에 있거나 사용자의 조작으로 암시되는, 서버가 제공한 선택지를 클라이언트가 고르는 것으로 이루어져야 한다고 적습니다 — 응답에 실린 선택지를 따라가는 것이 하이퍼텍스트로 굴러간다는 것의 실제 모습입니다.
Google 의 자원 지향 설계 문서는 이 다툼의 어느 편도 들지 않습니다. 자기를 REST 라 부르는 대신 RPC API 를 규정하는 패턴이라고 소개합니다. API 의 근본 구성 요소는 개별 이름이 붙은 자원과 그 사이의 관계·계층이라고 적습니다. 소수의 표준 메서드가 흔한 동작 대부분의 의미를 맡는다고 적습니다. 표준 메서드가 맞지 않는 상황에서는 커스텀 메서드를 쓸 수 있다고 적습니다. 같은 문서는 독자가 이 원칙들과 REST 의 몇몇 원칙 사이의 닮음을 알아챌지도 모른다고 적습니다. 자원 지향 설계가 REST 에서 많은 원칙을 빌려 오면서도 적절한 자리에서는 자기 나름의 패턴을 정의한다고 적습니다.
한쪽은 하이퍼텍스트 제약이 빠진 것을 REST 라 부를 수 없다고 적습니다. 다른 쪽은 REST 에서 원칙을 빌려 온다고만 적을 뿐, 스스로를 REST 라 부르지 않습니다. 다툼은 REST 라는 이름을 쓰는 쪽과 안 쓰는 쪽 사이에 있지, 같은 이름을 걸고 벌어지지 않습니다.
관련 항목
접점을 내는 방식
REST · gRPC · GraphQL · RPC · 자원 지향 설계 · 통일된 인터페이스 · 자기 서술적 메시지 · 하이퍼미디어 · 표현 · 스텁 · 서비스 정의 · 원격 호출 가능한 메서드
이것을 정의하는 표준·문서
OpenAPI · 인터페이스 기술 · 스키마 · JSON(JavaScript Object Notation, 자바스크립트 객체 표기법) 스키마 · 프로토콜 버퍼 · proto 파일 · 메시지 · 필드 · 직렬화 · 쿼리 언어 · 타입 시스템 · 미디어 타입
이름과 자원
자원 · URI · 요청 대상 · 요청 메서드 · 표준 메서드 · 커스텀 메서드 · 자원 계층 · PUT · DELETE · 데이터 요구사항
성패를 알리는 상태 코드
상태 코드 · 사유 구절 · 상태 코드 등급 · 리다이렉션 · 클라이언트 오류 · 서버 오류 · 200 OK · 201 Created
접점의 변경
버저닝 · 메이저 버전 · 시맨틱 버저닝 · 하위 호환 · 하위 비호환 변경 · 안정성 수준 · 마이너 릴리스 · 패치 릴리스
한 번에 주고받는 양
페이지네이션 · 컬렉션 · 속도 제한 · RateLimit 헤더 필드 · 쿼터 정책 · 서비스 한도 · 스로틀링
반복 호출
이것이 지키는 성질
인증 · 인가 · 보안 스킴 · API 키 · HTTP 인증 · 상호 TLS(Transport Layer Security, 전송 계층 보안) · 클라이언트 인증서 · OAuth 2.0 · 클라이언트 자격 증명 · 인가 코드 · 암묵적 흐름 · OpenID Connect 디스커버리
다른 이름: API design · api design · 인터페이스 설계