[CS] CH01. 디자인 패턴과 프로그래밍 패러다임

유지민·2023년 11월 15일
0

CS

목록 보기
11/11
post-thumbnail

면접을 위한 CS 전공지식 노트

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

  • 라이브러리 : 공통으로 사용될 수 있는 특정한 기능들을 모듈화한 것 → 폴더명, 파일명 등에 대한 규칙 X, 프레임워크 대비 자유로움
  • 프레임워크 : 공통으로 사용될 수 있는 특정한 기능들 모듈화 → 폴더명, 파일명 등에 대한 규칙 O, 라이브러리 대비 자유로움
  • 디자인 패턴 : 프로그램 설계 시 발생한 문제를 객체 간 상호 관계 등을 이용해 해결할 수 있도록 규약 형태로 만들어놓은 것

1. 싱글톤 패턴

하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴

→ 데이터베이스 연결 모듈에 많이 사용

  • 하나의 인스턴스를 만들어놓고, 해당 인스턴스를 다른 모듈들이 공유하며 사용 good → 인스턴스 생성 시 드는 비용 절감 (장점) → 의존성 높아짐 (단점)
  • JS : 리터럴 {}, new Object로 객체 생성 시 → 다른 어떤 객체와도 같지 않음 → 자체만으로 싱글톤 구현 O

  • 싱글톤 패턴 단점
    • TDD(테스트 주도 개발)에 걸림돌

      → 단위 테스트 : 테스트가 서로 독립적이어야 함 
      
      → 테스트를 어떤 순서로든 실행할 수 있어야 함

      : 싱글톤 패턴 - 미리 생성된 하나의 인스턴스 기반으로 구현 → 각 테스트별 독립적 인스턴스 생성 hard

  • 의존성 주입
    • 모듈 간 결합을 강하게 만들 수 있음 (단점) → 의존성 주입(DI, Dependency Injection) 통해 모듈 간 결합 느슨하게 만들어 해결 가능
      • 의존성(= 종속성) : A가 B에 의존성 ? B의 변경사항에 대해 A도 변해야 함을 의미
    • 메인 모듈이 직접 하위 모듈에 의존성 주는 것 X → 의존성 주읩자가 가로채 간접적으로 의존성 주의 → 메인 모듈이 하위 모듈에 대한 의존성 ⬇️ == 디커플링
    • 모듈 쉽게 교체할 수 있는 구조 됨 (장점)
    • 마이그레이션, 테스팅 용이 (장점)
    • 구현 시 추상화 레이어, 이를 기반으로 구현체 넣어줌 → 애플리케이션 의존성 방향 일관됨, 추론 쉬워짐, 모듈 간 관계 명확해짐
    • 의존성 주입 단점 : 모듈이 더 분리, 클래스 수 늘어 복잡성 증가될 수 있음, 약간의 런타임 패널티
    • 의존성 주입 원칙
      • “상위 모듈은 하위 모듈에서 어떤 것도 가져오지 않아야 함”
      • “둘 다 추상화에 의존해야 함”
      • “추상화는 세부 사항에 의존하지 않아야 함”

2. 팩토리 패턴

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

상속 관계에 있는 두 클래스에서

  • 상위 클래스 - 중요한 뼈대 결정
  • 하위 클래스 - 객체 생성에 관한 구체적 내용 결정 → 분리되므로 느슨한 결합, 상위 클래스 : 인스턴스 생성 방식 알 필요 X → 유연성 ⬆️ → 객체 생성 로직이 따로 떼어져 있으므로 코드 리팩터링 시 한 곳만 수정 → 유지보수성 ⬆️

  • enum : 상수의 집합 정의에 사용되는 타입

3. 전략 패턴 (= 정책 패턴)

객체의 행위를 바꾸고 싶은 경우 직접 수정, 전략이라 부르는 캡슐화한 알고리즘을 컨텍스트 내에서 바꿔 상호교체되도록 하는 패턴

  • passport : Node.js에서 인증 모듈 구현 시 쓰는 미들웨어 라이브러리 → 전략 기반 인증

