Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Home coming day 2024 presentation 1, "Discovering Design Patterns" #51

Open
jongfeel opened this issue Nov 12, 2024 · 0 comments
Open
Assignees
Labels
enhancement New feature or request

Comments

@jongfeel
Copy link
Member

jongfeel commented Nov 12, 2024

Overview

디자인 패턴을 공부하고 싶어하는 수 많은 주니어 개발자들을 위해
디자인 패턴이 왜 어려운지와 함께
디자인 패턴 공부하는 방법을 소개합니다.

빠른 한 줄 요약:
"디자인 패턴은 구현하는 것이 목적이 아니라, 설계를 하면서 더 좋은 설계를 위해 발견(discover)해야 하는 것이다."

디자인 패턴을 공부하고자 하는 이유

대체적으로 여러 이유가 있지만 그 이유를 종합해 보면 아래 한 문장으로 모여집니다.
"실력 있는 개발자가 되기 위해"

보통 주니어 개발자들이 생각하는 개발은 코딩에 가깝지만
사실 개발에는 아주 많은 활동들이 포함되어 있습니다.

디자인, 정말 하고 있는가?

Design
여기서 얘기하는 디자인design은
Graphic(UI) design이 아닌 Software design입니다.
혼동 금지!

코딩은 보통 정해진 일정 내에 구현해야 하는 기능과 그 난이도의 적절성에 따라 동작하는 걸 볼 수 있기 때문에
주니어 개발자들이 아주 좋아하는 활동입니다.
"업무 지시만 하면 코드 몽키가 되겠다!" 라는 주니어 개발자 분도 있으니까요.

하지만 코딩 이외에 (소프트웨어) 개발이라는 활동에는
설계, 문서, 테스트, 운영 환경 설정 등도 개발 활동에 포함됩니다.

그 와중에 잘 안하려고 하는 것과 못하는 것 순서대로 나열해 보면

  • DevOps
  • Documentation
  • Test(Unit, Integration)
  • (Software) Design

순서일 것입니다.

그러니까 설계를 제일 안하려고 하는 것도 있고, 실무에서 실제로도 안하기도 합니다.
또 하려고 하는데 뭘 해야 설계를 하는 것인지를 몰라 또 못하는 것도 있죠.

그러면 이렇게 얘기해 볼 수 있습니다.
"설계는 안하는데 디자인 패턴을 실무에서 쓸 수 있는 실력 있는 개발자가 되고 싶다."

디자인 패턴은 디자인을 해야 의미가 있다

그러면 디자인 패턴에서 디자인이 무엇을 뜻하는지 생각해 볼 필요가 있습니다.

Design pattern
설계의 일정한 형태나 유형

을 뜻한다고 볼 수 있습니다.

그러니까 설계를 하면서 보이는 크고 복잡한 문제점들
또는 문제는 크게 없지만 반복적이거나 재사용할 수 있거나 변경에 유연하게 설계를 하는 과정에서
패턴으로 정하고 이름을 붙이고 정형화한 디자인 패턴이라는 것을
"발견"하는 게 중요합니다.

그러니까 소프트웨어를 만들어 가면서 설계를 하고 설계를 하는 부분이 생겨야
문제점을 파악하고 패턴으로 변경을 하던가
잘 알려진 패턴의 규칙을 발견하고 적용할 수 있는 기회가 생긴다고 볼 수 있는 것이죠.

하지만, 디자인 패턴을 공부한다면서 구현 패턴을 공부하고 있다

그래서 이제 설계는 안하지만 디자인 패턴을 공부해야지 하며 시작을 합니다.
그리고 몇 가지 패턴을 보고, 코드를 바로 봅니다.
예제로 알려주는 코드는 별거 아닌거 같습니다.

"Factory method pattern은 객체를 생성해주는 메서드를 호출해서 원하는 객체를 얻는다는 거로군, 별거 아니네"
라고 생각합니다.
(물론 자신의 수준에 따라 그럴 수도 있고 아닐 수도 있습니다)

이 시점에서 중요한 걸 놓치거나 보지 않고 바로 코드를 짜봅니다.

중요한 것

  • 내 설계의 문제가 무엇인지 (설계를 안했으므로 문제가 없다!?)
  • 왜 이 패턴으로 해결해야 하는지 (객체를 상황에 맞게 생성해주는게 좋은 것 같으니까)
  • 적용을 언제 해야 맞는지 (지금 공부했으니까 당장 하자)
  • 이 패턴의 단점이 무엇인지... (디자인 패턴이 얼마나 유명하고 좋은건데 단점이 있어?)

어쨌든 코드 예시가 있으니까 얼른 Visual Studio에서 코딩해서 빌드 해보고 싶은 욕구가 가득합니다.
코드를 바로 짜 보고 예제의 이름을 내가 하는 프로젝트의 도메인에 맞는 이름으로 바꿔보고
빌드해서 에러가 안나면?

