자바 디자인 패턴 용어 사전
행위 패턴인터프리터

Interpreter

문법 규칙을 클래스로 표현해 문장을 해석하는 패턴. 간단한 DSL에 쓴다.

문법 규칙 하나하나를 클래스로 표현해 문장을 해석하는 패턴.

interface Expression { int interpret(Map<String,Integer> ctx); }

class Number implements Expression {
    private final int v;
    public int interpret(Map<String,Integer> c) { return v; }
}
class Add implements Expression {
    private final Expression l, r;
    public int interpret(Map<String,Integer> c) {
        return l.interpret(c) + r.interpret(c);      // 재귀 해석
    }
}

// (1 + 2) 를 트리로 만들어 해석한다
new Add(new Number(1), new Number(2)).interpret(ctx);   // 3

Composite와의 관계

Interpreter 의 구문 트리는 사실상 Composite 구조다 단말 표현식(Number) = Leaf

  • 비단말 표현식(Add) — = Composite

차이는 목적이다 — Composite 는 '부분-전체를 같게 다루기', Interpreter 는 '문법을 해석하기'

언제 쓰나 — 좁다

  • 적합 — 문법이 단순하고 안정적이다 (규칙 수십 개 이하)

    • 예) 검색 필터 식, 권한 규칙, 수식 계산기
  • 부적합 — 문법이 복잡하다

    • 클래스 수가 규칙 수에 비례해 폭발한다
    • ANTLR·JavaCC 같은 파서 생성기를 쓴다

GoF 23개 중 실무에서 직접 구현하는 일이 가장 드문 패턴이다. 다만 정규식·SQL·SpEL처럼 이미 만들어진 인터프리터를 쓰는 경우는 매우 흔하다.

실무에서

java.util.regex.Pattern       // 정규식 해석
Spring Expression Language    // #{...} 평가
java.text.MessageFormat

면접 함정

  • "복잡한 언어 파싱에 쓴다" → 오히려 복잡하면 파서 생성기를 쓴다.
  • Visitor와 무관하다고 답변 → 구문 트리에 연산을 추가할 때 Visitor를 함께 쓴다.

왜 직접 구현이 드문가

문법 규칙 하나 = 클래스 하나

  • 사칙연산만 해도 Number·Add·Sub·Mul·Div·Paren...

게다가 파싱(문자열 → 트리)은 이 패턴이 다루지 않는다

  • Interpreter 는 '이미 만들어진 트리의 해석' 만 담당한다

그래도 값을 하는 자리

사용자가 규칙을 입력하는 기능

  • 알림 조건식 "금액 > 10000 AND 지역 = '서울'" · 할인 규칙 · 검색 필터

규칙을 하드코딩하면 배포 없이 못 바꾼다 표현식으로 저장해 해석하면 데이터만 바꾸면 된다

대안을 먼저 본다

Spring Expression Language(SpEL) · 규칙 엔진(Drools) · 파서 생성기(ANTLR) 스크립트 엔진(JSR-223) — 다만 임의 코드 실행 위험

보안 주의

사용자 입력을 해석하는 순간 공격면이 생긴다 — 깊은 중첩으로 스택 오버플로, 반복 폭발로 CPU 소진. 깊이 제한·평가 시간 제한·허용 연산 화이트리스트가 필요하다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 행위 패턴 ① — 요청을 객체로 다룬다