4. 옵저버 패턴

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

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

주로 이벤트 기반 시스템에 사용, MVC(Model-View-Controller) 패턴에도 사용

  • 상속 : 자식 클래스가 부모 클래스의 메서드 등을 상속받아 사용, 자식 클래스에서 추가 및 확장 O → 재사용성, 중복성 최소화
  • 구현 : 부모 인터페이스를 자식 클래스에서 재정의해 구현 → 반드시 부모 클래스의 메서드를 재정의해 구현(상속과의 차이)

→ 상속 : 일반 클래스, abstract 클래스 기반 구현

→ 구현 : 인터페이스 기반 구현

  • JS에서의 옵저버 패턴
    • 프록시 객체 : 어떠한 대상의 기본적 동작의 작업을 가로챌 수 있는 객체
      - 프록시 객체가 가지는 두개의 매개변수
      - target : 프록시할 대상
      - handler : target 동작을 가로채고 어떤 동작을 할 것인지 설정된 함수

      → vue.js 3.0 : ref, reactive로 정의 시 해당 값이 변경되었을 때 자동으로 DOM에 있는 값 변경됨

      → vue.js 3.0의 옵저버 패턴

5. 프록시 패턴과 프록시 서버

4의 프록시 객체 : 프록시 패턴이 녹아든 객체

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

  • 객체의 속성, 변환 등을 보완

  • 보안, 데이터 검증, 캐싱, 로깅에 사용

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

    → 캐시 : 캐시 안에 정보 담아두고, 캐시 안에 있는 정보를 요구하는 요청에 대해 원격 서버 요청 X, 캐시 내부 데이터 활용

ex) nginx : 비동기 이벤트 기반의 구조, 다수의 연결 효과적으로 처리 가능한 웹서버

Node.js 서버 앞단 프록시 서버로 사용

ex) cloudflare : 웹 서버 앞단에 프록시 서버로 두어 DDOS 공격 방어, HTTPS 구축에 사용

  • CORS(Cross-Origin Resource Sharing) & FE의 프록시 서버
    • CORS : 서버가 웹 브라우저에서 리소스를 로드할 때 다른 오리진을 통해 로드하지 못하게 하는 HTTP 헤더 기반 메커니즘
    • 해결 법으로 FE에서 프록시 서버 만들기도 함

6. 이터레이터 패턴

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

→ 이터레이터는 하나의 인터페이스로 순회 가능 (여러가지 자료형의 구조와 상관 X)

  • 이터레이터 프로토콜 : 이터러블한 객체들을 순회할 때 쓰이는 규칙
  • 이터러블한 객체 : 반복 가능한 객체로 배열을 일반화한 객체

7. 노출모듈 패턴

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

→ JS에서 노출모듈 패턴을 통해 private, public 접근 제어자 구현

→ JS에서 노출모듈 패턴을 기반으로 만든 자바스크립트 모듈 방식 : CJS(Common JS)

  • public : 클래스에 정의된 함수에서 접근 가능, 자식 클래스와 외부 클래스에서 접근 가능한 범위
  • private : 클래스에 정의된 함수에서 접근 가능, 자식 클래스와 외부 클래스에서 접근 불가능한 범위
  • protected : 클래스에 정의된 함수에서 접근 가능, 자식 클래스와 외부 클래스에서 접근 가능한 범위
  • 즉시실행함수 : 함수를 정의하자마자 바로 호출하는 함수. 코드, 라이브러리 내 전역 변수의 충돌 방지

8. MVC 패턴

  • Model + View + Controller

  • 장점 : 재사용성과 확장성이 용이

  • 단점 : 애플리케이션이 복잡해질수록 모델과 뷰의 관계가 복잡해짐

  • 모델

    • 애플리케이션의 데이터인 DB, 상수, 변수 등 의미
    • ex) 사각형 양 박스 안에 글자
      • 사각형 모양의 박스 위치 정보, 글자 내용, 글자 위치, 글자 포맷 등의 정보
    • 뷰에서 데이터 생성 & 수정 → 컨트롤러 통해 모델 생성 or 갱신
    • 사용자 인터페이스 요소(inputbox, checkbox, textarea)
    • 모델을 기반으로 사용자가 볼 수 있는 화면
    • 모델이 가지고 있는 정보 따로 저장하면 X, 단순히 사각형 모양 등 화면에 표시하는 정보만
    • 변경이 일어나면 컨트롤러에 이를 전달해야 함
  • 컨트롤러

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

