본문 바로가기

Backend/디자인 패턴

(8)
Middleware Pattern (미들웨어 패턴) 저는 주로 Node.JS 를 사용해서 미들웨어라는 게 익숙합니다만, 다른 언어 혹은 프레임워크에서도 미들웨어가 이렇게 적극적으로 쓰이는지는 잘 모르겠습니다. 아무튼 미들웨어는 Node.JS 에서 가장 특징적인 패턴입니다. 미들웨어는 아무래도 Express 에서 용어가 대중화되었고 이 패턴을 적극적으로 사용하고 있지 않나 싶습니다. function(req, res, next) { ... } Express 에서 미들웨어는 위와 같이 생겼습니다. 저기서 req 는 Http request, res 는 Http response 이며 next 는 이 미들웨어가 작업을 완료하고 다음 차례의 미들웨어를 트리거할 때 호출되는 콜백 함수입니다. 미들웨어 함수를 정의할 때 저 next 가 빠져있으면 미들웨어로 간주되지 않아..
Template Pattern (템플릿 패턴) 템플릿 패턴은 알고리즘을 나타내는 부분을 추상 클래스로 캡슐화하는 것으로 구성됩니다. 이 추상클래스의 일부 메서드는 정의되지 않은 채로 남아있으며, 서브 클래스는 이 정의되어있지 않은 메서드를 구현하여 알고리즘의 비어있는 부분을 채울 수 있습니다. import * as fs from 'fs'; abstract class Config { protected data: Record; public read(file: string) { this.data = this.deserialize(fs.readFileSync(file, 'utf-8')); } protected deserialize(data: string): Record { throw new Error(); } public get(key: string): a..
Strategy Pattern (전략 패턴) 전략 패턴이란 이름 그대로 전략을 쉽게 바꿀 수 있는 패턴을 말합니다. 상호 교환 가능한 개별 전략 이라는 객체들로 추상화함으로써 어떤 로직이나, 문제를 해결하는 알고리즘등의 변형을 지원합니다. 이 패턴에 대해서 2가지 예시를 들도록 하겠습니다. import fs from 'fs'; class Config { private jsonData: Record; constructor() { this.jsonData = {}; } getData(key: string): any { return this.jsonData[key]; } readJson(file: string): void { this.jsonData = JSON.parse(fs.readFileSync(file, 'utf-8')); } } const co..
Adapter Pattern (어댑터 패턴) 어댑터 패턴은 다른 인터페이스를 사용해도 대상 객체를 사용할 수 있도록 객체를 약간 조정합니다. 이런 방법으로 다른 인터페이스를 사용해도 객체의 함수에 접근할 수 있도록 합니다. class OurSpec { method1(): void { console.info('method1'); } } interface ShareSpec { method2(): void; } class AdapterSpec implements ShareSpec { private readonly ourSpec: OurSpec; constructor(ourSpec: OurSpec) { this.ourSpec = ourSpec; } method2(): void { this.ourSpec.method1(); } } const spec = n..
Decorator Pattern (데코레이터 패턴) 데코레이터는 기존 객체의 동작을 동적으로 증강시키는 패턴입니다. 상속과의 차이점은 동일한 클래스의 모든 객체에 적용되지 않고 명시적으로 데코레이트한 인스턴스에만 추가되는 것 입니다. 데코레이트 라는 이름처럼 기존 객체를 추가적으로 좀 더 꾸며준다고 보면 쉬울 것 같습니다. 방식은 프록시 패턴과 비슷하게 볼 수 있지만, 객체의 기존 동작을 수정하는 대신 새로운 기능을 추가함으로써 기능을 증가시킵니다. const decorate = (target) => { target.method2 = () => { return 'method2'; }; return target; }; class Subject { method1() { return 'method1'; } } const decoratedSubject = dec..
Proxy Pattern (프록시 패턴) 일반적으로 프록시는 다른 객체에 대한 접근을 제어하는 객체입니다. 여기서 프록시와 다른 객체는 동일한 인터페이스를 가지고 있으며 이를 통해 다른 인터페이스와 호환되도록 바꿔버릴 수도 있습니다. 프록시 패턴은 다른 객체에서 실행될 작업의 전부 혹은 일부를 가로채서 해당 동작을 변경합니다. (이 패턴은 서로게이트 라고도 합니다) 아래는 프록시의 여러 유용한 케이스입니다. Data validation : 프록시가 다른 객체로 입력을 전달하기 전에 데이터 유효성을 검사 Security : 권한을 체크하고 확인되었을 경우에만 프록시가 다른 객체로 요청을 전달 Caching : 프록시가 캐싱을 해 캐싱된 데이터가 없을 경우에만 다른 객체로 작업 전달 Lazy initialization : 필요할 때 까지 다른 객체..
Revealing Constructor Pattern (공개 생성자 패턴) JS 에서 객체를 생성하는 패턴 중 하나인 공개 생성자 패턴은 객체를 생성하는 시점에만 객체 내부의 동작 혹은 상태를 변경할 수 있도록 노출하는 패턴입니다. const promise = new Promise((resolve, reject) => { ... }); JS 에서 공개 생성자의 대표적인 예시는 Promise 입니다. 생성자의 인자로 함수를 받아들이는데 이러한 함수를 executor 라 하고, 객체의 내부 상태를 변경할 수 있는 resolve 와 reject 함수를 외부에 노출합니다. 이렇게 객체를 생성할 때만 resolve 와 reject 에 접근할 수 있고, 객체가 생성된 이후에는 다른 부분에서 resolve 와 reject 를 호출해 객체 내부 상태를 변경할 수 없습니다. const fs ..
Factory Pattern (팩토리 패턴) 팩토리 패턴 예시부터 보겠습니다. const createImage = (name) => { if (name.match(/\.jpeg$/)) { return new Jpeg(name); } else if (name.match(/\.gif$/)) { return new Gif(name); } else if (name.match(/\.png$/)) { return new Png(name); } else { throw new Error('Not supported format'); } }; 누군가가 보기엔 이건 팩토리 패턴이 아니라 그냥 전략 패턴이 아니냐 라고 할 수 있긴 합니다만.. 팩토리 패턴은 이름 그대로 객체를 생성하는 공장으로 받아들이면 심플하며, 객체를 생성하는 책임을 다른 무언가로 분리하는 것입니다..