많은 곳에서 API 게이트웨이를 사용하고 있다. 그런데 이 용어의 뜻을 찾아보면 난해한 설명만 나와 있다. 그래서 나름대로 설명을 좀 쉽게 풀어보았다.
게이트웨이는 무엇인가. 위키피디아에서는 다른 네트워크로 들어가는 입구 역할을 하는 네트워크 포인트라고 나와 있다. 매우 적절한 설명이 아닐 수 없다. 그렇다면 이걸 바탕으로 API 게이트웨이를 설명할 수 있지 않을까. 이를 NHN 토스트 블로그에서 설명을 잘 하고 있다. 해당 설명을 좀 더 쉽게 풀어보면...
사용자(백엔드 개발자 혹은 인프라 담당자)가 설정한 라우팅 설정에 따르며, 여러개의 서비스에 향하는 클라이언트로부터의 요청을 받아서 각 엔드포인트(실제 API)로 (클라이언트를 대리하여) 요청하고 응답을 받으면 다시 클라이언트에게 전달하는 프록시 역할
이런 API 게이트웨이를 사용했을 때, 어떤 이점이 있길래 많은 곳에서 사용하는 것일까? (아래 내용 출처 : 두발로걷는개의 발자국 블로그)
- 유입되는 모든 요청/응답이 통하기 때문에 인증/보안을 적용하기 좋다.
- URI에 따라 서비스 엔드포인트를 다르게 가져가는 동적 라우팅이 가능해진다. 예를 들면 도메인 변경없이 레거시 시스템을 신규 시스템으로 점진적으로 교체해 나가는 작업을 쉽게 진행할 수 있다.
- 모든 트래픽이 통하기 때문에 모니터링 시스템 구성이 단순해진다.
- 동적 라우팅이 가능하므로 신규 스팩을 서비스 일부에만 적용하거나 트래픽을 점진적으로 늘려나가는 테스트를 수행하기에 수월해진다.
이런 API 게이트웨이는 스프링 클라우드 게이트웨이(SCG)말고도 Kong, Netflix Zuul(배달의 민족에서 사용 중) 등이 있다. 필자의 현업에서는 이 중 스프링 게이트웨이를 사용하고 있고 이 부분을 다루다가 생긴 이슈를 공유해보고자 한다. 바로 환경 세팅이다.
이제 이슈를 정리해본다. 필자의 현업에서는 로컬 환경 외에 개발 환경, 운영환경 등이 존재한다. 이를 yml 파일로 관리하고 있다. 지금부터 새로운 서비스를 추가하기, 원하는 환경 액티브, API가 호출이 안되었던 경험 공유를 하고자 한다.
🍰 새로운 서비스를 추가하기
위 이미지처럼 미리 환경이 준비되어 있다는 전제조건에서 설명을 진행한다. 먼저 기본 환경 세팅인 application.yml을 바라보자. 구동(Run)했을 때 사용되는 Port 정보가 먼저 입력된다. 이것은 스프링 게이트웨이 서비스 구동에 필요한 정보이고 실제 게이트웨이의 설정값은 "spring.cloud.gateway:" 아래부터 시작한다.
# application.yml
server:
port: 80
spring:
cloud:
gateway:
globalcors:
(생략)
default-filters:
(생략)
routes:
(여기서 서비스를 추가)
routes에서 서비스를 추가한다. 그 이전에 나타나는 것은 간단하게만 설명한다. globalcors는 CORS Configuration으로 여기서 CORS는 교차 출처 리소스 공유(Cross-Origin Resource Sharing)를 뜻한다. 교차 출처라는 말이 어려울텐데 실제는 간단하다. 요청하는 클라이언트의 웹페이지 혹은 브라우저 도메인과 요청 대상이 되는 API 서비스의 도메인이 다를 경우 세팅해야 되는 것을 globalcors에 작성한다. default-filters는 전역 필터다. 민감한 헤더 정보를 제거하는 등의 필터를 사용할 때 사용된다. 마지막으로 우리가 주목해야 하는 routes는 말 그대로 이 게이트웨이의 라우트다. API 서비스 정보를 담는 곳이다. 좀 더 자세히 알아보자.
routes:
- id: sample-service
uri: http://localhost:3000
predicates:
- Method=GET,POST,PUT,PATCH,DELETE,OPTIONS
- Path=/sample/refresh,/sample/member/group,/sample/member/person
filters:
- RewritePath=/(?<segment>.*), /sample-service/$\{segment}
- id: new-api-service
(생략)
- id: 해당 라우트 고유 식별자
- uri: 해당 라우터의 주소
- predicates: 해당 라우터의 조건을 작성
- filters: 해당 라우터의 필터, RewritePath는 강제로 Path를 다시 작성
예시로 2개의 라우트가 등록되어 있다. (sample-service, new-api-service) 이렇게 여러개의 API 서비스를 등록할 수 있다. 로컬에서 개발하고 있다면 위 예시처럼 localhost에 포트를 추가해서 uri를 작성하면 되지만 별도의 도메인이 등록된 경우라면 해당 uri를 정확하게 입력해야 한다. 물론 포트도 틀려서는 안된다. 특정 하위 path만 별도의 라우트를 가질수도 있다. (아래 예시의 path 부분 참고)
routes:
- id: sample-service-1
uri: http://localhost:3000
predicates:
- Method=GET,POST,PUT,PATCH,DELETE,OPTIONS
- Path=/sample/member/**
filters:
- RewritePath=/(?<segment>.*), /sample-service/$\{segment}
- id: sample-service-2
uri: http://localhost:3000
predicates:
- Method=GET,POST,PUT,PATCH,DELETE,OPTIONS
- Path=/sample/member/group
filters:
- RewritePath=/(?<segment>.*), /sample-service/$\{segment}
🍰 만약 로컬 환경에서 테스트를 하고 싶다면?
위에서 가이드한 것처럼 API 서버(혹은 서비스)를 게이트웨이에 등록했다. 그런데 지금은 기본 환경(application.yml)만 바라보고 다른 dev 혹은 local 환경은 무시하고 있다. 기본 환경은 운영 환경이니 개발 DB 등으로 테스트를 하고 싶으면 환경을 변경해야 한다. "---"로 표시된 것을 포함하여 아래 코드를 입력하면 "application-local.xml"에 세팅된 환경으로 구동된다.
# application.yml
server:
port: 80
spring:
cloud:
gateway:
globalcors:
(생략)
default-filters:
(생략)
routes:
(생략)
---
spring:
profiles:
active: local
🍰 만약 GET, POST는 잘 호출이 되는데 PATCH 메소드만 호출이 안된다면?
개발을 완료하고 클라이언트 개발자에게 API 정보를 넘겨줬는데, 다음과 같은 메세지가 오면서 정상적인 호출이 안된다는 피드백이 왔다.
{
"message": "no Route matched with those values"
}
확인해보니 routes 설정에서 patch 메소드만 빠져서 생긴 이슈였다. 알고보면 별거 아니지만 모르면 정말 원인을 찾기 힘든 그런 케이스였다.
# Before
routes:
- id: sample-service-1
uri: http://localhost:3000
predicates:
- Method=GET,POST,PUT,DELETE,OPTIONS
(이하 생략)
# After
routes:
- id: sample-service-1
uri: http://localhost:3000
predicates:
- Method=GET,POST,PUT,PATCH,DELETE,OPTIONS
(이하 생략)
아. 이번 포스팅도 참 보람차다. 오늘은 여기까지.
그럼 안뇽.
'Spring' 카테고리의 다른 글
Kotlin에서 RestTemplateClient를 만들어보자 (0) | 2021.12.23 |
---|---|
미해결사건. @Valid가 작동하지 않는다?? (0) | 2021.12.15 |
oauth 세팅 중 yml과 properties가 이해되지 않을 때, 스프링 시큐리티와 프로바이더 (0) | 2021.09.28 |
Postman에서 Mock Server과 API 만들고 테스트하기 (하) (0) | 2021.06.23 |
Postman에서 Mock Server과 API 만들고 테스트하기 (상) (2) | 2021.06.23 |
Comment