Post

[오픈 미션 회고] 이메일 스케줄러와 조금 더 가까워진 느낌

‘오픈 미션 주제 뭐하지?’ 고민하던 게 정말 엊그제 같은데, 벌써 끝이라니 믿기지 않는다.
프리코스 총 5주가 길게 느껴지기도 했지만, 막상 끝나가니 아쉬움이 더 크다.
특히 이번 기수에는 ‘오픈 미션’이라는 새로운 도전이 주어졌고, 그것이 나를 더 믿어보는 계기가 되었다.

우테코는 참 신기하다.
이렇게 짧은 시간에 사람을 이만큼 성장시킬 수 있을까?
이번 과정을 통해 내가 생각했던 것보다 훨씬 많은 자신감을 얻게 된 것 같다.

1주차부터 3주차까지 회고록을 꾸준히 작성해왔기에, 오픈 미션 회고록도 꼭 남기고 싶었다.
미션을 진행하며 배운 개념, 구현 과정, 겪었던 문제들을 블로그에 기록했었다.
이렇게 2주 동안 거의 매일 블로그 글을 작성한 건 이번이 처음이었다.

학습한 내용이 너무 많아서 기록하지 않으면 금방 잊어버릴 것만 같았고,
이 경험 덕분에 기록의 중요성을 다시 한번 느낄 수 있었다.
“내가 이걸 배웠구나.”하고 돌아볼 수 있는 흔적이 생긴 것이 참 좋았다.


오픈 미션 주제 선정 배경

나는 평소 뉴스레터를 즐겨 읽는 편인데, 자연스럽게 뉴스레터는 어떤 구조로 동작할까?하는 궁금증이 생겼다.
만약 내가 뉴스레터 서비스를 직접 구현해야 한다면, 어떤 흐름으로 돌아가고 어떤 기술이 쓰일까? 궁금했다.

자료조사를 하다 보니 RabbitMQ, Message Queue, Scheduler 같은 단어들이 계속 등장했고,
“이번 기회에 한번 이 개념들을 제대로 파보자!”하는 마음이 생겼다.

그리고 생각해보면 뉴스레터만 그런게 아니다.
토스, 카카오 같은 서비스도 특정 시각에 알림이나 쿠폰을 동시에 사용자들에게 보내지 않는가?
이 구조도 비슷하다고 생각이 들었다.

이번에 제대로 학습해두면 다음에 비슷한 시스템을 구현할 때 훨씬 수월해지겠다고 생각했다.
그렇게 주제 선정에 있어서 확고해졌고, 내 마음속에는 이미 ‘이메일 스케줄러 서버 만들기’에 대한 설렘이 가득했다.


기술 스택 선택 과정

RabbitMQKafka 중 무엇을 사용할지 고민했지만,
초기 학습 목적에 맞게 RabbitMQ를 선택했다.

Kafka는 확실히 실시간 스트리밍 처리와 대용량 데이터 처리에 강력하지만,
나는 메시지 큐의 기본 개념인 Producer, Consumer, Exchange, Queue를 명확히 이해하는 것이 목표였다.
RabbitMQ가 더 직관적이었고, AMQP라는 표준 프로토콜 구조도 학습하고 싶었다.

그리고 그때는 몰랐다.
내가 RabbitMQ와 2주간 그렇게 지독하게 얽히게 될 줄은… (하지만 재밌었다)


과제 진행 여정

1주차 : 기초 기술 이해

  • Spring @Scheduled 내부 동작 원리 학습
  • RabbitMQ와 AMQP 개념 이해
  • 단일 Queue에서 Fanout Pub/Sub까지 확장

Spring에는 정말 친절하게도 @Scheduled라는 어노테이션을 붙이면 스케줄러 동작을 쉽게 구현할 수 있었다.
따라서 이 @Scheduled라는 어노테이션이 도대체 어떻게 동작하는건지? 그 원리를 이해하려고 했다.

RabbitMQ와 함께 AMQP 구조까지 학습하며
비동기 메시지 전달, Queue 역할, Exchange 타입 등을 이해하고
직접 코드로 구현하면서 전체 흐름이 머릿속에서 그려지기 시작했다.

2주차 : 실제 구현 및 리팩토링

  • 메일 발송 기본 구조 구현
  • HashMap 직렬화 문제, 무한 반복 버그 해결
  • 구독자 3명에서 10만 명 늘린 후, 성능 테스트
  • 페이징, 배치 처리, 트랜잭션 분리
  • 입력/유효성 검증 로직 구현

2주차는 1주차에 습득한 개념들을 맘껏 활용해 볼 수 있었다.
그 과정에서 문제가 생기면 원인을 분석해 해결해 나갔다.

10만 명 테스트도 해보고,
메일 본문을 .md 파일로 만들어 보내보기도 하고,
구독자 추가/취소 로직까지 직접 구현해보며 내가 생각한 구조를 눈으로 동작하는 모습을 보는게 너무 흥미로웠다.


아쉬웠던 점과 개선 아이디어

구현하지 못한 부분

  • 실제 이메일을 발송하고 받아보는 기능
  • Kafka 기반 구조로 확장해보기

구조적으로 개선하고 싶은 부분

지금 구조는 구독을 취소해도 active=false만 되고 DB에서 삭제되진 않는다.
사실 비활성 구독자를 DB에 계속 쌓아둘 이유가 없다.
따라서 구독 중인 사용자만 DB에 남겨두고, 구독을 취소하면 바로 삭제하는 방식이 더 나을 것 같다.


전반적인 소감

이번 오픈 미션을 진행하면서 ‘정답이 없는 문제를 스스로 정의하고, 부딪히며 해결해보자’고 다짐했다.
그리고 그 다짐을 지켰다고 생각한다.

매일 과제를 진행하며, 더 나은 방식을 고민하고, 문제가 생기면 왜 이런 문제가 생겼는지, 왜 이 해결 방식이 타당한지 스스로 끊임없이 질문하고 답하며 성장했다.

또한 “내가 만든 구조가 실제로 이렇게 동작하는구나”를 직접 확인하는 재미가 있었다.
그리고 그 과정들을 기록으로 남기면서 내가 왜 이런 결정을 했는지 설명할 수 있도록 하고 싶었다.

이렇게 2주가 지나고 마지막 소감문 제출만 남았다는 게 시원섭섭하다.
과제를 잘해내고 싶은 마음이 가득했던 2주였고, 그만큼 보람찼다.


© sihyun. Some rights reserved.