[CS] 디자인 패턴에 대해서

2025. 6. 4. 21:53·🍞 Computer Science

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

 

1. 싱글톤 패턴

싱글톤 패턴은 하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴이다. 하나의 클래스를 기반으로 여러 개의 개별적인 인스턴스를 만들 수 있지만, 그렇게 하지 않고 하나의 클래스를 기반으로 단 하나의 인스턴스를 만들어 이를 기반으로 로직을 만드는 데 쓰이며, 보통 데이터베이스 연결 모듈에 많이 사용된다.

 

하나의 인스턴스를 만들어 놓고 해당 인스턴스를 다른 모듈들이 공유하며 사용하기 때문에 인스턴스를 생성할 때 드는 비용이 줄어든다는 장점이 있다. 하지만 의존성이 높아진다는 단점이 있다.

 

장점 => 인스턴스 생성 비용 줄어듦

단점 => 의존성 높아짐 

 

자바스크립트의 싱글톤 패턴

자바스크립트에서는 리터럴 {} 또는 new Object로 객체를 생성하게 되면 다른 어떤 객체와도 같지 않기 때문에 이 자체만으로 싱글톤 패턴을 구현할 수 있다.

 

데이터베이스 연결 모듈

싱글톤 패턴은 데이터베이스 연결 모듈에 많이 쓰인다.

DB.instance라는 하나의 인스턴스를 기반으로 생성할 수 있다.

이를 통해 데이터베이스 연결에 관한 인스턴스 생성 비용을 아낄 수 있다.

 

자바에서 싱글톤 패턴

자바로는 중첩 클래스를 이용해서 만드는 방법이 가장 대중적이다. 

public class Singleton {
    // 1. 외부에서 인스턴스 생성을 막기 위해 생성자를 private으로 선언
    private Singleton() {}

    // 2. 정적 내부 클래스: SingletonHolder는 Singleton 클래스가 로드될 때는 로딩되지 않음
    private static class SingletonHolder {
        // 3. SingletonHolder가 로드될 때 인스턴스가 생성됨 (lazy loading)
        private static final Singleton INSTANCE = new Singleton();
    }

