Foundry
알림 시스템 설계
고급
핵심

두 번 보내지 않기

정확히 한 번은 불가능하고 선택이 남는다

요구사항에 같은 알림을 두 번 보내지 않는다고 적었습니다. 그런데 이것은 완벽히 달성할 수 없습니다. 그 이유와 대응이 이 절입니다.

넘기기와 기록 사이에 틈이 있다

넘긴 뒤 기록에 실패하면 다시 시도하게 되고 사용자는 두 번 받는다 보내고 기록하는 사이 제공자에 넘김 기록 실패 다시 시도 사용자는 같은 알림을 두 번 받는다 순서를 바꿔도 문제가 남는다 먼저 기록하고 보내면, 보내기가 실패했을 때 안 보낸 채로 끝난다 두 방향 중 하나를 골라야 한다 중요 알림은 두 번을 감수하고, 마케팅은 안 보내는 쪽을 고른다 채널마다 다르다. 문자는 돈이고 푸시는 짜증이다

제공자에게 넘긴 뒤 "보냈다" 를 기록해야 합니다. 그 사이에 우리 프로세스가 죽으면, 다시 살아난 뒤 그 알림을 아직 안 보낸 것으로 보고 다시 보냅니다.

순서를 바꿔도 문제가 남습니다. 먼저 기록하고 보내면 보내기가 실패했을 때 안 보낸 채로 끝납니다.

순서실패하면
보내고 기록두 번 보낼 수 있다
기록하고 보내기안 보낼 수 있다

둘 중 하나를 골라야 합니다. 정확히 한 번은 없습니다.

채널마다 다르게 고른다

무엇이 더 나쁜지가 알림 종류와 채널에 따라 다릅니다.

알림고르는 쪽이유
인증 번호두 번을 감수한다못 받으면 로그인을 못 한다
마케팅 문자안 보내는 쪽두 번 보내면 돈이 두 배이고 짜증이 두 배
결제 완료 푸시두 번을 감수한다못 받으면 불안하다

이 판단을 알림 종류마다 적어 둡니다. 시스템 전체에 하나로 정하면 어느 쪽에서는 반드시 잘못된 선택이 됩니다.

중복을 줄이는 장치

완전히 없앨 수 없지만 크게 줄일 수 있습니다.

보내는 서비스가 알림마다 고유한 키를 붙인다
우리는 그 키를 기록하고, 이미 있으면 보내지 않는다

키를 우리가 만들면 안 됩니다. 서비스가 같은 요청을 두 번 보낸 경우를 구분할 수 없기 때문입니다. 키는 보내는 쪽이 그 알림을 식별하는 값이어야 합니다.

키가 없으면 우리가 만들 수는 있습니다. 받는 사람과 알림 종류와 시간 구간을 합치는 방식입니다. 완벽하지 않지만 같은 알림이 몇 초 안에 두 번 오는 흔한 경우를 잡습니다.

사용자 눈에 보이는 중복

기술적으로 한 번 보냈어도 사용자가 두 번 본 것처럼 느끼는 경우가 있습니다.

상황사용자가 느끼는 것
같은 내용이 푸시와 메일로두 번 받았다
비슷한 알림이 연달아시끄럽다
이미 읽은 것에 대한 알림왜 또 오나

중복 방지의 목적은 기록의 정확성이 아니라 사용자 경험입니다. 그래서 채널을 넘어선 판단이 필요합니다. 같은 알림을 여러 채널로 보내기로 했다면, 한 채널에서 확인되면 나머지를 취소하는 것이 좋습니다.

기록을 언제까지 두나

중복 판정을 위한 키 기록은 영구히 둘 필요가 없습니다. 중복은 대개 짧은 시간 안에 생깁니다.

며칠 정도 두고 지운다
그 기간이 곧 우리가 막을 수 있는 중복의 범위다