짜잔!
이제 나도 디자인 패턴을 쓸 수 있는 실력 있는 개발자가 되는 거야. 크하하하하

(유튜버 김성회 음성지원) 그게 아니죠!

image

앞선 상황 예제는
디자인 패턴을 공부하고 있는게 아니라
"구현" 패턴을 공부하고 가져다 쓴다고 이야기 해야 하는 게 맞습니다.

사실 디자인 패턴은 어떻게 구현하느냐가 그렇게 중요하지 않습니다.
제 관점에서 극단적으로 얘기해 보자면 구현하는 방법을 알고 있어야 하는 건 하나도 중요하지 않습니다.
구현하는 방법 보다는, 왜 이 디자인 패턴이 적용되어야 하는가에 대한 여러 고려 사항을 생각해 봐야 하는게 더 중요합니다.

  • 지금 내가 직면한 문제를 더 쉽게 해결해주는가? (진짜 문제가 뭔지 아직도 모르는 상태)
  • 현재 코드의 복잡성을 제거해 주는가? (본인이 만들어 놓은 복잡성을 디자인 패턴으로 해결하려는 잘못된 접근 방법)
  • 반복적으로 생성될 코드를 줄여줄 수 있는가? (반복적으로 코드가 생성되도 문제는 없으니까 디자인 패턴을 발견해야 한다는 사실을 모름)
  • 새로운 요구사항 정책이 추가되면 기존 코드를 얼마나 수정해야 하는가? (Ctrl+H로 한꺼번에 수정하면 되는데 뭔가 문제죠? 라며 버럭함)

등등 많은 고려사항이 있죠.

하지만 저런 고려 사항이 먼저 생각나기 보다는
실무에서 내가 하는 프로젝트나 제품에 디자인 패턴을 어떻게 적용해야 하지?
와 같은 고민만 계속 하다 보니 이 문제가 더 큽니다.

저는 이런 고민을 하며 어려워 할 거면
차라리 디자인 패턴 공부를 하지 않는 걸 더 추천합니다.
공부하지 않으면 어려워할 필요도 없고 고민도 안해도 되니까요.

하지만 다들 디자인 패턴 공부는 했는데 내 회사 프로젝트나 제품에 적용하는게 어렵다고 느끼는 부분 때문에
디자인 패턴은 기껏 공부해 봤자 코드 적용해서 쓰기가 어렵다고 하소연하고 웃으면서 모르는 척 다들 넘어가는 거죠.

디자인 패턴이 어렵다는 것의 핵심

그런데 그건 어려운 것이 아닙니다.
즉, 어렵다고 느끼는 포인트가 잘못됐다는 것입니다.

물론 저도 디자인 패턴 코드를 내 프로젝트에 넣어서 쓰는게 어렵다고 느끼는 잘못된 시기를 겪었습니다.
18년 전 쯤 C++로 싱글턴 패턴을 구현하고 좋아했었던 기억이 아직도 생생합니다.
15년 전 쯤 C#으로 윈도우 프로그래밍을 한참 할 때도 상속도 잘 모르고 인터페이스도 잘 모르면서
이게 디자인 패턴에 나왔던 그 코드대로 한 거다 라고 우겼던(?) 부끄러운 기억도 있습니다.

디자인 패턴은 설계 관점인데, 그걸 자꾸 코드로 구현하고 싶어하는 게
어렵다고 느끼는 부분의 핵심입니다.

잠깐, 디자인 패턴 이전에 객체지향을 알아야 할 필요가 있다

여태 긴 설명을 하면서 객체지향에 대해 언급하지 않았는데
이제 객체지향의 핵심 중 하나인 인터페이스에 대해 얘기해야 할 시점이 왔습니다.

설계의 관점이라는 건
객체지향에서의 인터페이스의 관점과 매우 유사합니다.

설계: 필요한 데이터가 특정 알고리즘에 의해 처리되고 결과를 도출하는 걸 정의
인터페이스: 인터페이스에 메시지(Message) 혹은 퍼블릭 오퍼레이션(public operation)이라고 부르는 정의에 따라 파라리터를 통해 데이터를 전달하고 원하는 처리를 한 후 상태가 변경되면 리턴 값이나 다른 속성 값을 통해 결과를 얻는 걸 정의

디자인 패턴은 객체지향 프로그래밍을 할 때 의미가 있으며
1990년대 초반 책에서 소개가 되었을 당시에도 C++, smalltalk과 같은 객체지향 언어로 소개가 되었기에
객체지향 설계를 통해 디자인 패턴을 이해해야 할 필요가 있는 것입니다.

GoF Design Pattern, 매우 유명하죠 그런데 부제가 뭔지 아십니까?

보통 디자인 패턴 혹은 GoF의 디자인 패턴 까지만 알고 계실겁니다.
그런데 이 책에는 부제가 있습니다.
"Elements of Reusable Object-Oriented Software"로
번역본 제목은
"재사용 가능한 객체지향 소프트웨어의 핵심요소"
입니다.

