Introduction

우리나라말로 전략(strategy)라고 부르는 이 패턴은 GoF의 분류에서 보면 '행위'에 속합니다.
우선 코드를 통해 생각해 보고, 설명하도록 하겠습니다.
간단한 ATM Machine 을 만들어 봅시다. 조건은 TCP 방식과 UDP 방식으로 은행 DB서버와 통신해야 합니다.

※ 코드가 다소 부실하거나, 억지스러울 수 있으나 요점은 패턴에 대한 이해이기 때문에 너그러히 봐 주시기 바랍니다.

ATM Machine 만들기

패턴은 생각치 않고, 만들어 봅시다.
C와 같이 절차지향 언어만 하다가 객체지향을 처음 접한 사람이 흔히들 만드는 바보같은 코드입니다.
(물론 함수 포인터를 이용하면 얼마든지 해결 할 수 있습니다 ^-^)


TCP로 할 것인지 UDP로 할 것인지 Flag 를 하나 두고, 이에 따라서 동작 방식을 변경하도록 만들었습니다. 물론 동작은 이상없이 잘 될 것입니다.

프로젝트의 요구사항 변경

"TCP, UDP 이외에 회사 제체 개발한 WIT 방식으로 통신이 가능하도록 추가해 주세요" 라는 요구사항을 전달 받았다고 가정합시다.

위 코드는 어떻게 수정/추가 되어야 할까요?
현재 구조로는 Flag 에 WIT 를 추가하고(bool 이 아닌 enum을 써야 겠지요), 모든 함수에 if 조건문을 추가해야만 합니다.

잠시 생각해 보죠. 이런 방식으로 조건이 계속 하나 둘 추가된다면 어떤 불편함/문제점이 생기게 되나요?
그렇습니다. 매번 이미 작성해 놓은 코드를 수정/추가 해야 하는 번거로움이 발생합니다. 그럼 어떻게 해야 할까요?

객체지향에 '상속'을 사용하면 되겠군요. 코드를 변경해 봅시다.

상속을 이용해 봅시다

 우선 통신방식에 대한 부분을 제외하고 나머지 부분을 ATMMachine 이라는 부모 클래스로 만들어 봅시다.
그리고 통신에 따라 이를 상속받는 자식 클래스를 만들면 될 것입니다.







이렇게 한다면 새로운 WIT 통신방식을 추가하더라도 기존 코드를 변경할 필요가 없겠군요.
그런데 또 다른 문제가 발생하였습니다.

통신 방식을 매 순간 마음대로 변경할 수 있도록 해 주세요

위와 같은 요구사항이 들어왔습니다.
지금의 방법으로는 동적으로 통신 방식을 변경한다는게 불가능 합니다. 왜냐면 위에 코드에는 생략한 수많은 부모 클래스의 상태(Login 등)들을 유지하기 힘드니까요. 단순히 통신 방식만을 변경하면 되는데, 수 많은 문제점들이 발생하게 됩니다.

이제 패턴을 적용해 봅시다.

StrategyPattern

패턴을 적용해 보겠습니다.









자, 이제 새로운 WIT 통신방식 뿐만 아니라 새로운 통신 방식을 추가하더라고, 기존 완성된 코드는 전혀 손을 댈 필요가 없어졌습니다.
왜냐면 INetwork 라는 Interface 를 구현하는 클래스를 새로 만들어 주기만 하면 되니까요.

이렇게 필요한 '행동'에 대한 부분만 따로 때어서 개발하면, 유지보수의 상당한 비용을 줄일 수 있게 됩니다.

Pattern 정리

Strategy 패턴은 다음 세가지 문제를 해결 하기 위해서 많이 쓰입니다. 물론 공식적인 내용이라기보다 제 개인적인 경험에서 나열해 놓은 것입니다.

1. 함수의 '행동(동작)'이 실시간 적으로 변경되어야 할 경우

게임을 만든다고 가정해 봅시다. 게임속 유닛은 자신이 들고 있는 무기(권총, 칼, 주먹 등)에 따라서 공격 방식이 바뀝니다. 호출하는 쪽에서는 Attack() 을 호출하지만, 행동 방식이 변경되야 한다는 것입니다. 이럴 경우 Weapone 이라는 Interface 를 만들고, 각각의 무기는 이를 구현하면 될 것입니다.

2. 상속 구조에서 '행동(동작)'을 재사용 할 경우

