1. 디자인 패턴과 프로그래밍 패러다임 - 1. 디자인 패턴

jiji·2023년 11월 23일
0

CS 전공지식 노트

목록 보기
4/12

용어

공통으로 사용될 수 있는 특정한 기능들을 모듈화 한 것

  • 라이브러리 : 폴더, 파일명의 규칙이 없고 프레임워크에 비해 자유로움.
    ex) 도구인 가위를 사용해 '내가 직접' 컨트롤
  • 프레임워크 : 폴더, 파일명에 규칙이 있다.
    ex) 도구인 비행기를 타고 이동하지만 '비행기가 컨트롤하고' 나는 가만이 앉아 있다

디자인 패턴

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

Is using design patterns always a good idea?
디자인패턴은 문제해결에 대한 이점을 제공하는 것으로 알려져 있다. 하지만 과도하게 사용하면 부작용이 있을 수 있다.
따라서 개발자는 디자인패턴을 사용하는 것이 프로젝트에 효율적이고 적절한지 고려하고 대안적인 솔루션을 찾아 디자인패턴과 비교해야 한다. 디자인패턴을 채택하기 전에 디자인패턴의 고유한 제약 조건과 절충안을 이해하는 것이 중요하다.

👤 싱글톤 패턴

객체의 인스턴스를 오직 하나만 생성하는 것
ex1. 데이터베이스 연결 모듈
ex2. Setting을 관리하는 클래스 (다크모드를 설정하면, 모든 페이지에 다크모드가 적용되어야 함)

객체 인스턴스를 어디서든지 액세스 할 수 있게 만들 수 있습니다. (하나의 인스턴스를 다른 모듈들이 공유하며 사용)

비용 절감 BUT 의존성 상승

HOW?

생성자를 private으로 변경 -> 다른 클래스에서 new로 생성할 수 없게 된다
클래스 안에 자신의 타입을 갖는 객체를 선언한다
static 아닌 변수는 객체가 생성될 때마다 동적공간에 메모리가 할당되지만, static 변수는 메모리가 지정된 정적 공간에 딱 하나만 존재한다 (컴파일 할 때부터)
static 메소드는 이미 메모리의 정적 공간에 자리를 차지하고 있으므로 해당 객체를 new로 생성하지 않아도 바로 불러 사용할 수 있다

그냥 정적 변수를 쓰지 왜 싱글톤을 쓸까?
인터페이스의 사용이나 lazy loading 등 싱글톤으로 할수 있는 것들이 더 많기 때문에
인스턴스가 하나만 필요한 경우에 Singleton pattern을 사용한다. 클래스의 인스턴스화를 제한하여 데이터베이스, 저장소 및 파일과 같은 공유 리소스에 대한 제어를 유지하는 것이다.
최초로 인스턴스 생성 이후에는 생성자 호출 시 최초의 생성자가 생성한 인스턴스를 리턴한다.

TDD(Test Driven Development)

  • 단위 테스트 시 독립적이여아함,근데 독립적인 인스턴스를 만들기가 어려움

의존성(=종속성) 주입

  • 싱글톤 패턴은 사용하기 쉽고 실용적이지만 모듈간 결합이 강함 → 의존성 주입(DI)을 통해 느슨하게

장점

  • 메모리적 측면 : 최초 한번의 new 연산자를 통해 고정된 메모리 영역을 사용
  • 데이터 공유가 쉽다.
  • 테스팅 하기 쉽고 마이그레이션하기도 수월
  • 추상화 레이어를 넣고 이를 기반으로 구현체를 넣어 주기 때문에 애플리케이션 의존성 방향이 일관되고, 쉽게 추론 할 수 있으며, 모듈간의 관계들이 명확해짐

단점

모듈들이 더 분리가 되어 복잡성이 증가. (런타임 페널티 발생 가능성)

  • 구현 코드가 많이 필요하다
  • 테스트가 어려움(자원을 공유하기 때문에 인스턴스의 상태를 초기화 시켜주어야 한다)
  • 내부 상태를 변경하기 어렵다
  • 유연성이 떨어지는 편

