Server-Driven UI로 어드민 만드는 법
Server-Driven UI(SDUI)는 모바일만의 기술이 아닙니다. 권한과 정책이 핵심인 어드민에서는 오히려 더 강력합니다. SDUI 개념부터, 이를 YAML로 제품화한 셀렉트 어드민 사례까지 정리합니다.
오늘은 Server-Driven UI(SDUI)를 어드민 개발에 적용하는 이야기를 해보려 합니다. SDUI는 최근 모바일 앱 개발에서 주목받는 기술이지만, 사실 어드민 같은 내부 도구에도 잘 맞는 패턴입니다. 이 글에서는 SDUI의 핵심 개념과, 이를 실제 제품으로 구현한 셀렉트 어드민(Select Admin)을 중심으로 어드민 개발의 접근법을 소개합니다.
서버 드라이븐 UI(SDUI)란 무엇인가?
SDUI(Server-Driven UI)는 서버가 UI의 구조와 동작을 JSON이나 YAML 같은 스펙으로 정의해서 클라이언트에 전달하고, 클라이언트는 이를 받아서 렌더링만 하는 아키텍처입니다. 전통적인 방식에서는 클라이언트가 UI 로직을 가지고 있지만, SDUI에서는 서버가 "이 버튼을 여기 놓고, 이 API를 호출해"라고 지시합니다.
주요 장점:
- 앱 배포 없이 UI 변경 가능
- 크로스 플랫폼 일관성 (iOS, Android, Web이 같은 스펙 공유)
- A/B 테스트가 쉬움
모바일 앱 회사들이 홈 화면이나 피드를 빠르게 실험하기 위해 SDUI를 도입하는 경우가 많습니다. 하지만 SDUI의 진가는 단순한 UI 변경이 아니라, 정책과 권한을 서버에서 통제하는 데 있습니다.
어드민에 SDUI가 잘 맞는 이유
어드민(admin)의 본질은 UI가 아니라 정책입니다. "누가 이 데이터를 볼 수 있는가?", "누가 이 버튼을 눌러도 되는가?"가 핵심이죠.
일반적인 어드민 개발 과정을 보면:
- 프론트엔드에서 화면을 만들고
- 백엔드에서 API를 만들고
- 권한 로직을 양쪽에 흩어 놓고
- 변경할 때마다 양쪽 다 배포
이런 과정은 반복적이고 오류가 많고 권한 누락 리스크가 발생할 수 있습니다.
한국에서도 일부 기업이 SDUI를 시도하고 있습니다. 카카오스타일은 모바일 커머스 UI를 SDUI로 최적화했고, 토스는 SLASH 23 컨퍼런스에서 어드민 플랫폼을 DSL 기반으로 구축한 사례를 공유했습니다.
셀렉트 어드민: SDUI를 제품으로
셀렉트 어드민은 SQL과 API, YAML만으로 어드민을 만드는 플랫폼입니다. Retool이나 Appsmith처럼 내부 운영 도구를 빠르게 만드는 로우코드 도구이지만, SDUI를 핵심 아키텍처로 채택한 점이 차별점입니다.
셀렉트의 Server-driven UI 구조
셀렉트는 다음과 같은 계층으로 SDUI를 구현합니다:
[사용자 브라우저]
↓
[셀렉트 어드민 UI] ← Vercel/Cloudflare CDN으로 제공
↓
[셀렉트 인증서버] ← SSO/JWT 인증
↓
[YAML Config API] ← 어드민 스펙 정의
↓
[Block API] ← SQL/API 실행
↓
[고객사 DB/API] ← SSL, VPC Peering, Private Network 등
핵심은 이렇습니다:
- YAML Config API: 페이지 구조, 블록 배치, 권한 규칙을 YAML로 정의
- Block API: 실제 데이터 조회/수정을 실행 (SQL 쿼리나 HTTP API 호출)
- 클라이언트 UI: 스펙을 받아서 렌더링만 함
즉, 개발자는 YAML로 "어떤 화면을 보여줄지"만 정의하면, 서버가 권한 검증, 데이터 실행, UI 렌더링을 모두 제어합니다.
배포 형태: 클라우드와 Self-hosted
셀렉트는 두 가지 배포 형태를 지원합니다:
1. Cloud (클라우드형) - 메인
- 가장 빠른 시작: 가입 후 바로 사용
- 셀렉트 클라우드가 호스팅
- 고객사 DB 연결: SSL, VPC Peering 지원
- 환경: api.selectfromuser.com
2. CLI (Self-hosted, 설치형)
- 사내망에서 실행: localhost:9500
- 로컬에서 YAML 파일 관리
- Private Network로 DB 접근
- 환경별 분리 지원 (namespace 기능)
Self-hosted CLI에 대한 자세한 내용은 공식 문서를 참고하세요.
모든 배포 형태가 동일한 YAML 스펙을 공유하므로, 로컬에서 테스트 후 클라우드로 옮기거나 클라우드에서 먼저 가볍게 사용하는것도 가능합니다.
실제 사용: YAML로 어드민 만들기
간단한 예시를 보겠습니다. 주문 조회 및 환불 처리 페이지를 만든다고 가정해봅시다.
1) 주문 조회 블록
pages:
- path: orders
blocks:
- type: query
resource: mysql.sample
sqlType: select
sql: |
SELECT
id,
order_no,
buyer_name,
total_amount,
paid_at
FROM orders
ORDER BY id DESC
LIMIT 50
paginationOptions:
enabled: true
perPage: 10
searchOptions:
enabled: true
이렇게 쓰면 셀렉트가:
- Block API를 통해 SQL 실행
- 결과를 테이블로 렌더링
- 페이지네이션, 정렬, 검색 자동 추가
2) 환불 버튼 추가
pages:
- path: orders
blocks:
- type: query
resource: mysql.sample
sqlType: select
sql: |
SELECT
id,
order_no,
buyer_name,
total_amount,
paid_at
FROM orders
ORDER BY id DESC
LIMIT 50
paginationOptions:
enabled: true
perPage: 10
searchOptions:
enabled: true
columns:
작업:
append: true
buttons:
- label: 환불
type: danger-light
openModal: refund-:id # row의 id를 모달 path 파라미터로 전달
modals:
- path: refund-:id
blocks:
# (선택) 모달에서 주문 1건 상세 보여주기
- type: query
resource: mysql.sample
sqlType: select
sql: |
SELECT id, order_no, total_amount
FROM orders
WHERE id = :id
params:
- key: id
valueFromRow: id
actions:
- name: do_refund
label: 환불 실행
single: true
type: http
confirmText: 정말 환불하시겠습니까?
axios:
method: POST
url: https://api.domain.com/refunds
data:
order_id: "{{order_id}}"
amount: "{{amount}}"
params:
- key: order_id
valueFromRow: id
- key: amount
valueFromPrompt: true
promptText: 환불 금액을 입력해주세요.
roles:
edit:
- admin
- cs-manager
여기서 중요한 점:
roles필드로 권한을 YAML에서 선언적으로 정의confirm으로 실수 방지{{...}}문법으로 다른곳에서 데이터 참조
코드를 한 줄도 안 짰지만, 서버가 권한을 검증하고 API를 호출합니다.
토스처럼 하고 싶다면?
토스는 내부적으로 DSL 기반 어드민 플랫폼을 만들어서 문제를 해결하고 있습니다. 하지만 플랫폼 팀을 구성하고 수개월 이상 개발하는 것은 대부분의 팀에게 효율적인 선택은 아닐 것입니다.
셀렉트 어드민은 이 접근을 제품화했습니다. 토스가 DSL로 화면과 정책을 정의하듯 셀렉트는 YAML로 정의하고 컨트롤 합니다. 차이는 직접 만들 필요 없이 가입 후 바로 쓸 수 있다는 점입니다.
사용 사례
셀렉트 어드민은 다양한 맥락에서 사용되고 있습니다:
CS 도구
- 고객 조회, 주문 내역, 환불 처리
- CS 팀원마다 다른 권한 부여
- 민감 정보 마스킹
파트너 센터
- 입점사나 협력사가 로그인해서 사용
- 자사 직원과 다른 권한 테이블
- 외부 노출이지만 인증/권한은 강력하게
내부 대시보드
- SQL 쿼리 결과를 차트로 시각화
- 매출/지표 조회
- 엑셀 다운로드
데이터 수정 도구
- 운영팀이 특정 레코드 수정
- 변경 이력 자동 기록
- 승인 워크플로우 추가 가능
이런 용도들의 공통점은 "자주 바뀌고, 권한이 중요하고, 빠르게 만들어야 한다"는 점입니다. 바로 SDUI가 빛을 발하는 영역이죠.
Server-driven UI의 한계와 적합성
SDUI가 만능은 아닙니다. 다음과 같은 경우에는 적합하지 않습니다:
- 복잡한 인터랙션: 드래그 앤 드롭, 복잡한 애니메이션
- 완전한 커스텀 UI: 픽셀 퍼펙트 디자인이 필요한 경우
- 오프라인 동작: 네트워크 없이 작동해야 하는 앱
하지만 어드민은 대부분:
- CRUD 중심 (조회, 생성, 수정, 삭제)
- 테이블, 폼, 버튼 위주의 UI
- 항상 온라인 환경
SDUI로 충분히 커버 가능한 영역이고 셀렉트는 어드민을 이를 잘 지원하는 데 집중합니다.
마무리: SDUI로 어드민을 만들고 싶다면
Server-Driven UI는 단순한 UI 기술이 아니라, 정책과 권한을 서버에서 선언적으로 관리하는 패턴입니다. 특히 어드민처럼 "누가 무엇을 할 수 있는가"가 핵심인 도메인에서 강력합니다.
SDUI에 관심이 있거나 효과적인 어드민 개발 방법이 고민이셨다면, 셀렉트 어드민을 한번 써보세요. 템플릿과 예제, 지원팀이 함께 있습니다.
참고 자료:
- 셀렉트 어드민: https://www.selectfromuser.com
- 셀렉트 문서: https://docs.selectfromuser.com
- 셀렉트 커뮤니티: https://ask.selectfromuser.com/
- 토스 SLASH 23 - Server-driven UI로 토스의 마지막 어드민 만들기: https://toss.tech/article/slash-23-A1-2