사람함께에이전트▾
사람 — 직접 정하고 책임지는 비즈니스 규칙과 흐름. 직접 읽어보세요.
함께 — 개념은 알아두고, 세부 규칙은 에이전트가 따릅니다.
에이전트 — 에이전트가 따르는 규칙과 레퍼런스. 필요할 때 찾아보세요.
CLI 레퍼런스▾
AkanJS 레퍼런스▾
UI 레퍼런스▾

시스템 UI

기능 위젯이 아니라 화면을 둘러싼 부품입니다. 앱 셸, 테마와 언어 전환, API 탐색기, 탭, 애니메이션을 다룹니다. root layout, 관리자 페이지, signal 대시보드, 탭으로 나뉜 상세 화면, 애니메이션 UI에 쓰며 모두 akanjs/ui에서 가져옵니다.
이 페이지에서 쓰는 말
앱 셸
모든 페이지가 그 안에서 그려지는 틀로, 테마, 폰트, 언어, 토스트, 소켓 연결을 맡습니다.
Suspense
안쪽 내용이 준비될 때까지 대신 보여 줄 fallback을 그리는 React 경계입니다.
serialized signal
endpoint 전부와 그 인자, guard, 반환 모델을 담은 정보로, fetch.serializedSignal로 전달됩니다.
에이전트 툴
컨트롤이 공개하는 동작으로, 인페이지 에이전트가 사용자의 클릭과 같은 일을 할 수 있게 합니다.
컴포넌트 고르기
컴포넌트
자동
서버
툴
앱 셸
System.Provider
✓
✓
Akan이 root _layout.tsx를 감싸는 앱 프레임입니다.
System.Reconnect
✓
✓
.reconnect()를 켜면 Provider가 마운트하는 연결 끊김 오버레이입니다.
직접 놓는 컨트롤
System.ThemeToggle
✓
✓
색 테마를 바꾸고 applyTheme 툴을 공개합니다.
System.SelectLanguage
✓
✓
URL의 언어를 바꾸고 setLanguage 툴을 공개합니다.
System.DevModeToggle
✓
개발자 전용 UI를 켜고 끕니다.
Tab
✓
✓
패널이 서버에 남는 탭으로, namespace가 있을 때만 툴을 공개합니다.
개발 도구와 기본 부품
Signal.*
API 탐색기입니다. 관리자나 문서 화면에 둡니다.
ClientSide
✓
loading fallback을 가진 Suspense 경계입니다.
animated
react-spring으로 움직이는 div, g, progress입니다.
✓예아니요
  • 자동은 직접 쓸 일이 없다는 뜻입니다. Provider가 모든 페이지를 감싸고, root layout이 .reconnect()를 호출하면 Reconnect도 마운트합니다.
  • 서버는 직접 "use client"를 달 필요가 없다는 뜻입니다. page, layout, View에서 바로 그리면 되고, 브라우저가 필요한 부분에는 이미 "use client"가 붙어 있습니다. Signal 부품과 animated는 첫 줄이 "use client"인 파일에서 써야 합니다.
  • 툴은 인페이지 에이전트도 쓸 수 있다는 뜻입니다. ThemeToggle이나 SelectLanguage를 놓기만 하면, 에이전트도 사용자와 같은 방식으로 테마와 언어를 바꿀 수 있습니다.
함께 볼 페이지

System