    // 4. 외부에서 접근할 수 있는 유일한 메서드
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

 

 

싱글톤 패턴의 단점

싱글톤 패턴은 TDD(Test Driven Development)를 할 때 걸림돌이 된다. TDD를 할 때 단위 테스트를 주로 하는데, 단위 테스트는 테스트가 서로 독립적이어야 하며 테스트를 어떤 순서로든 실행할 수 있어야 한다. 하지만, 싱글톤 패턴은 미리 생성된 하나의 인스턴스를 기반으로 구현하는 패턴이므로 각 테스트마다 독립적인 인스턴스를 만들기 어렵다.

 

의존성 주입

또한, 싱글톤 패턴은 사용하기가 쉽고 굉장히 실용적이지만 모듈 간의 결합을 강하게 만들 수 있다. 이때 의존성 주입(DI, Dependency Injection)을 통해 모듈 간의 결합을 조금 더 느슨하게 만들어 해결할 수 있다.

참고로 의존성이란 종속성이라고도 하며 A가 B에 의존성이 있다는 것은 B의 변경 사항에 대해 A 또한 변해야 된다는 것을 의미한다.

 

메인 모듈이 직접 다른 하위 모듈에 대한 의존성을 주기보다는 중간에 의존성 주입자가 이 부분을 가로채 메인 모듈이 간접적으로 의존성을 주입하는 방식이다. 이를 통해 메인 모듈은 하위 모듈에 대한 의존성이 떨어지게 된다. 참고로 이를 디커플링이 된다라고 한다.

 

- 장점

모듈들을 쉽게 교체할 수 있는 구조가 되어서 테스팅하기 쉽고, 마이그레이션 하기도 수월하다.

또한, 구현할 때 추상화 레이어를 넣고 이를 기반으로 구현체를 넣어주기 때문에 애플리케이션 의존성 방향이 일관되고, 애플리케이션을 쉽게 추론할 수 있으며, 모듈 간의 관계들이 조금 더 명확해진다.

의존성을 사용하면 상위 모듈(클라이언트 코드)이 하위 모듈(구현체)에 직접 의존하지 않고, 대신 인터페이스나 추상 클래스(추상화 레이어)에 의존하게 되므로, 의존성 방향이 항상 추상 -> 구현으로 일관되게 흐름이 유지된다.

- 단점

모듈들이 더욱 더 분리되므로 클래스 수가 늘어나 복잡성이 증가될 수 있고, 약간의 런타임 페널티가 생긴다.

- 원칙

상위 모듈은 하위 모듈에서 어떠한 것도 가져오지 않아야 한다. 또한, 둘 다 추상화에 의존해야 하며, 이때 추상화는 세부 사항에 의존하지 말아야 한다.라는 의존성 주입 원칙을 지켜서 만들어야 한다.

 

2. 팩토리 패턴

팩토리 패턴은 객체를 사용하는 코드에서 객체 생성 부분을 떼어내 추상화한 패턴이자 상속 관계에 있는 두 클래스에서 상위 클래스가 중요한 뼈대를 결정하고, 하위 클래스에서 객체 생성에 관한 구체적인 내용을 결정하는 패턴이다.

상위 클래스와 하위 클래스가 분리되기 때문에 느슨한 결합을 가지며 상위 클래스에서는 인스턴스 생성 방식에 대해 전혀 알 필요가 없기 때문에 더 많은 유연성을 갖게 된다. 그리고 객체 생성 로직이 따로 떼어져있기 때문에 코드를 리팩터링 하더라도 한 곳만 고칠 수 있게 되어 유지 보수성이 증가된다.

 

 

3. 전략 패턴

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

 

 

4. 옵저버 패턴

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

 

주체란, 객체의 상태 변화를 보고 있는 관찰자이며

옵저버들이란, 이 객체의 상태 변화에 따라 전달되는 메서드 등을 기반으로 추가 변화 사항이 생기는 객체들을 의미한다.

 

또한, 주체와 객체를 따로 두지 않고 상태가 변경되는 객체를 기반으로 구축하기도 한다.

옵저버 패턴은 주로 이벤트 기반 시스템에 사용하며 MVC 패턴에도 사용된다.

예를 들어 주체라고 볼 수 있는 모델(model)에서 변경사항이 생겨 update() 메서드로 옵저버인 뷰(View)에 알려주고 이를 기반으로 컨트롤러(Controller) 등이 작동하는 것이다.

 

 

추가) 상속과 구현

implements 등 자바의 상속과 구현의 특징과 차이에 대해 알아보자.

 

상속 (extends)

자식 클래스가 부모 클래스의 메서드 등을 상속받아 사용하며 자식 클래스에서 추가 및 확장을 할 수 있는 것을 말한다. 이로 인해 재사용성, 중복성의 최소화가 이루어진다.

 

구현 (implements)

부모 인터페이스(interface)를 자식 클래스에서 재정의하여 구현하는 것을 말하며, 상속과는 달리 반드시 부모 클래스의 메서드를 재정의하여 구현해야 한다.

 

상속과 구현의 차이

상속은 일반 클래스, abstract 클래스를 기반으로 구현하며, 구현은 인터페이스를 기반으로 구현한다.

 

자바스크립트의 옵저버 패턴

자바스크립트에서의 옵저버 패턴은 프록시 객체를 통해 구현할 수도 있다.

 

프록시 객체

프록시(proxy) 객체는 어떠한 대상의 기본적인 동작(속성 접근, 할당, 순회, 열거, 함수 호출 등)의 작업을 가로챌 수 있는 객체를 뜻하며, 자바스크립트에서 프록시 객체는 두 개의 매개 변수를 가진다.

target: 프록시할 대상
handler: target 동작을 가로채고 어떠한 동작을 할 것인가 설정되어 있는 함수

 

 

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

