본문 바로가기
OOP

[OOP] 디자인 패턴을 사용하는 이유

by ifhead 2022. 9. 9.
반응형

디자인 패턴은 도움이 되는가?

 

객체지향적 프로그래밍이 무엇인지 이야기할 때 빠지지 않는 것이 디자인 패턴입니다. 팩토리 패턴, 어댑터 패턴, 옵저버 패턴 등 잘 알려진 패턴부터 새롭게 연구된 패턴까지 그 종류가 족히 수백가지에 달합니다. 이것을 더 이상 패턴이라 부르는 게 과연 의미가 있을까 싶을 정도로 많은 종류의 패턴이 고안되었습니다.

 

디자인 패턴을 하나씩 이해하는 것은 쉽습니다. 그러나 패턴을 외울 작정으로 접근하면 서로 비슷한 패턴이 많아서 헷갈리기 시작합니다. 패턴들 사용에 대한 불편함은 점점 커지다가 근본적인 질문으로 이어집니다.

 

"이 패턴들이 실무에서 도움이 될까?"



이 질문은 공부하기 싫은 사람이 내뱉는 푸념이 아닙니다. 구현을 빨리 하고 싶어서 코드를 패턴에 끼워맞추다 보면 그 코드는 엉망이 됩니다. 스스로 이해할 수 없는 코드가, 쉽게쉽게 짜여서 잘 동작되는 코드보다 좋은 점이 어디 있겠습니까. 실제로 패턴이 왜 사용되어야 하는지, 패턴이 어떤 의도로 고안되었는지 이해해야 합니다. 패턴을 사용하는 것에 급급하지 말고 각 패턴이 존재하는 이유를 이해해야 합니다. 그래야만 패턴이 언제 효과적인지 스스로 떠올릴 수 있습니다.

 

디자인 패턴은... 패턴입니다

 

패턴들은 서로 유사한 점이 많습니다. 말 그대로 '패턴'입니다. 우리는 다른 사람이 패턴을 이용해 짠 코드를 보면 쉽게 이해할 수 있습니다. 하지만 패턴이 어떤 합의를 가지고 탄생했는지, 어떤 형태를 띄고 어떤 의도로 사용되는지 이해하지 못한다면 다른 사람의 코드에서 '패턴'을 읽어내기란 어렵습니다. 당연하게도 당신 또한 그 패턴을 코딩에서 활용할 수 없습니다.

 

우리는 "안전하고 확실한 방법"으로 코딩함으로써 기능이 동작하기를 바랍니다. 복잡하고 멋지게 만들려는 허영심으로 코딩하지 않습니다. 그러니 디자인 패턴의 존재 이유를 이해하지 못한 사람은 점점 패턴을 기피하게 됩니다. 대신 직관적이고 단세포적인 코드, 습관으로 굳어진 방식을 선택합니다. 디자인 패턴이 뜬구름 잡는 소리처럼 느껴지게 되는 것입니다. "내가 익숙하고 확실한 방법을 아는데, 굳이 패턴을 써야 해?"라는 의구심이 끊임없이 고개를 듭니다. 매우 합당한 의심입니다.

 

 

수천 줄 규모의 작은 프로그램이라면 패턴을 사용하든 사용하지 않든 수정과 확장에 대응하기 충분할 정도로 단순합니다. 그래서 많은 사람들이 "OOP는 대규모 협업에서 유지보수성을 높이는 프로그래밍 패러다임이니, 작은 단위에서는 사용하나 마나 마찬가지다."라고 이야기합니다. 그러나, 큰 프로그램은 작은 프로그램의 연합체입니다. 저는 이 사실을 잊어서는 안 된다고 생각합니다.

 

작지만 세심하게 설계된 고품질 코드는 프로젝트가 크든 작든 어느 상황에서라도 능률을 높여줍니다. 만약 당신이 작은 프로젝트에 착수하고 계시다면 더욱 설계 방법론을 적용해야 할 때입니다. 가까운 미래에 당신의 프로그램이 커지거나, 망가지거나, 변경될 가능성을 배제하지 마십시오.

 

디자인 패턴을 사용하는 이유

 

GoF에 의해 패턴이 정리되어 널리 알려지기 전부터 패턴은 쓰여왔습니다. 패턴이 정리되기 전에도 객체지향은 존재했으며, 반복되는 프로그래밍 방법이 관측되었습니다. 이 말은 곧 패턴을 "외워서" 틀에 "끼워 맞추는" 방식이 주객전도라는 사실을 방증합니다. 패턴은  선배 프로그래머들이 "코드를 잘 짜려고 고생한 결과"인데, 코드를 잘 짜려는 고민은 하지 않고 틀에 끼워맞추려니 잘 될 리가 없습니다. 그렇게 패턴을 공부하다가는 금방 질려버려서 패턴을 버리게 될 것입니다.

 

