카테고리 없음

면접을 위한 cs 전공지식 노트 [디자인 패턴]

mjth1s1s 2025. 2. 5. 21:51

 

[디자인 패턴]

디자인 패턴이란?

프로그램을 설계할 때 발생했던 문제점들을 객체 간 상호관계 등을 이용하여 해결할 수 있도록 하나의 '규약' 형태로 만들어 놓은 것

 

1) 싱글톤 패턴

하나의 클래스에 하나의 인스턴스만 가짐 (ex) 데이터베이스 연결 모듈)

-원래는 하나의 클래스로 여러 인스턴스를 만들 수 있음

 

장점: 하나의 인스턴스만으로 다른 모듈들이 공유하며 사용 -> 인스턴스 생성 비용 감소

단점: TDD의 단위테스트는 서로 독립적이어야하며 테스트를 어떤 순서로든 실행할 수 있어야함.

하지만 싱글톤 패턴은 미리 생성된 하나의 인스턴스를 기반으로 구현하는 패턴이라 각 테스트마다 독립적인 인스턴스 만들기 어려움,

모듈간의 결합을 강하게 만들어 의존성 높아짐

a) Node.js에서 MongoDB 연결할때 mongoose 모듈의 connect() 함수는 싱글톤 인스턴스 반환

b) Node.js에서 MySQL 연결할때 

 

의존성 주입

높은 의존성에 대한 해결법.

장점: 의존성 주입을 통해 모듈 간 결합 느슨하게 만들기 (디커플링) -> 모듈들을 쉽게 교체할 수 있어 테스팅, 마이그레이션 쉬움.

단점: 모듈들이 더욱 분리되어 클래스 수 늘어나고 복잡성 증가

원칙: "상위 모듈은 하위모듈에서 어떠한 것도 가져오면 안됨, 추상화에 의존해야됨, 추상화는 세부사항에 의존하지 말아야됨"

 

 

2) 팩토리 패턴

객체를 사용하는 코드에서 객체 생성 부분을 떼어내 추상화한 패턴.

상속관계에 있는 두 클래스에서 상위 클래스가 뼈대를 결정, 하위 클래스에서 구체적인 내용 결정

 

상위클래스와 하위클래스가 분리 -> 느슨한 결합

상위클래스에서 인스턴스 생성 방식을 알필요 없음 -> 유연성 증가

객체 생성 로직이 따로 떼어져 있음 -> 리팩토링시 한곳만 고치면 돼서 유지보수성 증가

 

의존성 주입이라고도 볼 수 있음 -> 상위클래스에서 하위인스턴스 생성하지 않고 하위클래스에서 생성한 인스턴스를 상위클래스에 주입.

*static 키워드로 정의하면 클래스 기반으로 객체 만들지 않고 바로 호출 가능, 해당 메서드에 대한 메모리 할당을 한번만 가능

 

 

3) 전략 패턴

객체의 행위를 바꾸고 싶은 경우 '직접' 수정하지 않고 전략을 컨텍스트 안에서 바꿔주면서 상호 교체가 가능하게 만드는 패턴

(ex) 네이버페이, 카카오페이 등 다양한 방법으로 결제 / passport의 전략 패턴)

 

예시 결제 코드)

 

interface PaymentStrategy {

    public void pay(int amount)

}

 

class KAKAOCardStrategy implements PaymentStrategy {}

 

*passport 는 Node.js 에서 인증 모듈을 구현할때 쓰는 미들웨어 라이브러리로, 여러가지 '전략'을 기반으로 인증할 수 있게 함

서비스 내의 회원가입된 아이디, 비번을 기반으로 인증하는 LocalStrategy 전략 / 페북, 네이버 등 다른 서비스를 기반으로 인증하는 OAuth 전략 지원

 

 

4. 옵저버 패턴

주체가 어떤 객체의 상태 변화를 관찰하다가 상태 변화가 있을 때마다 메서드 등을 통해 옵저버들에게 변화를 알려주는 디자인 패턴.

(ex) 트위터 등 이벤트 기반 시스템)

 

주체: 객체의 상태 변화를 보고 있는 관찰자 

옵저버: 이 객체의 상태 변화에 따라 전달되는 메서드를 기반으로 '추가 변화 사항'이 생기는 객체들

 

옵저버 패턴 구조(MVC 패턴에도 쓰임)

Model(주체) <- Controller <- View(옵저버)

