Skip to content
문서

SDUI

Server-Driven UI로 동적 인터페이스를 구축하세요.

개요

Server-Driven UI를 사용하면 JSON으로 UI 구조를 정의하고 동적으로 렌더링할 수 있습니다.

SDUI (Server-Driven UI)는 서버가 JSON으로 UI 정의를 전송하고 클라이언트가 컴포넌트 레지스트리를 사용하여 렌더링하는 패턴입니다. 이를 통해:

  • 앱 릴리스 없이 동적 UI 업데이트
  • 서버에서 다른 레이아웃의 A/B 테스트
  • 사용자 데이터 기반 개인화된 경험
  • JSON 정의로 빠른 프로토타이핑
Import
import {
  defaultRegistry,
  extendRegistry,
  type SDUINode,
  type SDUIPageSchema
} from '@hua-labs/ui/sdui';

Hue 에디터

코드 작성 없이 드래그앤드롭으로 SDUI 인터페이스를 만들 수 있는 비주얼 에디터입니다.

Hue - 비주얼 SDUI 에디터

Hue는 누구나 SDUI를 쉽게 사용할 수 있도록 개발 중인 비주얼 에디터입니다. UI를 시각적으로 디자인하고 프로덕션 레디 JSON으로 내보내세요.

기능

  • 드래그앤드롭 UI 구성 - 팔레트에서 컴포넌트를 드래그하여 레이아웃 구성
  • 실시간 프리뷰 - 디자인하면서 변경 사항을 즉시 확인
  • 속성 편집 패널 - 직관적인 컨트롤로 컴포넌트 props 설정
  • SDUI JSON 내보내기 - 디자인을 프로덕션 레디 JSON 스키마로 내보내기
  • 조건부 렌더링 및 액션 시스템 - 코드 작성 없이 인터랙티브 기능 추가

Hue는 현재 개발 중입니다. GitHub에서 업데이트를 확인하세요!

스키마 구조

SDUI JSON 스키마 형식 이해하기.

SDUINode

SDUI의 기본 빌딩 블록. 각 노드는 props와 children을 가진 컴포넌트를 나타내요.

TypeScripttypescript
interface SDUINode {
  type: string;                    // Component type (e.g., "Button", "Card")
  props?: Record<string, unknown>; // Component props
  children?: SDUINode[] | string;  // Child nodes or text content
  key?: string;                    // Unique key for lists
  when?: SDUICondition;            // Conditional rendering
  on?: SDUIEventHandlers;          // Event handlers
}

SDUIPageSchema

메타데이터와 루트 노드를 포함한 전체 페이지 정의.

TypeScripttypescript
interface SDUIPageSchema {
  id: string;                      // Page ID
  title?: string;                  // Page title
  meta?: {
    description?: string;
    keywords?: string[];
  };
  data?: Record<string, unknown>;  // Initial data context
  root: SDUINode;                  // Root component tree
}

컴포넌트 레지스트리

사용 가능한 컴포넌트 및 레지스트리 확장 방법.

내장 컴포넌트

BoxFlexGridContainerSectionSpacerDividerTextH1H2H3H4LinkButtonBadgeAvatarSkeletonProgressInputTextareaLabelCheckboxSwitchCardCardHeaderCardTitleCardContentCardFooterAlertAccordionTabsHeroSectionHeaderImageIcon

레지스트리 확장하기

custom-registry.tstypescript
import { defaultRegistry, extendRegistry } from '@hua-labs/ui/sdui';

const customRegistry = extendRegistry({
  // Add your custom components
  MyCustomCard: ({ title, children }) => (
    <div className="custom-card">
      <h3>{title}</h3>
      {children}
    </div>
  ),

  // Override existing components
  Button: ({ variant = 'custom', ...props }) => (
    <button className={`btn-${variant}`} {...props} />
  ),
});

export { customRegistry };

이벤트 및 액션

이벤트 핸들러와 액션으로 유저 인터랙션 처리.

조건부 렌더링

when 속성으로 컴포넌트를 조건부로 렌더링해요.

JSON
{
  "type": "Button",
  "props": { "children": "Login" },
  "when": {
    "path": "user.isLoggedIn",
    "operator": "eq",
    "value": false
  }
}

지원되는 연산자

OperatorDescription
eq같음
neq같지 않음
gt / lt보다 큼 / 보다 작음
exists값이 존재함
notExists값이 존재하지 않음

이벤트 핸들러

JSON
{
  "type": "Button",
  "props": { "children": "Submit" },
  "on": {
    "click": {
      "type": "api",
      "payload": {
        "method": "POST",
        "endpoint": "/api/submit"
      }
    }
  }
}

액션 타입

  • navigate - 페이지 이동
  • api - API 호출
  • setState - 상태 업데이트
  • openModal / closeModal - 모달 열기/닫기
  • custom - 커스텀 액션 핸들러

전체 예시

여러 컴포넌트가 포함된 전체 페이지 스키마.

landing-page.json
{
  "id": "landing",
  "title": "Welcome",
  "root": {
    "type": "Box",
    "props": { "className": "min-h-screen" },
    "children": [
      {
        "type": "Header",
        "props": { "sticky": true, "blur": true },
        "children": [
          {
            "type": "Flex",
            "props": { "justify": "between", "align": "center" },
            "children": [
              { "type": "H4", "children": "My App" },
              {
                "type": "Button",
                "props": { "variant": "outline" },
                "children": "Login",
                "on": {
                  "click": {
                    "type": "navigate",
                    "payload": { "path": "/login" }
                  }
                }
              }
            ]
          }
        ]
      },
      {
        "type": "HeroSection",
        "props": {
          "title": "Welcome to My App",
          "subtitle": "Built with SDUI",
          "centered": true
        }
      }
    ]
  }
}