노트

책임 연쇄 패턴

Chain of Responsibility

설계#pattern · 연결된 개념 6개

쉽게 말하면

책임 연쇄 패턴은 공항 출국 심사처럼 여러 창구를 차례로 거치게 하는 거예요. 창구마다 통과시키거나 그 자리에서 돌려보내니까, 요청을 보내는 쪽은 누가 처리할지 몰라도 돼요.

비유가 깨지는 곳 공항은 순서가 정해져 있지만 코드에서는 처리자 순서를 직접 맞춰야 해요. 인증보다 권한 검사가 먼저 오면 안 되고, 아무도 처리하지 않을 수 있으니 사슬 끝에 실패 처리를 둬요.

요청을 처리할 수 있는 처리자들을 사슬로 잇고, 각 처리자가 직접 처리하거나 다음 처리자에게 넘기게 하는 패턴. 요청을 보내는 쪽은 누가 처리할지 몰라도 된다.

type Handler = (req: Req, next: () => Res) => Res
 
const auth: Handler = (req, next) => (req.user ? next() : { status: 401 })
const rateLimit: Handler = (req, next) => (tooMany(req) ? { status: 429 } : next())
 
function chain(handlers: Handler[], final: (req: Req) => Res) {
  return (req: Req): Res => {
    const call = (i: number): Res => (i < handlers.length ? handlers[i](req, () => call(i + 1)) : final(req))
    return call(0)
  }
}
  • 웹 프레임워크의 미들웨어(Middleware)가 대표적이다. 인증, 권한, 로깅, 요청 제한을 순서대로 거친다. 스프링 시큐리티의 시큐리티 필터체인, 장고의 Django 미들웨어와 로그인 흐름, Express·NestJS의 미들웨어(NestJS)가 모두 이 구조다
  • 처리자를 추가·제거·재배치하기 쉽다
  • 순서가 중요하다. 인증보다 권한 검사가 먼저 오면 안 된다
  • 아무도 처리하지 않을 수 있으니, 반드시 처리되어야 하는 요청이라면 사슬 끝에 실패 처리를 명확히 둔다
  • 흐름이 사슬 전체에 흩어져 있어 어디서 요청이 멈췄는지 추적하기 어렵다. 처리자마다 로그를 남기면 도움이 된다

DOM 이벤트가 요소 트리를 따라 위로 올라가며 처리될 기회를 주는 버블링(Event Bubbling)도 비슷한 모양이다(이벤트 버블링·캡처링과 위임). 요청 제한 처리자의 예는 요청 제한 (Throttling). 행동 패턴 전체는 행동 패턴.

출처: Chain of Responsibility — Refactoring.Guru

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 커맨드 패턴

    요청이나 작업을 실행 가능한 객체로 포장하는 패턴. 작업을 값처럼 저장·전달·대기열에 넣을 수 있게 되고, 되돌리기 같은 부가 연산을 붙일 수 있다.

  • 상태 패턴

    객체의 행동이 현재 상태에 따라 달라질 때, 상태마다 별도 객체를 두고 현재 상태 객체에 행동을 맡기는 패턴. 상태별 조건문이 메서드마다 반복되는 문제를 푼다.

  • Spring MVC 요청 흐름

    Spring MVC는 모든 HTTP 요청을 DispatcherServlet 하나가 받아, 알맞은 컨트롤러 메서드로 보내고 결과를 응답으로 바꾸는 프런트 컨트롤러(Front Controller) 구조다. 스프링 이전에는 URL마다 서블릿을 직접 만들고 매핑했다.

  • 퍼사드 패턴

    복잡한 하위 시스템 앞에 단순한 창구 하나를 세워, 호출자가 내부의 여러 객체와 호출 순서를 몰라도 되게 하는 패턴.

  • DRF 인증과 권한

    DRF는 요청 처리를 두 단계로 나눈다. 인증 클래스(authentication class)는 요청을 보낸 사용자가 누구인지 식별해 request.user·request.auth를 채우기만 하고, 권한 클래스(permission class)가 그 사용자에게 이 요청을 허용할지 결정한다. 인증만으로는 요청이 막히지 않는다(authn-authz).

보기 옵션