9. MVP 패턴

MVC패턴으로부터 파생, MVC의 C에 해당하는 컨트롤러가 프레젠터로 교체

  • 뷰 : 프레젠터 = 1 : 1 → MVC 패턴보다 강한 결합
  • ex) Spring MVC

10. MVVM 패턴

MVC의 C에 해당하는 컨트롤러가 뷰 모델(VM)으로 바뀐 패턴

  • 뷰 모델 : 뷰를 더 추상화한 계층

  • MVVM(MVC와의 차이) : 커맨드데이터 바인딩을 가지는 특징

    • 커맨드 : 여러가지 요소에 대한 처리를 하나의 액션으로 처리할 수 있는 기법
    • 데이터 바인딩 : 화면에 보이는 데이터와 웹 브라우저의 메모리 데이터 일치시키는 방법
      • 뷰 모델 변경 시 뷰가 변경됨
  • 뷰와 뷰 모델 사이 양방향 데이터 바인딩 지원

  • UI를 별도 코드 수정 없이 재사용 가능, 단위 테스팅에 용이

  • ex) Vue.js MVVM → watch, computed 등으로 반응형적 값 구축

    • 함수 사용 없이 값 대입만으로 변수 변경, 양방향 바인딩, html 토대의 컴포넌트 구축
  • 프로그래밍 패러다임 : 프로그래머에게 프로그래밍의 관점을 갖게 해주는 역할의 개발 방법론

    • ex) 객체 지향 프로그래밍 : 프로그래머가 프로그램을 상호작용하는 객체들의 집합으로 보도록
    • ex) 함수형 프로그래밍 : 상태값을 지니지 않는 함수값들의 연속으로 보도록
  • 프로그래밍 패러다임

    • 선언형
      • 함수형
    • 명령형
      • 객체지향형
      • 절차지향형

1. 선언형과 함수형 프로그래밍

선언형 프로그래밍 : 무엇을 풀어내는가에 집중하는 패러다임

→ “프로그램은 함수로 이루어진 것이다.” 라는 명제가 담긴 패러다임

→ 함수형 프로그래밍은 선언형 패러다임의 일종 (함수형은 선언형의 subset)

const list = [1, 2, 3, 4, 5, 11, 12]
const ret = list.reduce((max, num) => num > max ? num : max, 0)
console.log(ret) // 12
  • reduce : 배열만 받아 누적한 결괏값을 반환하는 순수함수

함수형 프로그래밍 : 작은 순수함수들을 블록처럼 쌓아 로직 구성, 고차함수를 통해 재사용성을 높인 프로그래밍 패러다임

→ JS : 함수가 일급 객체이므로 객체지향보다 함수형이 선호됨

  • 순수함수 출력이 입력에만 의존하는 것을 의미
    const pure = (a, b) => {
    	return a + b
    }
  • 고차 함수 함수가 함수를 값처럼 매개변수로 받아 로직을 생성할 수 있는 것 의미
    • 일급 객체 (특징)
      - 변수나 메서드에 함수 할당 X
      - 함수 안에 함수를 매개변수로 담을 수 O
      - 함수가 함수를 반환할 수 O

      함수형 프로그래밍 : 커링, 불변성 등 많은 특징

2. 객체 지향 프로그래밍

OOP : 객체들의 집합으로 프로그램의 상호 작용 표현

→ 데이터를 객체로 취급해 객체 내부에 선언된 메서드 활용하는 방식

  • 설계에 많은 시간 소요
  • 처리 속도가 상대적으로 느림
