CHAPTER 1. 디자인 패턴과 프로그래밍 패러다임
SECTION 1. 디자인 패턴
디자인 패턴이란❓
→ 프로그램을 설계할 때 발생했던 문제점들을 객체 간의 상호 관계 등을 이용해 해결할 수 있도록 하나의
‘규약’ 형태로 만들어 놓은 것을 의미한다.
1-1-1. 싱글톤 패턴(Singleton Pattern)
싱글톤 패턴은 하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴이다. 하나의 클래스를 기반으로 여러 개의 개별적인 인스턴스를 만들 수 있지만, 그렇게 하지 않고 하나의 클래스를 기반으로 단 하나의 인스턴스를 만들어 이를 기반으로 로직을 만드는 데 쓰이며, 보통 DB Connection Module에 많이 사용된다. 하나의 인스턴스를 만들어 놓고 해당 인스턴스를 다른 모듈들이 공유하며 사용하기 때문에 인스턴스를 생성할 때 드는 Cost를 절감할 수 있는 장점이 있지만, 의존성이 높아진다는 단점또한 존재한다.
싱글톤 패턴의 단점
→ 싱글톤 패턴은 단위 테스트를 주로 진행하는 TDD(Test Driven Development)를 할 때 걸림돌이 된다. 단위 테스트는 테스트가 서로 독립적이어야 하며 테스트를 어떤 순서로든 실행할 수 있어야 하지만 싱글톤 패턴은 미리 생성된 하나의 인스턴스를 기반으로 구현하는 패턴이므로 각 테스트마다 ‘독립적인’ 인스턴스를 만들기가 어렵다.
의존성 주입
→ 또한, 싱글톤 패턴은 사용하기 쉽고 실용적이지만 모듈 간 결합을 강하게 만들 수 있다는 단점이 있다. 이 단점은 의존성 주입(DI, Dependency Injection)을 통해 모듈 간 결합을 느슨하게 만들어 해결할 수 있다.
앞의 그림처럼 메인 모듈이 ‘직접’ 다른 하위 모듈에 직접 의존성을 주는게 아닌, 중간에 의존성 주입자(Dependency Injector)가 이 부분을 가로채 메인 모듈이 ‘간접’적으로 의존성을 주입하는 방식이다.
이를 통해 메인 모듈(상위 모듈)은 하위 모듈에 대한 의존성이 떨어지게 된다. 이를 ‘디커플링이 된다’라고 말한다.
의존성 주입의 장점
→ 모듈들을 쉽게 교체할 수 있는 구조가 되어 테스팅하기 쉽고 마이그레이션하기도 수월하다. 또한, 구현할 때 추상화 레이어를 넣고 이를 기반으로 구현체를 넣어 주기 때문에 애플리케이션 의존성 방향이 일관되고, 애플리케이션을 쉽게 추론할 수 있으며, 모듈 간의 관계들이 명확해진다.
의존성 주입의 단점
→ 모듈들이 더욱더 분리되므로 클래스 수가 늘어나 복잡성이 증가될 수 있으며 약간의 런타임 패널티가 생길 수 있다.
의존성 주입 원칙
→ 의존성 주입은 “상위 모듈은 하위 모듈에서 어떠한 것도 가져오지 않아야 한다. 또한, 둘 다 추상화에 의존해야 하며, 이때 추상화는 세부 사항에 의존하지 말아야 한다.” 라는 의존성 주입 원칙을 지켜주면서 만들어야 한다.
1-1-2. 팩토리 패턴(Factory Pattern)
팩토리 패턴은 객체 생성 부 분을 떼어내 추상화한 패턴이자 상속 관계에 있는 두 클래스에서 상위 클래스가 중요한 뼈대를 결정하고, 하위 클래스에서 객체 생성에 관한 구체적인 내용을 결정하는 패턴이다.
클래스가 분리되어 있기 때문에 느슨한 결합을 가지며, 유연성을 가지게 된다. 또한 코드를 리팩터링에 대한 유지 보수성이 증가된다.
1-1-3. 전략패턴(Strategy Pattern)
전략 패턴(Strategy Pattern)은 정책 패턴(Policy Pattern)이라고도 불린다. 객체의 전략 및 정책을 변경하고 싶은 경우 ‘직접’ 수정하지 않고 ‘캡슐화한 알고리즘’을 통해 상호 교체가 가능하게 한다.
예를들어, 구매 결제 방식으로 네이버 페이, 카카오 페이 등 여러가지를 선택할 수 있는 것과 같이 결제 방식의 ‘전략’만 바꾸는 것이다.
1-1-4. 옵저버 패턴(Observer Pattern)
옵저버 패턴은 주체가 어떤 객체의 상태 변화를 관찰하다가 상태 변화가 있을 때, 메서드 등을 통해 옵저버 목록에 있는 옵저버들에게 변화를 알려주는 디자인 패턴이다.
여기서 주체란 객체의 상태 변화를 보고 있는 관찰자이며, 옵저버들이란 이 객체의 상태 변화에 따라 전달되는 메서드 등을 기반으로 ‘추가 변화 사항’이 생기는 객체들을 말한다.
또한, 앞의 설명과 다르게 주체와 객체를 따로 두지 않고 하나로 설정하기도 한다. 옵저버 패턴을 활용한 대표적인 서비스로는 트위터가 있다.
또한, 옵저버 패턴은 주로 이벤트 기반 시스템에 사용되며, MVC패턴에도 사용된다. 주체라고 볼 수 있는 Model에 Update가 발생하면, 이를 기반으로 컨트롤러가 작동하는 것이다.
💡 JAVA : 상속과 구현의 차이 → 상속은 일반 클래스, abstract 클래스를 기반으로 구현하며, 구현은 인터페이스(interface)를 기반으로 구현한다.
자바스크립트에서는 Proxy(프록시) 객체를 통해 구현할 수 있다. Target 속성으로 지정되어 있는 것의 변화가 생기면 handler가 실행이 되며, 이 진행 흐름이 옵저버 패턴과 같다.
1-1-5. 프록시 패턴과 프록시 서버
프록시 패턴(Proxy Pattern)은 대상 객체(Subject)에 접근하기 전 흐름을 가로채 대상 객체 앞단의 인터페이스 역할을 하는 디자인 패턴이다.
이를 통해 객체의 속성, 변환등을 보완하며 보안, 데이터 검증, 캐쉬, 로깅등에 사용한다.
💡 프록시 서버에서의 캐싱
→ 불필요하게 원격 서버까지 가지 않고 프록시 서버의 캐시를 활용해 트래픽을 줄일 수 있다.
프록시 서버
→ 프록시 서버는 클라이언트와 서버 사이에서 클라이언트가 자신을 통해 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해주는 것을 말한다.
프록시 서버를 사용함으로써 실제 서버의 직접적인 접근을 막을 수 있어 보안적으로 좋다. 또한 중간에서 정적자원을 gzip 압축하거나, 로깅을 할 수 있다.
CloudFlare
→ CloudFlare는 전 세계적으로 분산된 서버가 있고, 이를 통해 콘텐츠 전달을 빠르게 할 수 있는 CDN 서비스이다.
또한, Proxy 서버로도 사용이 가능한데, 의심스러운 트래픽인지 먼저 판별해주는 CAPTCHA등을 기반으로 DDOS 공격으로 방어가 가능하다.
CORS(Cross-Origin Resource Sharing)
→ 서버가 웹 브라우저에서 리소스를 로드할 때 다른 오리진을 통해 로드하지 못하게 하는 HTTP 헤더 기반 메커니즘이다.
프론트엔드 서버 앞단에 프록시 서버를 놓으면 자연스레 CORS문제를 해결 할 수 있다.
1-1-6. 이터레이터 패턴
이터레이터 패턴(Iterator Pattern)을 사용하여 컬렉션의 요소들에 접근하는 디자인 패턴이다. 이를 통해 순회할 수 있는 여러 가지 자료형의 구조와는 상관없이 이터레이터라는 하나의 인터페이스로 순회가 가능하다.
JavaScript (ES2015)에서는 이터러블 프로토콜을 준수하는 Array, Map, Set과 같은 객체들에 대해서 for ... of
을 사용하여 순회할 수 있다.
1-1-7. 노출모듈 패턴
노출모듈 패턴은 즉시 실행 함수를 통해 private, public 과 같은 접근 제어자를 만드는 패턴을 말한다. 자바스크립트는 접근 제어자가 존재하지 않고 전역 범위에서 스크립트가 실행되기 때문에 노출 모듈패턴을 사용해서 접근 제어자를 구현할 수 있다.
💡 즉시 실행 함수?
→ 함수를 정의하자마자 바로 호출하는 함수를 말한다. 전역 스코프에 불필요한 변수를 추가해서 오염되는 것을 방지할 수 있고 다른 변수들이 접근하는 것을 막을 수 있다.
1-1-8. MVC 패턴
MVC 패턴은 모델(Model), 뷰(View), 컨트롤러(Controller)로 이루어진 디자인 패턴이다. 애플리케이션의 역할을 나뉘어 개발할 수 있어 재사용성과 확장성이 용이하다는 장점이 있지만, 프로젝트의 규모가 커지면 모델과 뷰의 관계가 복잡해질 수 있다.
컨트롤러(Controller)
→ 하나 이상의 모델과 하나 이상의 뷰를 잇는 다리 역할을 하며 이벤트 등 메인 로직을 담당한다. 또한, 모델과 뷰의 생명주기도 관리하며, 모델이나 뷰의 변경 통지를 받으면 이를 해석해 각각의 구성 요소에 해당 내용에 대해 알려준다.
1-1-9. MVP 패턴
MVP 패턴은 MVC 패턴으로부터 파생되었으며 MVC의 컨트롤러가 프레젠터(Presenter)로 교체된 패턴이다. 뷰와 프레젠터는 일대일 관계이기 때문에 MVC 패턴보다 더 강한 결합을 지닌 패턴이라고 볼 수 있다.
1-1-10. MVVM 패턴
MVVM 패턴은 MVC의 C에 해당하는 컨트롤러가 뷰모델로 바뀐 패턴이다.
MVVM 패턴은 MVC 패턴과는 다르게 데이터 바인딩을 가지는 것이 특징이다. 뷰와 뷰모델 사이의 양방향 데이터를 지원하며 UI를 별도의 수정 없이 재사용할 수 있으며, 단위 테스팅하기 쉽다는 장점이 있다.
SECTION 2. 프로그래밍 패러다임
프로그래밍 패러다임은 프로그래머에게 프로그래밍의 관점을 갖게 해주는 역할을 하는 개발 방법론이다.
1-2-1. 선언형과 함수형 프로그래밍
선언형 프로그래밍이란 ‘무엇을’ 풀어내는가에 집중하는 패러다임이며 함수형 프로그래밍에 속한다.
순수 함수
→ 출력이 입력에만 의존하는 것을 말한다.
const pure = (a, b) => {
return a * b;
}
pure 함수는 들어오는 매개변수 a, b에만 영향을 받는다, 만약 다른 전역 변수 c 등이 이 출력에 영향을 주면 순수함수가 아니다.
고차 함수
→ 고차 함수란 함수가 함수를 값처럼 매개변수로 받아 로직을 생성할 수 있는 것을 말한다.
이때, 고차 함수를 쓰기 위해서는 해당 언어가 일급 객체라는 특징이 있어야한다.
- 변수나 메서드에 함수를 할당할 수 있다.
- 함수 안에 함수를 매개변수로 담을 수 있다.
- 함수가 함수를 반환할 수 있다.
함수형 프로그래밍은 작은 ‘순수 함수’들을 블록처럼 쌓아 로직을 구현하고 ‘고차 함수’를 통해 재사용성을 높인 프로그래밍 패러다임이다. 자바스크립트는 단순하고 유연한 언어이며, 함수가 일급 객체이기 때문에 객체지향 프로그램이 보다는 함수형 프로그래밍이 선호된다.
1-2-2. 객체지향 프로그래밍
객체지향 프로그래밍(OOP, Object-Oriented Programming)은 객체들의 집합으로 프로그램의 상호 작용을 표현하며 데이터를 취급해 객체 내부에 선언된 메서드를 활용하는 방식을 말한다.
객체지향 프로그래밍의 특징
다형성
→ 다형성이란 하나의 메서드나 클래스가 다양한 방법으로 동작하는 것을 말한다, 대표적으로 오버로딩, 오버라이딩이 있다.
오버로딩(Overloading)
→ 같은 이름을 가진 메서드를 여러 개 둔다. 메서드의 타입, 매개변수의 유형, 개수 등으로 여러 개를 둘 수 있으며 컴파일 중 발생하는 ‘정적’ 다형성이다.
오버라이딩(Overriding)
→ 주로 메서드 오버라이딩을 말한다. 상위 클래스로부터 상속받은 메서드를 하위 클래스가 재정의 하는 것을 말한다. 이는 런탕미 중 발생하는 ‘동적’ 다형성이다.
설계원칙
객체지향 프로그래밍을 설계할 때는 SOLID 원칙을 준수해야 한다.
1-2-3. 절차지향 프로그래밍
절차지향 프로그래밍은 로직이 수행되어야 할 연속적인 계산 과정으로 이루어져 있다. 진행되는 방식으로 코드를 구현하기만 하면 되기 때문에 가독성이 좋고 실행 속도가 빠르다는 장점이 있다. 하지만 모듈화 하기 어렵고 유지 보수성이 떨어진다는 단점이 있다.
1-2-4. 패러다임의 혼합
단순히 어떤 패러다임의 옳고 그름을 따지기는 어렵다. 비즈니스 로직이나 서비스의 특징을 고려해서 정하는 것이 좋다.
'IT > IT 도서 리뷰' 카테고리의 다른 글
[면접을 위한 CS 전공지식 노트] - Chapter 02. 네트워크 (0) | 2024.01.02 |
---|