앱 셸입니다. Provider는 Akan이 대신 마운트하고, Reconnect는 켜 두면 Provider가 마운트합니다. ThemeToggle, SelectLanguage, DevModeToggle은 직접 배치하는 컨트롤입니다.
속성과 API
System.Provider{ appName, params, of, children, className?, env?, theme?, prefix?, manifest?, head?, fonts?, layoutStyle?, reconnect?, wsConnect?, dictionary?, allDictionary? }
root _layout.tsx를 감싸는 앱 프레임으로, 값은 rootLayout() 단계에서 정합니다.
System.Root{ st, children }
지원이 중단되었고 st는 무시한 채 children만 그리므로, 자식을 바로 렌더하면 됩니다.
System.ThemeToggle{ themes?: string[] }
data-theme을 themes 중 하나로 바꾸며, 두 개면 스위치, 셋 이상이면 드롭다운으로 그립니다.
System.SelectLanguage{ className?, languages?: string[] }
현재 URL에서 /:lang 구간만 바꾸고 나머지 경로와 쿼리는 그대로 두는 드롭다운입니다.
System.Reconnect{}
소켓이 끊기고 서버 ping도 실패하면 화면을 덮고, 다시 연결되면 페이지를 새로고침합니다.
System.DevModeToggle{}
store의 devMode 플래그를 켜고 끄는 스위치로, 값이 localStorage에 남아 새로고침해도 유지됩니다.
  • 프레임은 root layout에서 정합니다. .theme(), .fonts(), .manifest(), .layoutStyle(), .reconnect(), .wsConnect()가 Provider의 prop이 되고, env는 env/env.client.ts에서 옵니다.
  • Reconnect는 로컬 개발용입니다. root layout에서 .reconnect()를 호출해야 켜지고, AKAN_PUBLIC_ENV가 local일 때만 화면에 나타납니다.
  • ThemeToggle에는 테마가 두 개 이상 필요합니다. themes를 빼거나 하나만 넘기면 아무것도 그리지 않습니다. 고른 테마는 theme 쿠키에 남습니다.
  • languages의 기본값은 앱의 locale 목록입니다. 앱이 서비스하지 않는 언어 코드는 메뉴에서 빠집니다. 고르면 404로 가기 때문입니다.
  • devMode는 개발자 전용 UI가 읽는 값입니다. 관리자 화면은 이 값을 보고 개발자용 기능을 보여 줄지 정하고, @libs/shared/ui의 Only.Dev는 이 값이 켜져 있을 때만 자식을 그립니다.
  • 토스트 묶음은 일부러 멤버에서 뺐습니다. Provider가 마운트하며, msg.* 연결, store 읽기, body 수준 portal, 자동 닫힘 타이머를 스스로 가집니다. 그래서 오버라이드 슬롯은 토스트가 언제 뜨고 사라질지 정하는 부분이 아니라 겉모습인 Toast와 ToastItem입니다.
사용 예시

ClientSide

작은 React Suspense 경계입니다. 안쪽 내용이 suspend되는 동안 loading을 보여 줍니다. 아직 chunk를 받는 중인 lazy() 컴포넌트가 대표적입니다.
속성과 API
childrenReactNode
suspend될 수 있는 내용입니다.
loadingReactNode
그동안 보여 줄 fallback이며, 빼면 아무것도 보이지 않습니다.
  • 자식을 클라이언트 전용으로 만들지는 않습니다. "use client" 없는 평범한 Suspense라서, 서버에서 그릴 수 있는 자식은 그대로 서버에서 그려집니다.
  • 예시의 StoreMap은 lazy()로 내보낸 컴포넌트입니다. ui/StoreMap/index_.tsx 경계에서 오므로, chunk를 받는 동안 loading이 대신 보입니다.
사용 예시

Signal

API 탐색기를 부품으로 나눈 것입니다. 서버가 앱과 함께 보내는 serialized signal, 즉 endpoint 전부와 그 인자, guard, 반환 모델을 읽어서, 읽기만 하는 문서가 아니라 endpoint를 직접 호출해 볼 수 있는 문서를 그립니다.
속성과 API
Signal.Doc.Zone · .Explorer · .Setting · .AuthModal · .DocSignals · .DocSignal
Zone({ refName })은 signal 하나를 문서로 그리고, Explorer({ include?, exclude? })는 전체를 사이드바 뒤에 둡니다.
Signal.RestApi.Endpoints · .Endpoint · .Interface · .Try
HTTP 쪽으로, Endpoints가 query와 mutation을 나열하고 endpoints를 넘기면 그것만 보여 줍니다.
Signal.WebSocket.Endpoints
websocket endpoint를 같은 방식으로 나열하며, 각 행은 PubSub이나 Message가 그립니다.
Signal.PubSub.Endpoint · .Interface · .Try
구독 하나의 room과 payload 형태, 그리고 도착하는 프레임을 바로 보여 주는 Try입니다.
Signal.Message.Endpoint · .Interface · .Try
단방향 message endpoint용으로 같은 세 부품을 제공합니다.
Signal.Listener.Result
Result는 Try가 결과를 적는 실시간 창이며, byte payload는 짧은 16진수 미리보기로 보입니다.
Signal.Object.Type · .Detail · .Schema
constant class를 읽어 모델을 타입 칩, 필드 표, 제목이 붙은 스키마 중 하나로 보여 줍니다.
Signal.Argcomponent · .Table · .Param · .Query · .FormData · .ID · .Int · .Float · .String · .Boolean · .Date · .Json · .Upload
유일하게 그 자체로 컴포넌트이며, Arg({ argType, value, onChange })가 scalar 하나의 입력칸을 그립니다.
  • 루트가 아니라 멤버를 씁니다. Signal.Doc과 형제들은 네임스페이스이므로 Signal.Doc.Zone이나 Signal.RestApi.Endpoints를 씁니다. 그 자체로 컴포넌트인 것은 Signal.Arg뿐입니다.
  • 페이지에서 바로 렌더합니다. 멤버마다 따로 클라이언트 경계를 넘고 fetch는 앱 자신의 것이 기본값이므로 "use client" 래퍼가 필요 없습니다. 다른 앱의 proxy를 문서로 보여 줄 때만 fetch를 넘깁니다.
  • 마운트된 signal만 나옵니다. 탐색기는 fetch.serializedSignal을 읽으므로, 앱이 마운트하지 않은 signal은 빈 화면이 아니라 등록되지 않았다고 표시됩니다.
  • 설정은 화면 전체에 한 번입니다. Doc.Setting에서 고른 guard 필터와 JWT는 store에 있으므로, 화면의 모든 endpoint 목록과 REST Try가 같은 값을 따릅니다.
  • REST 행마다 guard와 MCP 상태가 보입니다. 배지가 MCP 툴로 공개되는지 알려 주고, 거부된 endpoint에는 그 이유가 함께 나옵니다.
