메모 서비스 — 풀스택 한선씨 데모 + crowny:// 전용 게이트
개요
HTML/CSS/JS를 손으로 한 줄도 쓰지 않고,
프론트엔드와 백엔드를 전부 한선씨로 구현한
작은 메모 목록 서비스. 한 한선씨 소스에서 두 출력을 낸다:
- 크라우니 브라우저(crowny://) → space-cmd IR → 페이지렌더러 → 네이티브 픽셀(PNG)
- 일반 브라우저(https://) → 인터랙티브 HTML 폴백 또는 티어 게이트 426 차단
화면.한선 DSL(앞선 작업) 위에 데이터 계층·라우팅 게이트·전송 글루를 얹어 풀스택을 완성.
무엇을 했는지
- 백엔드(데이터 제공자) —
메모백엔드.한선
- PSV 저장소(
/tmp/메모저장.psv) 씨드/로드/추가.
메모로드()가 문자열 배열 반환.
- 프론트는 데이터 출처를 모른 채 배열만 렌더(관심사 분리).
- 프론트엔드(화면 조립) —
메모앱.한선
-
가져오기 "화면.한선" +
가져오기 "메모백엔드.한선". 백엔드 데이터로 제목·부제(
MEMO N=라이브 개수)·입력칸·ADD 버튼·목록 렌더.
-
CROWNY_OUT=cmd|html 한 환경변수로 두 출력 분기.
- crowny:// 전용 게이트 —
메모라우팅.한선
-
티어판정.한선 접근판정() 재사용(로직 SSOT 1곳). 서비스 정책:
_서비스전용=참, _요청등급=0.
- 크라우니브라우저→cmd / 일반+폴백html→html / 일반+엄격→426 / 소진→402 / 미인증→401.
- 전송 글루(서버 스텁) —
메모서비스.js
- 로직 아님. UA로 크라우니 브라우저 식별 → cmd, 아니면 FALLBACK=html|strict.
- 기존
게이트검증.js(한선씨 SSOT 미러)의
게이트판정/UA파싱 재사용.
X-Crowny-Gate 진단 헤더(ASCII).
-
/act?a=메모추가&v=… →
메모추가.한선(한선씨 백엔드 쓰기) → 개수 증가(라이브 루프).
- 라이브 쓰기 진입점 —
메모추가.한선: 환경변수 CROWNY_ADD를 백엔드에 append, 갱신 개수 JSON 반환.
작동 증거
네이티브 픽셀: /tmp/memo.png (800×600, 글리프 잉크 744px/36글리프). 제목 "크라우니" + 골드 "MEMO 4" + 입력힌트 + 코랄 ADD + 목록 4행("크라우니 글자/벡터삼진/안녕하세요/한글폰트") 전부 CIF 폰트로 렌더 확인.
HTML 폴백: /tmp/memo.html (24줄) — doctype 1·button 1·input 1·div 12·crownyAct onclick·</html> 종료, HTMLParser 무오류.
서버 라우팅(실측 curl):
일반브라우저 → 200 text/html(doctype 확인)
크라우니브라우저(유효서명) → 200 application/x-crowny-cmd, 본문 INIT 800 600…, 헤더 X-Crowny-Gate: allow:200
strict 모드: Mozilla → 426, Crowny → 200 cmd
라이브 루프: 빈 저장소에서 추가1→count 1, 추가2→count 2, 재렌더 부제 MEMO 2 반영.
히트맵 사이드카 /tmp/히트맵.psv 6행(입력1·버튼1·목록4) — 양 모드 공통 인터랙션 기록.
게이트 자가검증: 메모라우팅.한선 5케이스 전부 기대값 일치.라우팅 요약 (crowny:// 전용 게이트 연결방식)
요청 → UA파싱(게이트검증.js)
├ CrownyBrowser/5 + Crowny; → 전용 게이트 통과 → CROWNY_OUT=cmd → 네이티브 픽셀
└ 일반 브라우저
├ FALLBACK=html (개방 데모) → CROWNY_OUT=html → HTML 폴백
└ FALLBACK=strict(전용) → 426 "크라우니 브라우저로 여세요"
판단 SSOT = 메모라우팅.한선(=티어판정.한선 접근판정). JS는 HTTP로 옮기는 어댑터일 뿐.
관련 파일
/Users/ef/CrownyBrowser/src/메모백엔드.한선 — 데이터 제공자
/Users/ef/CrownyBrowser/src/메모앱.한선 — 프론트(듀얼 에미트)
/Users/ef/CrownyBrowser/src/메모추가.한선 — 백엔드 쓰기 진입점
/Users/ef/CrownyBrowser/src/메모라우팅.한선 — crowny:// 게이트 결정 SSOT
/Users/ef/CrownyBrowser/src/메모서비스.js — 전송 글루(서버 스텁)
- 기반:
화면.한선(DSL)·티어판정.한선/게이트검증.js(게이트)·페이지렌더러.한선+페이지배선.py(픽셀)
빌드/실행
bashcd /Users/ef/CrownyOS/crownyc
export CROWNY_STD=libs:/Users/ef/CrownyBrowser/src
./hanseonc_high /Users/ef/CrownyBrowser/src/메모앱.한선 > /tmp/memoapp.toau
./hanseonc_high /Users/ef/CrownyBrowser/src/메모추가.한선 > /tmp/memoadd.toau
# 두 출력
CROWNY_OUT=html ./crownyc run /tmp/memoapp.toau > /tmp/memo.html
CROWNY_OUT=cmd ./crownyc run /tmp/memoapp.toau > /tmp/memo.cmd
CW=800 CH=600 python3 /Users/ef/CrownyBrowser/native/m3-배선/페이지배선.py /tmp/memo.cmd
PLAN_FILE=/tmp/page_plan.psv CROWNY_FB_PPM=/tmp/memo.ppm ./crownyc run /tmp/render.toau
sips -s format png /tmp/memo.ppm --out /tmp/memo.png
# 서버
node /Users/ef/CrownyBrowser/src/메모서비스.js # :7788 html 폴백
FALLBACK=strict node /Users/ef/CrownyBrowser/src/메모서비스.js
잔여 이슈
- 픽셀 렌더 1회 ~3분(소프트GPU 직접드로우 36글리프). 글리프 캐싱/배치 여지.
- 픽셀 텍스트는 CIF 가용 글리프(한글 33+ASCII)에 한정 — 데이터 단어를 가용 글자로 제약.
메모라우팅.한선이 티어판정.한선을 임포트하면 후자의 주() 자가검증이 함께 실행(노이즈). 동명 주() 충돌 회피 위해 엔트리명을 라우팅검증()으로 분리함.
- 페이지배선.py가 RECT+TEXT만 소비 → 둥근모서리/그림자는 HTML 전용(cmd는 RECT 폴백).