프로그래머가 알아야 할 '디자인패턴'

김zunyange·2023년 12월 11일
0

최근 나를 포함한 개발자에게 디자인 패턴에 묻는 일이 많았다. 몇 달 전 [CS 전공지식] 서적을 읽으며 공부했던 부분이었는데 정말 1도 생각이 안났다. 물론 그 당시 책의 1장이기도 했고, 어느 정도로 이해하고 넘어가야 할지 몰라서 대충 얼렁뚱땅 넘어가게 되었다.

그런데 최근 중요성을 느끼며 검색을 해보니 정말 개발자가 알아야할 기초이자, 같이 협업하는 개발자가 디자인 패턴에 대한 내용을 숙지하고 있다면, 개발자간의 원활한 소통이 가능하다고 한다. 이전에 디자인 패턴에 대해 자세히 정리해놓은 글이 있어 오늘은 핵심만 다시 정리해보겠다!

Design Pattern

디자인패턴은 소프트웨어 엔지니어가 자주 접하는 문제에 대한 답변이다. 이것은 코드가 아니며 문제에 접근하여 해결책을 찾는 방법을 설명하는 것과 같다.

디자인 패턴은 프로그래머들 사이에서 공유되는 패턴으로, 프로그래머들이 의사소통을 할 때 양쪽 모두 디자인 패턴을 알고 있다면 간단한 단어로 복잡한 의사소통을 대체하는 것이 가능해진다. 그렇게 되면 프로그래밍 구조 관점에서 프로그램에 대해 논의하는 것이 수월해진다.
즉, 많은 프로그래머들이 디자인 패턴을 중요하게 생각하는 이유는 디자인 패턴을 통해 프로그램 설계에 대한 추상화를 할 수 있기 때문이다.

나같은 주니어 개발자가 디자인패턴을 알아도 어떤 코드가 어떤 역할을 수행하는지 파악하는 데에도 시간이 많이 걸려서 해당 프로젝트의 디자인패턴은 어떤 것을 사용했는지는 크게 궁금해하지 않는 것 같다.
하지만 소프트웨어 개발 경력이 진행됨에 따라 패턴을 인식하고 이를 활용하여 마이크로서비스/시스템/솔루션을 구성하는 능력을 갖추어야 한다.

그래서 디자인패턴이 뭐라고?

GoF 왈, "특정한 상황에서 일반적 설계문제를 해결하기 위해 상호교류하는 수정 가능한 객체와 클래스들에 대한 설명이다."

프로그래밍을 하다보면 유사한 상황을 자주 만나게 된다. 특정 상황에 사용되는 패턴을 정형화해 두면 이후 비슷한 상황을 마주했을 때 더욱 빠르고 유연하게 대처할 수 있다.

  • 특징 1. 경험을 통하여 얻을 수 있다.
  • 특징 2. 특정한 형식을 갖고 체계적으로 작성되는 것이 일반적이다.
  • 특징 3. 패턴에는 각기 다른 추상화 수준이 존재하며 계속 진화한다.

디자인 패턴의 분류

새로운 소프트웨어를 개발할 때마다 대부분 개발자는 어떤 클래스를 만들고 어느 시점에 객체를 생성하고 소멸시킬지, 데이터를 어떻게 받아서 처리할지, 구조 설계를 어떻게 할지 고민한다. 디자인 패턴 분류는 코드를 작성할 때 자주 반복되는 특정 상황에서 설계를 용이하게 하며 코드의 재사용이 용이하도록 패턴을 정리해 놓은 것이다. 그중 가장 잘 알려진 분류법으로 GoF의 패턴분류 방법이 있다. 위에 디자인패턴을 정의한 GoF 맞다. GoF는 디자인 패턴을 목적과 범위로 분류했다.

디자인 패턴의 '목적'

패턴이 무엇을 하는지 정의하는 것으로 생성, 구조, 행동 중의 한 가지 목적을 갖는다.

생성 (Creational Pattern)
객체의 생성 과정에 관여하는 패턴이다.

구조 (Structural Pattern)
클래스나 객체의 구성을 통해 더 큰 구조로 만들 수 있게 해주는 것과 관련된 패턴이다.

행동 (Behavioral Pattern)
패턴을 주로 클래스에 적용하는지 아니면 객체에 적용하는지에 따라 구분되는 패턴이다.

디자인 패턴의 '범위'

