FiveAI Fusion 언어
SpaceFive · Five 공식 데모

언어는 하나.
바이너리도 하나.
웹의 모든 것.

SpaceFive는 순수 Five로 만든, 필요한 것이 다 들어 있는 웹 프레임워크입니다. HTTP와 WebSocket, PostgreSQL, bcrypt, AES, 다국어까지 런타임이 직접 처리합니다. Node도, FFI도, ORM 서버도 없습니다. 정적 바이너리 하나가 Postgres와 바로 통하고, 그 위에서 진짜 앱 세 개가 지금 이 순간 돌아가고 있습니다.

—
등록된 자산
—
자산 총액
—
재직 인원
1
바이너리 하나
01 — 라이브 데모

앱은 셋, 프레임워크는 하나,
디자인도 하나.

클릭하는 모든 것이 Five 핸들러의 응답입니다. 화면 일부만 바꾸는 하이퍼미디어 갱신, 서버에서 그린 폼, CSV 내보내기, 사진 업로드, 실시간 이벤트까지.

02 — xBase · Harbour 개발자라면

이 언어, 이미 알고 계십니다.
달라진 건 화면뿐입니다.

Clipper나 FoxPro, Harbour로 코드를 짜 보셨다면 SpaceFive 페이지는 수백 번 만들어 본 다이얼로그처럼 읽힙니다. 아래 예제는 전부 진짜입니다. 오른쪽 위젯은 왼쪽 코드가 지금 이 요청에서 직접 그린 결과입니다.

메뉴 — MENU … ENDMENU
MENU hMenu MENUBAR
   MENUITEM "Assets"      ACTION "/assets"
   MENUITEM "People"      ACTION "/people"
   MENUITEM "+ New asset" ACTION "/assets/new" GOLD
ENDMENU
cHtml := MENU_HTML( hMenu )
지금 이 요청으로 그린 화면

FiveWin 문법 그대로입니다. MENU_HTML()이 마크업을 돌려주고, 어떻게 보일지는 스킨이 정합니다.

통계 카드 — DASHBOARD … STAT
hStat := DB_ONE( cAssetStats, {} )

DASHBOARD hDash
   STAT "Total assets"   VALUE hStat[ "n" ] GOLD
   STAT "Total value"    VALUE Money( hStat[ "total" ], "USD" ) GOLD
   STAT "Active"         VALUE hStat[ "active" ] OK
   STAT "In maintenance" VALUE hStat[ "maint" ] WARN
ENDDASHBOARD
cHtml := DASH_HTML( hDash )
지금 이 요청으로 그린 화면

쿼리 하나에 STAT 네 줄. GOLD, OK, WARN은 색상이고, 숫자는 PostgreSQL에서 방금 읽어 온 값입니다.

Total assets
14
Total value
$66,745
Active
12
In maintenance
1
브라우즈 — TABLE … COLUMN
aRows := DB_QUERY( cFirstEmployees, {} )

TABLE hList OF aRows LINK "/people/:id"
   COLUMN "name"       HEADER "Employee" THUMB "photo" SUB "emp_no"
   COLUMN "position"   HEADER "Position"
   COLUMN "status"     HEADER "Status" BADGE
   COLUMN "salary"     HEADER "Salary" MONEY CURRENCY "currency" RIGHT
ENDTABLE
cHtml := TABLE_HTML( hList )
지금 이 요청으로 그린 화면

웹판 TBrowse입니다. 필드마다 COLUMN 한 줄, THUMB·BADGE·MONEY·RIGHT로 표시 방법을 정하고, LINK 하나면 모든 행이 클릭됩니다.

EmployeePositionStatusSalary
사진 카드 — GALLERY … CARD
GALLERY hCards OF aRows LINK "/people/:id"
   CARD PHOTO "photo"  INITIALS "name"
   CARD BADGE "status"
   CARD TAG   "position"
   CARD TITLE "name"
   CARD META  "department"
   CARD VALUE "salary" CURRENCY "currency"
ENDGALLERY
cHtml := GALLERY_HTML( hCards )
지금 이 요청으로 그린 화면

CARD는 필드를 카드의 자리(사진, 배지, 태그, 제목, 부가 정보, 값)에 연결합니다. 카드 모양 자체는 스킨 폴더의 HTML 파일 하나입니다.

