Spring Cloud Gateway 설정은 마이크로서비스 아키텍처에서 여러 개의 독립된 서비스로 나누어진 애플리케이션에 대한 요청을 중앙에서 관리하고, 라우팅과 필터링을 수행하기 위한 구성입니다. 이를 통해 사용자는 여러 서비스에 개별적으로 접근하지 않고, 하나의 진입점(Gateway)을 통해 서비스에 접근할 수 있게 됩니다.
1. 프로젝트 환경 설정
- Spring Boot 프로젝트 생성: Spring Initializr 또는 IDE를 통해 Spring Boot 프로젝트를 생성하고, Spring Cloud Gateway와 Security에 필요한 의존성을 추가합니다.
- 의존성 추가:
- Spring Cloud Gateway: 라우팅과 필터링을 제공.
- Spring Security: 보안 기능을 제공하여 인증과 인가를 처리.
2. Gateway 서버 설정
- 포트 설정: application.yml 파일에 Gateway 서버의 포트를 설정합니다.
server: port: 80
When a client sends a request, it goes directly to the API gateway rather than each microservice.
A gateway consolidates all API endpoints into a single entry point, making it easier for clients to interact with various services.
- The gateway can handle common requirements like authentication, authorization, logging, rate limiting, load balancing, and monitoring, reducing redundancy across services.
- The gateway can route requests, transform data, and even aggregate multiple responses, providing a unified and simplified interface for clients.
- An API Gateway can distribute requests across multiple instances of a service, improving performance and availability.
게이트웨이가 없는 경우와 비교
게이트웨이가 없는 경우에는 각 서비스의 실제 URL을 사용해야 하므로 다음과 같은 식으로 요청이 분리됩니다:
- 사용자 서비스 URL: https://user-service.example.com/login
- 주문 서비스 URL: https://order-service.example.com/create
- 상품 서비스 URL: https://product-service.example.com/list
3. 라우팅 설정
- 라우팅 규칙 정의: 각 마이크로서비스에 대한 요청을 Gateway가 처리할 수 있도록 application.yml에 라우팅 규칙을 정의합니다.
- 각 서비스마다 id, uri, predicates를 통해 어떤 경로로 들어오는 요청이 어떤 서비스로 라우팅될지 지정합니다
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://USER-SERVICE
predicates:
- Path=/user/**
- id: order-service
uri: lb://ORDER-SERVICE
predicates:
- Path=/order/**
Each route has predicates (like Path=/user/**), which tell the gateway to match certain URL patterns.
Spring Cloud Gateway reads this configuration at startup to know how to handle incoming requests.
The gateway serves as the single entry point to manage routing, authentication, rate limiting, and more.
- Additional Configuration (Optional):
- You may also configure filters (e.g., for logging, authentication) in the gateway configuration.
- Set up service discovery (such as Eureka) if your services are registered dynamically.
- . Eureka as a Service Registry
Eureka’s primary function is service discovery. It allows microservices to register themselves and discover other services without needing hardcoded IP addresses.
5. JWT 토큰 기반 인증 필터 작성
- Jwt Filter 작성: JWT를 이용해 인증을 처리하는 필터를 작성합니다. 이 필터는 post-service와 같은 인증이 필요한 서비스로의 요청에만 적용됩니다.
- JWT 토큰을 Authorization 헤더에서 추출하고, 유효성을 검증하여 인증된 요청만 서비스로 전달합니다.
- 로그아웃을 할 때 백엔드에서 Refresh Token을 사용해 해당 사용자 세션을 무효화해야 하는 경우가 많기 때문에, 이 Refresh Token을 포함하여 로그아웃 요청을 보내야 합니다. Refresh Token이 HTTP-Only 쿠키에 있을 때, allowCredentials: true 설정이 없으면 브라우저는 CORS 정책상 다른 출처로의 요청에 쿠키를 포함시키지 않기 때문에, 로그아웃 요청에 Refresh Token이 누락됩니다.
7. 각 서비스 (마이크로서비스) 설정
- 각 마이크로서비스의 보안 설정: 각 서비스에서도 JWT 또는 OAuth2와 같은 보안 설정을 추가하여 인증된 요청만 접근할 수 있도록 설정합니다.
- 서비스 간 연결 테스트: Gateway를 통해 라우팅된 요청이 각 서비스로 정상적으로 전달되는지 확인합니다.
8. 모듈간 동기적 연결 : Feign Client
FeignClient는 다른 서비스의 컨트롤러를 호출하는 역할을 합니다.Feign Client는 Spring Cloud에서 제공하는 HTTP 클라이언트로, REST API 호출을 간편하게 만들기 위한 도구입니다. Feign Client는 HTTP 요청을 메서드 호출처럼 간단하게 작성할 수 있도록 도와주며, HTTP 통신을 추상화하여 인터페이스 기반의 선언적 프로그래밍 방식을 지원합니다. Feign은 Spring Cloud와의 통합 덕분에 로드 밸런싱이나 장애 복구 등을 쉽게 구현할 수 있어 마이크로서비스 아키텍처에서 많이 사용됩니다.
구현순서
0. fein client를 위한 controller 별도 생성
명확한 책임 분리 (Clear Separation of Concerns)
내부 Feign 클라이언트 호출을 처리하기 위한 별도의 컨트롤러나 서비스 레이어를 두면, 외부 클라이언트가 사용하는 외부 API 엔드포인트와 다른 마이크로서비스에서 사용하는 내부 엔드포인트를 명확히 분리할 수 있습니다. 이렇게 하면 아키텍처가 더 모듈화되고 관리가 용이해집니다.
보안 및 접근 제어 (Security and Access Control)
Feign을 통해 내부 요청을 처리할 때, 외부 클라이언트 요청과 다른 보안 또는 권한 규칙이 필요할 수 있습니다. 분리를 통해 내부 접근 제어를 더 잘 시행하거나, 신뢰할 수 있는 마이크로서비스에만 접근을 허용하는 제한을 설정할 수 있습니다.
1. 의존성 추가
- build.gradle 파일에 Feign 관련 의존성을 추가합니다. Spring Cloud를 사용하는 경우, Spring Cloud Starter OpenFeign을 추가하면 됩니다.
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
}
2. Feign Client 활성화
- @EnableFeignClients 어노테이션을 메인 애플리케이션 클래스에 추가하여 Feign Client를 활성화합니다.
@SpringBootApplication
@EnableFeignClients
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
3. Feign Client 인터페이스 작성
- FeignClient는 특정 서비스를 호출할 수 있는 창구처럼 작동한다고 볼 수 있습니다. 이를 통해 내부 서비스에서 외부 API에 대한 요청을 직접 관리할 필요 없이, 인터페이스만으로 외부 서비스를 쉽게 호출할 수 있게 됩니다. FeignClient는 내부 서비스가 외부 API에 요청을 보내는 창구 역할을 하는 반면, 컨트롤러는 외부 요청을 수신하는 창구 역할을 합니다.
- 호출할 외부 API에 대한 인터페이스를 작성합니다. 인터페이스에는 호출할 엔드포인트를 정의하고, 각 메서드에 HTTP 메서드(@GetMapping, @PostMapping 등)를 명시합니다. UserClient라는 인터페이스에 @FeignClient 어노테이션을 붙여서 user-service라는 서비스의 API를 호출할 수 있게 설정했습니다.
- getUserById() 메서드는 @GetMapping을 사용해 HTTP GET 요청을 보냅니다. 요청 URL은 http://localhost:8080/api/users/{id}이며, {id} 자리에 실제로 전달되는 ID 값이 들어가게 됩니다.
@FeignClient(name = "exampleClient", url = "https://api.example.com")
public interface ExampleClient {
@GetMapping("/data")
ResponseEntity<String> getData();
@PostMapping("/data")
ResponseEntity<String> postData(@RequestBody DataDto dataDto);
}
4. Configuration 설정
필요 시 Feign Client의 로깅, 타임아웃, 예외 처리 등을 위한 추가 설정을 합니다. Spring Boot의 application.yml 파일에서 설정할 수도 있고, 별도의 Configuration 클래스를 생성할 수도 있습니다.
feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: FULL
5. Feign Client 사용
- 필요한 서비스 또는 컨트롤러 클래스에서 @Autowired 또는 생성자 주입으로 Feign Client를 주입하여 호출합니다.
- UserService 클래스에서 UserClient 인터페이스를 주입받아 getUserById() 메서드를 호출하면, Feign이 인터페이스 메서드 호출을 실제 HTTP 요청으로 변환해주고 그 결과를 반환합니다.
@Service
public class ExampleService {
private final ExampleClient exampleClient;
public ExampleService(ExampleClient exampleClient) {
this.exampleClient = exampleClient;
}
public String getDataFromExternalService() {
return exampleClient.getData().getBody();
}
}
9. 모듈간 비동기적 연결 : webclient
'개발기술 > Spring' 카테고리의 다른 글
비동기 Web Flux (0) | 2024.11.19 |
---|---|
Spring 스케쥴러 (1) | 2024.11.15 |
Spring 동시성이슈 해결 (0) | 2024.07.30 |
스프링 전체구조 (0) | 2024.07.24 |
Java 프로젝트 초기 환경설정 (스프링 부트, Package, Configuration) (0) | 2024.07.23 |