[React] 작은 설계 차이가 만드는 큰 유지보수성

0_jin·2025년 8월 17일
0

서비스 개발을 하다 보면, 사용자에게 팝업을 띄우는 것처럼 단순해 보이는 기능조차도 의외로 많은 고민을 요구합니다.

예를 들어, openModal() 함수를 어떻게 설계하느냐에 따라 코드의 확장성과 유지보수성이 크게 달라질 수 있습니다.

1. 데이터 객체를 통째로 주입하는 방식

openModal(data);
  • 호출부에서는 데이터만 넘겨주면 된다.
  • 함수 내부에서 알아서 분기해 UI를 결정한다.
  • 사용자는 단순히 openModal만 호출하면 되니 편리하다.

2. Mode 별 interface를 명시적으로 주입하는 방식

openModal({ mode: 'card', ... });
  • 어떤 모달 UI가 노출될지 명확하게 알 수 있다.
  • interface 확장 시 기존 로직에 영향을 주지 않는다.
  • 불필요한 데이터가 주입되는 것을 막아 유지보수성이 높다.

왜 interface 분리가 더 좋은가?

단순히 “깔끔해 보인다”는 이유 때문이 아닙니다.
예측 가능성확장성 이라는 중요한 원칙을 지킬 수 있기 때문입니다.

1. 예측 가능성

호출부에서 mode만 봐도 어떤 UI가 렌더링될지 알 수 있습니다.
이 작은 차이가 협업 시 오해를 줄이고, 버그 발생 가능성을 낮춥니다.

2. 확장에 유리함 (SOLID: Open-Close Principle)

새로운 모달 타입이 추가되더라도 기존 호출부에는 영향을 주지 않습니다.
반면, data 객체를 통째로 넘기는 방식은 기존 필드와 충돌하거나 불필요한 필드 관리가 필요해져 유지보수 비용이 커집니다.

다음은 예제 코드입니다.

// 공통 data 객체
interface ModalData {
  title?: string;
  description?: string;
  cardNumber?: string;
  productId?: string;
  // 앞으로 계속 추가될 수 있음...
}

function openModal(data: ModalData) {
  if (data.cardNumber) {
    // 카드 모달
  } else if (data.productId) {
    // 상품 모달
  } else {
    // 기본 모달
  }
}

새로운 모달 타입(예: couponModal)이 추가된다면,
ModalData에 { couponId?: string } 같은 필드를 추가하고,
openModal() 내부에도 else if (data.couponId) 분기를 또 작성해야 합니다.

이 경우 호출부는 openModal이 내부 조건 분기에 따라 어떻게 동작할지 예측하기 어렵습니다.
또한 새로운 타입 추가로 인해 불필요한 필드 주입까지 요구되면서, 호출부 개발자는 어떤 데이터를 넘겨야 할지 혼란스러워집니다.
결국 이는 연관 없는 모달 로직에도 사이드 이펙트를 유발합니다.

3. 불필요한 의존성 제거 (SOLID: Interface Segregation Principle)

각 모달이 필요로 하는 데이터만 interface로 정의됩니다.
덕분에 한 모달이 다른 모달의 데이터 구조에 불필요하게 의존하지 않게 됩니다.

// 모달별 interface 정의
interface CardModalProps {
  mode: 'card';
  cardNumber: string;
}

interface ProductModalProps {
  mode: 'product';
  productId: string;
}

interface CouponModalProps {
  mode: 'coupon';
  couponId: string;
}

// union 타입으로 확장
type ModalProps = CardModalProps | ProductModalProps | CouponModalProps;

function openModal(props: ModalProps) {
  switch (props.mode) {
    case 'card':
      // 카드 모달
      break;
    case 'product':
      // 상품 모달
      break;
    case 'coupon':
      // 쿠폰 모달
      break;
  }
}
  • 새로운 모달을 추가하더라도 기존 interface나 호출부를 수정할 필요가 없습니다.
  • ModalProps union에 새로운 타입을 추가하는 것으로 확장이 끝납니다.
  • OCP 원칙(기존 코드 닫혀 있음, 확장에는 열려 있음)에 부합.

마치며

팝업 호출이라는 단순한 기능에서도 원칙 있는 설계는 큰 차이를 만듭니다.
저는 interface 분리 방식을 통해 예측 가능한 코드, 변경에 강한 구조를 지향합니다.

결국 좋은 아키텍처는 화려한 기술이 아니라, 작은 선택에서 비롯되기에 간단한 코드 작성 또한 심의를 기울여야합니다.

profile
가독성 좋은 코드, 성능 개선, 좋은 dx 경험, 자동화 를 생각합니다.

0개의 댓글