기간을 정하지 않으면 그 기록이 계속 자라고, 하루 5천만 건 규모에서는 곧 큰 저장소가 됩니다. 막을 범위를 정하는 것이 저장 비용을 정합니다.

면접에서 이렇게 나옵니다

Q.같은 알림을 두 번 보내지 않는 것을 보장할 수 있나요

완벽히는 불가능합니다. 넘기기와 기록 사이에 틈이 있습니다.

순서실패하면
보내고 기록두 번 보낼 수 있다
기록하고 보내기안 보낼 수 있다

제공자에게 넘긴 뒤 기록하기 전에 프로세스가 죽으면, 다시 살아나 그 알림을 안 보낸 것으로 보고 또 보냅니다. 순서를 바꾸면 반대 문제가 생깁니다.

둘 중 하나를 골라야 합니다.

흔한 실수: 트랜잭션으로 묶으면 된다고 답하는 것. 제공자 호출은 외부 시스템이라 우리 트랜잭션에 들어오지 않습니다. 넘긴 것을 되돌릴 수 없다는 것이 문제의 본질입니다.

Q.두 번 보내는 쪽과 안 보내는 쪽 중 무엇을 고르시겠습니까

알림 종류와 채널마다 다르게 고릅니다.

알림고르는 쪽이유
인증 번호두 번을 감수못 받으면 로그인을 못 한다
마케팅 문자안 보내는 쪽돈이 두 배이고 짜증이 두 배
결제 완료 푸시두 번을 감수못 받으면 불안하다

시스템 전체에 하나로 정하면 어느 쪽에서는 반드시 잘못된 선택이 됩니다.

이 판단을 알림 종류마다 적어 두면 새 알림을 추가할 때 그 결정을 하게 됩니다.

흔한 실수: 기본값을 정하지 않는 것. 종류마다 정하라고 해 두면 대부분은 정하지 않고 넘어갑니다. 기본값을 두고 예외를 적게 만드는 편이 실제로 지켜집니다.

Q.중복 방지 키를 누가 만들어야 하나요

보내는 서비스가 만듭니다. 우리가 만들면 안 됩니다.

우리가 만들면 서비스가 같은 요청을 두 번 보낸 경우를 구분할 수 없습니다. 두 요청이 우리에게는 서로 다른 것으로 보입니다.

서비스가 알림마다 고유한 키를 붙인다
우리는 그 키를 기록하고 이미 있으면 보내지 않는다

키가 없으면 받는 사람과 알림 종류와 시간 구간을 합쳐 만들 수 있습니다. 완벽하지 않지만 같은 알림이 몇 초 안에 두 번 오는 흔한 경우는 잡습니다.

흔한 실수: 키를 필수로 만들지 않고 나중에 도입하려는 것. 키가 없는 요청 경로가 한 번 열리면 모든 서비스가 그 경로를 쓰게 됩니다. 처음부터 필수로 두는 편이 쉽습니다.

Q.중복 판정 기록을 언제까지 두시겠습니까

며칠 정도 두고 지웁니다. 중복은 대개 짧은 시간 안에 생깁니다.

기간이 곧 우리가 막을 수 있는 중복의 범위다

기간을 정하지 않으면 기록이 계속 자라고 하루 5천만 건 규모에서는 곧 큰 저장소가 됩니다. 막을 범위를 정하는 것이 저장 비용을 정합니다.

그리고 사용자 눈에 보이는 중복은 별개입니다. 같은 내용이 푸시와 메일로 오면 기술적으로 한 번씩이지만 사용자는 두 번 받았다고 느낍니다.

흔한 실수: 중복 방지를 기록의 정확성 문제로 보는 것. 목적은 사용자 경험입니다. 그래서 채널을 넘어선 판단이 필요하고, 한 채널에서 확인되면 나머지를 취소하는 것이 좋습니다.

먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.

읽었으면 문제로 확인해보세요

알림 시스템 설계 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.