원칙

  • 상위 모듈은 하위 모듈에서 어떤 것도 가져오지 않아야 한다.
  • 둘다 추상화에 의존, 추상화는 세부 사항에 의존하지 말아야 한다

🏭 팩토리 패턴

객체 생성 부분을 떼어내 추상화한 패턴

상속 관계에 있는 두 클래스에서 상위 클래스가 뼈대를 결정, 하위는 객체 생성의 구체적인 내용을 결정하는 패턴

  • 느슨한 결합. 상위 클래스는 인스턴스 생성 방식을 알 필요 없기 때문에 더 많은 유연성을 가짐
  • 생성 로직이 따로 떨어져 있기 때문에 코드 리팩터링 시 유지 보수성 증가
    ex. (하위 클래스)아메리카노, 라떼 레시피 -(전달)-> (상위 클래스)바리스타 공장 = 우유.. 등을 생산

Enum
상수의 집합을 정의할 때 사용되는 타입
상수 뿐만 아니라 메서드를 넣어 관리 할 수도 있음.

  • 본질적으로 스레드세이프 하기 때문에 싱글톤 패튼을 만들 때 도움이 됨!

🗾 전략(strategy) 패턴 / 정책(policy) 패턴

객체의 행위를 바꾸고 싶을 때, '직접' 수정하지 않고 전략이라 부르는 '캡슐화한 알고리즘'을 컨텍스트 안에서 바꿔주면서 상호 교체가 가능하게 만드는 패턴이다.

ex. 우리가 물건을 살 때 네이버 페이, 카카오 페이 처럼 여러 방법으로 결제하듯, 결제 방식의 '전략'만 바꾸는 방식

컨텍스트
: 상황, 맥락, 문맥을 의미. 개발자가 어떠한 작업을 완료하는데 필요한 모든 관련 정보

WHEN

특정한 계열의 알고리즘을 정의하고 각 알고리즘을 캡슐화하며 이 알고리즘들을 해당 계열 안에서 상호 교체가 가능하게 만든다.

기능 알고리즘을 Strategy라고 하는 독립적인 기능으로 분리하여 개발하도록 한다.

프로그램 실행 중 선택된 모드에 따라 실행되는 방식, 즉 전략이 결정될 때

예: 전체, 이미지, 뉴스, 지도 선택/검색 클릭 -> 검색할 때 선택한 검색 모드에 따라 각각 다른 검색 방식이 실행됨

HOW?

  • 위 예시를 전략패턴을 적용하지 않고 구현한다면?
    SearchButton을 눌렀을 때 onClick함수에서 조건문을 사용해, 검색 모드에 따라 동작을 다르게 실행한다. 수정사항이 생기거나 모드가 추가되면 onClick은 한없이 길어짐 -> 소프트웨어가 커지고 복잡해 질수록 코드 분석,관리가 어려워지는 우아하지 않은 설계 && 클래스마다 역할지정을 뚜렷히 하여 모듈화 된 소프트웨어를 구축하는 객체지향 철학에 어긋남

  • 전략패턴을 사용하면?
    모드마다의 동작 하나하나를 모듈로 따로 분리하여 검색버튼을 누를 때 실행될 검색 모듈을 갈아끼워주는 방식 사용

SearchStrategy 인터페이스를 만들고 onClick에서 searchStrategy의 search() 함수만 호출한다. setter를 이용해 searchStrategy 를 SearchStategy 인터페이스를 상속 받은 다른 검색 전략으로 갈아끼울 수 있다.

passport의 전략 패턴

passport란?

전략 패턴을 활용한 라이브러리이다.
Node.js에서 인증 모듈을 구현할 때 쓰는 미들웨어 라이러버리로, 여러 가지 '전략'을 기반으로 인증할 수 있게 한다.

