100줄 YAML로 구성하는 QR 코드 생성기
UI는 셀렉트 어드민 YAML, 서버는 LLM 기반 스캐폴딩으로 빠르게 구축하는 패턴
내부용 유틸리티는 대개 단순합니다.
하지만 프론트엔드 화면·상태 관리·테이블·모달 구성 등에 시간을 쓰다 보면 실제 목적에 비해 개발 비용이 과도해지는 경우가 많습니다.
아래 예제는 프론트엔드 없이 YAML만으로 UI·동작을 정의하고,
백엔드 서버는 해당 YAML을 기반으로 LLM에게 스캐폴딩하도록 하는 방식을 보여줍니다.
구성 개요
- YAML은 UI 구조 + API I/O를 동시에 정의합니다.
- 서버는 YAML을 기준으로:
- POST:
/local/qr/save-json - GET:
/local/qr/list - GET:
/local/qr/read?id=... - GET:
/local/qr/download?id=...
등의 엔드포인트를 제공하면 됩니다.
- POST:
- UI는 셀렉트 어드민이 자동으로 렌더링합니다.
- 서버 구현은 초기에는 LLM에게 생성시키고, 이후 원하는 형태로 확장하면 됩니다.
전체 YAML 스펙 (UI + API 요청 스펙)
blocks:
# 1) QR 생성 폼
- type: http
name: QR 생성
method: POST
display: form
formOptions: { firstLabelWidth: 200px, width: 800px }
fetchFn: |
try {
const base = API || 'http://localhost:9500'
const payload = {
text: String(text || '').trim(),
size: Number(size || 256),
margin: Number(margin || 2),
ecLevel: String(ecLevel || 'M'),
fmt: String(fmt || 'png'),
}
if (!payload.text) return { error: '텍스트를 입력하세요.' }
const r = await fetch(`${base}/local/qr/save-json`, {
method: 'POST', headers: {'Content-Type':'application/json'},
body: JSON.stringify({ payload })
})
const data = await r.json().catch(() => ({}))
return { result: data }
} catch (err) { return { error: String(err) } }
params:
- { key: text, label: 텍스트/URL, placeholder: QR에 넣을 내용 }
- { key: size, label: 사이즈(px), defaultValue: 256 }
- { key: margin, label: 여백(px), defaultValue: 2 }
- key: ecLevel
label: 오류 보정
dropdown: [L, M, Q, H]
defaultValue: M
- key: fmt
label: 포맷
dropdown: [png, svg]
defaultValue: png
# 2) QR 생성 내역 리스트
- type: http
name: 생성 내역
method: GET
fetchFn: |
try {
const r = await fetch((API || 'http://localhost:9500') + '/local/qr/list')
const data = await r.json().catch(() => ({}))
return (data.rows || []).map(row => ({
...row, label: row.text?.slice(0,60) || ''
}))
} catch (err) { return [] }
searchOptions: { enabled: true }
columns:
label: { width: 380px, openModal: preview-:id }
imageUrl:
width: 180px
template: |
<img src="{{imageUrl}}" style="width:120px;height:120px;object-fit:contain;border:1px solid #eee;border-radius:8px;padding:4px;" />
ecLevel: { width: 80px }
fmt: { width: 70px }
createdAt: { width: 180px }
' ':
append: true
template: |
<a href="http://localhost:9500/local/qr/download?id={{id}}" class="bg-slate-100 p-2">다운로드</a>
# 3) 미리보기 모달
modals:
- path: preview-:id
width: 720px
title: QR 미리보기
blocks:
- type: http
method: GET
fetchFn: |
try {
const base = API || 'http://localhost:9500'
const url = new URL(`${base}/local/qr/read`)
url.searchParams.set('id', id)
const r = await fetch(url)
const data = await r.json().catch(()=>({}))
return [data.row || {}]
} catch(e){ return [] }
params:
- { key: id, valueFromRow: id }
columns:
text: { width: 520px }
imageUrl:
template: |
<div style="display:flex;gap:20px;align-items:center;">
<img src="{{imageUrl}}" style="width:260px;height:260px;object-fit:contain;border:1px solid #eee;border-radius:12px;padding:8px;" />
<a href="{{imageUrl}}" target="_blank" class="no-underline bg-slate-500/5 rounded-lg p-2 flex items-center">
<span class="mdi mdi-download mr-1"></span>
<span>원본 다운로드</span>
</a>
</div>
이 YAML이 곧:
- UI 구성
- API 요청 방식
- 데이터 구조
- 모달/리스트/다운로드 흐름
을 정의합니다.

서버는 어떻게 구성하나?
서버는 별도의 UI 작업 없이 다음 역할만 충족하면 됩니다.
save-json→ QR 생성 요청을 받아 JSON(또는 DB)에 저장list→ 생성된 QR 목록 반환read→ 단건 조회download→ QR 이미지 생성 및 응답
초기 개발 속도를 높이고 싶다면,
서버 초안은 LLM에게 YAML을 그대로 넘겨 생성할 수도 있습니다.
예시 요청
아래 YAML 스펙에 맞는 Node.js + Express 서버 코드를 작성해주세요.
환경:
- Node.js 20
- "type": "module" (ESM)
- Express
<여기에 위 YAML 전체 붙여넣기>
이 방식은 “코드를 대신 작성해준다”기보다
“스캐폴딩을 자동화하고, 필요한 부분만 개발자가 덧붙인다”에 가깝습니다.
이후 원하는 스토리지 형태(JSON/SQLite/Postgres)로 쉽게 전환할 수 있습니다.
마무리
위 QR 생성기 예제는 작은 구성입니다.
이외에 여러 내부용 도구에도 동일하게 적용할 수 있습니다.
- URL 단축 툴
- 내부용 토큰 뷰어
- 간단한 쿠폰/코드 발급기
- 파일 처리 도구
- 운영/테스트용 작은 CRUD 도구
등은 모두 이 패턴으로 빠르게 구축할 수 있습니다. 서버는 어떤 언어로 구현해도 상관 없습니다.
프론트 개발 및 관리, 배포, 운영에 고민이 있으시다면
셀렉트 어드민을 통해 지금 필요한 도구를 만들어보세요.
개발자 문서 보기:
