1. 다양한 형태의 로그를 파싱할때
온프레미스, SCP, AWS, Azure, GCP 등 다양한 인프라에서 시스템을 운영하는 경우,
하나의 대시보드에서 주요 로그와 metric을 확인하기위해
로그 파싱을 위한 별도의 어플리케이션이 필요하다.
기존에 시스템의 규모가 크지 않을때는 shell 파일, 또는 단일 java 파일로 rule based 로직을 통해 충분히
필터링 후 DB에 데이터를 넣을 수 있었지만, 사용하는 WAS, DB의 종류가 다양해지면서
log의 파싱이 점차 복잡해졌다.
향후 확장성과 코드의 가독성을 고려해 디자인패턴을 도입해 개선하기로 했고 찾아보던 중
책임 연쇄 패턴 (Chain of Responsibility Pattern)을 발견했다.
https://ko.wikipedia.org/wiki/%EC%B1%85%EC%9E%84_%EC%97%B0%EC%87%84_%ED%8C%A8%ED%84%B4
쉽게 생각해보면 try catch 문을 생각하면 된다.
각각의 step 에서 필요한 filtering 로직을 실행할 수 있고, 경우에 따라 filter를 여러개 꼈다 뺏다 할 수 있다.
대략적으로 2가지 효과를 고려했다.
① 각 필터의 디커플링 - 확장성, 독립성 보장 (추가, 수정, 삭제가 용이)
② 클린 코드에 부합 - 필터 로직을 캡슐화할 수 있음
2. CDC 프로그램을 만들때
서비스가 성장하면 시스템과 아키텍처의 복잡도는 증가할수밖에 없다.
이때 다양한 종류의 RDB(Oracle, MariaDB, PostgreSQL 등), NoSQL, Document DB 를 사용할 수 있고
하나의 데이터를 다양한종류의 DB에 Insert 해야할 수 있다.
이 때 책임연쇄패턴을 통해 각 DB에 필요한 filter들을 정의해 데이터를 정제해 Insert할 수 있다.
예를 들면, Oracle에서는 ROWNUM 을 통해 결과의 수를 제한하고, MariaDB와 PostgreSQL은 LIMIT 를 통해 결과의 수를 제한한다.
각각 ROWNUM Filter, LIMIT Filter를 만들어 Handler에서 필요한 Filter를 조합해서 쓰는 경우,
효율적인 코드작성이 가능하다.
3. Java 구현 예시
* 패키지 구조
├── chainofresponsibility
│ ├── FilterChainBuilder.java # filter를 조합하는 빌더
│ ├── FilterChainConfig.java # bean을 만들기위한 설정파일
│ ├── FilterHandler.java # filter 인터페이스
│ ├── impl # 각 기능별 filter
│ │ ├── TrimFilterHandler.java
│ │ ├── SpecialCharactersFilterHandler.java
│ │ ├── ...
* FilterChainBuilder.java
public class FilterChainBuilder {
public static FilterHandler buildChain() {
// Create instances of handlers
FilterHandler trimHandler = new TrimFilterHandler();
FilterHandler specialCharactersHandler = new SpecialCharactersFilterHandler();
// Set the chain of responsibility
trimHandler.setNext(specialCharactersHandler);
return trimHandler;
}
}
* FilterChainConfig.java
@Configuration
public class FilterChainConfig {
@Bean
public FilterHandler filterChain() {
return FilterChainBuilder.buildChain();
}
}
* FilterHandler.java
public interface FilterHandler {
void setNext(FilterHandler handler);
String handle(String input);
}
* TrimFilterHandler.java
public class TrimFilterHandler implements FilterHandler {
private FilterHandler next;
@Override
public void setNext(FilterHandler handler) {
this.next = handler;
}
@Override
public String handle(String input) {
input = input.trim(); // Trim whitespaces
if (next != null) {
return next.handle(input);
}
return input;
}
}
* SpecialCharactersFilterHandler.java
public class SpecialCharactersFilterHandler implements FilterHandler {
private FilterHandler next;
@Override
public void setNext(FilterHandler handler) {
this.next = handler;
}
@Override
public String handle(String input) {
// Remove special characters
input = input.replaceAll("[^a-zA-Z0-9]", "");
if (next != null) {
return next.handle(input);
}
return input;
}
}
'아키텍처 Architecture > Software Architecture' 카테고리의 다른 글
Spring Boot HTTP, HTTPS 모두 사용하기 ( tomcat redirection ) (5) | 2022.02.20 |
---|---|
SpringBoot 무료 SSL 인증서 적용하기 (Certbot) (0) | 2022.02.19 |
금융IT와 MSA - 4. 도커 실습 - github (0) | 2022.01.29 |
금융IT와 MSA - 3. 도커 실습 - 설치&가동 (0) | 2022.01.21 |
금융IT와 MSA - 2. SAGA 패턴 (0) | 2021.12.23 |