사용 예시

Tab

패널이 서버에 남도록 부품으로 나눈 탭 묶음입니다. 상태는 provider와 menu만 가지고, Tab.Panel은 받은 것을 그대로 그리므로 패널 안의 마크업은 번들에 들어가지 않습니다.
속성과 API
Tab{ className?, defaultMenu?, namespace?, children? }
선택된 메뉴를 쥐는 provider로, 처음엔 defaultMenu가 선택되고 빼면 아무 메뉴도 선택되지 않습니다.
Tab.Menus{ className?, children }
메뉴 버튼이 놓이는 role="tablist" 줄입니다.
Tab.Menu{ menu, children, className?, activeClassName?, disabledClassName?, disabled?, tooltip?, scrollToTop? }
탭 버튼 하나이며, key는 value가 아니라 menu입니다.
Tab.Panel{ menu, children?, className?, loading?: "eager" | "lazy" | "every" }
자기 menu가 선택된 동안 보이는 본문이며, 언제 마운트할지는 loading이 정합니다.
  • loading이 패널의 마운트 시점을 정합니다. 기본값 "eager"는 모든 패널을 처음부터 그리고 나머지를 숨깁니다. "lazy"는 처음 선택될 때 마운트해 계속 두고, "every"는 선택될 때마다 마운트하고 떠나면 내립니다.
  • namespace가 있어야 인페이지 에이전트에 공개됩니다. namespace="product"를 주면 tabsInProduct 상태와 switchTabInProduct 툴이 생깁니다. 없으면 아무것도 공개하지 않습니다.
  • 비활성 메뉴는 선택된 채로 남지 않습니다. 선택된 Tab.Menu를 비활성화하면 다른 활성 메뉴 중 첫 번째로 선택이 옮겨 가고, scrollToTop을 주면 클릭할 때 창을 맨 위로 올립니다.
  • 이 모양을 따라 합니다. mode useState 하나와 모든 패널을 인라인한 "use client" 파일 하나로 만들지 마세요. 그러면 모든 패널의 마크업이 JavaScript로 실려 갑니다.
사용 예시

animated

Akan UI 컴포넌트가 쓰는 react-spring animated 요소를 그대로 다시 내보낸 것입니다. 직접 만드는 애니메이션 화면에서 spring hook과 함께 씁니다.
속성과 API
animated.divreact-spring animated div
움직이는 div입니다.
animated.greact-spring animated g
움직이는 SVG 그룹 g입니다.
animated.progressreact-spring animated progress
움직이는 progress 요소입니다.
  • "use client" 파일에서 씁니다. 이것을 움직이는 spring hook은 브라우저에서만 돌고, 멤버도 서버 컴포넌트에서는 쓸 수 없습니다.
  • 감싼 태그는 div, g, progress뿐입니다. 다른 태그가 필요하면 useSpring처럼 ui/ 파일에서 react-spring의 animated를 직접 가져다 씁니다.
사용 예시

MIT 라이선스 하에 배포되었습니다.

내 AI에 이 문서 연결하기

MCPhttps://akanjs.com/mcp
Copyright © 2026 Akan.js 모든 권리 보유.시스템 관리자bassman