Yes24의 2015년 출판된 개정판 화면은 다음과 같습니다.
image
https://www.yes24.com/Product/Goods/17525598

디자인 패턴을 검색했을 때 나오는
위키피디아의 설명도 한번 확인해 보죠.

image

이건 외국인들의 관점에서 적인 위키니까 한국적이지 않을 것 같죠?
그럼 나무위키는 어떨까요?

image

결론: 어렵다고 느끼는 디자인 패턴의 다른 해석

이즘에서 얻을 수 있는 디자인 패턴이 어렵다는 말의 표현은 다음과 같은 관점으로 바꿔볼 수 있습니다.

"저는 설계를 하지 않았습니다. 그러므로 디자인 패턴이 어렵다는게 잘못 됐다는 걸 알았습니다."

이는 자연스러운 결론일 것입니다.

다시 이런 결론을 얻을 수도 있습니다.

"객체지향에 대해, 인터페이스에 대해 모르고 있었습니다. 23개의 디자인 패턴 코드를 쓰는데 인터페이스 코드가 왜 어렵다고 느껴지는지 이제 이해가 되었습니다."

One more things!

GoF의 디자인 패턴은 23개의 패턴을 소개 하고 있습니다.

이중 인터페이스를 사용하지 않는 디자인 패턴은 몇 개일까요?

"저는 인터페이스도 안쓰고, 객체지향도 모르는데 디자인 패턴 쓰고 싶단 말입니다.
제발 1/3인 8개 정도만이라도 인터페이스 없는 패턴이라고 얘기해 주세요! 제발!"

하지만 정말 아쉽게도 인터페이스를 사용하지 않는 디자인 패턴은 단 3개 뿐입니다.

  • "싱글턴 패턴", (초 수퍼 울트라 안티 패턴, 절대 사용 금지!!!!)
  • 메소드 연쇄 호출로 객체를 생성하는 패턴인 "빌더 패턴", (이 마저도 자바 외에 다른 언어에서는 패턴 취급도 안해줌)
  • 중복 코드 재사용을 부모 클래스로 옮기는 것 정도인 "템플릿 메소드" 패턴, (그냥 상속 구조에 메소드 오버라이드 쓰는게 패턴이라고 부르기도 민망함)

나머지 20개 패턴은 인터페이스를 통한 추상화와 의존성 주입이 핵심인 패턴들 뿐입니다.

이제부터 해야 할 디자인 패턴 공부 방향

여태까지 절만편만 설명드린 것 같아
이제 희망편을 설명드리려고 합니다.

생각의 방향을 기능이 동작한다의 범위를 넓혀
객체가 해야 하는 일이 무엇인가로 확장해 보는 훈련이 필요합니다.

객체가 하는 일이 파악이 되면 메소드를 정의해볼 수 있고
필요한 데이터를 전달하거나 반환 값으로 확인해 볼 수 있을 것입니다.

예로
"앨리스가 (물컵의) 물을 마신다." 라는 문장에는 중요한 두 개의 객체인 "앨리스"와 "물컵"이 있고
이들 끼리의 상호작용에 대한 행동을 메소드로 정의해 보는 훈련을 조금씩 해보는 거죠.

이제 외부 객체와 상호작용을 할 수 있는 메소드를 인터페이스로 정의하고
이렇게 도메인 내에 있는 객체들 끼리의 상호작용을 인터페이스를 통해 동작하게 만들다 보면
반복되는 패턴이 눈에 보이게 되고 이걸 디자인 패턴의 어떤 한 해결 방법에 따라 정리해 보거나 혹은 발전시키는 방향으로 한다면
이제 설계도 하고 디자인 패턴의 첫 걸음을 걸어볼 수 있을 것입니다.

잠깐? 설계를 안 했는데 설계를 했다고요?

객체들이 어떤 행동을 할지 결정하고 필요한 데이터를 주고 받는 걸 정했다면
이미 설계를 하고 있었던 것입니다.
그러면 사실 자연스럽게 디자인 패턴을 발견할 수 있는 밑거름을 한 셈이 됩니다.

비유가 적절할지 모르겠지만
머털도사에서 마치 누덕 스승이 머털이 한테 머리털 세우는 방법을 알려줬는데
그걸 응용하면 도술을 부릴 수 있는 것처럼요.
설계를 하고 있다면, 이미 디자인 패턴을 발견할 준비가 된 것입니다.

머리털을 세웠다는 건 도술을 부릴 준비가 이미 되어 있다는 뜻입니다
image

설계 그림을 그려보고 객체 까리 주고 받는 메시지를 인터페이스로 만들었다? 설계 하신 겁니다.
image

참고 자료

Refactoring guru

@jongfeel jongfeel added the enhancement New feature or request label Nov 12, 2024
@jongfeel jongfeel self-assigned this Nov 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant