이벤트 소싱이란 application의 모든 상태를 일으키는 이벤트를 순서에 맞게 저장하여 status를 만들어내는 방법입니다.
이렇게 말하면 어떤 말인지 이해하기 어렵습니다. 그러면 기존 DB와 차이점은 무엇인가?부터 알아봅시다.
아래의 그림을 보면 이해하기 쉬울 것입니다.
위의 그림을 보면 데이터 한 컬럼에 이벤트 소싱은 많은 컬럼을 가져가는 것을 알 수 있습니다. 하지만 그 데이터가 어떻게 나오게 되었는지 알 수 있는 장점을 가집니다.
기존의 모놀리식에서는 Server와 클라이언트 및 API와 DB의 연결이 끊기지 않으면 데이터의 유실 확률이 현저히 낮았다. 하지만 방대한 데이터 처리와 그를 해결하기 위해 등장한 MSA의 구조에서는 종종 데이터 유실이 발생할 수 있다. 예를 들어 우리는 다른 서비스의 데이터를 이용하기 위해 API를 통해 통신해야하는데 어떠한 이유로 데이터를 유실할 수 있다.
이러한 경우가 만약 결제와 같은 중요한 데이터라고 생각해보자...끔찍하다. Log를 추적한다해도 왜 유실이 일어났는지 우리는 알 수가 없다. 사라진 순간만 알 수 있을 뿐이다.
하지만 이벤트 소싱을 활용하면 언제 왜 어떻게 에러가 발생했는지 알 수 있으며, 에러가 일어나기 전의 상태로 돌아갈 수 있다.
kafka는 이벤트 소싱에서 이벤트 스토어로 많이 이용하는데, Kafka는 기본적으로 application간의 이벤트를 처리하는 파이프라인이라고 생각하면 쉽습니다. 위의 처리구조와 이벤트 소싱을 처리하는데 최적화이기 때문에 Kafka를 이벤트 소싱 패턴에서 사용합니다. 필자가 아직 Kafka에 대한 이해가 부족하기에 여기에서 Kafka에 대해 마치겠습니다.(잘 모르는 지식을 퍼뜨리는 것이 제일 무섭기 때문에)
Open Feign은 Netflix에 의해 처음 만들어진 Declarative(선언적인) HTTP Client 도구로써, 외부 API 호출을 쉽게할 수 있도록 도와준다. 여기서 “선언적인” 이란 어노테이션 사용을 의미하는데, Open Feign은 인터페이스에 어노테이션들만 붙여주면 구현이 된다. 이러한 방식은 Spring Data JPA와 유사하며, 상당히 편리하게 개발을 할 수 있도록 도와준다.
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); }
다른 부분보다 테스트 도구를 제공하지 않는다는 점은 꽤나 치명적이다. 왜냐하면 어노테이션과 인터페이스 기반으로 프로그래밍하는 만큼 테스트를 통해 코드에 문제가 없는지, API 호출이 정상적으로 되는지 빠르게 확인할 필요가 있기 때문이다. 그래서 테스트 작성을 위한 설정 부분은 이어지는 포스팅에서 보완할 예정이다.
https://sabarada.tistory.com/231
https://m.blog.naver.com/rogman0/221488686499
https://blog.voidmainvoid.net/429
https://mangkyu.tistory.com/278