넘겨받은 커머스에서 마케팅 문자와 앱 푸시를 다시 보내려면 먼저 답해야 할 질문이 있었다. 이 고객들에게 광고를 보내도 되는가. 고객 명단은 영업과 함께 넘어왔지만, 광고 수신 동의까지 넘어왔다고 볼 수는 없었다. 그래서 설계는 법령 원문을 확인하는 데서 시작했다.
Table of contents
Open Table of contents
배경 — 법령 기준 여섯 가지
정보통신망법 제50조와 시행령 제61조·제62조의2·제62조의3, 그리고 방송미디어통신위원회·KISA 의 「불법스팸 방지를 위한 정보통신망법 안내서」(2025년 12월 제7차 개정)를 원문으로 대조했다. 조문은 법령 미러에서 받아 안내서의 조문 박스와 문언이 같은지 확인했다. 법제처 사이트는 본문을 스크립트로 그려 그대로 받으면 비어 있었다.
| # | 물음 | 기준 |
|---|---|---|
| ① | 사전 동의 범위 | 문자·이메일·앱 푸시로 보내는 영리목적 광고는 명시적 사전 동의가 필요하다. 약관 동의로 갈음할 수 없고, 기본 체크도 안 된다 |
| ② | 야간 별도 동의 | 21:00~다음 날 08:00, 수신자에게 도달한 시각 기준. 예외 매체는 이메일 하나다 |
| ③ | 처리 결과 통지 | 의사를 표시한 다음 날부터 14일 안. 홈페이지·앱에서 한 의사표시는 화면 팝업으로 갈음할 수 있다 |
| ④ | 정기 재확인 | 2년마다, 최종 동의일 기준. 안내한 날부터 다시 세지 않는다 |
| ⑤ | 이력 보존 기간 | 법정 기간이 없다. 동의 증명 책임은 보내는 쪽에 있다 |
| ⑥ | 거래관계 예외 | 영업 양수로 넘겨받은 고객 명단은 「직접 수집」이 아니다. 승계할 동의도 없다 |
가장 중요한 것은 ⑥이다. 넘겨받기 전의 거래 관계를 근거로 광고를 보낼 수 없으므로, 발송 필터는 동의 기록만 봐야 한다. OS 의 알림 허용도 동의가 아니다. 앱 푸시에도 제50조가 그대로 적용되고, 개인정보보호법상 마케팅 처리 동의와 광고 수신 동의는 따로 받아야 한다.
판단 — 동의 기록을 어디에 둘 것인가
저장 위치는 다음 두 가지 안 가운데서 골랐다.
- 고객 노드 아래(
customers/{uid})에 동의 값을 둔다 - Realtime Database 의 서버 전용 최상위 노드에 동의(
marketingConsent)와 이력(marketingConsentLog), 전화번호 색인(byPhone)을 둔다
2번으로 선택한 이유는 동의 증명 책임이 보내는 쪽에 있기 때문이다. 고객 노드 아래에 두면 고객이 자기 노드에 직접 쓸 수 있어 기록을 신뢰할 수 없고, 탈퇴할 때 노드가 지워지면 증명 이력도 함께 사라진다. 반면 대가는 고객 화면이 동의를 바꿀 때 직접 쓰지 못하고 반드시 서버 API 를 거쳐야 한다는 점이다. 보존 기간은 법정 기준이 없으므로 「철회·탈퇴 뒤 5년, 분리 저장」을 권고로 두고 기간 값은 법무 판단을 받을 빈칸으로 남겼다.
동의를 처음 받는 경로도 정했다. 전 고객을 한 번 로그아웃시키고, 다시 로그인할 때 화면 팝업으로 받는다. 팝업은 약관과 분리된 항목이고 기본값은 해제다. 다만 이 팝업은 처음 동의를 받는 경로로만 쓰고, 2년 재확인 수단으로는 쓰지 않는다.
해결 — 광고 발송 필터
발송 쪽은 광고와 서비스 메시지를 데이터에서 가른다. 앱 푸시는 FCM data 에 push_kind: 'ad' | 'service' 를 싣고, ad 는 서버가 동의가 true 인 uid 의 토큰에만 보낸다. 야간이면 야간 동의도 본다. 문자 광고는 전화번호 색인의 동의와 수신 거부 목록을 함께 본다. 거부 목록과 동의는 양방향으로 맞춘다. 문자 동의는 거부 목록을 풀되 최신 명시 의사가 이길 때만 풀고, 수신 거부 전화를 받으면 문자 동의를 내리고 그 사실을 문자로 통지한다.
원인 — 설계 중에 찾은 거부 무시 결함
구현 계획을 세우며 문자 처리기를 읽다가 결함 하나를 찾았다. 광고 문자 캠페인을 만드는 쪽은 수신 거부 번호를 빼지 않고 수신자에 reject: true 표시만 달아 큐에 넣는다. 그런데 그 큐를 받는 운영 처리기(PM2 로 도는 Node.js)는 그 표시를 보지 않는다. 배포본 파일과 그 처리기가 실제로 불러오는 발송 클라이언트 디렉터리 전체를 grep 해도 reject 는 0줄이었다. 같은 VM 의 알림톡 처리기에는 else if (data.reject) 갈래가 있어, 조회가 제대로 닿는다는 대조군이 됐다. 지금 예약된 광고 문자 캠페인은 0건이지만, 다음 캠페인을 내는 순간 거부 번호에도 나간다. 처리기가 reject 를 지키고 광고면 동의 색인까지 보게 고치는 일을 구현 목록에 넣었다.
결과 — 동의 없는 명단에서 시작한 설계
- 법적 위험. 넘겨받은 명단을 근거로 광고를 보내는 길을 설계 단계에서 닫았다. 발송 필터는 새로 받은 동의만 본다
- 증명 책임. 동의 기록을 고객이 직접 쓸 수 없고 탈퇴해도 남는 Realtime Database 의 서버 전용 최상위 노드에 두어, 동의를 받았다는 것을 보내는 쪽이 증명할 수 있게 했다
- 잠재 사고의 차단. 설계 중에 PM2 로 도는 Node.js 문자 처리기가 수신 거부 표시를 읽지 않아 광고 문자가 거부 번호에도 나가는 결함을 찾아, 다음 광고 캠페인이 나가기 전에 고칠 목록에 올렸다
정리
- 영업을 넘겨받으면 고객 명단은 오지만 광고 수신 동의는 오지 않는다. 광고는 새로 받은 동의만 근거로 삼는다
- 동의 기록은 고객이 직접 쓸 수 없고 탈퇴해도 남는 자리에 둔다. 증명 책임이 보내는 쪽에 있다
- 광고와 서비스 메시지는 데이터에 종류를 싣고, 서버가 동의를 확인한 뒤에만 보낸다
- 거부 표시는 다는 쪽과 지키는 쪽이 다를 수 있다. 큐를 받는 처리기가 그 표시를 읽는지까지 확인한다