노트

설정 기반 UI

Configuration-Driven UI

설계#pattern · 연결된 개념 7개

쉽게 말하면

설정 기반 UI는 화면을 코드로 하나하나 짜는 대신 공연 순서표만 적어 두면 무대 감독이 그대로 올려 주는 방식이에요. 순서를 바꾸고 싶으면 무대 장치는 그대로 두고 순서표만 고치면 돼요.

비유가 깨지는 곳 순서표에 조건과 예외가 계속 붙으면 그 자체가 읽기 어려운 작은 언어가 돼요. 항목이 몇 개뿐이라면 설정 배열 없이 컴포넌트를 그냥 나열하는 편이 더 단순해요.

화면 구조를 컴포넌트를 나열한 코드가 아니라 설정 데이터(보통 배열)로 선언하고, 렌더러가 그 설정을 읽어 그리는 패턴. 구조를 바꿀 때 렌더링 코드 대신 데이터만 고친다.

type Section =
  | { type: 'banner'; id: string; image: string }
  | { type: 'products'; id: string; heading: string; query: string }
  | { type: 'custom'; id: string; render: () => ReactNode; shouldRender?: () => boolean }
 
const PAGE: Section[] = [
  { type: 'banner', id: 'hero', image: '/hero.png' },
  { type: 'products', id: 'best', heading: '베스트', query: 'sort=best' },
]
 
function Page() {
  return PAGE.filter(s => s.type !== 'custom' || (s.shouldRender?.() ?? true)).map(s => {
    switch (s.type) {
      case 'banner': return <Banner key={s.id} src={s.image} />
      case 'products': return <ProductList key={s.id} heading={s.heading} query={s.query} />
      case 'custom': return <Fragment key={s.id}>{s.render()}</Fragment>
    }
  })
}

이 구조는 몇 가지 생각이 겹친 것이다.

  • 선언적 렌더링(Declarative Rendering): 어떻게 그릴지가 아니라 무엇을 그릴지를 적는다(선언형과 명령형 프로그래밍)
  • 판별 유니언(Discriminated Union): type 필드로 항목 종류를 나눠 각 항목에 맞는 속성을 타입으로 보장한다(판별 유니언)
  • 전략(Strategy): 항목마다 render·shouldRender 함수를 두면 렌더링 방식을 항목이 고른다(전략 패턴)

같은 설정 배열에서 탭 메뉴·목차·스크롤 위치 같은 파생 UI도 함께 만들 수 있어, 구조 정보가 한곳에만 있게 된다(DRY 원칙). 라우터의 라우트 설정, 폼 라이브러리의 필드 설정, Storybook의 스토리 설정(Storybook)이 같은 계열이다.

설정에 조건과 예외가 계속 늘면 설정 자체가 읽기 어려운 작은 언어가 된다. 항목이 몇 개뿐이라면 컴포넌트를 그냥 나열하는 편이 단순하다(YAGNI).

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • React Testing Library

    React Testing Library(RTL)는 컴포넌트를 jsdom 같은 테스트용 DOM(Document Object Model) 환경에 렌더하고, 사용자가 실제로 쓰는 방식으로 요소를 찾고 조작하게 해 주는 테스트 도구다. 내부 구현(state, 메서드)이 아니라 화면에 보이는 동작을 검증하라는 철학을 강하게 가진 라이브러리다.

  • 하이드레이션

    하이드레이션(Hydration)은 서버가 미리 렌더해 보낸 HTML(HyperText Markup Language)을 클라이언트에서 다시 만들지 않고, 그 DOM(Document Object Model)에 React 컴포넌트를 연결해 이벤트 핸들러와 상태를 붙이는 과정이다(hydrateRoot). Dan Abramov의 비유로는 "마른 HTML에 상호작용이라는 물을 주는 일"이다.

  • React로 보는 SOLID

    SOLID는 원래 객체 지향 설계 원칙이지만 React 컴포넌트·props·훅에도 그대로 옮겨 볼 수 있다. 원칙 자체보다 "어떤 코드 모양이 되는가"를 짧게 정리한다.

  • Activity와 숨겨진 라우트 보존

    Activity는 React 19.2의 컴포넌트로, UI를 언마운트하지 않고 display: none으로 숨기면서 state와 DOM(Document Object Model)을 보존한다. 숨기는 동안 Effect는 정리(cleanup)된다. 예전 이름은 Offscreen이다.

  • 유니언·인터섹션·리터럴 타입

    유니언 타입(Union Type, A | B)은 "A이거나 B인 값"이고, 인터섹션 타입(Intersection Type, A & B)은 "A이면서 B인 값"이다. 리터럴 타입(Literal Type)은 'left'나 3처럼 특정 값 하나만 허용하는 타입이다.

보기 옵션