필터 순서가 데이터를 삼켜버린 날
6
필터 순서가 데이터를 삼켜버린 날
2026-03-04
발단
알림센터에 알림이 안 들어간다는 리포트가 왔다. 푸시는 받은 사용자가 있는데, 알림센터에는 아무것도 없는 사용자가 있다고.
확인해보니, push token이 없는 사용자의 알림이 알림센터에도 안 들어가고 있었다.
이게 왜 문제인데?
알림센터와 푸시 발송은 별개의 기능이다.
알림센터: 앱 안에서 알림 목록을 보여주는 기능 (DB에 저장)
푸시 발송: FCM으로 핸드폰에 알림을 보내는 기능 (push token 필요)
- push token이 없어도 알림센터에는 저장되어야 한다
- push token이 있어야 푸시 발송이 가능하다
이 두 가지는 독립적이다. 그런데 코드에서 이걸 섞어버렸다.
원인: 필터 순서
기존 코드의 흐름:
// 1. push token이 있는 사용자만 조회
List<User> usersWithToken = getUsersWithValidToken(targetMyCodes);
// 2. 알림센터 저장 (push token이 있는 사용자만!)
saveNotifications(usersWithToken);
// 3. FCM 발송 (push token이 있는 사용자만)
sendFcm(usersWithToken);
문제가 보이는가? 1번에서 push token 기준으로 필터링한 결과를 2번 알림센터 저장에도 그대로 쓰고 있었다.
전체 대상: [A, B, C, D, E]
↓ push token 있는 사람만 필터
push token 유효: [A, B, C]
↓ 이 리스트로 알림센터도 저장
알림센터 저장: [A, B, C] ← D, E 누락!
FCM 발송: [A, B, C] ← 이건 맞음
D, E는 push token이 없을 뿐이지 알림센터에서 알림을 볼 수 있는 사용자인데, 아예 기록이 안 된 것이다.
해결: 저장을 필터 전에 하기
// 1. 알림센터 저장 (전체 대상)
saveNotifications(targetMyCodes); // 필터 전!
// 2. push token이 있는 사용자만 조회
List<User> usersWithToken = getUsersWithValidToken(targetMyCodes);
// 3. FCM 발송 (push token이 있는 사용자만)
sendFcm(usersWithToken);
전체 대상: [A, B, C, D, E]
↓ 전체 대상으로 알림센터 저장
알림센터 저장: [A, B, C, D, E] ← 모두 저장 ✅
↓ push token 필터링
FCM 발송: [A, B, C] ← token 있는 사람만
이 패턴이 위험한 이유
하나의 파이프라인(데이터가 여러 단계를 순서대로 거치며 처리되는 흐름)이 두 가지 목적을 가질 때 발생한다.
데이터 흐름: 전체 대상 → [필터] → 결과
목적 1: 알림센터 저장 (필터 불필요)
목적 2: FCM 발송 (필터 필요)
필터가 목적 2를 위해 존재하는데, 목적 1까지 영향을 준 것이다.
일반화하면
// 위험한 패턴
filtered = applyFilter(allData);
doTaskA(filtered); // A는 필터가 필요 없는데?
doTaskB(filtered); // B만 필터가 필요
// 안전한 패턴
doTaskA(allData); // 필터 불필요 → 원본 사용
filtered = applyFilter(allData);
doTaskB(filtered); // 필터 필요 → 필터된 결과 사용
배운 것
- 하나의 파이프라인이 여러 목적을 가지면, 필터 순서에 주의하자. 한 목적을 위한 필터가 다른 목적의 데이터를 삼킬 수 있다.
- "필터 이전"과 "필터 이후"를 명확히 구분하고, 각 작업이 어느 시점의 데이터를 써야 하는지 따져보자.
- 이 버그는 "일부 사용자에게만 안 된다"는 리포트로 오기 때문에 전수 조사를 해봐야 발견된다.