Message Filter

Message Filter는 특정 기준에 따라 원하지 않는 메시지를 제거하고 원하는 메시지만 통과시키는 패턴이다.
이 패턴은 컴포넌트가 관심 없는 메시지를 받지 않도록 하여 시스템의 효율성을 높이는 데 사용된다.

Message Filter 패턴을 적절히 활용하면 MSA 환경에서 메시지 처리의 효율성을 크게 높일 수 있다. 하지만 필터링 로직의 복잡성과 유지보수성을 고려하여 설계해야 한다.

주요 특징

  1. 단일 입력 채널과 단일 출력 채널을 가진다.
  2. 정의된 기준에 따라 메시지를 평가한다.
  3. 기준을 충족하는 메시지만 출력 채널로 전달한다.
  4. 기준을 충족하지 않는 메시지는 폐기된다.

구현 방법

  1. 필터 조건 정의: 메시지를 평가할 기준을 설정한다.
  2. 메시지 평가: 입력된 메시지가 정의된 조건을 충족하는지 확인한다.
  3. 메시지 라우팅: 조건을 충족하는 메시지는 다음 단계로 전달하고, 그렇지 않은 메시지는 폐기한다.

구현 방식

메시지 필터는 주로 다음과 같은 방식으로 구현된다:

  1. 헤더 기반 필터링: 메시지의 헤더 정보를 기반으로 필터링 조건을 설정한다. 예를 들어, 메시지의 우선순위나 타입에 따라 필터링할 수 있다.
  2. 내용 기반 필터링: 메시지의 본문 내용을 분석하여, 특정 키워드나 패턴에 따라 필터링한다.
  3. 속성 기반 필터링: 메시지에 포함된 메타데이터나 속성을 활용하여 필터링 조건을 정의한다.

장점

  1. 불필요한 메시지 처리 방지로 시스템 부하 감소
  2. 컴포넌트 간 결합도 감소
  3. 메시지 흐름의 유연성 증가

주의사항

  1. 필터 로직의 복잡성 관리
  2. 폐기된 메시지의 처리 방안 고려
  3. 과도한 필터링으로 인한 중요 메시지 손실 방지

메시지 필터의 활용 사례

  • 에러 처리 분리: 시스템에서 발생하는 에러 메시지를 별도의 에러 처리 큐로 분리하여 관리함으로써, 일반 메시지 처리 흐름과 분리된 에러 처리를 수행할 수 있다.
  • 다양한 수신자 지원: 동일한 메시지를 여러 수신자가 구독하되, 각 수신자가 필요한 메시지만을 수신하도록 필터를 적용하여 효율적인 메시지 처리를 구현할 수 있다.

확장 기능

  1. 다중 필터 조건: 여러 조건을 조합하여 복잡한 필터링 로직 구현
  2. 동적 필터링: 런타임에 필터 조건을 변경할 수 있는 기능 추가
  3. 필터링 로그: 폐기된 메시지에 대한 로깅 및 모니터링 구현

구현 예시

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// Message Filter 구현
class MessageFilter {
    constructor(options = {}) {
        this.filters = new Map();
        this.defaultHandler = options.defaultHandler || this.defaultMessageHandler;
        this.errorHandler = options.errorHandler || this.defaultErrorHandler;
    }

    // 필터 규칙 추가
    addFilter(name, condition, handler) {
        this.filters.set(name, {
            condition,
            handler,
            metrics: {
                processed: 0,
                filtered: 0,
                errors: 0
            }
        });
    }

    // 메시지 처리
    async processMessage(message) {
        try {
            // 메시지 유효성 검사
            if (!this.validateMessage(message)) {
                throw new Error('Invalid message format');
            }

            let handled = false;
            
            // 등록된 필터들을 순회하며 조건 검사
            for (const [name, filter] of this.filters) {
                if (await filter.condition(message)) {
                    await filter.handler(message);
                    filter.metrics.processed++;
                    handled = true;
                    break;
                } else {
                    filter.metrics.filtered++;
                }
            }

            // 어떤 필터도 처리하지 않은 경우 기본 핸들러로 처리
            if (!handled) {
                await this.defaultHandler(message);
            }

        } catch (error) {
            await this.errorHandler(message, error);
        }
    }
}

참고 및 출처