brunch

You can make anything
by writing

C.S.Lewis

by 홍성호 Apr 23. 2019

[서평] 코드로 작성된 드라마, 디자인 패턴

JAVA 언어로 배우는 디자인 패턴 입문을 읽고서

지난달에 헤드퍼스트 디자인 패턴을 읽었습니다. 객체의 역할에 관심을 갖게 되었고, 설계 원칙에 대해서 어렴풋이 배웠습니다. 한 가지 아쉬웠던 점이 GoF의 디자인 패턴 책에 나오는 모든 패턴을 배우지 못했다는 점이었습니다. 그래서 다음 책으로 GoF로 넘어가려 했지만, 좀 더 실력을 쌓고 읽어보는 것이 좋다는 조언을 들었습니다. 대신 ‘JAVA 언어로 배우는 디자인 패턴’을 읽었습니다.

이 책은 학부 과정 때 디자인 패턴 수업의 교과서로 쓰이기도 했습니다. 솔직히 그때는 책을 읽을 생각은 별로 안 했습니다. 이런 원리를 배우기보다는 눈에 보이는 결과물을 빠르게 만들어보고 싶다는 생각이 강했습니다. 과거를 반성하는 마음으로 이번에는 모든 연습문제를 풀어보면서 시간을 두고 고민했습니다.


헤드퍼스트 디자인 패턴과는 다른 구석이 많았습니다. 문제에 대한 맥락 없이 갑자기 예제 프로그램부터 나오는 느낌이라서, 흥미가 덜 생긴다는 아쉬운 점이 아쉬웠습니다. 하지만 끝까지 읽어보니 익숙해져서 재밌게 읽을 수 있었습니다. 제가 생각하는 이 책의 장점은 다음과 같습니다.  


클래스 다이어그램을 읽는 방법을 익히고, 객체 간의 관계를 ‘패턴의 등장인물’ 코너에서 자세하게 볼 수 있습니다.

해당 패턴에서 알 수 있는 설계 철학을 ‘독자의 사고를 넓히기 위한 힌트’에서 배울 수 있습니다.


패턴의 등장인물

드라마를 보면 등장인물들이 있습니다. 재밌는 드라마는 각 캐릭터 뚜렷하고 인물들 간의 관계를 통해 긴장감을 느낄 수 있죠. 그런 것과 비슷하게 객체지향 프로그램에서는 등장인물들이 있고, 그 인물들 간의 관계가 있습니다. (드라마처럼 적대관계는 없겠지만요)

드라마의 인물관계도와 클래스 다이어그램


책의 제일 처음에는 UML에 대한 설명부터 나옵니다. 앞서 얘기했듯이 반성하는 마음을 가지고 읽었기 때문에 원래라면 대충 지나갔을 테지만, 이번에는 정성껏 읽어봤습니다. 클래스 다이어그램의 정의를 보면 다음과 같습니다.

UML의 클래스 다이어그램(Class Diagram)은 클래스나 인스턴스, 인터페이스 등의 정적인 관계를 표현한 것입니다.

처음에는 뭔가 무지막지해 보이고, 화살표들을 따라가는 게 쉽지 않았는데 책에는 최대한 단순하게 되어있어서 개념을 잡기 좋았습니다. 화살표의 종류가 많은데 책에서 소개된 3가지만 알아보겠습니다. 화살표의 방향이 일단 헷갈리는데, 화살표를 가리키는 것을 알고 있다고 생각하면 좋습니다. 상대를 지목하려면 상대를 알고 있어야 합니다.

상속: 하위 클래스에서 상위 클래스로 화살표가 향합니다. Child 객체는 Parent 객체를 알고 있습니다. Parent객체 입장에서는 Child 객체가 존재할지 모릅니다.

인터페이스 구현: 구현 클래스에서 인터페이스로 화살표가 향합니다.

갖고 있음: 집약(aggregation)이라고 표현되는데, 갖고 있음으로 표현하는 게 더 직관적이라서 그렇게 적어봤습니다. Basket 안에는 Fruit가 있습니다. Basket은 Fruit를 갖고 있습니다.


이제 화살표에 대해서 배웠으니, 제가 좋아하는 Strategy 패턴을 클래스 다이어그램을 통해 읽어보겠습니다. 어떤 문제를 해결할 때 상황에 맞는 전략을 선택하곤 합니다. 그것을 객체로 표현한 것이 이 패턴입니다.


Context는 전략을 선택하고 실행하는 역할을 합니다. 선택한 전략을 실행하려면 전략을 소유하고 있어야 합니다. 그래서 앞에서 배웠던 것과 같이 갖고 있음을 표현하기 위해 마름모(◇)가 있는 화살표를 사용했습니다.


알고리즘에 따라 Strategy의 구현은 다르지만, 외부에서 호출할 때 같은 형태로 호출합니다. 예를 들어 정렬을 한다고 하면 Quick Sort, Selection Sort 등 많은 구현 방법들이 있지만, 이것을 외부에서 사용할 때는 “정렬해줘”라는 한마디만 있으면 됩니다. 같은 형태를 따르기 때문에 interface로 표현되었습니다. interface의 구현은 점선으로 표현한다고 했습니다. 그래서 점선으로 연결되어 있습니다.


