[CS 인터뷰 기초] 디자인패턴

Donghun Seol·2023년 3월 13일
1

CS 인터뷰 기초

목록 보기
1/5

1. 디자인 패턴

싱글턴 패턴

개념과 사용 사례

  • 하나의 클래스에 하나의 인스턴스만 가지는 패턴
  • DB 연결과 같이 공유자원을 사용하는 코드에 주로 쓰인다

장단점

  • 인스턴스 생성의 비용이 줄어든다
  • 모듈간 결합이 높아져 독립적인 인스턴스를 구현하기 힘들어 테스트가 어렵다. 이를 해결하기 위해 의존성 주입을 활용할 수 있다.

의존성 주입

개념

  • 먼저 의존성에 대해 파악해야 한다. A가 B에 의존한다면, B가 변경시 A도 변경된다는 것을 의미한다. A ➡️ B
  • 객체지향에서는 메인 모듈과 하위 모듈을 디커플링하는 것이 코드의 확장성과 유지보수성을 높이기 위해 필요하다.
  • A클래스에서 B클래스의 인스턴스 사용시 A클래스 내에서 B클래스의 인스턴스를 직접 생성하는 대신, 의존성을 주입해주는 모듈(의존성 주입자)을 통해 인스턴스를 전달받는 것이다. 추상화된 의존성 주입자를 중간의 매개로 두고, 원래의 A, B 모듈이 모두 의존성 주입자에 의존하게 만든다.
  • 화살표가 뒤바뀐 것을 볼 수 있는데, 이것이 의존관계가 역전되었다고 한다.
  • 따라서 상위 모듈은 하위모듈에서 어떠한 것도 가져오지 않아야하며, 둘 다 추상화(인터페이스)에 의존해야 한다. 이때, 추상화는 세부 사항에 의존하지 말아야 한다.

장점

  • 모듈들을 외부에서 주입하므로 쉽게 교체 가능하다.
  • 단위 테스팅과 마이그레이션이 쉬워진다.
  • 애플리케이션 의존성 방향이 일관되어 코드를 추론하기 쉬워진다.

단점

  • 모듈들이 분리되어 클래스 수가 많아지고 복잡해진다.
  • 참조관계의 증가로 약간의 성능하락이 생길 수 있다.

팩토리 패턴

개념

  • 객체를 사용하는 코드에서 생성 부분을 분리하여 추상화한 패턴이다. 상위 클래스에서 중요한 뼈대를 결정하고, 하위 클래스에서 구체적인 내용을 결정한다.
  • 추상화 계층을 도입하여 하위 클래스에서 어떤 구체적인 객체가 생성되는지 알지 못하더라도 일관된 방식으로 객체를 사용가능하다

장단점

  • 객체 생성을 캡슐화하기 때문에, 코드의 유연성과 확장성을 높일 수 있습니다. 즉, 객체 생성 로직의 변경이 필요할 때, 변경이 필요한 부분만 수정하면 되기 때문입니다.
  • 코드의 중복을 줄일 수 있습니다. 객체 생성 로직을 중복해서 사용하지 않고, 팩토리 메서드를 사용하여 한 곳에서 관리하기 때문입니다.
  • 초기 구현비용이 높고, 추가적인 클래스 사용으로 코드의 복잡성이 증가할 수 있다.

사용 예시

  • 데이터베이스 연결 객체 생성
  • 게임 캐릭터 생성

전략 패턴

개념

  • 객체의 행위를 바꿀 때, 객체를 직접 수정하지 않고 캡슐화된 알고리즘을 바꿔주면서 상호 교체가 가능하도록 하는 패턴
  • 컨텍스트 객체에 전략객체를 탑재해 활용한다.

장단점

  • 알고리즘을 동적으로 바꿀 수 있어 유연하고 코드 재사용성이 높아진다.
  • 개방-폐쇄 원칙을 효과적으로 구현한 디자인 패턴이다.
  • 전략 객체를 생성하고 관리하기 위한 비용이 추가된다.

사용 사례

  • 다양한 정렬 알고리즘을 선택하는 정렬클래스
  • 신용카드, 페이팔, 계좌이체등을 전략객체로 구현해서 이를 활용하는 컨텍스트 객체를 활용한다.

옵저버 패턴

개념

  • 주체가 객체의 변화를 관찰하다가 상태변화가 있을 때 마다 옵저버들에게 변화를 알려주는 디자인 패턴. 주체와 객체를 동일하게 구현하기도 한다.
  • 주로 이벤트 기반 시스템에 사용되며 MVC 패턴에도 사용된다. 주체이자 객체인 Model이 변경되면 옵저버인 View에 이를 알려줘 화면을 렌더링하는 방식이다.

장단점

  • 주체와 옵저버간의 의존성이 줄어들어 유지보수와 확장성이 향상된다.
  • 이벤트 기반으로 이벤트가 발생할 때 마다 즉시 처리되므로, 성능과 반응성이 향상된다.
  • 순서보장이 되지 않고, 옵저버 객체가 많아지면 성능상 오버헤드가 발생할 수 있다.
  • 주체와 옵저버 객체간의 참조가 끊어지지 않으면 메모리 누수발생도 가능하다.

사용 예시

  • 자바스크립트 DOM 이벤트 핸들링
  • React, Vue 등에서의 데이터 바인딩. 데이터의 변경을 감지하여, 해당 변경 사항을 화면에 자동으로 반영하는 것을 말합니다.

코드

