0. 디자인 패턴
- 라이브러리 : 공통으로 사용될 수 있는 기능들을 모듈화한 것. 규칙 없고 내가 직접 컨트롤하며 사용.
- 프레임워크 : 공통으로 사용될 수 있는 기능들을 모듈화한 것. 규칙 있고 컨트롤되어 있는 것을 사용.
- 디자인 패턴 : 프로그램 설계 시의 문제점들을 해결할 수 있도록 '규약' 형태로 만들어 놓은 것
1. 싱글톤 패턴
- 정의 : 클래스 하나에 인스턴스 하나인 패턴
- 사용 예 : 데이터베이스 연결 모듈에 많이 사용, I/O 바운드(네트워크, DB, file system에 요청) 작업에 많이 사용
- 장점 : 해당 인스턴스를 다른 모듈이 공유하며 사용하므로 인스턴스 생성 비용 감소
- 단점 : 해당 인스턴스에 의존성 높아짐. TDD(Test Driven Development)에 불리함. 단위 테스트할 때 독립적인 인스턴스 생성이 어려움
- 코드 예 :
- Javascript
- 리터럴 {} 또는 new Object 이용
const URL = 'mongodb://localhost:27017/kundolapp'
const createConnection = url => ({"url" : url})
class DB {
constructor(url) {
if (!DB.instance) {
DB.instancee = createConnection(url) //인스턴스가 없을 경우 해당 url의 인스턴스 생성
}
return DB.instance //인스턴스 이미 있을 경우 그냥 그 인스턴스 반환
}
connect() {
return this.instance
}
}
// a와 b는 하나의 DB 인스턴스를 가짐
const a = new DB()
const b = new DB()
console.log( a == b ) // true
- JAVA
- 중첩 클래스 이용
class Singleton {
private static class singleInstanceHolder {
pirvate static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return singleInstanceHolder.INSTANCE;
}
}
public class HelloWorld {
public static void main(String[] args) {
Singleton a = Singleton.getInstance();
Singleton b = Singleton.getInstance();
System.out.println(a.hashCode());
System.out.println(b.hashCode());
if (a == b) {
System.out.println(true);
}
}
}
/*
705927765
705927765
true
*/
- 의존성 주입 = 디커플링
(1) 정의 : 메인 모듈이 직접 의존성을 하위 모듈에 주입(X), 의존성 주입자가 간접적으로 주입(O)
(2) 장점 : 모듈 교체 용이 -> 테스팅, 마이그레이션 쉬움. 모듈 간 관계 구체화
(3) 단점 : 클래스 수 증가. 런타입 패널티 발생
(4) 의존성 주입 원칙 : 상위 모듈은 하위 모듈에서 어떠한 것도 가져오지 않아야 한다. 둘 다 추상화에 의존해야 하며, 추상화는 세부 사항에 의존하지 말아야 한다.
2. 팩토리 패턴
- 정의 : 객체 생성 부분을 떼어내 추상화한 패턴
: 상속 관계의 두 클래스 - 상위 클래스(중요한 뼈대 결정) / 하위 클래스(객체 생성 관련 구체적 내용 결정)
- 사용 예 : 하위 클래스(레시피) / 상위 클래스(레시피를 토대로 하는 생산 공정)
- 장점 : 상속 관계 클래스가 분리되므로 느슨한 결합을 가짐. -> 리팩터링 용이하여 유지 보수성 증가
- 단점 : 클래스 수 증가 / 코드 복잡성 증가 / 객체 생성 로직을 캡슐화하므로, 객체가 어떻게 생성되는지 클라이언트에서 명확히 알기 어려움
- 코드 예
- Javascript
- extends 로 상속 관계 표현
- LattefFactory(하위 클래스)에서 인스턴스를 생성해서 CoffeeFactory(상위 클래스)에 주입
- JAVA
- abstract 으로 Coffee 추상 클래스 생성
- CoffeeFactory(팩토리 클래스) 안에 Coffee 클래스를 상속받는 Latte, Espresso(구체적인 클래스) 객체를 반환하도록 함.
3. 전략 패턴 (= 정책 패턴)
- 정의 : 런타임 중에 캡슐화된 알고리즘(= 전략)을 선택하여 객체 동작을 실시간으로 바뀌도록 할 수 있게 하는 행위 디자인 패턴
- 사용 예 : 추상화된 전략 클래스(결제) / 구체적 전략 클래스(카카오페이, 신용카드 등) / 컨텍스트(쇼핑)
- 장점 : Open/Closed 원칙 준수, 유연한 알고리즘 변경 가능, 클라이언트와 알고리즘 분리됨
- 단점 : 클래스 수 증가, 알고리즘 선택 책임의 클라이언트 전가
- 유의점
- DIP 원칙
- 객체(클래스, 모듈, 함수 등)는 구현된 클래스를 직접 참조하는 것이 아니라 그 대상의 상위 요소(추상 클래스 or 인터페이스)로 참조해야 한다.
- OCP 원칙
- 객체(클래스, 모듈, 함수 등)는 확장에 대해 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 한다
4. 옵저버 패턴
* 옵저버 : 객체의 상태 변화에 따라 추가 변화가 발생하는 객체
- 정의 : 주체가 어떤 객체의 상태 변화를 관찰하다가 상태 변화 있을 때마다 옵저버들에게 변화를 알려주는 패턴
- 사용 예 : SNS(팔로우한 상대의 포스팅에 영향 받는 옵저버), MVC 패턴에 사용됨.
- 장점 : 주체(Subject)와 옵저버(Observer)가 느슨하게 결합 -> 확장성 증가, 주체의 상태 변경이 모든 옵저버에 동기화
- 단점 : 옵저버 추가/삭제를 동적으로 관리해야 하므로 구현이 복잡, 상태 변경 시 모든 옵저버에게 알림을 보내는 과정에서 성능 문제가 발생할 수도 있음
- 코드 예
- 프록시 객체
- 정의 : 어떠한 대상의 기본적인 동작의 작업을 가로챌 수 있는 객체
- 사용 예 : Proxy를 통하면 객체의 속성 값을 설정할 때, 동작을 가로채서 다른 객체가 동작하도록 하여 옵저버 패턴을 구현.
5. 프록시 패턴과 프록시 서버
5-1. 프록시 패턴
* 캐싱 : 캐시 안에 정보를 두고 원격 서버에 접근하지 않고 캐시 안의 데이터를 활용하는 것
- 정의 : 대상 객체에 접근하기 전에 그 접근에 대한 흐름을 가로채서 해당 접근을 필터링 등의 역할 하는 계층이 있는 패턴
- 사용 예 : 보안, 데이터 검증, 캐싱, 로깅 등
- 장점 : 프록시를 통해 실제 객체에 대한 접근을 제어, 객체의 주 기능과 부가적인 작업(로깅, 인증 등)을 분리
- 단점 : 프록시 클래스를 추가로 작성해야 함. 실제 객체에 접근하므로 의존성 증가
5-2. 프록시 서버
- 정의 : 서버와 클라이언트 사이에서 클라이언트가 다른 네트워크 서비스에 간접적으로 접속하게 해주는 서버
- 사용 예 : nginx(Node.js 서버의 프록시 서버로 활용) -> 실제 포트를 숨기고, 정적 자원 압축, 메인 서버 앞단에서의 로깅 가능, : CloudFlare(웹 서버의 프록시 서버) -> DDOS 공격 방어나 HTTPS 구축에 사용
- DDOS 공격 방어
- 짧은 기간 동안 네트워크에 요청을 대량으로 보내서 네트워크를 마비시키는 공격
- CloudFlare 사용 예 : 의심스러운 트래픽 자동 차단, 방화벽 대시보드 제공
- HTTPS 구축
- 보통 인증서 기반 구축
- CloudFlare 사용 예 : 별도의 인증서 설치 없이 HTTPS 구축 가능
- CORS 에러 해소
- SOP(Same Origin Policy) : 서버가 웹 브라우저 리소스 로드할 때 같은 origin끼리만 접근 가능하게 하는 정책
- CORS : 서로 다른 origin 간에도 리소스를 전달할 수 있도록 제어하는 HTTP 헤더 기반 매커니즘
- 프록시 서버 사용 예 : 백엔드 서버와 프론트엔드 서버의 포트 번호가 달라 발생하는 CORS 에러를 프록시 서버를 통해 origin을 변경하여 해소
6. 이터레이터 패턴
- 정의 : 이터레이터를 사용하여 컬렉션 요소들에 접근하는 디자인 패턴. 자료형의 구조와는 상관없이 이터레이터라는 하나의 인터페이스로 순회 가능
- 사용 예 : JAVA (java.util.Iterator)를 통한 요소 순회 등
- 장점 : 컬렉션의 내부 구현을 클라이언트로부터 숨기므로 내부 구조 알 필요 없이 요소에 접근 가능
- 단점 : 단순한 순회를 구현하는 경우 클래스가 많아져 복잡도 증가
7. 노출모듈 패턴
- 정의 : 즉시 실행 함수를 통해 private, public 같은 접근 제어자 만드는 패턴
- 사용 예 : CJS(노출모듈패턴 기반 자바스크립트 모듈) - 접근 제어자가 존재하지 않는 자바스크립트에 접근 제어자 구현
- 장점 : 코드 응집성 향상, private 으로 정보 은닉 가능, 외부에는 필요한 기능만을 노출하여 테스트 용이
- 단점 : 완전한 캡슐화 제공하지 않음, 즉시 실행 함수로 모듈 생성하기 때문에 여러 인스턴스 생성이나 확장 어려움
8. MVC 패턴
- 정의 : 모델(Model), 뷰(View), 컨트롤러(Controller)
- 사용 예 : Spring의 WEB MVC
- 장점 : 재사용성, 확장성 용이
- 단점 : 복잡해수록 모델과 뷰의 관계도 복잡
- 코드 예
- 모델 : 데이터베이스, 상수, 변수 등의 애플리케이션 데이터
- 뷰 : 사용자가 볼 수 있는 화면에 표시하는 정보 포함. 변동 사항 발생 시 컨트롤러에 전달
- 컨트롤러 : 모델 - 뷰의 중간 다리. 메인 로직을 담당
9. MVP 패턴
- 정의 : 모델(Model), 뷰(View), 프레젠터(Presenter)
- 특징 : 뷰 - 프레젠터 (1:1 관계)
10. MVVM 패턴
- 정의 : 모델(Model), 뷰(View), 뷰모델(View Model)
- 특징 : 뷰모델(= 뷰를 더 추상화한 계층). 뷰-뷰모델 사이 커맨드와 양방향 데이터 바인딩 지원.
- 사용 예 : 뷰(Vue.js) - 함수 사용 안하고 값 대입만으로 변수가 변경되며 양방향 바인딩, html 토대의 컴포넌트 구축 가능
- 장점 : 단위 테스팅 용이, 코드 재사용 가능
마무리하며..
각 디자인 패턴들의 차이를 명확히 알지 못했는데 이번 기회에 개념 정리를 제대로 할 수 있어서 좋았고, 앞으로 디자인 패턴을 좀 더 상황에 맞게 사용할 수 있을 것 같아 유익했습니다. 또한, DDOS 공격 유형과 각각을 완화하기 위한 프로세스가 다양해서 이 부분을 좀 더 공부해보고 싶었고(참조), 각각의 패턴을 JAVA, Javascrpit, Node.js 등 어떻게 실제로 구현하는지 좀 더 찾아보고 적용해보는 시간을 가져야겠다고 생각했습니다.
'CS > 면접을 위한 CS 전공지식 노트' 카테고리의 다른 글
[CH2.4] IP 주소 (0) | 2024.12.13 |
---|---|
[CH2.3] 네트워크 기기 (0) | 2024.12.12 |
[CH2.2] TCP/IP 4계층 모델 (0) | 2024.12.11 |
[CH2.1] 네트워크의 기초 (1) | 2024.12.11 |
[CH1.2] 프로그래밍 패러다임 (0) | 2024.12.06 |