프록시 패턴은 대상 객체(subject)에 접근하기 전 그 접근에 대한 흐름을 가로채 대상 객체 앞단의 인터페이스 역할을 하는 디자인 패턴이다. 이를 통해 객체의 속성, 변환 등을 보완하며 보안, 데이터 검증, 캐싱, 로깅에 사용한다. 이는 프록시 객체로 쓰이기도 하지만, 프록시 서버로도 활용된다.

 

프록시 서버

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

 

프록시 서버로 쓰는 nginx

nginx는 비동기 이벤트 기반의 구조와 다수의 연결을 효과적으로 처리 가능한 웹 서버이며, 주로 Node.js 서버 앞단의 프록시 서버로 활용된다. Node.js의 버퍼 오버플로우 취약점을 예방하기 위해서는 nginx를 프록시 서버로 앞단에 놓고, Node.js를 뒤쪽에 놓는 것이 좋다고 한다. 이 말은 Node.js 서버를 운영할 때 교과서처럼 참고되어 많은 사람들이 이렇게 구축하고 있다.

 

Node.js 서버를 구축할 때 앞단에 nginx를 둔다. 이를 통해 익명 사용자가 직접적으로 서버에 접근하는 것을 차단하고, 간접적으로 한 단계를 더 거치게 만들어서 보안을 강화할 수 있다. 이처럼 nginx를 프록시 서버로 둬서 실제 포트를 숨길 수 있고 정적 자원을 gzip 압축하거나, 메인 서버 앞단에서의 로깅을 할 수 있다.

 

 

 

프록시 서버로 쓰는 CloudFlare

CloudFlare는 전 세계적으로 분산된 서버가 있고 이를 통해 어떠한 시스템의 콘텐츠 전달을 빠르게 할 수 있는 CDN 서비스이다.

CloudFlare는 웹 서버 앞단에 프록시 서버로 두어 DDOS 공격 방어나 HTTPS 구축에 쓰인다. 또한, 서비스를 배포한 이후에 해외에서 무언가 의심스러운 트래픽이 많이 발생하면 이 때문에 많은 클라우드 서비스 비용이 발생할 수 있는데, 이때 CloudFlare가 의심스러운 트래픽인지를 먼저 판단해 CAPTCHA 등을 기반으로 이를 일정 부분 막아주는 역할도 수행한다.

 

사용자, 크롤러, 공격자가 자신의 웹 사이트에 접속하게 될텐데 이때 CloudFlare를 통해 공격자로부터 보호할 수 있다.

 

DDOS 공격 방어

DDOS는 짧은 기간 동안 네트워크에 많은 요청을 보내 네트워크를 마비시켜 웹 사이트의 가용성을 방해하는 사이버 공격 유형이다. CloudFlare는 의심스러운 트래픽, 특히 사용자가 접속하는 것이 아닌 시스템을 통해 오는 트래픽을 자동으로 차단해서 DDOS 공격으로부터 보호한다. CloudFlare의 거대한 네트워크 용량과 캐싱 전략으로 소규모 DDOS 공격은 쉽게 막아낼 수 있으며 이러한 공격에 대한 방화벽 대시보드도 제공한다.

 

HTTPS 구축

서버에서 HTTPS를 구축할 때 인증서를 기반으로 구축할 수도 있다. 하지만 CloudFlare를 사용하면 별도의 인증서 설치 없이 좀 더 손쉽게 HTTPS를 구축할 수 있다.

 

CORS와 프론트엔드의 프록시 서버

CORS(Corss-Origin Resource Sharing)는 서버가 웹 브라우저에서 리소스를 로드할 때 다른 오리진을 통해 로드하지 못하게 하는 HTTP 헤더 기반 메커니즘이다.

 

+ Origin(오리진)

프로토콜과 호스트 이름, 포트의 조합

https://kundol.com:12010/test라는 주소에서 https://kundol.com:12010을 말한다.

 

