Head First Design Patterns를 읽고서
안녕하세요 이번에 Head First Design Patterns를 읽고 현재 실력에서 드는 생각과 앞으로의 계획에 대해 정리해보려 합니다. 주니어 개발자라서 객체의 설계에 대한 경험이 많지 않습니다. 잘못된 개념이 있을 수도 있으니, 자유롭게 피드백 주시면 앞으로 학습해가는데 많은 도움이 될 것 같습니다.
요즘 회사 앱에 설정 화면을 위한 라이브러리를 만들고 있습니다. 작년부터 진행을 했었는데, 첫 번째 버전으로 완성했던 것은 기대했던 것과 생김새가 다르고, 사용법이 달랐습니다. 그래서 올해 두 번째 버전을 만들었습니다. 직접적인 구현보다 나름대로 설계에 대해 더 많이 고민하며 만들었습니다. 작년에 만들 때는 RxSwift를 어떻게든 사용하면 더 좋은 코드가 작성될 것으로 막연히 기대하며 작성했기 때문에, 이번에는 MVVM에 대해서 좀 더 많이 고민하고 적용해보기로 했습니다.
MVVM을 공부하면서 WPF 진영의 블로그 글도 정리해보기도 했습니다. Model이 변경되면 ViewModel을 생성하고 View에 그것이 반영된다는 단순한 내용이었지만, 실제로 각 객체가 어떤 책임을 가지고 있는지 구체적으로 정의하는 것은 쉽지 않았습니다. 플랫폼의 상황별로 약간의 변주가 있다는 것도 알게 되었습니다. 현재 상황에 맞게 나름대로 정의하고, 적용을 했더니 제 기준에서는 예전보다 나은 프로그램을 작성할 수 있게 되었습니다. (물론 나중에 코드를 봤을 때는 부끄럽겠지만요)
이번 일로 객체의 역할을 어떻게 나누는지가 중요하다는 것을 알게 되었습니다. 객체의 역할을 잘 나눠둔 것이 패턴이라는 추측을 하게 되었습니다. 정말 그런지 확인하고 싶었고, 디자인 패턴에 대한 책을 찾아보게 되었습니다. 학부 때 수업으로 패턴들의 이름을 달달 외운 것 밖에는 기억이 나지 않았기 때문에, 이 참에 제대로 확인해보는 것이 좋겠다는 생각을 했습니다. 왠지 학부생 때 읽었어야 하는 입문서라는 느낌이 들어서 조금 부끄러웠지만, 기초부터 차분히 고민하는 것이 제일 빠른 길이라는 믿음을 가지고 Head First Design Patterns를 구입했습니다.
조금 산만하긴 하지만 이야기로 풀어낸다는 점에서 흥미로웠습니다. 그리고 각 챕터별로 복습이 있기 때문에 헷갈리는 내용이 정리되는 느낌을 받았습니다. 객체들이 역할을 나누고, 그 객체들을 유연하게 소통시키는 방법을 알 수 있었습니다. 추상적인 개념으로 다가왔던 몇 가지 객체지향 원칙에 대해서, 문제 상황에 적용시키면서 배울 수 있었다는 점이 좋았습니다.
책을 읽기 전에 원칙에 대해서 들어본 것은 ‘SOLID 원칙’을 처음 접했었습니다. 구체적인 문제 상황에서 원칙을 접한 것이 아니라서, 좋은 건 알겠는데 뭔가 전설 속에만 존재하는 느낌으로 다가왔습니다. 책에는 특정 패턴을 사용해서 구체적인 문제를 해결하고, 그 속에 숨어있는 원칙을 소개하는 식으로 설명되어 있습니다. 아쉽지만 이 글에서 그 문제 상황을 다 설명할 수 없기 때문에 기존과 비슷하게 원칙을 나열하는 식이 될 것 같습니다.
바뀌는 부분을 캡슐화한다.
상속보다는 구성을 활용한다.
구현이 아닌 인터페이스에 맞춰서 프로그래밍한다.
서로 상호작용을 하는 객체 사이에서는 가능하면 느슨하게 결합하는 디자인을 사용해야 한다.
클래스는 확장에 대해서는 열려 있지만 변경에 대해서는 닫혀 있어야 한다. (OCP)
추상화된 것에 의존하라. 구상 클래스에 의존하지 않도록 한다.
친한 친구들하고만 이야기한다.
먼저 연락하지 마세요. 저희가 연락드리겠습니다.
어떤 클래스가 바뀌게 되는 이유는 단 한 가지뿐이어야 한다.
한번 쓰고 버리는 코드라면 이런 원칙들이 도움이 되지 않을 것 같습니다. 하지만 적어도 지속적인 유지보수가 필요하다면 이런 원칙들이 도움이 된다고 생각합니다. 클래스 간의 역할 분리와 의존성을 느슨하게 만들도록 도와주기 때문입니다. 만약 회원관리 로직을 바꿨는데, 생각지도 못한 뷰를 수정하게 만드는 일을 없애줍니다.
바뀌는 부분을 캡슐화한다는 부분은 제일 처음에 나와있으면서도 대다수의 상황에 적용할 수 있겠다는 생각을 했습니다. 변하는 부분과, 변하지 않는 부분을 나눠보는 것입니다. 함수 단위로도 의미가 있고, 클래스 단위로도 의미가 있습니다. 변하는 것을 캡슐화해두면, 앞으로 유지보수할 때 특정 부분만 고치면 되기 때문에 유용합니다. 이런 원칙들은 유용하지만, 모든 상황에서 지킬 수 있는 것은 아닙니다. 장단점을 따져보고 장점이 큰 형태를 취해야 합니다.
그렇다면 이런 원칙들만 있으면 되는 것 아닐까요? 단편적인 몇몇 패턴들을 주워듣고 적용해보고 싶다는 마음 때문에, 불필요하게 클래스의 복잡도를 증가시키는 경험을 해본 적 있습니다. 그래서 디자인 패턴은 별로 중요하지 않다고 마음속으로 생각하고 있었습니다. 책을 읽으면서 이런 오해들이 조금씩 풀렸습니다.
디자인 패턴은 의사소통을 도와줍니다. 어떤 클래스를 설명할 때 “이 클래스는 자신에게 관심을 가지고 있는 모든 객체들을 관리하고 새로운 데이터가 들어올 때마다 자신에게 관심을 가지고 있는 객체들한테 메시지를 보냅니다. 더 멋있는 건, 그 방송용 객체에 관심을 가지고 있는 객체들이 언제든지 자신을 새로 청취자 목록에 추가할 수도 있고, 더 이상 관심이 없어지면 청취자 목록에서 탈퇴할 수도 있다는 것입니다.”라고 설명하는 것과 “옵저버 패턴”이라고 설명하는 것은 많은 차이가 있습니다. 한 단어로 간결하고, 정확하게 의사표현을 할 수 있습니다. 그리고 패턴이 적용된 코드를 유지보수할 때도 객체의 형태에 대해서 좀 더 빠르게 유추할 수 있습니다.
디자인 패턴은 문제 해결 시간을 단축해 줍니다. 이미 발견되어 있는 패턴들이 많기 때문에 상황에 맞게 드러나는 패턴을 선택해서 적용할 수 있습니다. 각 객체의 역할과 흐름을 고민하는 시간을 줄여줄 수 있다고 생각합니다. 이 부분은 개발하면서 좀 더 겪어보고 싶습니다.
거의 마지막 챕터에서는 잘못 사용될 수 있는 부분들을 잘 짚어줍니다. 그중에 밑줄 그어둔 부분이 있습니다. “반드시 디자인 원칙을 바탕으로 네가 할 일을 완수할 수 있는 가장 간단한 코드를 만들어야 한다.” 무작정 패턴을 적용하려 하기보다는, 가장 간단한 코드를 만들어야 한다는 것입니다. 몇 번이고 곱씹게 되는 말이 었는데, 패턴 적용하기 전에 한 번씩 떠올려 보려 합니다.
iOS 플랫폼에서 개발할 때 자주 접하던 MVC 패턴에 대해서도 배울 수 있는데, 요즘 MVC의 단점(Massive Controller)에 대해 많이 듣고 있어서 더욱 관심 있게 보게 되었습니다. 개념을 배우고 나니 제가 MVC로 작성할 때 Model에 대한 정의가 뚜렷하게 되어 있지 않았다는 것을 알게 되었습니다. 그리고 Controller가 거대해지도록 만들었던 것은 설계 원칙을 지향하면서 만들지 않았기 때문이라는 것도 깨닫게 되었습니다. API 호출, Router, Value Conveter 등에 대한 고민 없이 Controller에서 무조건 처리했던 것을 생각하며 반성하게 되었습니다. 그러면서 앞으로 개발할 때 염두할 점을 생각했습니다.
객체지향 원칙으로 점검하기
패턴이 적용되어야 할 때만 적용하기
패턴이 모든 것을 해결해 줄 것이라고 맹신하지 않기
요즘은 MVC를 대신해서 MVVM이나 VIP를 적용하는 것에 고민을 하고 있습니다. 좋은 패턴이 있으면 더 나은 코드가 만들어질 것이라는 낙관적인 생각을 가지고 있었습니다. 그런데 설계 원칙에 대한 고민 없이는 기존의 코드에서 발생했던 것처럼 의존성이 발생할 수 있다는 것을 알게 되었습니다.
앞으로 GoF디자인 패턴 책으로 한번 더 공부할 생각입니다. 그리고 iOS 앱 개발을 하면서도 원칙에 대한 적용을 계속해 나가야겠다는 생각을 했습니다. 두꺼운 분량의 책이라서 생각이 날아가기 전에 정리해두고 싶었습니다. 디자인 패턴을 처음 접했을 때는 이런 쓸데없는 것을 왜 하지?라는 고민이 들었었는데, 이번에는 좀 더 유용하게 느껴졌습니다. 실전을 조금 더 겪고 다시 공부할 때는 또 다른 느낌이 들 것 같아서 기대가 됩니다. 헤드 퍼스트 책과는 달리 딱딱한 긴 글 읽어주셔서 감사합니다!