디자인 패턴

EUNJI LEE·2023년 8월 23일
0

CS 전공지식

목록 보기
1/2
post-custom-banner

디자인 패턴

프로그램 설계 시 발생했던 문제점들을 객체 간의 상호 관계 등을 이용해서 해결할 수 있도록 “규약” 형태로 만들어 놓은 것을 의미한다.

설계 문제의 해결책으로 디자인 패턴을 이용하여 프로그램을 설계하면 협업 시 팀원 간의 소통을 원활하게 할 수 있고 일정 패턴을 가지고 프로그램을 설계하기 때문에 유지 보수에 있어서도 장점을 보인다.

싱글톤 패턴(Singleton pattern)

싱글톤 패턴은 하나의 클래스에 하나의 인스턴스만 가지는 패턴을 이야기한다. 하나의 인스턴스만 만들어서 이것을 기반으로 로직을 작성하는데 쓰이고 보통 DB 연결 모둘에서 많이 사용하는 디자인 패턴이다.

싱글톤 패턴을 이용하면 하나의 인스턴스를 다른 모듈이 공유하면서 사용하기 때문에 인스턴스 생성 비용이 줄어든다는 장점이 존재하지만 의존성이 높아진다는 단점도 있다.

Class Test{
	prviate static class singleInstanceHolder{
		private static final Test INSTANCE=new Test();
	}
	public static Test getInstance(){//객체의 인스턴스를 반환하는 메소드 작성
		return singleInstanceHolder.INSTANCE;
	}
	
}

public class HelloSingle{
	public static void main(String[] args){
		Test a=Test.getInstance();
		Test b=Test.getInstance();
		if(a==b){ //static영역의 변수로 같은 해시코드를 가짐
			System.out.println(true); //true 출력
		}
	}
}

싱글톤 패턴 단점

TDD(Test Driven Development : 태스트 주도 개발)를 할 때 싱글톤 패턴은 문제가 된다. TDD를 할 때 단위 테스트를 주로 하게 되는데 단위 테스트는 서로 독립적이여야 어떤 순서로 진행하더라도 테스트할 때 문제가 되지 않는다.

하지만 싱글톤 패턴은 하나의 인스터스를 기반으로 구현하고 있는 디자인 패턴으로 각 테스트 마다 독립적인 인스턴스를 가질 수 없다.

💡 TDD?
Test Driven Development. 테스트 주도 개발이라고 한다. 프로그램 개발 시 불확실성이 높을 때 개발 방법이다.
TDD 사이클은 실패할 테스트 구현>성공할 프로덕션 테스트 코드>테스트 코드와 프로덕션 코드의 중복 제거 리팩토링 순서로 이루어진다.
TDD를 이용하면 개발이 끝난 뒤 테스트 코드를 작성하지 않아도 되고 단위 테스트를 진행 시 전체 코드를 돌리지 않기 때문에 개발 중인 코드를 테스트하기에 적합하다는 장점이 있다.

팩토리 패턴(Factory pattern)

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

부모, 자식 클래스가 분리되어 있기 때문에 느슨한 결합도를 가지고 있고 부모 클래스는 인스턴스 생성 방식에 관여하지 않게 되기 때문에 더 많은 유연성을 갖는다는 장점이 있다. 또한, 객체 생성 로직이 따로 분리되어 있기 때문에 코드를 리팩터링 해도 한 부분만 고칠 수 있기 때문에 유지 보수에 유리하다.

🤔 왜 사용할까?

예를 들어 빵가게라는 프로그램을 만들기 위해서 다양한 종류의 빵(객체)를 만든다고 가정해보자. 마늘빵, 소금빵, 피자빵 … 다양한 빵 클래스를 만들어서 팔던 도중 빵가게에서 들어오는 밀가루가 쌀가루로 변경됐다. 그러면 나는 내가 만들어둔 모든 빵(클래스)에 대해서 밀가루를 하나씩 수정해야 하는 대참사가 일어난다.