모델에서 변경사항이 생겨 update() 로 옵저버인 뷰에게 알려주고 이를 기반으로 컨트롤러가 작동

 

상속 vs 구현

- 상속: 자식 클래스가 부모 클래스의 메서드 등을 상속받아 사용하며 자식 클래스에서 추가 및 확장을 할 수 있는 것

일반 클래스, abstract 클래스를 기반으로 구현

- 구현: 부모 인터페이스를 자식 클래스에서 재정의하여 구현하는 것. 꼭 부모 클래스의 메서드를 재정의하여 구현해야함

인터페이스를 기반으로 구현

 

*js에서의 옵저버 패턴은 프록시 객체를 통해 구현할 수도 있음

프록시 객체

어떠한 대상의 기본적인 동작의 작업을 가로챌 수 있는 객체, target, handler 두개의 매개변수 가짐

target: 프록시할 대상

handler: target 동작을 가로채고 어떠한 동작을 할 것인지 설정돼있는 함수

프록시 객체의 get()은 속성과 함수에 대한 접근 가로챔, set()은 속성에 대한 접근 가로챔

 

 

5. 프록시 패턴

대상 객체에 접근하기 전 그 접근에 대한 흐름을 가로채 대상 객체 앞단의 인터페이스 역할을 하는 디자인 패턴

프록시 서버: 서버와 클라이언트 사이에서 클라이언트가 자신을 통해 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해주는 시스템, 응용 프로그램 (ex) nginx, CloudFlare)

 

CloudFlare의 역할

 

1) DDOS 공격 방어

짧은 기간 동안 네트워크에 많은 요청을 보내 네트워크를 마비시켜 웹 사이트의 가용성을 방해하는 사이버 공격 유형 -> CloudFlare를 통해 DDOS 공격으로부터 보호함

2) HTTPS 구축

서버에서 HTTPS를 구축할때 인증서를 기반으로 구축할 수 있는데 CloudFlare를 쓰면 별도의 인증서 설치 없이 손쉽게 구축 가능

 

CORS

서버가 웹 브라우저에서 리소스를 로드할때 다른 출처를 통해 로드하지 못하게 하는 HTTPS 헤어 기반 메커니즘

프론트엔드 서버가 백엔드 서버와 통신할때 CORS 에러 자주 마주침 -> 해결 위해 프론트엔드에서 프록시 서버 만듦

 

클라이언트는 기본적으로 127.0.0.1:3000라는 프론트엔드 서버에 요청을 보내는데 실제 데이터는 백엔드 서버 (127.0.0.1:12100)에 있음

프록시가 없으면 브라우저가 포트가 다른 서버 (127.0.0.1:12100)로의 요청을 차단함

-> 프록시 서버가 요청의 도메인을 변경함 -> 클라이언트 요청을 127.0.0.1:12100로 전달함 -> 클라이언트는 모든 요청이 동일한 포트에서 발생하는 것처럼 보이게 됨

 

 

6) 이터레이터 패턴

이터레이터를 사용하여 컬렉션의 요소들에 접근하는 디자인 패턴.

이를 통해 순회할 수 있는 여러 가지 자료형의 구조와는 상관없이 이터레이터라는 하나의 인터페이스로 순회 가능

 

 

7) 노출모듈 패턴

즉시 실행 함수를 통해 private, public과 같은 접근 제어자를 만드는 패턴

선언은 됐지만 반환되는 객체에 포함되지 않아 내부에서만 접근 가능함

 

private: 클래스에 정의된 함수에서 접근 가능하지만 자식 클래스와 외부 클래스에서 접근 불가능한 범위

protected: 클래스에 정의된 함수, 자식 클래스에서 접근 가능하지만 외부 클래스에서 접근 불가능한 범위

public: 클래스에 정의된 함수에서 접근 가능하며 자식 클래스와 외부 클래스에서 접근 가능한 범위

즉시실행함수: 함수를 정의하자마자 바로 호출하는 함수

 

 

8) MVC 패턴

모델, 뷰, 컨트롤러로 이루어진 디자인패턴

 

모델: 애플리케이션의 데이터인 데이터베이스, 상수, 변수 등

뷰에서 데이터를 생성 및 수정하면 컨트롤러를 통해 모델 생성 및 갱신

뷰: 사용자 인터페이스 요소. 모데을 기반으로 사용자가 보는 화면.

변경이 일어나면 컨트롤러에 이를 전달

