본문 바로가기
마이크로서비스

스프링 클라우드란?

by 이상한나라의개발자 2024. 10. 7.

스프링은 시장에서 검증된 수많은 오픈 소스 프로젝트를 모아 통칭 스프링 클라우드(Spring Cloud)라는 스프링 하위 프로젝트로 통합했다. 스프링 클라우드는 VMWare, 하시코프(HashiCorp), 넷플릭스 등 오픈 소스 회사의 제픔을 전달 패턴으로 모아 놓은 도구 집합이다.

스프링 클라우드는 프로젝트 설정 및 구성을 단순화하고 가장 흔히 접할 수 있는 패턴의 해결안을 스프링 애플리케이션에 제공한다. 덕분에 마이크로서비스 애플리케이션을 만들고 배포하는 데 필요한 모든 인프라스트럭처 구성에 대한 세부 사항은 신경 쓰지 않은 채 코드를 작성하는 데만 집중할 수 있다. 아래는 스프링 클라우드에 구현된 패턴이다. ( 서비스 라우팅 패턴 : Spring Cloud API Gateway )

 

마이크로서비스 패턴과 스프링 클라우드 기능의 매핑

 

 

구성 정보 관리 ( Spring Cloud Config )

Spring Cloud Config는 애플리케이션 구성 데이터를 관리한다. 애플리케이션 구성 데이터(특히 환경별 구성 데이터)는 배포된 마이크로서비스에서 완전히 분리된다. 따라서 아무리 많은 마이크로서비스 인스턴스를 실행하더라도 항상 동일한 구성을 보장할 수 있다. Spring Cloud Config는 자체 프로퍼터(property)관리 저장소가 있지만 다음과 같은 오픈 소스 프로젝트와도 통합된다.

 

  • 깃 (git) : 모든 테스트 파일을 변경 사항을 관리하고 추적할 수 있는 오픈 소스 버전 제어 시스템이다. Spring Cloud Config는 깃 백엔드 저장소와 통합되어 저장소의 애플리케이션 구성 데이터를 읽는다.
  • 콘술 (consul) : 서비스 인스턴스가 서비스에 등록되도록 만드는 오픈 소스 서비스 디스커버리다. 서비스 클라이언트는 콘술에 질의해서 등록된 서비스 인스턴스 위치를 찾을 수 있다. 콘술에는 애플리케이션 구성 데이터를 저장하는 용도인 키-값 저장소 데이터베이스도 포함된다.
  • 유레카 (eureka) : 콘술과 마찬가지로 유사한 서비스 디스커버리 기능을 제공하는 넷플릭스 오픈 소스 프로젝트이다. 유레카에도 Spring Cloud Config와 함께 사용 가능한 키-값 데이터베이스가 있다.

 

스프링 클라우드 서비스 디스커버리

스프링 클라우드 서비스 디스커버리를 사용하면 서비스를 소비하는 클라이언트에서 서버가 배포된 물리적 위치(IP 및 서버 이름)를 추상화할 수 있다. 서비스 소비자는 물리적 위치가 아닌 논리적 이름을 사용하여 서버의 비즈니스 로직을 호출한다. 또한 스프링 클라우드 서비스 디스커버리는 서비스 인스턴스가 시작되고 종료될 때 인스턴스 등록 및 등록 취소도 처리한다. 스프링 클라우드 서비스 디스커버리는 다음서비스를 사용하여 구현할 수 있다.

 

  • 콘술 (Consul)
  • 주키퍼 (Zookeeper)
  • 유레카 (Eureka)

* 콘술과 주키퍼가 강력하고 유연하지만 자바 개발자 커뮤니티는 여전히 유레카를 사용한다. 

 

스프링 클라우드와 로드 밸런싱

스프링 클라우드는 여러 오픈 소스 프프로젝트와 긴밀하게 통합된다. 마이크로서비스 클라이언트 회복성 패턴을 위해 스프링 클라우드는 로드 밸런서 프로젝트를 포함하여 마이크로 서비스 내부에서 이들을 사용하여 편리하게 구현되게 만들었다.

Resilience4j 라이브러리를 사용하면 회로 차단기, 재시도, 벌크헤드 등 서비스 클라이언트 회복성 패턴을 빠르게 구현할 수 있다.

 

스프링 클라우드 API 게이트웨이

API 게이트웨이는 마이크로서비스 애플리케이션을 위한 서비스 라우팅 기능을 제공한다. 서비스 요청을 프록시하고 대상 서비스가 호출되기 전에 마이크로서비스에 대한 모든 호출이 현관을 통과하도록 하는 서비스 게이트웨이다. 서비스 호출의 중앙 집중화로 보안 인가, 인증, 콘텐츠 필터링과 라우팅 규칙 등 표준 서비스 정책을시행할 수 있다. 스프링 클라우드 게이트웨이로 API 게이트웨이를 구현할 수 있다.

 

스프링 클라우드 스트림

스프링 클라우드 스트림은 경량 메시지 처리 기능을 마이크로서비스에 쉽게 통합하는 기술이며, 애플리케이션에서 발생하는 비동기 이벤트를 사용하는 지능형 마이크로서비스를 구축할 수 있다. 또한 RabbitMQ 와 카프카 같은 메시지 브로커와 마이크로서비스를 빠르게 통합할 수 있다.

 

스프링 클라우드 슬루스

고유한 추적 식별자를 애플리케이션에서 HTTP 호출 및 메시지 채널(RabbitMQ, Kafka)에 통합한다. 상관관계 ID나 트레이스 ID 라고도하는 이러한 추적 번호를 사용하면 애플리케이션 내 여러 서비스를 통과하는 트랜잭션을 추적할 수 있다.

