이벤트 소싱과 Kafka 그리고 OpenFeign

윤태호·2023년 3월 7일
0

TechTalk

목록 보기
4/8

이벤트 소싱이란?

이벤트 소싱이란 application의 모든 상태를 일으키는 이벤트를 순서에 맞게 저장하여 status를 만들어내는 방법입니다.
이렇게 말하면 어떤 말인지 이해하기 어렵습니다. 그러면 기존 DB와 차이점은 무엇인가?부터 알아봅시다.

  • 쉽게 말하면 RDBS와 NoSQL의 데이터 저장 방식은 현재 데이터의 상태를 저장하는 것입니다. (Key -value 타입이든, RDBS든 결국 데이터의 상태를 저장하는 것은 같다.)
  • 그에 반해 이벤트 소싱은 현재 데이터 상태가 어떤 이벤트를 거쳐서 만들어졌는지 그 모든 상태를 순서에 맞게 저장해놓는 것입니다.

아래의 그림을 보면 이해하기 쉬울 것입니다.

Example


위의 그림을 보면 데이터 한 컬럼에 이벤트 소싱은 많은 컬럼을 가져가는 것을 알 수 있습니다. 하지만 그 데이터가 어떻게 나오게 되었는지 알 수 있는 장점을 가집니다.

그러면 언제 어디서 왜 쓰는걸까?

기존의 모놀리식에서는 Server와 클라이언트 및 API와 DB의 연결이 끊기지 않으면 데이터의 유실 확률이 현저히 낮았다. 하지만 방대한 데이터 처리와 그를 해결하기 위해 등장한 MSA의 구조에서는 종종 데이터 유실이 발생할 수 있다. 예를 들어 우리는 다른 서비스의 데이터를 이용하기 위해 API를 통해 통신해야하는데 어떠한 이유로 데이터를 유실할 수 있다.
이러한 경우가 만약 결제와 같은 중요한 데이터라고 생각해보자...끔찍하다. Log를 추적한다해도 왜 유실이 일어났는지 우리는 알 수가 없다. 사라진 순간만 알 수 있을 뿐이다.
하지만 이벤트 소싱을 활용하면 언제 왜 어떻게 에러가 발생했는지 알 수 있으며, 에러가 일어나기 전의 상태로 돌아갈 수 있다.

단점은 없는건가??

  • 모든 이벤트를 저장하고 오류가 생기면 그것을 다시 조회하면서 찾는다?? --> read의 기능 악화(snapshot으로 필요하고자 하는 것만 일부분 저장하는 것으로 해결하고자한다.)
  • 이벤트를 읽고 저장하는데에 시간차이가 생긴다.(read write의 불일치성)하지만 Eventually Consistency의 장점을 챙길 수 있다.
  • 기존 모델에 비해서 상대적으로 데이터 저장을 더 많이 하기 때문에 대용량 데이터 처리에 대한 고민이 필요
  • read 모델과 write 모델의 불일치에 따른 CQRS 고민 필요

Kafka와 이벤트 소싱??

kafka는 이벤트 소싱에서 이벤트 스토어로 많이 이용하는데, Kafka는 기본적으로 application간의 이벤트를 처리하는 파이프라인이라고 생각하면 쉽습니다. 위의 처리구조와 이벤트 소싱을 처리하는데 최적화이기 때문에 Kafka를 이벤트 소싱 패턴에서 사용합니다. 필자가 아직 Kafka에 대한 이해가 부족하기에 여기에서 Kafka에 대해 마치겠습니다.(잘 모르는 지식을 퍼뜨리는 것이 제일 무섭기 때문에)

OpenFeign??

Open Feign은 Netflix에 의해 처음 만들어진 Declarative(선언적인) HTTP Client 도구로써, 외부 API 호출을 쉽게할 수 있도록 도와준다. 여기서 “선언적인” 이란 어노테이션 사용을 의미하는데, Open Feign은 인터페이스에 어노테이션들만 붙여주면 구현이 된다. 이러한 방식은 Spring Data JPA와 유사하며, 상당히 편리하게 개발을 할 수 있도록 도와준다.

OpenFeign의 장점

  • 인터페이스와 어노테이션 기반으로 작성할 코드가 줄어들음
  • 익숙한 Spring MVC 어노테이션으로 개발이 가능함
  • 다른 Spring Cloud 기술들(Eureka, Circuit Breaker, LoadBalancer) 과의 통합이 쉬움

OpenFeign의 가장 큰 장점은 인터페이스와 어노테이션 기반으로 작성할 코드가 줄어든다는 것이다. 아래의 코드는 환율 조회 API를 RestTemplate으로 작성한 것인데, 요즘 같이 API 호출이 잦은 MSA의 시대에서 이런 코드를 반복한다는 것은 번거롭다.

@Component
@RequiredArgsConstructor
class ExchangeRateRestTemplate {
    private final RestTemplate restTemplate;
    private final ExchangeRateProperties properties;
    private static final String API_KEY = "apikey";
    public ExchangeRateResponse call(final Currency source, final Currency target) {
        return restTemplate.exchange(
                        createApiUri(source, target),
                        HttpMethod.GET,
                        new HttpEntity<>(createHttpHeaders()),
                        ExchangeRateResponse.class)
                .getBody();
    }
    private String createApiUri(final Currency source, final Currency target) {
        return UriComponentsBuilder.fromHttpUrl(properties.getUri())
                .queryParam("source", source.name())
                .queryParam("currencies", target.name())
                .encode()
                .toUriString();
    }
    private HttpHeaders createHttpHeaders() {
        final HttpHeaders headers = new HttpHeaders();
        headers.add(API_KEY, properties.getKey());
        return headers;
    }}

위의 코드를 OpenFeign으로 작성하면 아래의 코드로 끝이다. OpenFeign으로 코드를 작성하면 생산성이 상당히 높아질 것이라는 장점은 직접 쳐보지 않아도 느낄 수 있을 것이다.

@FeignClient(name = "ExchangeRateOpenFeign", url = "${exchange.currency.api.uri}")
public interface ExchangeRateOpenFeign {
    @GetMapping
    ExchangeRateResponse call(
            @RequestHeader String apiKey,
            @RequestParam Currency source,
            @RequestParam Currency currencies);
}

OpenFeign의 단점 및 한계

  • 기본 Http Client가 Http2를 지원하지 않음 → Http Client에 대한 - 추가 설정 필요
  • 공식적으로 Reactive 모델을 지원하지 않음 → 비공식 오픈소스 라이브러리로 사용 가능
  • 경우에 따라서 애플리케이션이 뜰 대 초기화 에러가 발생할 수 있음 → Object Provider로 대응 필요
  • 테스트 도구를 제공하지 않음 → 별도의 설정 파일을 작성하여 대응 필요

다른 부분보다 테스트 도구를 제공하지 않는다는 점은 꽤나 치명적이다. 왜냐하면 어노테이션과 인터페이스 기반으로 프로그래밍하는 만큼 테스트를 통해 코드에 문제가 없는지, API 호출이 정상적으로 되는지 빠르게 확인할 필요가 있기 때문이다. 그래서 테스트 작성을 위한 설정 부분은 이어지는 포스팅에서 보완할 예정이다.

참고 문헌

https://sabarada.tistory.com/231
https://m.blog.naver.com/rogman0/221488686499
https://blog.voidmainvoid.net/429
https://mangkyu.tistory.com/278

profile
성장하는것을 제일 즐깁니다.

0개의 댓글