상속은 객체지향 프로그래밍에서 필수적인이며, 코드의 재사용을 하기 위해서 많이 사용됩니다.
A, B, C 에서 같은 동작을 P클래스로 빼내고, A, B, C가 이를 상속받는 구조로 구현하지요.
다음 상황을 생각해 봅시다. Move 라는 abstract method 가 부모클래스 P에 추가되었습니다. A, B는 '걸어서' 이동을 해야하고, C는 '차를 타고' 이동한다고 합시다.

지금과 같은 구조에서는 A, B에 같은 코드가 작성되겠죠. 코드의 재사용을 할 수 없습니다. 재사용을 하기 위해서라면 클래스를 추가로 하나 더 만들어 P와 A,B 사이에 끼워 넣거나, 다른 방법을 써야 합니다.

이때 동작 Move 에 대해서 Interface로 만들고, 이를 상속받은 Walk, Vehicle 을 만들어 사용한다면 쉽게 해결 할 수 있습니다.

3. 조건문을 없애기 위해서

정확히 기억은 나지 않지만, 마틴 파울러의 리팩토링이라는 책에 보면 조건문은 구조를 통해서 충분히 없앨 수 있다고 되어있습니다. 다시말해 복잡한 if / else 문이나 switch 문이 있다면, 이것은 설계가 잘못 되었다는 것입니다. 이때 strategy 패턴을 사용하면 얼만든지 이 문제를 해결 할 수 있습니다.

신고

Introduction

안녕하세요? 앞으로 디자인패턴(DesignPattern)에 대해서 연재를 시작할 위트의 언더입니다.

여러분들은 어떠신가요?
디자인패턴에 대해서 얼마나 알고 계신가요? 알고있는 패턴은 얼마나 되나요?

 제가 처음 이것에 대해서 듣고 공부한때가 21살, 대학 2학년 나름 풋풋했던 때인것으로 기억합니다. 하지만 지금 기억나는 패턴은 몇 가지 되지 않고, 또한 실제로 활용하는 패턴은 그 보다 적은 수 인것 같습니다. 사실 패턴이라는 것이 개발하면서 관습적으로 자연스레 만들어진 것이기 때문에, "이것을 적용해서 개발을 하느냐" 라는 질문 자체가 우습긴 합니다. 패턴을 적용하지 않고 개발을 했다고 해도, 그것은 GoF(Gang of Four)가 정리한 패턴이 아닐 뿐이지, 나름 자신만의 패턴이 될 수 있으니까요. 그렇다고 해서 패턴이 중요하지 않다는 이야기는 아닙니다. GoF가 정리한 패턴은 오랜 기간동안 소프트웨어 공학의 역사에서 문제해결에 뛰어나다고 검증된 것들이기 때문입니다.

 참, 우리가 흔히 말하는 디자인패턴은 GoF가 만든것이 아니라, 개발에 있어서 문제 해결방식(패턴)을 정리했을 뿐 입니다. 다시말해, 오래전부터 사람들이 어떤 형태(패턴)의 문제를 해결하기 위해서 사용했던 방법을 체계화 했다는 말입니다.

 더불어 사견입니다만, 저는 개발자에게 정말 중요한것은 디자인패턴, 리팩토링, TDD, XP 와 같은 방법론이라고 생각합니다. 아무렇게나 프로그램이 돌아가도록 만드는 것은 '프로그래밍 언어'를 아는 사람이라면 누구나 만들 수 있습니다. 프로와 아마추어의 차이는 앞서 언급한 것들에서 온다고 생각합니다. 대규모 프로젝트에서 정말 중요한 것은 구현이 아니라 유지보수이기 때문입니다.



DesignPattern의 시작

디자인 패턴은 본래 건축학에서 쓰이는 용어였답니다. 건축가인 '크리스토퍼 알렉산더'가 건축의 여러가지 기법을 패턴으로 정리한데서 비롯되었지요. 당시 건축학에서는 큰 인기를 얻지 못하고, 컴퓨터 공학에서 이 방식을 도입하기 시작했습니다. 이를 구체화 시키고 체계화 시킨 사람이 에릭감마, 리차드 헬름, 랄프 존슨, 존 블리시디스. 즉 GoF(Gang of Four)입니다.
이들은 패턴을 23가지로 정리하고, 생성, 구조, 행위 3가지로 분류하였습니다.

패턴의 종류

생성패턴(creational)
Abstract Factory
Builder
Factory Method
Prototype
Singleton

구조패턴(Structual)
Adapter
Bridge
Composite
Decorator
Facade
Flyweight
Proxy

행위패턴(Behavioral)
Chain of Resp
Command
Interpreter
Iterator
Mediator
Memento
Observer
State
Strategy
Template Method
Visitor


앞으로 위 패턴들을 중심으로 구조를 알아보는 시간을 갖도록 하겠습니다.

신고