사전 필터
용어함정

필터

gabury1고친 사람 github-actions[bot]

필터는 흐름 한가운데 서서 지나가는 것을 거르거나 손봅니다. 그런데 어느 흐름에 서느냐에 따라 가리키는 것이 다릅니다. 데이터를 다룰 때는 조건에 맞는 항목만 남기는 연산입니다. 웹 서버에서는 요청이 처리 코드에 닿기 전에 거치는 코드입니다. 터미널에서 명령을 칠 때는 입력을 받아 가공해 내보내는 프로그램입니다.

쉽고 빠른 이해

무슨 일을 하는 물건인가 — 흐름 가운데 서서 지나가는 것을 거르거나 손보는 단계입니다. 주문 목록에서 결제된 주문만 남기는 것도 필터입니다. 모든 요청에 로그를 남기는 코드도 필터입니다. 터미널에서 파일의 줄을 정렬하는 명령도 필터입니다. 셋은 이름이 같을 뿐 하는 일이 서로 다릅니다.

왜 이렇게 하나 — 거르는 일을 따로 떼어 두면 앞뒤 단계는 자기 일만 합니다. 데이터는 필요한 것만 남겨서 뒤의 계산이 가벼워집니다. 웹 요청은 로그나 로그인 확인 같은 공통 코드를 한 번만 적으면 됩니다.

어떻게 도나

  1. 흐름 앞쪽에서 무언가가 들어옵니다. 목록의 항목 하나, 요청 하나, 텍스트 한 줄입니다
  2. 필터가 그것을 보고 넘길지 막을지, 고칠지 말지 정합니다
  3. 통과한 것만 다음 단계로 갑니다

대가 — 단계가 하나 늘어나는 만큼 흐름을 따라 읽기가 어려워집니다. 웹 서버의 필터는 모든 요청이 지나가므로 필터가 느려지면 모든 요청이 느려집니다.

상세

필터라는 이름은 쓰는 곳에 따라 다른 것을 가리킵니다. 이 절은 데이터 처리, 웹 서버, 셸 세 맥락을 먼저 표로 가릅니다. 그다음 맥락마다 무엇을 거르는지 따라갑니다.

셸은 터미널에 친 명령을 받아 프로그램을 실행해 주는 프로그램입니다. 셸의 필터는 그렇게 실행되는 프로그램의 한 종류입니다.

필터의 세 가지 뜻

맥락 필터가 하는 일 무엇이 지나가나 예
데이터 처리 조건에 맞는 항목만 남긴다 목록의 항목 · 테이블의 행 결제된 주문만 고르기
웹 서버 요청이 처리 코드에 닿기 전후에 끼어든다 요청과 응답 모든 요청에 로그 남기기
셸 입력을 읽어 가공한 결과를 내보낸다 텍스트 줄 줄 정렬 · 패턴에 맞는 줄 고르기

셋 모두 흐름 가운데 서서 앞에서 받은 것을 뒤로 넘깁니다. 닮은 점은 여기까지입니다. 무엇이 지나가는지가 다릅니다. 「거른다」는 말이 뜻하는 것도 다릅니다.

데이터 처리의 필터는 조건에 안 맞는 항목을 반드시 버립니다. 웹 서버와 셸의 필터는 하나도 안 버리고 모두 통과시킬 때가 많습니다. 이름만 보고 「무언가를 버리는 것」이라고 읽으면 뒤의 두 뜻에서 헷갈립니다.

데이터 처리의 필터

데이터를 다룰 때 필터는 목록에서 조건에 맞는 항목만 남기는 연산입니다. 항목마다 「이 조건에 맞나」를 묻습니다. 맞는 항목만 남깁니다. 주문 목록에서 결제가 끝난 주문만 고르는 일이 그 예입니다.

항목 하나를 받아 참이나 거짓을 돌려주는 조건을 술어라고 합니다. 필터는 술어 하나를 받아 목록 전체에 적용합니다. 조건을 코드 한 조각으로 떼어 넘길 수 있어서, 거르는 방법은 손대지 않고 조건만 바꿔 끼울 수 있습니다.

필터를 거친 목록은 항목 수만 줄어듭니다. 남은 항목은 손대지 않은 채 원래 순서대로 나옵니다.

자바의 스트림은 목록의 항목을 하나씩 흘려보내며 연산을 이어 붙이는 도구입니다. 아래는 스트림으로 숫자 목록을 거르는 코드입니다.

Java
List.of(3, 8, 1, 9).stream()
    .filter(n -> n > 5)   // 8, 9
    .toList();

n -> n > 5 가 술어입니다. 3과 1은 거짓이 나와 빠졌습니다. 8과 9는 원래 순서대로 남았습니다.

항목의 값을 바꾸는 일은 필터가 아니라 map 이 맡습니다. map 은 항목마다 새 값을 만듭니다. 항목 수는 바꾸지 않습니다.

