본문으로 건너뛰기
피드

Remails: 유럽에서 만든 오픈소스 메일 전송 에이전트(MTA)

backend 약 5분
vote
0
댓글
북마크

네덜란드 Tweede Golf가 만든 유럽 호스팅 기반 오픈소스 MTA. 단일 VPS에서 시작해 Kubernetes 고가용성 아키텍처로 진화하면서, BYOIP와 발신자별 IP 제어를 구현한 과정을 상세히 설명함.

  • 1

    유럽 클라우드 기반 MTA로 BYOIP 지원, 발신자별 전용 IP 할당 가능

  • 2

    DaemonSet + 호스트 네트워크로 아웃바운드 IP 제어, best-effort 메시지 버스로 컴포넌트 간 통신

  • 3

    무료 플랜 월 3,000통, GitHub 소스 공개로 셀프 호스팅 가능

  • 네덜란드의 Tweede Golf가 만든 Remails는 유럽 호스팅 기반의 메일 전송 에이전트(MTA)임. 이메일을 안정적으로 전달하기 위해 평판 좋은 IP로 릴레이하고, 적절한 헤더를 세팅하고, 실패 시 자동 재전송해주는 서비스
  • GitHub에 소스코드가 공개되어 있어서 셀프 호스팅 가능하고, remails.net에서 바로 쓸 수 있는 인스턴스도 제공함. 현재는 트랜잭셔널 이메일(비밀번호 리셋, 인증 코드 등) 전용이고, 대량 마케팅 메일은 아직 미지원

MVP에서 고가용성까지

  • 처음엔 유럽 클라우드의 단일 VPS에서 Docker Compose + PostgreSQL로 단일 바이너리 띄우는 구조로 시작했음
  • 이후 매니지드 Kubernetes 클러스터 + 매니지드 Postgres로 전환. 웹 API와 SMTP MTA를 분리해서 각각 여러 레플리카를 노드에 분산 배포하는 고가용성 아키텍처로 진화함
  • 데이터 가용성은 클라우드 프로바이더의 이중 DB 노드 + PITR 백업 + 독립 위치에 일일 풀백업으로 확보. 백업 실패 시 알람이 오도록 모니터링도 걸어둠

IP 주소 관리가 핵심 과제

  • 이메일 발송에서 발신 IP의 평판이 스팸 필터 통과에 결정적인데, 클라우드 퍼블릭 IP로는 좋은 평판 쌓기가 어려움. 그래서 자체 IP 블록을 가져오는 BYOIP(Bring Your Own IP) 방식을 채택
  • 핀란드 클라우드 프로바이더 UpCloud이 BYOIP를 지원해줬고, 여기에 더해 발신자별로 어떤 IP에서 메일을 보낼지 제어하는 기능이 필요했음. 대량 고객에게 전용 IP를 할당해서 다른 고객의 평판 영향을 받지 않게 하려는 것

아키텍처 리팩토링

  • SMTP를 인바운드아웃바운드로 분리함. 인바운드는 일반 Deployment로 노드에 랜덤 분산, 아웃바운드는 DaemonSet으로 각 노드에 정확히 1개씩 실행하면서 호스트 네트워크 접근 권한을 부여
  • Cloud IP Manager라는 컴포넌트를 추가해서 클라우드 API를 통해 각 노드에 필요한 IP를 할당. 하나의 노드에 여러 IP를 붙일 수 있고, 아웃바운드 Pod이 직접 네트워크 인터페이스에 접근해서 발신 IP를 선택
