μ±…μž„ 연쇄 νŒ¨ν„΄ (chain of responsibility pattern)

2024. 7. 5. 15:01Β·πŸ“‚ programming-language/java

1. μ±…μž„ 연쇄 νŒ¨ν„΄(Chain of Responsibility pattern)

μ±…μž„ 연쇄 νŒ¨ν„΄μ€ ν•Έλ“€λŸ¬λ“€μ˜ 체인(μ‚¬μŠ¬)을 따라 μš”μ²­μ„ 전달할 수 있게 ν•΄μ£ΌλŠ” 행동 λ””μžμΈ νŒ¨ν„΄μ΄λ‹€. 각 ν•Έλ“€λŸ¬λŠ” μš”μ²­μ„ λ°›μœΌλ©΄ μš”μ²­μ„ μ²˜λ¦¬ν• μ§€ λ˜λŠ” 체인의 λ‹€μŒ ν•Έλ“€λŸ¬λ‘œ 전달할지 κ²°μ •ν•œλ‹€.

 

μ±…μž„ 연쇄 νŒ¨ν„΄μ„ μ‚¬μš©ν•˜λ©΄ SRP λ₯Ό 지킬 수 μžˆλ‹€. SRP λŠ” κ°μ²΄λŠ” 단 ν•˜λ‚˜μ˜ μ±…μž„μ„ κ°€μ Έμ•Ό ν•œλ‹€λŠ” 원칙이닀. 즉, λ³€κ²½λ˜μ–΄μ•Ό ν•  이유 λ˜ν•œ ν•œκ°€μ§€μ—¬μ•Ό ν•œλ‹€λŠ” μ˜λ―Έμ΄λ‹€. μ±…μž„ 연쇄 νŒ¨ν„΄μ„ μ‚¬μš©ν•˜λ©΄ 각 ν•Έλ“€λŸ¬μ—κ²Œ μ±…μž„μ„ λ§‘κΈ°κ³  ν•Έλ“€λŸ¬ μ±…μž„ μ™Έμ—λŠ” λ‹€λ₯Έ ν•Έλ“€λŸ¬μ—κ²Œ μœ„μž„ν•˜κΈ° λ•Œλ¬Έμ— SRP λ₯Ό 지킬 수 μžˆλ‹€.

 

μ±…μž„ 연쇄 νŒ¨ν„΄μ€ μš”μ²­μ„ λ³΄λ‚΄λŠ” 주체와 μš”μ²­μ„ μ²˜λ¦¬ν•˜λŠ” 주체λ₯Ό λΆ„λ¦¬ν•˜λŠ” νŒ¨ν„΄μœΌλ‘œ μš”μ²­μ„ λ³΄λ‚΄λŠ” 주체가 μš”μ²­μ„ μ²˜λ¦¬ν•˜λŠ” ν•Έλ“€λŸ¬κ°€ ꡬ체적인 νƒ€μž…μ— 상관없이 λ””μ»€ν”Œλ§ 된 μƒνƒœμ—μ„œ 처리 κ°€λŠ₯ν•˜λ„λ‘ ν•΄μ£ΌλŠ” νŒ¨ν„΄μ΄λ‹€.

sample code : Client

class Main {
	public static void main(String[] args) {
		RequestHandler chainingRequestHandler =
			new RequestHandler(
				new RequestUuidHandler(
					new RequestLoggingHandler(null)));

		final Client client = new Client(chainingRequestHandler);
		client.doWork("hello request");
	}

}

class Client {

	private final RequestHandler requestHandler;

	public Client(final RequestHandler requestHandler) {
		this.requestHandler = requestHandler;
	}

	void doWork(final String request) {
		requestHandler.handle(request);
	}

}

 

sample code : RequestHandler Chaining

// RequestHandler
public class RequestHandler {

	private RequestHandler nextHandler;

	public RequestHandler(RequestHandler nextHandler) {
		this.nextHandler = nextHandler;
	}

	public void handle(String request) {
		nextHandler.handle(request);
	}
}

// RequestLoggingHandler
public class RequestLoggingHandler extends RequestHandler {

	private RequestHandler nextHandler;

	public RequestLoggingHandler(RequestHandler nextHandler) {
		super(nextHandler);
	}

	@Override
	public void handle(final String request) {
		System.out.println("2. request logging start ======================");

		System.out.println("logging request : " + request);

		System.out.println("2. request logging end ======================");
		if (nextHandler == null) {
			return;
		}

		super.handle(request);

	}

}

// RequestUuidHandler
public class RequestUuidHandler extends RequestHandler {

	private RequestHandler nextHandler;

	public RequestUuidHandler(RequestHandler nextHandler) {
		super(nextHandler);
	}

	@Override
	public void handle(final String request) {
		System.out.println("1. request uuid start ======================");

		UUID uuid = UUID.randomUUID();
		System.out.println("request uuid : " + uuid.toString());

		super.handle(request);
		System.out.println("1. request uuid end ======================");
	}
}

 

 

Result

 

2. μ±…μž„ 연쇄 νŒ¨ν„΄μ˜ μž₯단점

μ±…μž„ 연쇄 νŒ¨ν„΄μ˜ μž₯점은 SRP λ₯Ό μ§€ν‚€λ©΄μ„œ κΈ°λŠ₯을 μΆ”κ°€ν•  수 μžˆλ‹€. μƒˆλ‘œμš΄ κΈ°λŠ₯을 μΆ”κ°€ν•˜κ³  싢은 경우 μƒˆλ‘œμš΄ ν•Έλ“€λŸ¬λ₯Ό λ“±λ‘ν•˜κ³  μˆœμ„œλ₯Ό κ²°μ •ν•˜λ©΄ ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œ 변경없이 κΈ°λŠ₯을 μΆ”κ°€ν•  수 μžˆλ‹€.

 

