어서와, 개발은 처음이지?

팩토리 패턴(factory pattern)에 대한 생각 본문

디자인패턴

팩토리 패턴(factory pattern)에 대한 생각

오지고지리고알파고포켓몬고 2022. 10. 7. 03:19
반응형

영상으로 보기 - https://youtu.be/eSLrZbPHgoI

1.  팩토리 패턴

고전 자바 시절부터 내려오는 디자인 패턴 중 하나인 팩토리 패턴은, 모듈 내에서 객체 생성에 관련된 로직을 직접 구현하지 않고 객체 생성 역할을 대신 수행하는 layer를 두어 모듈과 객체 간 의존성을 낮추고 확장성을 높이는 패턴이라고 할 수 있습니다.

 

간단하게 예를 들면

class Human {
  void travel(String type) {    
    if(type.equals("땅") {
      new Car().depart();
    } else if(type.equals("바다") {
      new Boat().depart();
    } else {
      new Airplane().depart();
    }
  }
}

class Cargo {
  void delivery(String type) {    
    if(type.equals("땅") {
      new Car().depart();
    } else if(type.equals("바다") {
      new Boat().depart();
    } else {
      new Airplane().depart();
    }
  }
}

(예제를 위한 예제, 자바를 안써본지 오래된 부분을 감안해서 pseudo code라고 생각하고 봐주세요!)

 

이런식의 조건으로 분기되는 같은 맥락을 갖는 행위(예제 상은 '출발하는 행위')들이 여러 구현에 산재되어있는 경우, 아래처럼 '팩토리'라는 개념을 통해 맥락의 행위(아래에서는 interface의 역할)를 제공합니다.

interface Vehicle {
  void depart();
}

class VehicleFactory {
  static Vehicle createVehicle(String type) {
    if(type.equals("땅") {
      return new Car();
    } else if(type.equals("바다") {
      return new Boat();
    } else {
      return new Airplane();
    }
  }
}

class Human {
  void travel(String type) {    
    Vehicle vehicle = VehicleFactory.createVehicle(type);
    vehicle.depart();
  }
}

class Cargo {
  void delivery(String type) {    
    Vehicle vehicle = VehicleFactory.createVehicle(type);
    vehicle.depart();
  }
}

 

간단한 아이디어지만 이를 통해 기존 구현에 존재하던 '조건에 따른 분기'는 자연스럽게 팩토리로 응집되고, 탈것을 수행하는 class로부터의 의존성도 낮아지게됩니다.

 

그리고 마찬가지로 같은 맥락을 갖는 행위들이 각 구현에서 팩토리를 통해 제공되기 때문에, 수정사항이 발생했을 때 손 봐야할 범위도 줄어들게 됩니다.

 

기존에는 맥락이 변경되는 경우 각 구현이 모두 영향범위에 들어가는 반면, 팩토리를 사용하면 영향범위를 한정할 수 있다

 

2.  뭣이 중헌디?

class 따윈 필요없는 진성 javascript 개발자의 입장에선 class 지향적인 생성 패턴이 무슨 쓸모가 있겠느냐라고 생각할 수 있지만, 저는 팩토리 패턴의 가장 중요한 아이디어가 유사한 맥락을 갖는 행위를 응집하여 외부에 제공하는것에 있다고 생각합니다.

 

(뭐 당연한 얘기를 하느냐라고 생각하실 수 있지만) 어느 분야의 개발이나 마찬가지겠지만 프론트엔드 개발을 하면서 특히

너무 많은 맥락이 각각의 컴포넌트에 흩뿌려져있는, 심지어 그 수준조차 표현 영역(view혹은 page 수준의 컴포넌트) / 비즈니스 영역(hook 등) / 어딘가에서 참조하는 util 함수 수준 등으로 뒤죽박죽인 경우가 보였고

이에 따라 스펙 상 변경되는 사항이 있을때, 코드 상에서 수정 범위를 쉽게 예측할 수 없는 상황이 종종 생기는 경우도 있었습니다.

 

어쩌면 모던 웹 시대의 과도기에 발생한 필연이라고 볼수도 있겠죠.

하지만 우리는 같은 실수를 반복하기 않기위해 무언가 조치를 취해야합니다.

 

그래서 저는 최소한 도메인 로직들은 어느정도 수준의 응집력을 가져야한다고 생각하고있고, 팩토리가 주는 아이디어가 충분히 의미있다고 생각합니다.

 

3.  당신은 이미 알고있다

프론트 개발을 하다보면 아래처럼 각각의 기능들이 상태에 따라 다른 동작을 하는 경우를 많이 볼 수 있습니다.

동일 페이지에서 각 맥락(주문 여부, 멤버십 가입 여부)에 따라 다른 기능이 정의되는 모습
각기 다른 페이지에서 동일한 맥락에 따른 기능이 공유되는 모습

저는 이를 맥락이라고 표현하는데, 이미 많은 분들이 (react 기준)custom hook을 통해 business layer를 정의하고, 이를 공유하는 형태로 개발하고 계실 것 같습니다.

 

네, 그러한 형태가 이미 팩토리의 아이디어를 따르고 있는 것이라고 볼 수 있겠습니다.

custom hook에서 맥락에 따른 기능을 표현하고 있음

하지만 실무 상황에선 단순히 custom hook에 맥락을 응집하는 것으로 모든게 해결되진 않습니다.

 

이러한 hook의 대부분은 상태를 갖게 될텐데

다수의 맥락을 소수의 hook에 집어넣었을때 발생할 최적화 문제(페이지 A를 표현하는데 필요하지 않은 state가 사이드 이팩트에 따라서 리렌더링이 유발됨), 맥락이 많아질수록 hook이 비대해지는 문제 등 신경써야할 부분이 많습니다.

 

이런 경우에는 팩토리가 제공할 맥락과 state를 별개의 관점으로 보고, 상태 관리에 얽매이지 않도록 계층화 해보는 것 또한 한 가지 관전 포인트가 될 것입니다.

 

위 경우는 hook이 팩토리의 역할'도' 수행하고 있던 것이지 팩토리인것은 아니니까요.

 

4.  창의력을 발휘해보자

hook을 예로 들다보니 아무래도 상태에 따른 'label 값'이나 '수행할 로직'들이 주요 관심사로 떠올랐을 것 같아요.

하지만 팩토리가 하는 일이 '객체 생성의 위임'이 전부가 아니였듯이 맥락의 행위를 프론트엔드 개발의 다양한 관점으로 확장해볼 수 있습니다.

 

마치 컴포넌트를 직접 제공하는 역할처럼말이죠!

팩토리가 label이나 로직 뿐만아니라, 컴포넌트를 직접 제공하게 할수도 있다

이처럼 단순히 '생성을 위임'하는 역할 뿐만아니라 맥락을 응집하되, 그 응용 범위에 대해서 다양한 시도를 해볼 수 있을 것입니다.

5.  마무리

이번 글에서는 고전 디자인 패턴 중 하나인 팩토리 패턴에 대해서 이야기 해봤습니다.

 

디자인 패턴의 핵심은, 각 패턴이 어떤 문제를 해결하기위해서 어떤 아이디어를 사용했는지에 대해 이해하는것이라고 생각하는데

비록 class 지향 언어에서 파생되어나온 패턴이지만 많은 생각과 영감을 불어넣어주는 것 같습니다.

 

이렇듯 잘 정의된 아이디어를 바탕으로 창의력을 발휘해서 다양한 시도를 해보신다면 좀 더 풍부한 구조 설계를 진행할 수 있지않을까 싶습니다.

 

그럼 또 다른 디자인 패턴과 아이디어를 들고 다시 찾아오도록 하겠습니다!

Comments