이전에는 별로 관심 없었던 클래스 다이어그램이 중요하다고 생각하게 되었습니다. 다이어그램이 있으면 객체 관의 관계를 볼 수 있고, 차츰차츰 머릿속으로도 관계를 그려볼 수 있기 때문입니다.


독자의 사고를 넓히기 위한 힌트

패턴을 설명하고 나서 그치는 것이 아니라, 패턴으로 부터 얻을 수 있는 교훈을 설명하는 부분입니다.


부품으로써 재사용이 가능한가

지금 당장의 문제만 해결할 뿐 아니라, 앞으로도 다시 쓸 수 있을지에 대한 고민을 해야 한다는 것입니다. 프로그램을 작성할 때 완성된 것으로 보면, 재사용에 대한 고민을 하지 않게 됩니다. 앞으로도 계속해서 변화할 것이라는 전제로 두고 다음에도 사용될 수 있도록 해야 합니다. 그래서 ‘추상 클래스나 인터페이스를 사용해 프로그래밍한다’는 가르침이 있습니다. 결합을 약하게 해서 재사용 가능하게 만들어줍니다.


설계 시에 결정할 수 있는 것과 결정할 수 없는 것

재사용에 대한 고민을 하기 시작하면 딜레마에 빠집니다. 프로그램이 완결된 것으로 생각하지 않는다면, 얼마나 먼 미래까지 고민해야 할까? 이런 고민에 대한 해답으로 아래와 같이 나와있습니다.

클래스 설계자는 신이 아니기 때문에 가까운 미래에 일어날 모든 것을 예상할 수 없습니다. 단지, 가까운 미래에 발생할 것으로 예상되는 변화에 적응할 수 있도록 설계해야 합니다.

너무 먼 미래까지 염두해서 코드를 작성하면, 오버 엔지니어링에 빠지게 됩니다. ‘가까운 미래’라는 표현이 여전히 애매한 부분이지만, 사소한 변화가 있을 때 핵심 로직을 변경하지 않도록 만들어야겠다고 생각했습니다.


OCP: Open-Closed Principle

사소한 변화가 있을 때 핵심 로직을 변경하지 않아야겠다는 생각과 연결되는 부분이 OCP라고 생각합니다. 확장에 대해서는 열려있지만, 수정에 대해서는 닫혀 있어야 한다는 원칙입니다. 책에는 이런 설명이 있습니다.

이미 완성되어 테스트까지 마친 클래스를 수정한다면 소프트웨어의 품질을 떨어뜨릴 위험이 있습니다.

이 글을 읽기 전에는 OCP가 제대로 지켜지지 않는다면, 기능을 확장할 때 기존 클래스를 변경하는 번거로움이 있다는 정도로만 생각했었습니다. 검증된 부분을 검증되지 않은 부분으로 바꿔놓고, 의도치 않은 부수효과가 생길 수 있다는 점을 알게 되었습니다. 그래서 OCP가 프로그램의 품질과도 직결된다는 생각을 하게 되었습니다.


문제 상황을 클래스로 표현하기

이 부분은 책에 명시되어 있지 않은 제 생각입니다. 컴파일러 수업을 들을 때 작동방식이 이해가 안 가서 고생했던 기억이 있습니다. 그런데 Interpreter 패턴을 보면서 조금 놀랐습니다. 컴파일러를 위해 정의한 문법 자체도 객체로 옮겨 올 수 있고, 그것을 한번 설계해두면 아무리 복잡한 호출도 클라이언트 입장에서는 단순하게 사용할 수 있었습니다. 생각해보면 State 패턴도 ‘상태’ 자체를 객체로 만드는 방법이었습니다. 어떤 문제 상황이던지 추상화해서 복잡한 것을 단순하게 만들어가는 것을 보면서, 앞으로 복잡한 상황을 단순하게 만드는 노력을 해봐야겠다는 생각을 했습니다.


정리

이번 책을 통해 등장인물 간의 관계를 파악하는 연습을 할 수 있었습니다. 그 관계를 설계할 때 주의해야 할 점에 대해서도 패턴을 예시로 배울 수 있었습니다. 지난번에는 GoF의 디자인 패턴 23가지를 다 배우지는 못했는데, 이번에는 간단한 예제로 훑어볼 수 있어서 좋았습니다.


다만 지난 책과 동일한 디자인 패턴이라는 주제라서, 이번에는 훨씬 빨리 읽고 이해할 것으로 생각했는데 또 새롭게 느껴졌습니다. 아직 객체지향에 대한 정확한 이해가 부족하다는 생각이 들었습니다. 그리고 공부를 할수록 프로그램을 작성하기가 어려워지는 느낌을 받았습니다. 어설프게 아는 단계를 얼른 벗어나서 객체 간의 관계를 한 편의 드라마처럼 쉽게 읽히고 명확하게 정의할 수 있으면 좋겠습니다. 읽어주셔서 감사합니다.

작가의 이전글 [서평] 디자인 패턴의 가치와 앞으로의 계획
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari