서비스 간 API 엔드포인트 공유하기
여러 서비스 간 API 엔드포인트 공유하기
이번 장에서는 여러 서비스 간에 API Gateway를 활용하는 방법을 살펴보겠습니다. API를 여러 서비스로 분할할 때 직면하는 문제 중 하나는 동일한 도메인을 공유하는 것입니다. Serverless Framework 서비스의 일부로 생성된 API는 다음과 같은 고유한 URL을 갖는다는 것을 기억할 것입니다:
https://z6pv80ao4l.execute-api.us-east-1.amazonaws.com/dev
API에 커스텀 도메인을 연결하면 위와 같은 특정 엔드포인트에 연결됩니다. 이는 여러 API 서비스를 생성할 경우 각각 고유한 엔드포인트를 갖게 된다는 것을 의미합니다.
커스텀 도메인에 대해 다른 기본 경로를 할당할 수 있습니다. 예를 들어, api.example.com/notes
는 하나의 서비스를 가리키고, api.example.com/billing
은 다른 서비스를 가리킬 수 있습니다. 하지만 notes
서비스를 분할하려고 하면 커스텀 도메인을 공유하는 문제에 직면하게 됩니다.
우리의 노트 앱에는 notes-api
와 billing-api
라는 두 개의 서비스가 있습니다. 이번 장에서는 두 서비스가 단일 API 엔드포인트를 통해 제공되도록 API Gateway를 구성하는 방법을 살펴보겠습니다.
설정하려는 API 경로는 다음과 같습니다:
notes-api
모든 노트 목록 조회 ⇒ GEThttps://api.example.com/notes
notes-api
특정 노트 조회 ⇒ GEThttps://api.example.com/notes/{noteId}
notes-api
노트 생성 ⇒ POSThttps://api.example.com/notes
notes-api
노트 업데이트 ⇒ PUThttps://api.example.com/notes/{noteId}
notes-api
노트 삭제 ⇒ DELETEhttps://api.example.com/notes/{noteId}
billing-api
결제 ⇒ POSThttps://api.example.com/billing
API Gateway에서 경로가 작동하는 방식
API Gateway는 약간 까다로운 방식으로 구조화되어 있습니다. 이를 자세히 살펴보겠습니다.
- 각 경로 부분은 별도의 API Gateway 리소스 객체입니다.
- 그리고 경로 부분은 이전 부분의 자식 리소스입니다.
따라서 /notes
경로 부분은 /
의 자식 리소스입니다. 그리고 /notes/{noteId}
는 /notes
의 자식 리소스입니다.
우리의 설정에 따르면, billing-api
가 /billing
경로를 가지길 원합니다. 그리고 이는 /
의 자식 리소스가 됩니다. 그러나 /
는 notes-api
서비스에서 생성됩니다. 따라서 서비스 간에 리소스를 공유할 방법을 찾아야 합니다.
Notes Service
이를 위해 notes-api
는 API Gateway 프로젝트와 루트 경로 /
를 공유해야 합니다.
serverless-stack-demo-ext-api 저장소에서 services/notes-api/
디렉토리로 이동합니다. serverless.yml
파일의 끝 부분을 보면 다음과 같은 내용이 있습니다:
...
- Outputs:
ApiGatewayRestApiId:
Value:
Ref: ApiGatewayRestApi
Export:
Name: ${self:custom.stage}-ExtApiGatewayRestApiId
ApiGatewayRestApiRootResourceId:
Value:
Fn::GetAtt:
- ApiGatewayRestApi
- RootResourceId
Export:
Name: ${self:custom.stage}-ExtApiGatewayRestApiRootResourceId
여기서 무엇을 하고 있는지 살펴보겠습니다.
- 공유해야 하는 첫 번째 크로스 스택 참조는 이 서비스의 일부로 생성된 API Gateway ID입니다.
${self:custom.stage}-ExtApiGatewayRestApiId
라는 이름으로 이를 내보냅니다. 모든 환경/스테이지에서 내보내기가 작동하도록 스테이지 이름을 포함합니다. 이 내보내기의 값은 현재 스택에서ApiGatewayRestApi
라는 참조로 사용할 수 있습니다. - 또한
RootResourceId
를 내보내야 합니다. 이는 이 API Gateway 프로젝트의/
경로에 대한 참조입니다. 이 ID를 가져오기 위해Fn::GetAtt
CloudFormation 함수를 사용하고 현재ApiGatewayRestApi
를 전달한 후RootResourceId
속성을 조회합니다.${self:custom.stage}-ExtApiGatewayRestApiRootResourceId
라는 이름으로 이를 내보냅니다.
결제 서비스
위 내용을 어떻게 가져오는지 살펴보겠습니다. services/
디렉토리에서 billing-api
서비스를 열어보세요.
...
provider:
apiGateway:
restApiId: !ImportValue ${self:custom.stage}-ExtApiGatewayRestApiId
restApiRootResourceId: !ImportValue ${self:custom.stage}-ExtApiGatewayRestApiRootResourceId
...
functions:
billing:
handler: billing.main
events:
- http:
path: billing
method: post
cors: true
authorizer: aws_iam
notes-api
서비스와 동일한 API Gateway 도메인을 공유하기 위해 provider:
블록에 apiGateway:
섹션을 추가합니다.
-
여기서
notes
서비스의restApiId
를 사용하겠다고 명시합니다. 이전에 내보낸 크로스 스택 참조!ImportValue ${self:custom.stage}-ExtApiGatewayRestApiId
를 사용하여 이를 수행합니다. -
또한 이 서비스의 모든 API가
notes
서비스의 루트 경로 아래에 연결되도록 설정합니다. 이전에 내보낸 크로스 스택 참조!ImportValue ${self:custom.stage}-ExtApiGatewayRestApiRootResourceId
를restApiRootResourceId
로 설정하여 이를 수행합니다.
이제 billing-api
서비스를 배포할 때, Serverless Framework는 새로운 API Gateway 프로젝트를 생성하는 대신 가져온 프로젝트를 재사용합니다.
이 설정에서 주목할 점은 API Gateway가 이 서비스에서 생성된 라우트를 어디에 연결할지 알아야 한다는 것입니다. /billing
경로를 API Gateway 프로젝트의 루트에 연결하려고 합니다. 따라서 restApiRootResourceId
는 notes-api
서비스의 루트 리소스를 가리킵니다. 물론 이렇게 할 필요는 없습니다. /billing
경로를 메인 API 서비스에서 생성하고 여기서 연결하도록 서비스를 구성할 수도 있습니다.
의존성
API Gateway 프로젝트를 공유함으로써 billing-api
가 notes-api
에 의존하게 됩니다. 배포할 때는 notes-api
를 먼저 배포해야 합니다.
제약 사항
경로 부분은 한 번만 생성할 수 있습니다. 이 동작 방식을 이해하기 위해 예제를 살펴보겠습니다. 다음과 같은 엔드포인트를 사용하는 새로운 API 서비스를 추가해야 한다고 가정해 보겠습니다.
https://api.example.com/billing/xyz
이 새로운 서비스는 notes-api
에서 /
를 가져올 수 없습니다.
이는 Serverless Framework가 다음과 같은 두 가지 경로 부분을 생성하려고 시도하기 때문입니다:
/billing
/billing/xyz
하지만 /billing
은 이미 billing-api
서비스에서 생성되었습니다. 따라서 이 새로운 서비스를 배포하려고 하면 CloudFormation이 실패하고 리소스가 이미 존재한다는 오류를 발생시킵니다.
새로운 서비스는 /billing
을 billing-api
에서 가져와야 하며, 이렇게 하면 새로운 서비스는 /billing/xyz
부분만 생성하면 됩니다.
이제 서비스 구성이 완료되었고 배포할 준비가 되었습니다. 요약하자면, 리소스 저장소와 API 저장소에 몇 가지 의존성이 있습니다.
For help and discussion
Comments on this chapter