컨트롤러: 하나 이상의 모델과 하나 이상의 뷰를 잇는 다리 역할, 이벤트 등 메인 로직 담당.

모델과 뷰의 변경 통지 받으면 이를 해석하여 각 요소에 해당 내용 알려줌

 

 

9) MVP 패턴

MVC 패턴에서 컨트롤러가 프레젠터로 교체된 패턴

뷰와 프레젠터는 일대일 관계 -> MVC보다 강한 결합

 

10) MVVM 패턴

MVC의 컨트롤러가 뷰모델로 바뀐 패턴

뷰와 뷰모델 사이에 양방향으로 데이터 바인딩과 커맨드

 

뷰모델: 뷰를 더 추상화한 계층 .UI를 별도의 코드 수정 없이 재사용할 수 있고 단위테스팅하기 쉬움

커맨드: 여러 가지 요소에 대한 처리를 하나의 액션으로 처리할 수 있게 하는 기법

데이터 바인딩: 화면에 보이는 데이터와 웹 브라우저의 메모리 데이터 일치시키는 기법, 뷰모델을 변경하면 뷰가 변경됨

 

 

 

[프로그래밍 패러다임]

 

프로그래밍 패러다임이란?

프로그래머에게 프로그래밍의 관점을 갖게 해주는 역할을 하는 개발 방법론

 

1) 선언형

-함수형

2) 명령형

- 객체지향형

- 절차지향형

 

선언형 프로그래밍

무엇을 풀어내는가에 집중하는 패러다임. 프로그램은 함수로 이루어진 것이다

함수형 프로그래밍은 '순수함수'들을 쌓아 로직을 만들고 '고차함수'를 통해 재사용성을 높인 패러다임

 

*순수함수: 출력이 입력에만 의존하는 것 (함수내의 매개변수 a,b 에만 영향을 받음. 만약 a,b 이외의 전역 변수가 출력에 영향을 주면 순수함수가 아님

*고차함수: 함수가 함수를 값처럼 매개변수로 받아 로직을 생성할 수 있는 것

 

**일급객체여야 함!

-> 변수나 메서드에 함수 할당 가능

-> 함수 안에 함수를 매개변수로 담을 수 있음

-> 함수가 함수를 반환할 수 있음

 

 

객체지향 프로그래밍

 

객체들의 집합으로 프로그래밍의 상호 작용을 표현하며 데이터를 객체로 취급하여 객체 내부에 선언된 메서드를 활용하는 방식

단점: 설계에 시간소요 큼, 처리 속도가 다른 패러다임에 비해 느림

1) 추상화

-복잡한 시스템으로부터 핵심적인 개념이나 기능을 간추려내는 것

2) 캡슐화

- 객체의 속성과 메서드를 하나로 묶고 일부를 외부에 감추어 은닉하는 것

3) 상속성

- 상위 클래스의 특성을 하위 클래스가 이어받아서 재사용, 추가, 확장하는 것

4) 다형성

- 하나의 메서드나 클래스가 다양한 방법으로 동작하는 것

(ex) 오버로딩, 오버라이딩)

 

설계원칙

SOLID 원칙을 지켜야함

 

S 단일 책임 원칙

모든 클래스는 각각 하나의 책임만 가져야됨

 

O 개방-폐쇄 원칙

코드를 쉽게 확장할 수 있되 수정할 때는 닫혀있어야됨

 

L 리스코프 치환 원칙

객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야됨. 부모-자식 계층관계가 만들어질때 부모 객체에 자식 객체를 넣어도 시스템이 문제없이 돌아가야됨

 

I 인터페이스 분리 원칙

하나의 일반적인 인터페이스보다 구체적인 여러개의 인터페이스를 만들어야 함

 

D 의존 역전 원칙

자신보다 변하기 쉬운 것에 의존하던 것을 추상화된 인터페이스나 상위 클래스를 두어 변하기 쉬운 것의 변화에 영향받지 않게 하는 것

상위계층은 하위계층의 변화에 대해 독립해야됨

 

절차형 프로그래밍

수행되어야 하는 연속적인 계산 과정으로 이루어져있음

장점: 코드의 가독성이 좋고 실행속도가 빠름

(ex) 포트란을 이용한 대기 과학 관련 연산 작업, 머신 러닝의 배치 작업)

단점: 모듈화하기 어렵고 유지보수성 떨어짐