스프링 클라우드 슬루스의 진정한 가치는 ELK등 로깅 집계 기술 도구와 집킨(Zipkin)등 추적 도구와 결합될 때 발현된다. 오픈 집킨은 스프링 클라우드 슬루스에서 생성한 데이터를 받아 단일 트랜잭션과 연결된 서비스 흐름을 시각화할 수 있다. ELK 스택은 다음 세 가지 오픈 소스 프로젝트의 준말이다.

 

  • Elastic Search (일레스틱서치) : 검색 및 분석 엔진
  • Log Stash (로그 스태시) : 데이터를 소비한 후 stash로 전송하기 위해 변환하는 서버 사이드 데이터 프로세싱 파이프라인
  • Kibana (키바나) : 사용자가 전체 스택의 데이터를 질의 하고 시각화할 수 있는 클라이언트 UI

 

스프링 클라우드 시큐리티

스프링 클라우드 시큐리티는 서비스에 액세스할 수 있는 사용자와 이 사용자가 서비스에서 수행할 수 있는 작업을 제어하는 인증 및 인가(권한 부여) 프레임워크이다. 스프링 클라우드 시큐리티는 토큰을 기반으로 하기 때문에 서비스 인증 시스템에서 발급된 토큰을 사용하여 서로 통신할 수 있다. HTTP 호출을 받은 각 서비스는 전달받은 토큰을 확인하여 사용자의 신원과 액세스 권한을 검증한다. 스프링 클라우드 시큐리티는 JWT도 지원하며, JWT는 OAuth2 토큰 생성 포맷을 표준화하고 생성된 토큰에 대한 서명을 정규화 한다.

 

스프링 클라우드 예제

@SpringBootApplication
@RestController
@RequestMapping("/hello")
// 서비스를 유레카 서비스 디스커버리 에이전트에 등록하여 원격 서비스 위치를 검색하도록 지정한다.
// Spring 2.x 버전에서는 @EnableDiscoveryClient 어노테이션을 사용한다.
// Spring 3.x, Spring Cloud 2022.0.x 이상에서는 불필요하다.
@EnableEurekaClient 
public class MicroserviceApplication {

    public static void main(String[] args) {
        SpringApplication.run(MicroserviceApplication.class, args);
    }
    
    public String helloRemoteServiceCall(String firstName, String lastName) {
        RestTemplate restTemplate = new RestTemplate();
        // RestTemplate 을 사용하여 "논리적" 서비스 ID를 받으면 내부에서 유레카는 서비스의 물리적 위치를 검색한다.
        ResponseEntity<String> restExchange = restTemplate.exchange(
                "http://logical-service-id/name/" + "{firstName}/{lastName}",
                HttpMethod.GET,
                null,
                String.class,
                firstName,
                lastName
        );
        return restExchange.getBody();
    }
    
    @RequestMapping(value = "/{firstName}/{lastName}", method = RequestMethod.GET)
    public String hello(@PathVariable("firstName") String firstName, 
                        @PathVariable("lastName") String lastName) {
        return helloRemoteServiceCall(firstName, lastName);
    }
}

 

이 코드에는 많은 내용이 포함되어 있다. 가장 먼저 주목할 부분은 @EnableEurekaClient 애너테이션이다. 이 애너테이션은 서비스 디스커버리를 사용하여 원격 REST 서비스 앤드포인트를 조회하기 때문에 마이크로서비스 자신을 유레카 서비스 디스커버리 에이전트에 등록하도록 지시한다. 유레카 서버 위치와 포트 번호 등 구성 정보는 프로퍼티 파일에 기재된다는 것에 유의해야 한다.

 

두 번째 주목할 것은 helloRemoteServiceCall 메서드 내부에서 일어나는 일이다. 앞에서 @EnableEurekaClient 애너테이션으로 스프링 부트에 유레카 클라이언트를 활성화하도록 지정했다. pom.xml 파일에 해당 의존성 (spring-cloud-starter-netflix-eureka-client)을 추가 했다면 이 애너테이션은 선택 사항임을 아는 것이 중요하다. RestTemplate 클래스는 호출하려는 서비스에 대한 논리적 서비스 ID를 전달한다 예를 들어 다음 코드와 같다.

 

ResponseEntity<String> restExchange = restTemplate.exchange(
               http://logical-service-id/name/{firstName}/{lastName}

 

내부적으로 RestTemplate 클래스는 유레카 서비스와 통신해서 지명된 서비스 인스턴스의 물리적 위치를 하나 이상 조회한다. 실제 서비스 소비자의 코드에서는 서비스의 실제 위치를 몰라도된다.

 

RestTemplate 클래스는 스프링 클라우드 로드 밸런서(Spring Cloud LoadBalancer) 라이브러리도 사용하는데, 이 라이브러리는 해당 서비스의 모든 물리적 앤드포인트 목록을 조회한다. 클라이언트가 서비스를 호출할 때마다 중앙 집중식 로드 밸런서를 거치지 않고도 다른 서비스 인스턴스가 호출되도록 "라운드 로빈" 호출 방식을 사용한다. 중앙 집중식 로드 밸런서를 제거하고 클라이언트가 그 역할을 하게 함으로써 애플리케이션 인프라스트럭처에서 도 따른 장애 지점(로드 밸런서 다운 등) 을 제거한다.

 

여기에서 단지 몇 개의 애너테이션으로 상당한 수의 기능을 마이크로서비스에 추가했다는 점이 인상적인데, 이것이 스프링 클라우드의 진정한 매력이다. 개발자는 넷플릭스와 콘술과 같은 최고의 클라우드 회사가 제공하고 시장에서 검증된 마이크로서비스 기능을 활용할 수 있게 되는 것이다. 스프링 클라우드는 말 그대로 몇 가지 간단한 애너테이션과 구성 정보만으로 사용하기 쉽게 해 준다.