데이터베이스에서는 SQL(Structured Query Language, 구조화 질의 언어)의 WHERE 절이 필터입니다. 테이블의 행마다 조건을 묻고 맞는 행만 남깁니다. 이 일을 필터링이라고도 합니다.

집계는 여러 행을 묶어 합계나 개수 같은 값 하나로 합치는 계산입니다. 행을 묶는 일은 GROUP BY 절이 맡습니다. 「고객마다 주문 수」처럼 묶음마다 값이 하나씩 나옵니다.

필터는 집계의 앞과 뒤 양쪽에 설 수 있습니다. 묶기 전에 행을 거르는 것이 WHERE 입니다. 집계한 뒤 묶음을 거르는 것이 HAVING 입니다.

flowchart TD
    A["테이블의 행 전부"] --> B["WHERE · 조건에 맞는 행만 남긴다"]
    B --> C["GROUP BY · 남은 행을 묶는다"]
    C --> D["집계 · 묶음마다 값 하나로 합친다"]
    D --> E["HAVING · 조건에 맞는 묶음만 남긴다"]

먼저 거를수록 묶고 집계할 행이 줄어듭니다. 그래서 묶기 전에 걸러도 되는 조건은 WHERE 에 둡니다. 「주문이 열 건 넘는 고객」처럼 묶어야만 알 수 있는 조건만 HAVING 으로 갑니다.

검색 화면에서 가격대나 카테고리를 골라 결과를 좁히는 것도 이 뜻의 필터입니다. 검색어는 결과를 찾고 순서를 매기는 데 쓰입니다. 필터는 순서를 건드리지 않습니다. 조건에 안 맞는 결과를 빼기만 합니다.

조건마다 결과가 몇 건인지 옆에 세어 보여 주는 목록을 패싯이라고 합니다. 조건을 고르기 전에 몇 건이 남을지 미리 알 수 있습니다.

웹 서버의 필터

웹 서버에서 필터는 요청이 컨트롤러에 닿기 전에 거치는 코드입니다. 컨트롤러는 요청 하나를 받아 실제 업무 처리를 부르는 코드입니다. 필터는 그 앞에 줄지어 서서 들어오는 모든 요청을 먼저 봅니다.

로그 남기기, 로그인 확인, 문자 인코딩 맞추기는 어느 요청에나 필요합니다. 이런 일을 컨트롤러마다 적으면 같은 코드가 수십 군데 흩어집니다. 여러 모듈에 두루 걸치는 이런 일을 횡단 관심사라고 부릅니다. 필터에 한 번 적어 두면 모든 요청에 한꺼번에 적용됩니다.

필터 하나가 할 수 있는 일은 둘입니다. 요청을 다음으로 넘기거나, 거기서 막고 바로 응답을 돌려보냅니다. 넘긴 요청의 응답은 돌아올 때 같은 필터들을 거꾸로 다시 지납니다. 그래서 필터 하나가 요청이 들어올 때와 응답이 나갈 때를 둘 다 볼 수 있습니다.

sequenceDiagram
    participant 클라이언트
    participant 로그 필터
    participant 인증 필터
    participant 컨트롤러
    클라이언트->>로그 필터: 요청
    Note over 로그 필터: 도착 시각을 적는다
    로그 필터->>인증 필터: 넘긴다
    Note over 인증 필터: 로그인이 없으면 여기서 거절한다
    인증 필터->>컨트롤러: 넘긴다
    컨트롤러-->>인증 필터: 응답
    인증 필터-->>로그 필터: 응답
    Note over 로그 필터: 걸린 시간을 적는다
    로그 필터-->>클라이언트: 응답

그림의 클라이언트는 요청을 보낸 쪽입니다. 로그 필터는 요청을 하나도 막지 않습니다. 들어올 때 시각을 적습니다. 응답이 나갈 때 걸린 시간을 적을 뿐입니다.

인증 필터는 로그인이 안 된 요청을 거기서 되돌려 보냅니다. 이렇게 같은 필터라는 이름 아래 거르는 코드와 안 거르는 코드가 함께 섭니다. 이 맥락의 필터를 가르는 기준은 무엇을 버리느냐가 아닙니다. 요청이 오가는 길목에 서느냐입니다.

이렇게 줄지어 선 필터들을 필터 체인이라고 부릅니다. 순서가 결과를 바꿉니다. 인증 필터가 로그 필터보다 앞에 서면 거절당한 요청은 로그에 안 남습니다.

자바의 웹 표준인 서블릿이 이 코드를 필터라고 부릅니다. 다른 프레임워크는 같은 일을 하는 코드를 미들웨어라고 부르는 경우가 많습니다. 이름이 다를 뿐 요청 앞뒤에서 일한다는 점은 같습니다.