우리는 패턴에 맞추려고 디자인 패턴을 배워서는 안 됩니다. 패턴이 만들어진 이유를 이해하고 그 효과를 코드에 반영해야 합니다. 그것이 오히려 디자인 패턴을 잘 활용하는 일이며 객체를 지향하는 올바른 방법입니다. 디자인 패턴은 수단이지 목적이 아닙니다.

 

 

패턴은 우리보다 먼저 코딩을 시작한 사람들이 검증한 코드의 형태입니다. 여기서 핵심은 "이미 검증되었다"라는 사실에 있습니다. 개발자들은 복잡한 코드를 계속해서 다듬어 왔고, 안정화된 코드를 확보했으며, 그것들 사이에서 공통점을 발견했습니다. 이 공통점을 모아 특정 패턴으로 이름붙이는 방식이 발전된 형태가 바로 디자인 패턴입니다.

 

패턴과 리팩터링(다듬기)은 서로 강력한 연관을 가집니다. 리팩터링은 '대형 사고'를 미연에 방지해줍니다. 리팩터링을 거치지 않은 지저분한 코드에서 에러가 나왔을 때, 그 코드를 고치는 데 필요한 시간을 방정식으로 생각해봅시다. 문제를 일으키는 필드와 메서드를 찾아내는 시간, 디버깅하는 시간, 코드를 처음부터 다시 파악하는 시간 등 모든 경우의 수와 소요시간을 곱한다면 기하급수적으로 큰 시간이 필요할 것입니다. 고치려면 기하급수적인 시간이 필요한 에러가 커다란 사고라고 할 수 있습니다. 커다란 사고를 피하려면 리팩터링을 통해 코드에서 잠재적 위협을 제거해야 합니다.

 

기술 부채를 막는 리팩터링

 

실무에서 요구사항은 계속 추가됩니다. 게다가 나와 다른 사람의 변화무쌍한 코드로 인해 점점 버그가 난무합니다. 이런 끔찍한 코드를 내버려두면 '기술 부채'가 발생합니다. 기술 부채를 청산하지 않으면, 마지막에는 감당할 수 없이 거대해진 빚더미 위에 앉게 됩니다. 심각한 경우 프로그램을 고치기보다 아예 새롭게 시작하는 편이 낫다고 판단되는 때가 옵니다. 그 순간이 바로 데드크로스입니다. 당신이 착한 프로그래머라면 스스로 만든 프로그램이 끝장나기를 바라지는 않을 것입니다😏

코드가 죽어버리는 순간은 서서히 찾아옵니다. 처음에는 작은 에러들이 꼬리를 물며 나타납니다. 역시 평소처럼 안일하게 누덕누덕 코드를 고칩니다. 그런 일을 수 차례 반복하며 계속해서 요구사항에 대응합니다.

 

 

코드는 바닥이 비뚤어진 젠가 탑처럼 쌓아올려집니다. 그러다가 잠재되어 있던 불안정성이 마침내 프로그램 전체를 위협하는 순간이  닥쳐옵니다. 우리는 늘상 젠가 탑이 무너지기 직전까지 똑바로 코딩하고 있다고 믿곤 합니다. 이 경험을 해보신 분들은 공감하실 겁니다. 

디자인 패턴과 리팩터링은 프로그램의 죽음을 막아주는 여러 가지 수단 중 하나입니다. 그리고 많은 순간에 아주 강력한 효과를 발휘하기 때문에 그 필요성이 강조되어 왔습니다. 그 밖의 수단으로는 설계 이론, 알고리즘, 최적화, 협업 방법론 등 다수가 존재합니다. 그것들은 키보드에서 손을 뗀 상태에서 머리로 해야 할 일들입니다. 한편 디자인 패턴과 리팩터링은 프로그래머의 손끝에 좌지우지되는 최전선의 무기입니다. 잘못 활용하면 안 쓰느니만 못하지만, 그렇다고 아예 활용하지 않으면 기술 부채로 인한 파산이 우리를 기다리게 됩니다.

 

 

우리는 '디자인 패턴'을 무시할 수는 있어도 '기술 부채'는 무시할 수 없습니다. 우리는 어떤 방법으로든 죽어가는 코드를 살려내야 하고, 처음부터 건강한 코드를 만들 필요가 있습니다. 클린 코드를 위해서라면 그때그때 기꺼이 비용을 들여야 합니다. 그게 가장 싸게 먹히니까요!

 

 

반응형

댓글