👁️‍🗨️ 옵저버 패턴(Observer)

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

  1. 객체와 주체가 분리되어 있다

    주체 : 객체의 상태 변화를 보고 있는 관찰자
    옵저버 : 이 객체의 상태 변화에 따라 전달되는 메서드를 기반으로 '추가 변화 사항'이 생기는 객체들을 의미

  2. 주체-객체 따로 두지 않고, 상태가 변경되는 객체를 기반으로 구축하기도 함

  • ex. 트위터 : 내가 주체를 팔로우 했다면 추체가 포스팅시 알림이 팔로워에게로 감
  • ex2. 주로 이벤트 기반 시스템에 사용. MVC 패턴에도 사용됨.
    주체(model, 모델)에서 변경 사항이 생겨 update()메서드로 옵저버인 뷰(view)에게 알려주고 이를 기반으로 컨트롤러(controller)등이 작동함.

상속과 구현

  • 상속(abstract class) : 자식 클래스가 부모 클래스의 메서드 등을 상속받아 사용하며 자식 클래스에서 추가 및 확장을 할 수 있다. -> 재사용성, 중복성의 최소화
  • 구현(interface) : 부모 인터페이스를 자식 클래스에서 재정의하여 구현. 상속과 달리 반드시 부모 클래스의 메서드를 재정의하여 구현해야 한다.

when?

객체 간에 일대다 종속성을 정의하여, 한 객체의 상태 변경이 다른 객체들에게 알려지게 하는 패턴.

Observer pattern은 수많은 객체 간의 일대다 관계인 경우의 기초입니다.

예로는 React를 사용하면 상태관리를 하는 Redux에 대해 들어본 적 있을 것이다. Redux는 Observer pattern의 구현으로 store에서 action에 따른 상태 업데이트에 따라 - Components가 변경 사항을 표현한다.

Redux는 단방향 데이터 바인딩으로 flux pattern으로도 많이 소개되며 flux는 facebook에서 만든 사용자 인터페이스 구축을 위한 아키텍처이다.

또한 원격 저장소에 코드가 반영되는 경우 CI 환경에서 변경 사항을 모니터링하고 빌드를 실행하는 것도 Observing된다고 할 수 있다.

옵저버 패턴 구현 방법
여러 방법이 있지만 프록시 객체를 써서 하곤 한다.
프록시 객체를 통해 객체의 속성이나 메서드 변화 등을 감지하고 이를 미리 설정해 놓은 옵저버들에게 전달하는 방법으로 구현함.

👩‍👧‍👦 프록시 패턴과 프록시 서버

프록시 패턴(proxy)

  • 객체에 접근하기 전에 그 접근에 대한 흐름을 가로채 대상 객체 앞단의 인터페이스 역할을 하는 디자인 패턴
  • 객체의 속성, 변환 등을 보완하며 보안, 데이터검증, 캐싱, 로깅에 사용

프록시 서버에서의 캐싱
: 캐시 안에 정보를 담아두고, 캐시 안에 있는 정보를 요구하는 요청에 대해 다시 멀리 있는 원격 서버에 요청하지 않고 캐시 안에 있는 데이터를 활용하는 것.
이를 통해 불필요하게 외부와 연결하지 않기 때문에 트래픽을 줄일 수 있다.

프록시 서버

서버와 클라이언트 사이에서 자신을 통해 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해주는 컴퓨터 시스템이나 응용 프로그램이다.

프록시 서버 사용 사례

  • 서버 앞단에 둬서 캐싱, 로깅, 데이터 분석을 서버보다 먼저 하는 서버로 쓰임
  • 이를 통해 포트 번호를 바꿔서 사용자가 실제 서버의 포트에 접근하지 못하게 할 수 있음.
  • 공격자의 DDOS 공격을 차단하거나 CDN을 프록시 서버로 캐싱할 수 있으며, nginx로 Node.js로 이루어진 서버의 앞단에 둬서 버퍼 오버플로우를 해결할 수도 있음.

nginx

주로 Node.js 서버 앞단의 프록시 서버로 활용됨.(Node.js의 버퍼 오버플로우 취약점을 예방)
-> 이를 통해 익명 사용자가 직접 서버에 접근하는 것을 차단, 간접적으로 한 단계를 거치기 때문에 보안을 강화

버퍼 오버플로우
: 버퍼는 보통 데이터가 저장되는 메모리 공간으로 메모리 공간을 벗어나는 경우를 말한다. 이때 사용되지 않아야 할 영역에 데이터가 덮어씌워져 주소, 값을 바꾸는 공격이 발생하기도 한다.

CloudFlare

전 세계적으로 서버가 분산되어 있음.
이를 통해 어떤 시스템의 콘텐츠를 빠르게 전달 할 수 있는 CDN 서비스이다.

🔹 이터레이터 패턴(iterator)

이터레이터를 사용하여 컬렉션(collection)의 요소들에 접근하는 디자인 패턴이다.
이를 통해 순회할 수 있는 여러가지 자료형의 구조와는 상관없이 (어떤 컬렉션이든) 이터레이터라는 하나의 인터페이스로 순회가 가능하다.

🔹 노출모듈 패턴(revealing module)

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

☘️ MVC 패턴

Model-View-Controller 로 이루어짐

  • 애플리케이션의 구성 요소를 세 가지 역할로 구분. 개발 프로세스에서 각각의 구성 요소에만 집중해서 개발 가능.
  • 재사용성과 확장성 용이 / 애플리케이션이 복잡해지면 모델과 뷰의 관계가 복잡해 질 수 있음

모델

  • 애플리케이션의 데이터인 데이터베이스, 상수, 변수 등을 뜻함
  • 뷰에서 데이터를 생성(또는 수정)하면 컨트롤러를 통해 모델을 생성(또는 갱신)함.

  • inputbox, checkbox, textarea 등 사용자 인터페이스 요소. 즉, 모델을 기반으로 사용자가 볼 수 있는 화면.
  • 모델이 가지고 있는 정보를 따로 저장하지 않아야 하고, 단순히 화면에 표시하는 정보만 가지고 있어야 함
  • 변경 시 컨트롤러에 이를 전달해야 함

컨트롤러

  • 하나 이상의 모델과 뷰를 잇는 다리 역할
  • 이벤트 등 메인 로직을 담당
  • 모델과 뷰의 생명 주기 관리
  • 모델과 뷰로부터 변경 통지를 받으면 이를 해석하며 각각 구성 요소에 해당 내용을 전달

Spring

MVC 패턴을 이용한 대표적인 프레임워크

  • 에너테이션을 기반으로 사용자의 요청 값들을 쉽게 분석
  • 재사용 가능 코드, 테스트, 쉽게 리디렉션 가능

🔹 MVP 패턴

MVC로 부터 파생

  • Controller -> Presenter(프레젠터)
  • 뷰와 프레젠터는 1:1 관계 -> MVC보다 강한 결합

🔹 MVVM 패턴

  • C-> View Model(뷰모델)
  • 뷰모델 : 뷰를 더 추상화한 계층
  • 커맨드와 데이터 바인딩을 가짐!
  • 뷰와 뷰모델 사이의 양방향 데이터 바인딩을 지원
  • UI를 별도의 코드 수정 없이 재사용 가능, 단위 테스팅 쉬움

    커맨드
    여러가지 요소에 대한 처리를 하나의 액션으로 처리하는 기법
    데이터 바인딩
    화면에 보이는 데이터와 웹 브라우저의 메모리를 일치시키는 기법. 뷰모델을 변경하면 뷰가 변경된다.

Vue.js

MVVM 패턴을 가진 대표적인 프레임워크

[Ref]
https://kimsangyeon-github-io.vercel.app/blog/2022-04-15-design-patterns
https://velog.io/@syoung125/객체지향-디자인-패턴-13가지

0개의 댓글

관련 채용 정보