sequenceDiagram
    participant 웹API as 웹 API
    participant 메시지버스 as 메시지 버스
    participant 아웃바운드 as SMTP 아웃바운드 (DaemonSet)
    participant DB as PostgreSQL

    웹API->>DB: 이메일 저장
    웹API->>메시지버스: 발송 알림 (메시지ID + 발신IP)
    메시지버스->>아웃바운드: 브로드캐스트
    아웃바운드->>아웃바운드: 해당 IP 보유 여부 필터링
    아웃바운드->>DB: 발송 상태 업데이트
  • 컴포넌트 간 통신은 경량 브로드캐스트 메시지 버스를 도입. 재미있는 건 이 버스가 전달 보장(deliverability guarantee)이 없는 best-effort 방식이라는 거임
  • 그런데도 고가용성이 유지되는 이유가 기발함 — 모든 액션은 DB에 먼저 저장되고, 메시지 버스 알림이 실패하면 주기적 태스크(Periodic Tasks)가 미발송 메일을 찾아서 재시도함. 버스가 죽어도 약간의 지연만 생길 뿐 메일은 결국 나감

💡

> 현재 퍼블릭 베타 중이고, 무료 플랜으로 월 3,000통까지 발송 가능. 미국 프로바이더 대신 유럽 대안을 찾는다면 한번 써볼 만함.

  • 로드맵에는 DNS 레코드 이상 알림, 쿼타 경고, 감사 로그, 이메일 수신 기능(바운스 메시지/DMARC 리포트용) 등이 예정되어 있음

이메일 인프라를 직접 구축하면서 마주치는 IP 평판 관리와 고가용성 문제를 Kubernetes로 풀어낸 실전 아키텍처 사례. 메시지 버스의 best-effort 설계가 특히 인상적.

댓글

댓글

댓글을 불러오는 중...

backend

Go에서 Rust로 옮길 때 진짜로 바뀌는 것들

이 글은 Go 백엔드 서비스를 Rust로 옮길 때 속도보다 컴파일 타임 보장, 런타임 트레이드오프, 개발자 경험이 더 중요하다고 설명한다. nil 패닉, 데이터 레이스, 에러 처리, 제네릭, 비동기 모델, 마이그레이션 전략까지 실무 관점에서 Go와 Rust를 길게 비교한다.

backend

Python 3.15에서 헤드라인은 못 탔지만 꽤 쓸만한 기능들

Python 3.15에는 lazy imports나 Tachyon profiler 같은 큰 기능 말고도 실무에서 바로 체감될 만한 작은 개선들이 들어가. TaskGroup 취소, 컨텍스트 매니저 데코레이터 개선, 스레드 안전 이터레이터처럼 평소 애매하게 불편했던 지점들이 꽤 깔끔해졌어.

backend

심평원, DUR부터 의료영상 심사까지 클라우드로 갈아엎는다

심평원이 정보시스템 클라우드 전환과 함께 병·의원 업무에 직접 닿는 DUR, 의료영상 AI 심사, 요양급여내역 조회 시스템을 고도화한다. 핵심은 설치형 프로그램 중심이던 연계를 웹과 API 기반으로 넓히고, 진료·청구 과정에서 실시간 확인과 자동 판독을 강화하는 쪽이다.

backend

윈도우 에러 코드 7번 ‘ERROR_ARENA_TRASHED’는 어디서 왔을까

ERROR_ARENA_TRASHED는 Win32에서 실제로 쓰이는 현대적 에러라기보다 MS-DOS 시절 메모리 관리 구조에서 넘어온 잔재야. MS-DOS가 메모리 블록 앞의 arena 시그니처를 훑다가 예상한 값이 아니면 ‘arena가 망가졌다’고 보고 이 에러를 냈다는 이야기야.

backend

C/C++ 컴파일러의 느슨한 메모리 동시성 버그를 자동으로 잡는 박사논문

C와 C++ 컴파일러에서 relaxed memory 동시성 버그를 찾는 자동 테스트 프레임워크를 다룬 박사논문이 공개됐어. Téléchat, Atomic-mixer 같은 도구로 소스 수준 동작과 컴파일된 프로그램 동작을 비교하고, LLVM과 GCC 툴체인에서 실제 버그를 찾아낸 내용이 핵심이야.