그리고 μš”μ²­μ˜ 처리 μˆœμ„œλ₯Ό μ œμ–΄ν•˜κ³  νŠΉμ • μš”μ²­μ— ν•œν•΄μ„œλ§Œ μ‹€ν–‰ κ°€λŠ₯ν•˜λ„λ‘ 섀정이 κ°€λŠ₯ν•˜λ‹€. ν•˜μ§€λ§Œ νŠΉμ • μš”μ²­μ΄ μ²˜λ¦¬λ˜μ§€ μ•Šμ„ 수 있기 λ•Œλ¬Έμ— μ£Όμ˜ν•΄μ•Ό ν•œλ‹€.

 

단점은 디버깅이 λ²ˆκ±°λ‘­λ‹€. filter chaining 을 ν†΅ν•œ ν•Έλ“€λŸ¬κ°€ μ¦κ°€ν•˜λ©΄ μ›ν•˜λŠ” ν•Έλ“€λŸ¬λ₯Ό μ°ΎκΈ° μœ„ν•΄ 체이닝 λ˜μ–΄ μžˆλŠ” ν•Έλ“€λŸ¬λ₯Ό 탐색해야 ν•˜κΈ° λ•Œλ¬Έμ— λ²ˆκ±°λ‘­λ‹€.

 

3. μ±…μž„ 연쇄 νŒ¨ν„΄ μ˜ˆμ‹œ

μŠ€ν”„λ§ μ‹œνλ¦¬ν‹°μ—μ„œ filter chain λ₯Ό κΈ°λ°˜ν•΄μ„œ 인증, 인가 κΈ°λŠ₯을 μ œκ³΅ν•œλ‹€.

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
	// do something before the rest of the application
	chain.doFilter(request, response); // invoke the rest of the application
	// do something after the rest of the application
}

 

Reference

  • spring security architecture reference : https://docs.spring.io/spring-security/reference/servlet/architecture.html
  • [refactoring.guru] μ±…μž„ 연쇄 νŒ¨ν„΄ : https://refactoring.guru/ko/design-patterns/chain-of-responsibility
  • [inflearn] μ½”λ”©μœΌλ‘œ ν•™μŠ΅ν•˜λŠ” GoF의 λ””μžμΈ νŒ¨ν„΄

'πŸ“‚ programming-language > java' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

νΌμ‚¬λ“œ νŒ¨ν„΄(Facade Pattern)  (0) 2024.07.08
μ»€λ§¨λ“œ νŒ¨ν„΄(command pattern)  (0) 2024.07.08
싱글톀 νŒ¨ν„΄(singleton pattern)  (0) 2024.07.03
μ •λ°€ μ—°μ‚°μ—λŠ” BigDecimal 을 μ‚¬μš©ν•˜μž  (0) 2024.04.24
Garbage Collector simple summary  (0) 2024.03.04
'πŸ“‚ programming-language/java' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€
  • νΌμ‚¬λ“œ νŒ¨ν„΄(Facade Pattern)
  • μ»€λ§¨λ“œ νŒ¨ν„΄(command pattern)
  • 싱글톀 νŒ¨ν„΄(singleton pattern)
  • μ •λ°€ μ—°μ‚°μ—λŠ” BigDecimal 을 μ‚¬μš©ν•˜μž
cooper25
cooper25
  • cooper25
    dev cooper
    cooper25
  • 전체
    였늘
    μ–΄μ œ
    • λΆ„λ₯˜ 전체보기 (84)
      • πŸ“‚ backend (34)
        • spring (19)
        • architecture (10)
        • test (5)
      • πŸ“‚ computer-science (5)
      • πŸ“‚ programming-language (12)
        • java (12)
      • πŸ“‚ infra (9)
        • mysql (4)
        • redis (2)
        • message-queue (3)
      • πŸ“‚ cloud (2)
        • aws (2)
      • πŸ“‚ frontend (1)
        • react (0)
      • πŸ“‚ education & lecture (16)
        • 인프라 곡방 (11)
        • ν•­ν”Œ λ°±μ—”λ“œ 7κΈ° (5)
      • πŸ“‚ ai (1)
        • claude (1)
      • πŸ“‚ etc (2)
        • 회고 (1)
        • 컨퍼런슀 (1)
  • λΈ”λ‘œκ·Έ 메뉴

    • ν™ˆ
    • νƒœκ·Έ
    • λ°©λͺ…둝
  • 링크

  • 곡지사항

  • 인기 κΈ€

  • νƒœκ·Έ

    spring-batch
    nGrinder
    react
    ν•­ν•΄ν”ŒλŸ¬μŠ€
    AWS
    회고
    UUID
    Redisson
    JPA
    spring AOP
    가상 λ©΄μ ‘ μ‚¬λ‘€λ‘œ λ°°μš°λŠ” λŒ€κ·œλͺ¨ 섀계
    spring
    spring camp 2025
    gof
    kafka
    λ™μ‹œμ„±
    μŠ€ν”„λ§μΊ ν”„ ν›„κΈ°
    데이터 쀑심 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 섀계
    mysql
    인프라곡방
  • 졜근 λŒ“κΈ€

  • 졜근 κΈ€

  • hELLOΒ· Designed Byμ •μƒμš°.v4.10.6
cooper25
μ±…μž„ 연쇄 νŒ¨ν„΄ (chain of responsibility pattern)
μƒλ‹¨μœΌλ‘œ

ν‹°μŠ€ν† λ¦¬νˆ΄λ°”