디자인 패턴이란 프로그램을 설계할 때 발생했던 문제점들을 객체 간의 상호 관계 등을 이용하여 해결할 수 있도록 하나의 규약 형태로 만들어 놓은 것을 말한다.
-> 객체를 사용할 때 여러 문제들이 발생하는데, 이를 어떤 식으로 설계해서 해결할지에 대한 것을 약솔의 형태로 만들어둔 것이다.
싱글톤 패턴은 하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴이다.
쉽게 말해 하나의 클래스에는 하나의 인스턴스만!! 이런 것이다.
하나의 인스턴스를 만들어놓고, 해당 인스턴스를 다른 모듈들이 공유하는 형태이다.
1) 인스턴스 생성할 때 드는 비용이 줄어든다.
2) 사용하기 쉽다.
1) 의존성이 높아진다.
2) TTD를 할 때 걸림돌이 된다.
-> 이를 할 때 단위 테스트를 하는데, 이때는 테스트가 서로 독립적이어야 하며 어떤 순서로든 실행할 수 있어야 한다.
하지만 하나의 인스턴스를 공유하고 있기 때문에 독리적이라는게 어렵다.
싱글톤 패턴의 대부분의 단점은 의존성(결합)에서 비롯된 것이다.
이 결합을 조금 느슨하게 만들어 줄 수 있는 것이 있는데 그것이 의존성 주입이다.
위의 그림처럼, 기존 싱글톤 패턴은 메인 모듈이 직접 다른 하위 모듈에 대한 의존성을 준다. 하지만 의존성 주입 을 하게 되면 의존성 주입자가 이 부분을 가로채게 된다. 이 덕분에 메인 모듈이 간접 적으로 의존성을 주입하게 됩니다.
이를 통해 메인 모듈(상위 모듈)은 하위 모듈에 대한 의존성이 떨어지게 됩니다. (디커플링 이라고도 함)
이 의존성 주입을 통해 의존성을 떨어뜨려 위에 단점들에 대한 단점을 해소할 수 있다. 그렇다면 장점만 있는가? 위에 나온 싱글톤 디자인의 장점을 떨어뜨릴 수 있다. 자세히 말하면 아래와 같다.
장점
1) 테스팅하기 쉽고 마이그레이션 하기도 수월하다.
2) 애플리케이션 방향이 일관되고 쉽게 추론할 수 있다.
3) 모듈 간에 관계들이 조금 더 명확해진다.
단점
1) 복잡성이 늘어날 수 있다.
-> 모듈들을 분리하기 때문에 클래스 수가 늘어난다.
그렇다면 의존성 주입 너무 좋아보이는데, 이거 계속 쓰면 안되나 이런 생각이 든다.
팩토리 패턴이란, 객체를 사용하는 코드에서 객체 생성 부분을 떼어내 추상화한 패턴이자 상속 관계에 있는 두 클래스에서 상위 클래스가 중요한 뼈대를 결정하고, 하위 클래스에서 객체 생성에 관한 구체적인 내용을 결정하는 패턴이다.
쉽게 말해서 상위 클래스가 전체적인 부분, 상세한 부부은 하위 클래스가 맡는다.
더 쉬운 이해를 위해 예시를 들어보면 커피를 만드는 카페가 있고, 커피를 만들 레시피가 존재하는 느낌이다.
카페가 상위 클래스, 커피 레시피가 하위 클래스이다.
아래 코드를 봐보자.
const 변수 = new Object(값);
Object는 객체를 만드는 카페의 역할을 하며, 값이 어떤 변수냐에 따라 타입이 결정된다. 이 타입 결정하는 부분이 커피 레시피 같은 역할을 하는 것이다.
이는 정책 패턴 (policy pattern) 이라고도 하며, 객체의 행위를 바꾸고 싶은 경우 직접 수정하지 않고 전략이라고 부르는 캡슐화한 알고리즘 을 컨텍스트 안에서 바꿔주면서 상호 교체가 가능하게 만든 패턴이다.
이해가 잘 가지 않는다면 우리가 결제창을 생각해보자. 무언가를 구매할때 어떤 카드로 구매할지 고르게 된다. 이때 코드를 구현해야한다면, 각각의 카드마다 코드를 만드는 것이 아니라, 그 카드 부분 코드를 캡슐화하여 넣다뺏다 할 수 있게 만들어놓은 방식이다.
-> ex) node.js에서 쓰는 passport라이브러리가 그 대표적 예시이다.
이는 주체가 어떤 객체의 상태 변화를 관찰하다가 상태 변화가 있을 때마다 메서드 등을 통해 옵저버 목록에 있는 옵저버들에게 변화를 알려주는 패턴이다.
그 대표적 예시로 트위터가 존재한다. 트위터는 사용자가 트윗을 올리면 그 알림이 팔로우 모두에게 간다. 이때 트윗을 올린 것을 통해 상태 변화가 일어나고 옵저버 목록에 있는 팔로우에게 변화를 알려주는 패턴이라고 생각하면 된다.
프록시 패턴은 대상 객체에 접근하기 전 그 접근에 대한 흐름을 가로채 대상 객체 앞단의 인터페이스 역할을 하는 다지안 패턴이다.
이를 통해 보안, 데이터 검증, 캐싱, 로깅 등에 사용 된다.
프록시 서버는 서버와 클라이언트 사이에 클라이언트가 자신을 통해 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해주는 컴퓨터 시스템이나 응용 프로그램을 가리킨다.
이 대표적인 예시가 Nginx 이다.
Node.js에 대표적인 서버 앞단의 프록시 서버로 이것이 많이 사용된다. 이를 통해 어버 플로우의 취약점을 예방한다. 또한 익명 사용자가 간접적으로 서버에 접근하는 것을 차단하고, 간접적으로 한 단계를 더 거치게 만들어서 보안을 강화할 수 있다.
이뿐만 아니만 CloudFlare에서도 이를 많이 사용한다.
이를 쓰는 이유는 아래와 같다.
DDOS공격 방어
DDOS공격은 짧은 기간 동안 네트워크에 많은 요청을 보내 네트워크를 마비시키는 공격 유형이다 이는 앞단에 프록시 서버를 두어, 이를 자동으로 차단이 가능하게 하였다.
HTTPS구축
서버에서 HTTPS 를 구축할 때 인증서를 기반으로 구축할 수도 있다. 하지만 이를 사용하면 별도의 인증서 설치 없이 손쉽게 HTTPS를 구축할 수 있다.
이는 이터레이터를 사용하여 컬렉션의 요소들에 접근하는 디자인 패턴이다.
쉽게 말하면 여러가지 자료형이 있다하더라도, 하나의 이터레이터를 통해 구동이 가능하게 하는 것을 말합니다.
ex) 예시로 자바스크립트에서 set구조와 map구조 두개를 만들었을때, for문을 통해 똑같은 방법으로 순회가 가능하다. 이렇듯 자료형이 다르더라도 하나의 이터레이터를 통해 요소들에 접근하는 것을 말한다.
이는 즉시 실행함수를 통해 private, public 같은 접근 제어자를 만드는 패턴을 말합니다.
이는 다른 것에 비해 이해가 쉬울 것이다. C++같은 곳에서 클래스를 만들때도 이것이 이용되는 것을 쉽게 확인해볼 수 있다.
자바스크립트 같은 경우에는 이것이 없어서 이 패턴을 쓰고 싶다면 직접 구현한다.
이는 모델(Model), 뷰(View), 컨트롤러(Controller) 로 이루어진 디자인 패턴이다.
애플리케이션을 만들때 구성 요소를 세가지 역할로 구분하여 각각에 집중할 수 있다는 장점이 있다. 하지만 구조가 복잡해질수록 모델과 뷰의 관계가 복잡해질 수 있다.
그렇다면 모델(Model), 뷰(View), 컨트롤러(Controller)란 무엇인가?
쉽게 정리하면 모델-> DATABASE , 뷰 ->FE, 컨트롤러 ->BE 이정도로 생각하면 이해해기 좋을 것 같다.
이는 MVC에서 파생되었으며, C에 해당하는 컨트롤러가 프레젠터로 교체된 패턴이다.
이때 다른점은 뷰와 프레젠터가 일대일 대응이기 때문에 MVC보다 더 강한 결합을 가지고 있다고 볼 수 있다.
이 또한 MVC에서 파생되었으며, C에 해당하는 컨트롤러가 View Model로 바뀐 패턴이다.
여기서 뷰모델이란, 뷰를 더 추상화한 계층이다.
이것이 위와 다른점은 커맨드와 데이터 바인딩을 가지는 것이 특징이다.
뷰와 뷰모델 사이에 양방향 데이터 바인딩을 지원하며, UI를 별도의 코드 수정 없이 재사용할 수 있고, 단위 테스팅이 쉽다는 장점이 있다.
이번 블로깅에선 디자인 패턴이 무엇이며, 어떤 종류가 있는지 간단하게 알아보았다. 최대한 간단하게 적는것에 목표를 두었으며, 이 블로깅에선 넓은 길을 잡고, 더 자세한 설명이 알고 싶다면 각각을 구글링을 통해 공부하기를 추천한다.
위에서처럼 개발을 진행할때 상황에 맞게 쓸 수 있는 여러 다자인 패턴이 있다. 이를 고려하여 개발을 할때 최적의 디자인 패턴을 쓰는 것이 여러 장점을 누릴 수 있을 것이다.
[참고링크]