const ret = [1, 2, 3, 4, 5, 11, 12]
class List {
	constructor(list) {
		this.list = list
		this.mx = list.reduce((max, num) => num > max ? num : max, 0)
	}
	getMax() {
		return this.mx
	}
}

const a = new List(ret)
console.log(a.getMax())
  • OOP 특징

    • 추상화 : 복잡한 시스템으로부터 핵심적인 개념 또는 기능을 간추려내는 것
    • 캡슐화 : 객체의 속성과 메서드를 하나로 묶고 일부를 외부에 감추어 은닉
    • 상속성 : 상위 클래스의 특성을 하위 클래스가 이어받아 재사용 or 추가 or 확장
      • 코드의 재사용, 계층적 관계 생성, 유지 보수성 측면에서 중요
    • 다형성 : 하나의 메서드나 클래스가 다양한 방법으로 동작하는 것
      • ex) 오버로딩, 오버라이딩
        • 오버로딩 : 같은 이름을 가진 메서드를 여러 개 두는 것
          • 메서드 타입, 매개변수 유형, 개수 등으로 여러 개 둘 수 있음
          • 컴파일 중에 발생하는 정적 다형성
        • 오버라이딩 : 상위 클래스로부터 상속받은 메서드를 하위 클래스가 재정의하는 것
          • 주로 메서드 오버라이딩 의미
          • 런타임 중에 발생하는 동적 다형성
      • 오버로딩 예제 코드
      • 오버라이딩 예제 코드
  • 설계 원칙

    객체지향 프로그래밍 설계 시 SOLID 원칙 지켜야 함

    • S : 단일 책임 원칙 (SRP, Single Responsibility Principle) 모든 클래스는 각각 하나의 책임만 가져야 하는 원칙 ex) A라는 로직 존재 시 어떤 클래스는 A에 관한 클래스여야, 이를 수정해도 A와 관련된 수정이어야 함
    • O : 개방-폐쇄 원칙 (OCP, Open Closed Principle) 유지 보수 사항이 생기면 코드를 쉽게 확장할 수 있도록, 수정 시에는 닫혀 있도록 하는 원칙 기존의 코드는 잘 변경하지 않으면서, 확장은 쉽게 할 수 있어야 함
    • L : 리스코프 치환 원칙 (LSP, Liskov Subtitution Principle) 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 하는 것
      • 클래스 : 상속됨, 부모/자식이라는 계층 관계 생성됨 → 부모 객체에 자식 객체를 넣어도 시스템이 문제 없이 돌아가게 만드는 것 의미
    • I : 인터페이스 분리 원칙 (ISP, Interface Segregation Principle) 하나의 일반적인 인터페이스보다 구체적인 여러개의 인터페이스를 만들어야 하는 원칙
    • D : 의존 역전 원칙 (DIP, Dependency Inversion Principle) 자신보다 변하기 쉬운 것에 의존하던 것을 추상화된 인터페이스 or 상위 클래스에 두어 변하기 쉬운 것의 변화에 영향받지 않도록 하는 원칙 ex) 타이어 갈아끼울 수 있는 틀 만든 뒤 타이어 교체할 수 있도록 하는 시스템 → 상위 계층은 하위 계층의 변화에 대한 구현으로부터 독립되어야 함

3. 절차형 프로그래밍

로직이 수행되어야 할 연속적인 계산 과정으로 이루어짐

→ 장점 : 일이 진행되는 방식으로 코드 구현만 하면 되므로 코드 가독성 ⬆️, 실행 속도 빠름

→ 계산 많은 작업에 사용 ex) 포트란

→ 단점 : 모듈화 어려움, 유지보수성 떨어짐

4. 패러다임의 혼합

가장 좋은 패러다임은? → 없다.

  • BM, 서비스 특징 고려해 패러다임 설정
  • 하나의 패러다임으로 통일 or 여러 패러다임 조합해 상황/맥락에 따른 장점을 취해 개발
profile
끊임없이 도전하며 사고하는 주니어 Web 개발자 유지민입니다.

0개의 댓글