Mingyum-Kim / Iamhere

😉 국내 거주 외국인 매칭 서비스 "I-am-here" 😉
1 stars 0 forks source link

Spring Cloud Gateway (SCG) 프로젝트에 적용 #31

Closed Mingyum-Kim closed 1 year ago

Mingyum-Kim commented 1 year ago

🖤 설명

30 : 이 Pull Request의 연장선으로 해당 Pull Request를 작성한다.

클라이언트에서 리소스를 요청 시 JWT 인증을 수행하는 역할을 분리하기 위해 Spring Cloud Gateway를 사용하고자 한다. API Gateway는 클라이언트와 백엔드 사이에서 리버스 프록시 역할을 하는 서비스이다. 현재 서비스에서 Spring Cloud Eureka Server를 사용하고 있는 점, 그리고 타 프로젝트에 비해 레퍼런스가 많은 점을 기반으로 Spring Cloud Gateway를 선택하였다.

참고 : https://saramin.github.io/2022-01-20-spring-cloud-gateway-api-gateway/ 참고 : https://www.youtube.com/watch?v=HY4kTCNKwxkhttps://www.youtube.com/watch?v=5P6kXaFPhrM

정리하자면, API gateway 서버를 설치함으로써 Routing, Security, Monitoring, Canarying (트래픽이 몰리는 등의 위험 감지), Resiliency(회복), Monolith Strangling(모놀리스 전환) 등의 장점이 있다.

구성은 Route, Predicate, Filter 3가지로 나뉜다. Route는 서비스의 고유 id, 요청할 uri, Predicate, Filter로 구성되어있다. Predicate가 요청된 uri와 조건이 일치하는 지 확인 후 그렇지 않은 경우 404 Not Found 응답을 반환한다. Filter은 요청에 헤더나 쿠키 값을 설정하는 등 후처리를 할 수 있게 만든 요소이다.

⭐체크리스트

Mingyum-Kim commented 1 year ago

1. Route 설정 참고 : https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories 여기서 Route Predicate Factories 탭에 들어가면 라우팅 전략들을 확인할 수 있다. application.yml 에 기재하는 predicates은 하나의 조건으로, 해당 서비스로 분기하는 조건을 의미한다. After, Before, Between 을 사용해 시간을 기준으로 분기하거나 Cookie, Header 로 요청에 포함된 값으로 분기할 수도 있다. 혹은 Host, Method, Path를 이용해 URI 요청을 기반으로 분기할 수 있다. 나는 여기서 Path를 사용해 구현할 건데, URL 요청이 member/ 로 시작하거나 post/로 시작하는 경우를 나누어서 경로를 지정해줄 예정이다. 이외에 Query String, RemoteAddr (IP대역으로 분기), Weight Route (로드 밸런싱을 비율로 나누어서 분기) 등의 전략이 가능하다.

2. Filter 설정 (1) Global Filter : API gateway 자체 필터 설정 GlobalFilter은 AbstractGatewayFilterFactor를 상속받아 구현한다. 여기에서 MemberService에서 발급받은 토큰을 심게 되고, 다른 호출이 들어올 때 JWT 유효성 검사를 시행한다. image 로그를 보면 여러 스레드가 한번에 동작하는 것을 볼 수 있다. Spring Gateway가 Netty 기반의 프로젝트이기 때문에 가능한 것이다. (2) CustomFilter : 서비스 별 필터 설정 Global Filter와는 별개로 특정한 서비스를 호출하였을 때 개입되는 필터이다. 위와 마찬가지로 구현한다.

3. Gateway에서 Eureka의 역할이란 ? 포트를 지정하는 방식은 여러개의 마이크로 서비스에서 일일이 지정해주어야 하기 때문에 수동적이라는 단점이 있다. 이러한 한계 때문에, Scale-out을 고려하여 Eureka에 EventListener를 구현하여 Gateway에서 특정 서비스로 호출이 발생했을 때 이를 감지한다. 서버의 Up, Down 이벤트 둘 다 감지하게 되고, 어드민 컨트롤러를 만들어서 API 끼리 서로 호출할 수 있게 만든다면 더욱 동적인 서비스를 구현할 수 있다.