아래 자바스크립트 내장 객체인 프록시 객체의 get()함수는 속성과 함수에 대한 기본 접근을 가로채고, set()함수는 속성에 대한 변경을 가로챈다.

function createReactiveObject(target, callback) {
  const proxy = new Proxy(target, {
    set(obj, prop, value) {
      if (value !== obj[prop]) {
        const prev = obj[prop];
        obj[prop] = value;
        callback(`${prop}가 [${prev}] >> [${value}]로 변경되었습니다.`);
      }
      return true;
    },
  });
  return proxy;
}

const a = {
  jack: 'solo',
};

const b = createReactiveObject(a, console.log);
b.jack = 'solo';
b.jack = 'double';
b.jack = 'triple;';

PUB/SUB 패턴

개념

  • 메시지 발행자, 토픽, 구독자로 이루어진 디자인 패턴.
  • 발행자는 특정 토픽을 선택하고 토픽으로 메시지를 발행한다. 만약 해당 토픽에 구독자가 있으면 메시지를 전달받는다.

장단점

  • 컴포넌트간 의존성이 감소하여 코드의 유지보수성과 확장성이 향상된다.
  • 메시지의 전달이 보장되지 않으므로 누락이나 중복처리 문제를 해결해야 할 수도 있다.

사용 예시

  • 분산시스템에서 메시지큐를 활용해서 구현된다.
  • 확장성과 유연성이 뛰어나 많은 분산시스템에서 활용된다.

옵저버 패턴과 Pub/Sub 패턴의 차이점

Pub/Sub 모델과 옵저버 패턴은 비슷한 목적을 가지고 있지만, 몇 가지 차이점이 있습니다.

먼저, Pub/Sub 모델은 메시지 중심의 패턴으로, 메시지 발행자는 메시지를 발행하는 동시에, 누가 그 메시지를 받을지 신경쓰지 않습니다. 즉, 발행자와 구독자가 서로에 대해 알 필요가 없습니다. 이에 비해 옵저버 패턴은 객체 간의 의존성을 강화시키는 객체지향적인 패턴으로, 주체(Subject)와 옵저버(Observer) 객체가 서로에 대해 알고 있습니다.

두 번째로, Pub/Sub 모델은 하나의 발행자가 여러 개의 구독자에게 메시지를 보낼 수 있습니다. 이와 달리, 옵저버 패턴은 주체 객체가 옵저버 객체들에게 한 번에 하나의 메시지만 보낼 수 있습니다.

세 번째로, Pub/Sub 모델은 토픽(Topic)이라는 개념을 사용하여 발행자와 구독자를 연결합니다. 이에 비해 옵저버 패턴은 주체 객체와 옵저버 객체 간의 직접적인 연결을 사용합니다.

마지막으로, Pub/Sub 모델은 비동기적으로 동작하며, 발행자는 메시지를 발행하고 바로 다른 작업을 수행할 수 있습니다. 그리고 구독자가 메시지를 처리할 준비가 되면, 해당 메시지를 받아 처리합니다. 이에 비해 옵저버 패턴은 동기적으로 동작하며, 주체 객체는 옵저버 객체들이 메시지를 처리할 때까지 기다려야 합니다.

요약하자면, Pub/Sub 모델은 느슨한 결합(Loose Coupling)을 가지며, 비동기적으로 동작하며, 하나의 발행자가 여러 개의 구독자에게 메시지를 보낼 수 있습니다. 이와 달리, 옵저버 패턴은 강한 결합(Tight Coupling)을 가지며, 동기적으로 동작하며, 주체 객체는 옵저버 객체들에게 한 번에 하나의 메시지만 보낼 수 있습니다.

프록시 패턴

개념

  • 프록시 패턴은 대상 객체에 접근하기 전 접근에 대한 흐름을 가로채 앞단의 인터페이스 역할을 하는 디자인 패턴으로 원본에 여러가지 기능을 추가해 준다.
  • 보안, 데이터 검증, 캐싱, 로깅에 활용한다.

장단점

  • 보안성, 느린 객체에 대한 대처, 코드 간소화의 장점이 있다.
  • 성능저하, 복잡성의 증가, 디버깅이 어려워지는 단점이 있다.

프록시 서버

Node.js 서버의 모범 구축패턴

  • Node.js 서버 앞단에 nginx를 프록시 서버를 배치하는 것이 일반적이다.
  • 이를 통해 버퍼오버플로우 공격을 방어하고, 정적 자원을 압축하여 성능을 향상시킬 수 있으며 서버 앞단에서 로깅도 가능하다.

CloudFlare CDN 서버 활용

  • DDoS 공격 방어 가능
  • 인증서 없이 HTTPS 구축 가능

이터레이터 패턴

개념

  • 이터레이터를 활용하여 컬렉션의 요소들에 접근하는 디자인 패턴
  • 이터러블한 객체는 요소들의 자료형과 관계없이 이터레이터 프로토콜을 활용해서 순회할 수 있다.
  • 자바스크립트의 for a of b

노출모듈 패턴

개념

  • 즉시 실행 함수를 통해 private, public 같은 접근 제어자를 만드는 패턴이다. 자바스크립트는 접근제어자가 없으므로 노출모듈 패턴을 통해 접근제어자를 억지로 구현한다.

사용 사례

const pukuba = (() => {
    const a = 1
    const b = () => 2
    const public = {
        c : 2, 
        d : () => 3
    }
    return public
})()
console.log(pukuba)
console.log(pukuba.a)
// { c: 2, d: [Function: d] }
// undefined

MVC 패턴

profile
I'm going from failure to failure without losing enthusiasm

0개의 댓글