필터에도 대가가 있습니다. 모든 요청이 필터를 지나므로 필터가 느려지면 모든 요청이 느려집니다. 필터가 늘수록 요청 하나가 무엇을 거쳐 컨트롤러에 닿는지 코드만 보고 따라가기도 어려워집니다.

셸의 필터

셸에서 필터는 텍스트 줄을 받아 가공해 내보내는 프로그램입니다. 이 소절은 필터가 입력을 받고 내보내는 통로부터 봅니다. 그다음 필터 둘을 이어 붙인 예를 따라갑니다.

셸에서 실행하는 프로그램은 기본 통로 둘을 가집니다. 표준 입력은 프로그램이 파일을 따로 열지 않아도 읽을 수 있는 기본 입력 통로입니다. 표준 출력은 그 반대쪽인 기본 출력 통로입니다.

필터는 표준 입력에서 읽은 것을 가공해 표준 출력으로 내보냅니다. 패턴에 맞는 줄만 남기는 grep 이 흔히 쓰는 필터입니다. 필터는 이 두 통로만 쓰므로 입력이 어느 파일에서 오는지, 결과가 어디로 가는지 몰라도 됩니다.

파이프는 앞 프로그램의 표준 출력을 다음 프로그램의 표준 입력으로 곧장 잇는 통로입니다. 그래서 필터 여럿을 파이프로 이어 붙일 수 있습니다.

이렇게 이어 붙인 명령의 줄을 파이프라인이라고 합니다. 아래는 세 줄짜리 입력을 필터 둘에 차례로 통과시키는 파이프라인입니다. printf 는 적어 준 글자를 표준 출력으로 내보내는 명령입니다. 주석은 그 단계를 지난 뒤 남은 줄들입니다.

터미널
printf 'b\na\nb\n' |  # b a b
  sort |              # a b b
  uniq                # a b

sort 는 줄을 정렬합니다. uniq 는 바로 이웃한 같은 줄을 하나로 합칩니다.

sort 는 한 줄도 버리지 않았습니다. 순서만 바꿨습니다. 그래도 필터라고 부릅니다. 셸에서 필터를 가르는 기준은 표준 입력에서 받아 표준 출력으로 내느냐입니다.

이름만 겹치는 다른 기술

필터라는 이름을 단 기술은 이 밖에도 여럿입니다. 모두 무언가를 통과시키거나 막는다는 점만 닮았습니다. 하는 일은 저마다 다릅니다. 아래 표는 이름과 분야만 가려 둡니다.

이름 분야 가리키는 것
블룸 필터 자료구조 원소가 집합에 들어 있는지 빠르게 답하는 구조. 「없다」는 확실하고 「있다」는 틀릴 수 있다
패킷 필터 네트워크 보안 규칙에 따라 네트워크 패킷을 통과시키거나 버리는 방화벽 기능
필터 드라이버 운영체제 장치로 가는 요청 사이에 끼어 엿보거나 고치는 드라이버
텍스처 필터링 그래픽스 이미지를 늘리거나 줄여 그릴 때 주변 색을 섞어 매끄럽게 하는 방법
저역 통과 필터 신호 처리 느리게 변하는 성분만 남기고 빠르게 떨리는 성분을 깎는 처리

어느 뜻인지 가르는 단서

대화나 문서에서 「필터」가 나오면 함께 나오는 말을 봅니다. 대개 그것만으로 어느 뜻인지 가려집니다.

함께 나오는 말 뜻
조건 · 행 · WHERE · 스트림 · 검색 결과 좁히기 데이터 처리의 필터
요청 · 응답 · 체인 · 인증 · 서블릿 · 미들웨어 웹 서버의 필터
파이프 · 표준 입력 · grep · sort 셸의 필터

관련 항목

데이터 필터가 조건을 넘겨받는 방식

술어 · 람다 · 고차 함수 · 스트림 API · map 함수 · reduce 함수

데이터 필터를 적는 SQL 절

SQL · WHERE · HAVING · GROUP BY · 집계

필터로 검색 결과를 좁히는 검색 기능

불리언 검색 · 패싯 · 검색 연산자 · 랭킹

웹 요청이 컨트롤러까지 거치는 처리 단계

필터 체인 · 미들웨어 · 인터셉터 · 서블릿 · 컨트롤러

웹 필터에 모아 두는 횡단 관심사

횡단 관심사 · 관심사 분리 · 관점 지향 프로그래밍 · 로깅 · 인증 · CORS

셸 필터를 잇는 통로와 입출력

셸 · 파이프 · 파이프라인 · 표준 입력 · 표준 출력 · 리다이렉션

셸에서 필터로 쓰는 명령

grep · uniq · sed · awk · tr · cut

필터와 이름만 겹치는 다른 기술

블룸 필터 · 패킷 필터 · 필터 드라이버 · 텍스처 필터링 · 저역 통과 필터 · 방화벽

다른 이름: filter · 필터링