본문 바로가기
캠프/항해 플러스 4기

[9주차] WIL

by 핏차 2024. 5. 18.

”한 번의 실수는 배움이, 두 번의 실수는 실력이 된다.” 

 → 개선 사항 추적과 리마인드를 통해 동일한 문제나 같은 실수를 반복하는 결과를 만들지 않습니다.

”경험이 없다면 창조도 없다.”

→ 경험한 것을 기록해두면 더 잘 활용하기 위한 방법으로 연결시킬 수 있습니다.

“I may be wrong.”

→ 끊임없는 회고를 통해 자기객관화를 달성하고, 자신의 실수와 잘못을 인정할 줄 아는 용기 있는 사람이 됩니다.


 

9주차를 돌아보자.

이번 주차 과제는 음,, 서비스 규모가 확장되어 각 서비스가 분리된다면? 트랜잭션 분리 설계와 그 방안, 한계점을 파악해보는 것과 책임을 분리하는 방안을 설계해보는 것이었다. 책임과 트랜잭션을 분리하는 데에 있어서 이벤트 처리 또는 카프카 메세지 발행으로 구현해보는 것까지.

우선 회사에서는 이벤트 메세지 큐로 RabbitMQ를 이용하여 비동기로 처리할 로직, 자동 메일 발송이나 시간이 오래 걸리는 이미지 파일 리사이징 등을 처리하고 있다. 이미 되어 있는 로직을 따라 하긴 했지만, 이 부분은 나도 구현해봤기 때문에 이벤트 발송을 하는 부분은 어렵지 않을 것이라 생각했다.

 

지난 주 발제를 실강으로 듣지 못해서인지, 서비스 규모 확장에 따라 트랜잭션이 분리되는 것이 처음에는 더 좋은 방향성이라고 생각해버려서 내 작은 서비스를 열심히 트랜잭션을 분리하려고 노력하고, Saga 패턴으로 보상 트랜잭션을 구현하는 것을 목표로 구현을 해 나갔다.

 

하지만 멘토링을 듣고 생각이 바뀌었고, 적절한 책임과 관심사 분리를 하는 것은 중요하지만 트랜잭션은 분리하는 것만이 무조건적으로 좋은 방향이 아니라는 것을 깨닫게 되었다. 트랜잭션을 생성하는 비용도 있고, 하나의 비즈니스 기능 안에서라면 함께 처리되어야 할 일관성이 더 중요한 경우가 많기 때문이다. 서비스의 규모에 의해 도메인별로 서비스와 DB가 분리된다면 그 경우에는 불가피하게 한 로직 내에서 분리된 트랜잭션을 적절하게 작업해야 할 것이다. 

 

책임과 관심사의 분리로 인해 트랜잭션도 분리되는 것이 적절한 경우는, 보통 주요 기능이 아닌 부가 기능 때문에 트랜잭션의 길이가 너무 길어진다던지, 또는 부가 기능이 실패할 경우에 주요 기능이 함께 롤백되는 것이 불필요할 경우이다.

예를 들면, [회원 가입] 이후 [환영 쿠폰 발급]과 [가입 메일 발송] 등의 부가 기능이 있을 때, 이 부가 기능의 실패로 인해 가입이 롤백되면 안 되며 메일링 서비스가 오래 걸릴 경우에 회원 가입 로직이 커밋되지 못하고 오래 대기를 해야 할 필요가 없기 때문에 이런 부가 기능들은 가입 로직의 트랜잭션 커밋 이후에 이벤트 형식으로 후처리 작업되면 좋겠죠!

 

이번 주차에 한 것 1

이번 주차에 한 것 2

 

이번 주차에서는

트랜잭션의 적절한 범위, 책임과 관심사의 분리, 이벤트 처리와 카프카 발행에 대해서 학습하였다.

 

1. 트랜잭션,, 단일 업데이트 또는 단일 인서트 로직에서도 트랜잭션이 필요할까?

 

2. 이벤트 발행, 수신 시에 재시도하는 방법을 Spring에서 제공해주고 있음. Spring Retry → @Retryable, @Recover

 

3. 이벤트 발행 시 관심 끄기: 그동안 어떤이벤트발행, 그 다음에 땡땡이벤트발행, 잘 받았어? 받고 처리도 잘 했어? 이런 느낌으로 이벤트를 발행하고 관심을 주고 있었는데, '예약 끝났어, 이제 후처리 해!' 하고 이벤트 발행 후 발행 잘 되었으면 관심 끄는 것이 이벤트 처리 하는 근본적 목적과 일치한다.

 

4. Kafka 학습 (Spring-kafka)

kafka의 Producer, Consumer, ProducerListener, RetryScheduler를 간단히 구현해보았다.

* ProducerListener를 이용하면 발행의 실패에 대해 추적할 수 있다.

 

5. Saga 패턴 - 보상 트랜잭션 하는 법에 대해 개략적으로 이해함

롤백 topic을 따로 보내서 롤백 topic을 수신해서 롤백 처리하는 메서드를 따로 태움.. 쌩으로 하면 이런 느낌인 듯

 

6. 이벤트 형식의 후처리는 트랜잭션 커밋 이후에 하는 것이 좋음. 트랜잭션이 커밋되지 않았을 때 발행되면 만약 트랜잭션 실패했을 경우나, 읽기 타이밍이 다를 수 있음

 


* Gson으로 Json 직렬화, 역직렬화 하는 유틸을 만들었는데,

Gson은 ZonedDatetime 타입에 대해 직렬화, 역직렬화 할 때 실패한다. Gson이 기본으로 제공하지 않는 타입은 타입 adapter를 따로 작성해서 적용해주어야 한다.

Failed making field 'java.time.ZonedDateTime#dateTime' accessible; either change its visibility or write a custom TypeAdapter for its declaring type
com.google.gson.JsonIOException: Failed making field 'java.time.ZonedDateTime#dateTime' accessible; either change its visibility or write a custom TypeAdapter for its declaring type

 


 

 

Keep

1. 이벤트 방식과 카프카 방식으로 모두 구현해봐서 대략적인 흐름을 알게 된 점이 좋다.

2. 책임 분리와 트랜잭션 분리의 방안과 그 한계점, 효과 등에 대해서 고민해본 시간이 도움이 많이 되었다.

 

 

Problem

1. 카프카 payload에 대해서, key.. group-id... 등 어떤 역할인지, 동작 원리가 어떻게 되는지 깊게 학습하지는 못했다.

2. 이벤트 발행, 카프카 발행 테스트를 못 해서 테스트가 필요하다.

 

 

Try

1. 구현한 이벤트 로직에 대해서 테스트 해보고 보완할 점에 대해 보완하기

2. 카프카 조금 더 학습해보기

3. 현재 코드에서 예약 후 5분 임시 점유하는 부분 아직 좋지 않은 코드로 방치 중인데, 이번 여유 시간에는 이 부분도 레디스나 카프카로 리팩토링하기

 

 

9주차도 끝! 마지막 한 주 남았다!

728x90