프론트엔드 개발 시 프론트엔드 서버를 만들어서 백엔드 서버와 통신할 때 주로 CORS 에러를 마주치는데, 이를 해결하기 위해 프론트엔드에서 프록시 서버를 만들기도 한다. 예를 들어 프론트엔드에서는 127.0.0.1:3000으로 테스팅을 하는데 백엔드 서버는 127.0.0.1:12010이라면 포트 번호가 다르기 때문에 CORS에러가 난다. 이때 프록시 서버를 둬서 프론트엔드 서버에서 요청되는 오리진을 127.0.0.1.12010으로 바꾼다. 

참고로 127.0.0.1이란 루프백(loopback) IP로, 본인 PC 서버의 IP를 뜻한다. localhost나 127.0.0.1을 주소창에 입력하면 DNS를 거치지 않고 바로 본인 PC 서버로 연결된다.

 

6. 이터레이터 패턴

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

 

 

7. 노출모듈 패턴

즉시 실행 함수를 통해 private, public 같은 접근 제어자를 만드는 패턴을 말한다. 자바스크립트는 private나 public 같은 접근 제어자가 존재하지 않고 전역 범위에서 스크립트가 실행된다. 그렇기 때문에 노출모듈 패턴을 통해 private와 public 접근 제어자를 구현하기도 한다.

 

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

 

8. MVC 패턴

MVC 패턴은 모델(Model), 뷰(View), 컨트롤러(Controller)로 이루어진 디자인 패턴이다.

애플리케이션의 구성 요소를 세 가지 역할로 구분하여 개발 프로세스에서 각각의 구성 요소에만 집중해서 개발할 수 있다. 재사용성과 확장성이 용이하다는 장점이 있고, 애플리케이션이 복잡해질수록 모델과 뷰의 관계가 복잡해질 수 있다는 단점이 있다.

 

모델 (Model)

애플리케이션의 데이터인 데이터베이스, 상수, 변수 등을 뜻한다.

예를 들어 사각형 모양의 박스 안에 글자가 들어 있다면 그 사각형 모양의 박스 위치 정보, 글자 내용, 글자 위치, 글자 포맷에 관한 정보를 모두 가지고 있어야 한다. 뷰에서 데이터를 생성하거나 수정하면 컨트롤러를 통해 모델을 생성하거나 갱신한다.

 

뷰 (View)

사용자 인터페이스 요소를 나타낸다.

즉, 모델을 기반으로 사용자가 볼 수 있는 화면을 뜻한다. 모델이 가지고 있는 정보를 따로 저장하지 않아야 하며 화면에 표시하는 정보만 가지고 있어야 한다. 또한, 변경이 일어나면 컨트롤러에 이를 전달해야 한다.

 

컨트롤러 (Controller)

하나 이상의 모델과 하나 이상의 뷰를 잇는 다리 역할을 하며 이벤트 등 메인 로직을 담당한다.

또한 모델고 뷰의 생명 주기를 관리하며, 모델이나 뷰의 변경 통지를 받으면 이를 해석하여 각각의 구성 요소에 해당 내용에 대해 알려준다.

 

MVC 패턴의 예 스프링

MVC 패턴을 이용한 대표적인 웹 프레임워크는 자바 플랫폼을 위한 오픈 소스 애플리케이션 프레임워크인 스프링이 있다.

스프링의 WEB MVC는 웹 서비스를 구축하는 데 편리한 기능들을 많이 제공한다. 예를 들어 @RequestParam, @RequestHeader, @PathVariable 등의 애너테이션을 기반으로 사용자의 요청 값들을 쉽게 분석할 수 있으며 사용자의 어떠한 요청이 유효한 요청인지를 쉽게 거를 수 있다. 또한, 재사용 가능한 코드, 테스트, 쉽게 리디렉션 할 수 있게 하는 등의 장점이 있다.

 

9. MVP 패턴

MVP 패턴은 MVC 패턴으로부터 파생되었고, MVC에서 C에 해당하는 컨트롤러가 프레젠터(presenter)로 교체된 패턴이다.

뷰(View)와 프레젠터(Presenter)는 일대일 관계이기 때문에 MVC 패턴보다 더 강한 결합을 지닌 디자인 패턴이다.

 

10. MVVM 패턴

MVC의 C에 해당하는 컨트롤러가 뷰모델로 바뀐 패턴이다.

뷰모델은 뷰를 더 추상화한 계층이며, MVVM 패턴은 MVC 패턴과는 다르게 커맨드와 데이터 바인딩을 가지는 것이 특징이다. 뷰와 뷰모델 사이의 양방향 데이터 바인딩을 지원하며 UI를 별도의 코드 수정 없이 재사용할 수 있고 단위 테스팅하기 쉽다는 장점이 있따.

MVVM 패턴의 예 뷰

MVVM 패턴을 가진 대표 프레임워크는 뷰가 있다. Vue.js는 반응형이 특징인 프론트엔드 프레임워크다. 예를 들어 watch와 computed 등으로 쉽게 반응형적인 값들을 구축할 수 있다.

함수를 사용하지 않고 값 대입만으로도 변수가 변경되며 양방향 바인딩, html을 토대로 컴포넌트를 구축할 수 있다는 점이 특징이다. 재사용 가능한 컴포넌트를 기반으로 UI를 구축할 수 있다.

- 커맨드

여러 가지 요소에 대한 처리를 하나의 액션으로 처리할 수 있게 하는 기법이다.

- 데이터 바인딩

화면에 보이는 데이터와 웹 브라우저의 메모리 데이터를 일치시키는 기법으로, 뷰모델을 변경하면 뷰가 변경된다.

 

 

저작자표시 (새창열림)

'🍞 Computer Science' 카테고리의 다른 글

[CS] 프로그래밍 패러다임에 대해서  (1) 2025.06.06
[CS] 자료구조 총정리  (1) 2024.07.29
[데이터 통신] 7장 IP 프로토콜  (0) 2023.04.17
'🍞 Computer Science' 카테고리의 다른 글
  • [CS] 프로그래밍 패러다임에 대해서
  • [CS] 자료구조 총정리
  • [데이터 통신] 7장 IP 프로토콜
박빵이
박빵이
2025년에도 갓생살기
  • 박빵이
    기억보다 기록
    박빵이
  • 전체
    오늘
    어제
    • 분류 전체보기 (337)
      • 🍞 FrontEnd (97)
        • HTML+CSS (4)
        • JavaScript (17)
        • TypeScript (4)
        • React (52)
        • Next.js (2)
        • Android (15)
      • 🍞 BackEnd (24)
        • Java (15)
        • Node.js (6)
        • Spring (1)
      • 🍞 Cloud & Infra (0)
        • AWS SAA (0)
        • Microsoft Azure (0)
      • 🍞 Algorithm (147)
        • C++ (4)
        • Baekjoon (41)
        • Programmers (97)
      • 🍞 Computer Science (18)
        • 운영체제 (1)
        • 데이터 통신 (6)
        • 네트워크 (6)
        • 데이터베이스 (1)
      • 🍞 대외활동 & 부트캠프 (42)
        • 삼성 청년 SW 아카데미 (1)
        • LG유플러스 유레카 (0)
        • 한국대학생IT경영학회 (1)
        • IT연합동아리 UMC (17)
        • 길벗 블로깅 멘토 (18)
        • IT연합동아리 피로그래밍 (3)
        • 개발 컨퍼런스 (2)
  • 블로그 메뉴

    • Admin
  • 링크

    • GitHub
  • 인기 글

  • 태그

    길벗 블로깅 멘토링
    프로그래머스
    JavaScript
    level2
    백준
    알고리즘
    react
    코틀린
    Java
    위상정렬
    코딩자율학습
    유니온파인드
    level1
    umc
    map
    Front
    C++
    Android
    안드로이드
    길벗 블로깅 멘토
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
박빵이
[CS] 디자인 패턴에 대해서
상단으로

티스토리툴바