이때 Bread라는 부모 클래스가 밀가루를 갖고 있고 마늘빵, 소금빵, 피빵이 Bread를 상속 받고 있는 상태라면 어떨까?

Bread에 있는 밀가루만 수정하면 Bread를 상속 받고 있는 자식 클래스들을 하나씩 수정해주지 않아도 된다! 이렇게 부모 클래스를 상속 받고 있지만 빵을 만들기 위해서 필요한 뼈대만 가지고 있기 때문에 구체적인 재료는 자식 클래스가 입맛대로 만들어낼 수 있게 된다.

전략 패턴(Strategy pattern)

정책 패턴(policy pattern)이라고도 부르는 전략 패턴은 객체의 행위를 바꾸고 싶은 경우 직접 수정하는 것이 아니라 “전략”이라고 부르는 “캡슐화한 알고리즘”을 컨텍스트 안에서 바꾸면서 교체할 수 있도록 만드는 패턴이다.

예를 들어 어떤 물건을 사고 결제하려고 할 때 애플페이, 카카오페이, 삼성페이 등 여러가지 방법으로 결제할 수 있는 것처럼 물건을 사려고 할 때 결제 방식, “전략”만 바꿔서 결제하도록 하는 것을 말한다.

🤔 왜 사용할까?

전략 패턴을 이용하면 원하는 알고리즘을 선택적으로 교환할 수 있다. 상속을 이용하는 경우 공통된 내용을 분리해서 처리할 수 있지만 클래스간의 결합도(의존성)을 증가 시키고 인터페이스는 알고리즘의 구현 클래스를 적용해야하면서 사용하지 않을 메소드도 반드시 구현해야 하기 때문에 오버헤드가 발생하게 된다.

전략 패턴을 이용하면 알고리즘의 객체를 교환하여 사용한다는 점에서 유용하게 된다. 또한, 행동 변경 시 조건문을 사용하지 않기 때문에 알고리즘 캡슐화를 통해서 조건문 없이 원하는 행동으로 교체할 수 있게 된다.

옵저버 패턴(Observer pattern)

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

옵저버 패턴은 상태 변화에 따라 변화를 알리기 때문에 주로 이벤트 기반 시스템에서 사용하게 된다. 주체에 변화가 생겨 옵저버의 뷰에 변경 데이터를 알려주기 위해 컨트롤러가 작동하는 것을 보면 MVC 패턴에서도 사용된다 볼 수 있다.

💡 옵저버?
객체의 상태 화에 따라 전달되는 메소드 등을 기반으로 추가 변화 사항이 생기는 객체들을 의미한다.
예를 들면 인스타에서 내 계정(주체)를 팔로우하고 있는 계정들을 옵저버라고 말할 수 있다. 내가 인스타 게시글을 올리거나 스토리를 업로드하면 그 변화를 감지하고 옵저버(팔로워)의 피드에 내가 업로드한 게시글이 떠야 한다.

프록시 패턴(Proxy pattern)

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

프록시의 특징은 하나의 객체를 두 가지로 나눠서 재구성한다는 점에 있다. 직접적인 접근을 막고 대리할 객체를 구현하기 위하기 위해서다. 프록시 패턴은 응용되는 범위가 넓어서 원격 프록시, 가상 프록시, 보호 프록시, 스마트 프록시 등 다양하게 파생된 프록시들이 존재한다.

프록시 서버

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

  1. nginx

    프록시 서버로 사용하는 nginx(엔진엑스)는 비동기 이벤트 기반의 구조와 다수의 연결을 효과적으로 처리하는 웹 서버이다. 주로 Node.js 서버 앞에 프록시 서버로 활용한다. nginx를 프록시 서버로 두고 실제 포트를 숨기며 정적 자원을 gzip 압축하거나 메인 서버 앞에서 로깅을 하기도 한다. 이렇게 익명 사용자의 직접적인 서버 접근을 차단하고 간적접으로 한 단계를 거치면서 보안성을 강화시킨다.

  2. CloudFlare

    CloudFlare는 시스템 콘텐츠를 전 세계적으로 분산된 서버에 빠르게 전달할 수 있는 CDN 서비스이다. CDN 서비스 외에도 DDOS 공격 방어, HTTPS 구축을 제공한다.

이터레이터 패턴(Iterator pattern)

이터레이터(interator)를 사용해서 컬렉션 요소들에 접근하는 디자인 패턴을 말한다. 자료형의 구조와 상관없이 이터레이터라는 하나의 인터페이스를 이용해서 순회할 수 있다.

컬렉션 요소를 가지고 interator() 메소드 사용하기

[컬렉션]ArrayList, Set, Map, Tree

노출모듈 패턴(Revealing module pattern)

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

💡 즉시 실행 함수?
함수를 정의하자마자 바로 호출되는 함수로 초기화 코드, 라이브러리 내 전역 변수의 충돌 방지 등에 사용한다.

MVC 패턴

MVC 패턴은 Model, View, Controller로 이루어진 디자인 패턴을 말한다. 애플리케이션의 구성 요소를 3가지로 구분해서 각 구성 요소에만 집중해서 개발할 수 있도록 한다. 재사용과 확장성이 용이하다는 장점을 갖고 있지만 애플리케이션이 복잡해질수록 Model과 View의 관계가 복잡해진다는 단점을 갖는다.

Model

모델은 애플리케이션의 데이터인 DB, 상수, 변수 등을 뜻하는데 뷰에서 데이터를 생성하거나 수정하면 컨트롤러를 통해 모델을 생성하거나 갱신하게 된다.

View

뷰는 사용자 인터페이스 요소를 나타낸다. 모델을 기반으로 사용자가 볼 수 있는 화면을 말하는데 모델이 갖는 정보를 따로 저장하지 않고 단순히 화면에 표시하는 정보만을 갖는다. 또한 화면에서 어떤 변경이 일어나는 경우 컨트롤러에 이 변경을 전달한다.

Controller

컨트롤러는 모델과 뷰를 이어주는 다리 역할을 한다. 또한 이벤트 등 메인 로직을 담당하고 있다. 모델과 뷰의 생명 주기를 관리하기도 하며 모델이나 뷰에서 변경 사항을 받으면 해당 사항에 대해서 해석하여 각 구성 요소에 해당 내용을 전달한다. 즉, 어떤 요청이 왔을 때 어떤 동작을 행동할지 컨트롤하는 역할을 한다.

MVP 패턴

MVC 패턴에서 파생된 패턴으로 컨트롤러가 프레젠터(presenter)로 교체된 패턴을 말한다. 뷰와 프레젠터가 1:1 관계를 가지고 있기 때문에 MVC 패턴보다 더 강한 결합도를 지닌 디자인 패턴이다.

MVVM 패턴

마찬가지로 MVC 패턴에서 파생된 패턴으로 컨트롤러가 뷰모델(view model)로 교체된 패턴이다. 뷰모델은 UI 관련 데이터를 저장, 관리하며 뷰를 더 추상화한 계층이다.

뷰와 뷰모델 사이에서 양방향 데이터 바인딩을 지원하며 UI를 별도의 코드 수정 없이 재사용할 수 있고 단위 테스팅이 쉽다는 장점을 가진다. 대표적인 프레임워크로 Vue.js가 있다.

💡 데이터 바인딩?
화면(UI)에 보이는 데이터와 웹 브라우저의 메모리 데이터를 일치시키는 기법. 뷰모델을 변경하면 뷰가 변경된다. MVVM 패턴을 이용하면 코드량이 감소한다는 장점이 있지만 이처럼 데이터 바인딩을 필수로 갖고 설계가 어렵다는 단점이 있다.

참고 서적 : 면접을 위한 CS 전공지식 노트 - 주홍철

profile
천천히 기록해보는 비비로그
post-custom-banner

0개의 댓글