목록으로

필터 순서가 데이터를 삼켜버린 날

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);          // 필터 필요 → 필터된 결과 사용

배운 것

  1. 하나의 파이프라인이 여러 목적을 가지면, 필터 순서에 주의하자. 한 목적을 위한 필터가 다른 목적의 데이터를 삼킬 수 있다.
  2. "필터 이전"과 "필터 이후"를 명확히 구분하고, 각 작업이 어느 시점의 데이터를 써야 하는지 따져보자.
  3. 이 버그는 "일부 사용자에게만 안 된다"는 리포트로 오기 때문에 전수 조사를 해봐야 발견된다.