패턴을 클래스에 적용하는지 아니면 객체에 적용하는지에 따라 구분되는 패턴이다.

클래스 패턴 (Class Pattern)
클래스들과 하위 클래스 간의 관계를 다루는 패턴이다. 컴파일 시에 관계가 결정된다.

객체 패턴 (Object Patterns)
객체 간의 관계를 다루며 보통 구성을 통해 정의된다. 객체 패턴은 일반적으로 실행시간에 관계가 생성되기 때문에 더 동적이면서 유연하다.

디자인 패턴의 종류

1) 싱글턴 패턴 (Singleton Pattern)
목적 : 생성
범위 : 객체
객체의 생성에 관련된 패턴으로서 특정 클래스의 인스턴스가 오직 하나임을 보장하고 이 인스턴스에 접근할 방법을 제공한다.
=> 하나의 클래스에는 하나의 인스턴스만!!

2) 퍼사드 패턴 (Facade Pattern)
목적 : 구조
범위 : 객체
건물의 정문에 있는 안내소처럼 개발자가 사용해야 하는 서브 시스템의 가장 앞쪽에 위치하면서 하위 시스템에 있는 객체들을 사용할 수 있도록 하는 역할을 한다. 시스템의 복잡성을 줄이기 위해 서브 시스템을 구조화하고 서브 시스템으로의 접근을 하나의 퍼사드 객체로 제공하는 패턴이다.
=> 서브시스템에 있는 일련의 인터페이스를 통합 인터페이스로 묶어줌

3) 옵저버 패턴 (Observer Pattern)
목적 : 행위
범위 : 객체
객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 패턴이다.
=> 구독한 유투브, 트위터에게 알람이 오는!

4) 전략 패턴 (Strategy Pattern)
목적 : 행위
범위 : 객체
알고리즘을 담당하는 각각의 클래스를 만들어 책임을 분산하기 위한 목적으로 만든 행위 패턴이다.
=> 객체의 행위를 바꾸고 싶은 경우 직접 수정하지 않고 전략이라고 부르는 캡슐화한 알고리즘 을 컨텍스트 안에서 바꿔주면서 상호 교체가 가능하게 함

5) 팩토리 패턴 (Factory Pattern)
목적 : 생성
범위 : 클래스
객체를 생성하기 위한 인터페이스를 정의하지만 어떤 클래스의 인스턴스를 생성할지에 대한 결정은 하위 클래스에서 이루어지도록 인스턴스 생성의 책임을 떠넘기는 패턴이다.
=> 상위 클래스가 전체적인 부분, 상세한 부부은 하위 클래스가 맡음

예시
커피를 만드는 카페가 있고, 커피를 만들 레시피가 있을 때
카페가 상위 클래스, 커피 레시피가 하위 클래스이다.

const 변수 = new Object();

Object는 객체를 만드는 카페의 역할을 하며, 값이 어떤 변수냐에 따라 타입이 결정된다. 이 타입 결정하는 부분이 커피 레시피 같은 역할을 하는 것이다.

6) 어댑터 패턴 (Adapter Pattern)
목적 : 구조
범위 : 클래스, 객체
특정 틀래스 인터페이스를 클라이언트에서 요구하는 다른 인터페이스로 변환하는 패턴으로, 호환성이 없는 인터페이스 때문에 함께 동작할 수 없는 클래스들이 함께 동작하도록 해준다.


디자인 패턴이 만병통치약은 아니다. 모든 도구는 용도에 맞게, 적절하게 쓰일 때 그 위력을 발휘한다. 어울리지 않는 상황에서 남용하면 역효과가 발생하게 된다. 프로그램 복잡성을 높일 수도 있고, 패턴은 일반적으로 다른 클래스와 객체의 상호작용을 추가하므로 클래스 간의 관계가 더 복잡해질 수도 있다.

그럼에도 처음 배우는 단계에서는 어느 정도 남용도 하고, 알맞지 않은 디자인패턴을 사용하면서, 경험과 지식을 점점 쌓아서 디자인 패턴을 현명하게 활용하는 방법을 깨닫는 것이 좋겠다. 😊


📍출처
https://m.hanbit.co.kr/channel/category/category_view.html?cms_code=CMS8616098823
https://kotlinworld.com/361
📍더 알아보기
https://kotlinworld.com/category/Kotlin/Design%20Patterns

profile
배움은 즐거워 ~(*ૂ❛ᴗ❛*ૂ)

0개의 댓글