한국어 | English | 日本語
8.8년차 Web Application Developer 웹 개발자
기술·개발
engineering
웹 프론트엔드 및 백엔드 개발에 관련된 내용들을 주로 다룹니다

1. '디자인 패턴'이란?

Design Patterns 개요
디자인 패턴은 대학교에서 간단하게만 배웠던것으로 기억한다. 대학원이나 입사 준비시 디자인 패턴은 항상 시험에 나오는 주제였지만, 필자는 실제로 사용해본 경험이 적었기에 왜 이것이 중요한지에 대해서 체감할 일이 없었다. 부트코드와 이론보단 프로젝트를 많이하는 요즘의 시대엔 좀 다르겠지만 필자는 패턴이 왜 쓰이는지 경험적으로 습득한것은 입사하고 나서부터였기 때문이다.
다양한 디자인 패턴을 공부하기에 앞서, 왜 디자인 패턴이 필요한지? 그리고 디자인 패턴을 이해하는데 도움이 될 클래스 다이어그램을 짧게 학습해보도록 한다.

디자인 패턴

디자인 패턴은 짧게 ‘객체지향 패러다임에서 더 좋은 코드란 무엇인가에 대한 고민의 결과’ 이다. 처음 이 개념은 Gang of Four 라는 4명의 프로그래머가 작성한 Design Patterns 책을 통해 세상밖으로 나오게 되었고, 이는 꼭 객체지향 프로그램이이 아니더라도 어느 언어에서도 통용될 수 있는 개발 방식들을 담고 있다.

다양한 패턴들을 찾아보기에 앞서, 모든 패턴들을 가로지는 원칙이자 패턴들이 생겨나게된 이유인 원칙 3가지를 알아보자면 다음과 같다.

디자인 패턴 3 카테고리

디자인 패턴은 위와 같이 3가지로 구분되어 각각 하위에 정말 다양한 개수의 패턴들이 위치한다. Refacotring Guru 페이지를 꼭 참조하길 바란다. 실제로 각 카테고리면 어떤 패턴이 존재하는지 볼 수 있고, 각 패턴별로 왜 생겨났고 어떤 개념인지 예제 코드들과 함께 앞으로 학습에 큰 도움이 될것이다.

주니어에겐 너무나도 먼 디자인 패턴

어떻게보면 큰 프로젝트를 진행해보지 않은 한 디자인 패턴을 모르는건 당연하다.

코드 한 줄의 변경이 다른 줄의 드라마틱한 변경을 일으킬만한 큰 프로젝트를 만들어본적이 없다.

교내 팀 프로젝트로 유저 폰으로부터 주변 AP 정보를 받아 라즈베리 파이에게 해당 고객 위치를 전달해주는 재실표시기를 만들었을때도, 2개의 서버를 만들었음에도 코드가 복잡할것이 없었기에 패턴을 적용하고 말고를 고민할 것이 없었다. 학생분들이라면 알테지만, 계획 및 구축 60%, 개발 20% 를 사용한 뒤 남은 20% 은 술마시기에 여념이 없다.

또한, 팀 프로젝트 코드는 다신 볼일이 없다. 요구사항 변경을 요청할 교수도 다른 프로젝트에 활용할 일도 없다.

‘디자인 패턴’은 면접을 준비할때면 언제든 반복해서 접하는 주제지만 결국엔 코드로써 직접 프로젝트를 개발해보며 직접 겪어야한다. 본 블로그에 정리하는 디자인 패턴 글들은 이해에 주안점을 두고, 까먹지 않도록 복습하기 쉬운 형태로 짧게 게시하려한다. 각 패턴들은 글로 명료하게 설명하려 노력하겠지만 클래스 다이어그램에 대한 이해가 있어야, 더 구현에 맞는 이해를 할 수 있다.

클래스 다이어그램 - 화살표

클래스 다이어그램은 이름 자체가 내포하고있듯 Class 간의 관계를 표로 간단하게 설명한 것으로 Class 개념이 존재하는 객체지향 프로그래밍(OOP)에서 프로젝트 구현을 위한 설계도라고 보면 된다. 클래스 다이어그램은 Class, Interface 이 2개의 관계를 설명할 Implements, Extends, Composition 딱 이 3개의 핵심적인 화살표만 살펴보면 끝이다. 코드는 java-like psudo code 기반으로 설명한다.

implements (구현)

Implements

앞선 객제지향 프로그래밍 글을 잘 읽었다면, 객체지향 코드는 Class 보다 Interface 를 단위로 구성된다는것을 이미 알고있을것이다. ‘어떤 작업을 수행할지’는 Interface 로 명시한 채, ‘어떻게 작업할지’는 원하는 구현 클래스(Concrete Class) 를 적재적소에 주입하여 실제 작업을 수행한다.

Class 를 처음 배운 뒤엔 아래와 같이 정의하여 사용한다.

ConcreteClass clazz = new ConcreteClass();

그 다음 Interface 와 다형성을 배우면 Interface 에 구현 클래스(Concrete Class)를 대입할 수 있다.

Interface clazz = new ConcreteClass();

실전에선 유연성을 위해서 구현 클래스가 무엇인지 바로 명시하지 않고, 원하는 구현 클래스를 동적으로 Interface 에 외부에서 주입해주는 방식을 사용한다. 구현 클래스를 주입하여 수행한다는 의미에서 Dependency Injection 혹은 코드 자신이 ‘구현 결정권’을 갖지 않는다는 이유로 이를 Inversion of Control 라 부르기도 한다. 이건 매우 깊게, Spring 글에서 따로 다루겠다.

private Interface clazz;
public void setClass(Interface clazz) {
    this.clazz = clazz;
}
setClass(new ConcreteClass();

extends (상속)

Extends

상속은 Class 의 몇몇 함수에 대해 추가적인 기능을 확장하거나, 다른 로직의 함수로 대체할때 사용한다. 라떼는 상속을 Animal ‘부모 클래스’에 Cat, Dog 과 같은 ‘자식 클래스’로 배웠었는데, 이와 같은 상위-하위 개념은 앞서 배운 Implements 가 적절하고, 상속은 단순 기능/정의 확장에만 사용한다. 즉, 잘못배웠던 셈.

Cat 중에서 줄무늬가 있는 Cat 을 StripeCat 으로 정의할때, Cat 의 줄무늬를 제외한 모든 함수와 변수는 동일하다.

composite (구성, 합성)

Has-A

Class 의 기능/정의 확장에 상속만 있는것은 아니다. 구성도 있다.

객제지향 프로그래밍에선 상속(extends)보다 구성(composite)을 사용하라고 할까? 다시 한번 복습하자면

위 구성 예시 그림을 아래와 같이 interface(implements)를 추가했더니, Cat 종을 더 잘 표현할 수 있게 되었다.

Has-A and Implements

상위 개념인 ‘종’ 하위에 ‘줄무늬 종’, ‘검은 종’ 등을 다 처리할 수 있는 확장성을 갖게되었다. 바로 직전 상속(extends) 예시와 비교해보면, 자식 클래스였던 SpriteCatClass 가 갖고있던 Sprite 정보가 Cat 클래스 밖인 SpriteClass 로 이동되었다. 왜 Inversion of Control 라고 부르는지 알 수 있는 대목이다.

Openess, when we use Has-A and Implements

Cat 이 ‘줄무늬 종’뿐만 아니라 ‘오드아이’ 눈을 갖는다 가정해보자. 이 또한 interface(implements) 와 composite 을 통해 EyesClass 에 OddEyesClass 를 명시함으로써 Cat 은 이제 ‘종’과 ‘눈’에 확장성을 갖게 되었다.

이로써 앞서 배운 객제지향 프로그래밍의 제 1 원칙 “‘클래스-상속’보다 ‘인터페이스-구성’을 사용하라”와 제 2 원칙 “‘구현 클래스’보다 ‘인터페이스’로 구성하라”와 을 다시 한번 되새김질 할 수 있었다.

이제부턴 2 개의 원칙과 3 개의 화살표(구현, 상속, 구성)로 디자인 패턴들을 살펴보자.


  1. https://martinfowler.com/articles/injection.html
  2. http://www.nextree.co.kr/p11247/
  3. http://www.nextree.co.kr/p6753/
1. '디자인 패턴'이란?
Author
Aaron
Posted on
Licensed Under
CC BY-NC-SA 4.0
CC BY-NC-SA 4.0
같은 카테고리 내 다른 글들
최근에 게시된 글들
토스트 예시 메세지