입력 폼 — FORM … GET … COMBO
FORM hForm ACTION "/people" OF hReq
   GET   "emp_no" LABEL "Employee no." VALUE "E-2001"
   GET   "name"   LABEL "Name"
   COMBO "status" LABEL "Status" VALUE "active" ITEMS aStatuses
   GET   "salary" LABEL "Salary (annual)" VALUE 90000
   BUTTON "Save" GOLD
   LINK   "Cancel" ACTION "/"
ENDFORM
cHtml := FORM_HTML( hForm )
지금 이 요청으로 그린 화면

브라우저판 @ SAY … GET입니다. CSRF 토큰은 폼에 함께 실리고, Save를 누르면 정말로 직원이 등록됩니다.

Cancel

DOS 화면에서 브라우저로

예전에는 이렇게지금은 이렇게무엇을 하나
@ 10, 5 SAY "Name" GET cNameGET "name" LABEL "Name" VALUE cName라벨이 붙은 입력 칸 하나.
MENU oMenu … MENUITEM … ENDMENUMENU hMenu MENUBAR … MENUITEM … ENDMENU헤더 버튼도, 사이드바 칩도, 탭도 같은 문법으로.
TBrowse / dbEdit()TABLE hList OF aRows … COLUMN … ENDTABLE썸네일, 배지, 금액 열이 있는 클릭형 목록.
USE customers INDEX ON nameaRows := DB_QUERY( cSql, { cName } )PostgreSQL에 파라미터를 바인딩해 바로 조회. ORM 서버는 없습니다.
SET COLOR TO W+/Bpublic/skins/<skin>/skin.css생김새는 스킨의 몫. 디자이너가 고칠 수 있는 CSS와 작은 HTML 템플릿입니다.
ACTIVATE WINDOW oWndFV_SERVE( nPort, "public", {| hReq | APP_DISPATCH( hReq ) } )웹 서버 전체가 main.prg의 한 줄입니다.
03 — 작동 원리

런타임이 직접, 중간 다리 없이.

모든 층이 Five 런타임 라이브러리 호출입니다. PostgreSQL 말고는 설치할 게 없습니다.

FV_SERVE

HTTP, 처음부터 끝까지

헤더와 쿠키를 받고, 상태 코드와 set-cookie를 돌려줍니다. 요청마다 전용 VM 스레드에서 돕니다.

WsServe · WsSend

실시간

의존성 없는 WebSocket 서버. 이 페이지 아래의 피드가 지금 그것을 듣고 있습니다.

PG_OPEN · PG_QUERY

PostgreSQL 직결

pgx 위에서 파라미터를 바인딩한 쿼리. 마이그레이션은 부팅 때 자동으로, 몇 번을 돌려도 같은 결과입니다.

PWHASH · ENCRYPT · SECEQ

기본 설정부터 안전하게

bcrypt 비밀번호, AES-256-GCM 세션, 상수 시간 비교, CSRF 이중 제출.

T()

다국어 내장

카탈로그 기반 번역에 요청마다 로케일 결정. 지금 보시는 이 페이지도 locales/*.json에서 여섯 언어로 나갑니다.

hx.js

하이퍼미디어 UI

54줄짜리 HTMX식 심 하나. 부분 교체와 CSRF 헤더만 있고, 빌드 단계도 프레임워크도 없습니다.

04 — 코드

요청도 해시, 응답도 해시.
핸들러는 코드블록 하나.

지금 돌고 있는 앱의 실제 라우트 테이블과 실제 핸들러입니다.

routes/routes.prg
// asset manager — gallery, list, detail, CRUD, export
ROUTE( "GET",  "/assets",            {| hReq | ASSET_DASHBOARD( hReq ) } )
ROUTE( "GET",  "/assets/cards",      {| hReq | ASSET_CARDS( hReq ) } )
ROUTE( "POST", "/assets",            {| hReq | ASSET_CREATE( hReq ) } )
ROUTE( "GET",  "/assets/export.csv", {| hReq | ASSET_EXPORT( hReq ) } )

// main.prg — the whole server
FV_SERVE( hCfg[ "port" ], "public", {| hReq | APP_DISPATCH( hReq ) } )

// a handler: query → hash → JSON. The result lives in a variable; RETURN returns it.
FUNCTION ASSET_LIST( hReq )
   LOCAL aRows := Rows( hReq, 1000, 0 )
   LOCAL hRes  := RES_JSON( { "ok" => .T., "assets" => aRows, "count" => Len( aRows ) } )

RETURN hRes
 wss · /ws연결 중
RT_BROADCAST가 보내는 실시간 피드입니다. 다른 탭에서 레코드를 하나 만들어 보세요. 여기에 바로 뜹니다. 자산 추가 · 직원 추가