사람함께에이전트▾
사람 — 직접 정하고 책임지는 비즈니스 규칙과 흐름. 직접 읽어보세요.
함께 — 개념은 알아두고, 세부 규칙은 에이전트가 따릅니다.
에이전트 — 에이전트가 따르는 규칙과 레퍼런스. 필요할 때 찾아보세요.
소개▾
튜토리얼▾
핵심 개념▾
시스템 아키텍처▾

Akan 런타임

Akan 애플리케이션은 앱 코드, 생성 산출물, 서버 라우트, 페이지를 연결하는 Bun 기반 런타임 위에서 실행됩니다. 앱 엔트리 포인트(main.ts)는 런타임을 시작하고, 그 뒤의 서버 구성은 Akan이 담당합니다.
apps/myapp/main.ts
Akan App이 실행되면 Akan Server가 앱이 제공할 기능들을 준비합니다. 실제 런타임은 크게 네 가지 작업을 제공합니다.
  • Internal API (Queue, Timer, etc.): 브라우저 요청 없이 내부에서 실행되는 큐, 타이머 같은 작업입니다.
  • API (HTTP, WebSocket): 데이터 요청과 실시간 업데이트를 처리하는 HTTP, 웹소켓 통신 경로입니다.
  • SSR Pages (Web): 서버가 렌더링해서 브라우저로 보내는 웹 페이지입니다.
  • CSR Page (Android, iOS): Android, iOS 같은 네이티브 target에서 사용하는 클라이언트 렌더링 페이지입니다.
런타임 개요
앱 코드는 Akan App에서 실행되고 Akan App이 Akan 서버를 실행합니다. 서버는 큐·타이머용 내부 API, HTTP·WebSocket API, 웹용 SSR 페이지, Android·iOS용 CSR 페이지를 제공합니다.
AKAN_REPLICA는 역할별 서버 프로세스 개수를 정하며, 어디서나 기본값은 0,0,1입니다. all 서버 하나만 실행한다는 뜻입니다. 트래픽 replica가 하나면 분산할 대상이 없으므로, Akan App은 그 서버를 spawn해서 프록시하지 않고 자기 프로세스 안에서 직접 실행합니다. 컨테이너는 프로세스 하나만 갖고, 모든 요청이 프록시 홉을 건너뜁니다.
  • all: 하나의 서버 프로세스에서 federation과 batch 역할을 함께 실행합니다. 기본값이며, 대부분의 배포가 이 형태로 나갑니다.
  • federation: 페이지, API 호출, 웹소켓 연결 같은 브라우저 요청을 처리합니다.
  • batch: 큐, 타이머, 예약 작업 같은 백그라운드 작업을 실행합니다.
기본값: 프로세스 하나, 게이트웨이 없음
브라우저는 컨테이너 안의 프로세스 하나에 닿고, 그 안에서 Akan 앱과 Akan 서버가 함께 페이지·API·웹소켓을 처리하고 큐·타이머·잡을 실행합니다. 별도의 RSC 워커 프로세스는 웹일 때만 있습니다.
gateway가 다시 사용되는 경우는 다섯 가지입니다. replica가 둘 이상일 때, listen하지 않는 batch 전용 replica가 있을 때, AKAN_SOLO=false일 때, new AkanApp(...)에 replica를 넘겼을 때, 그리고 akan start일 때입니다. 이때 Akan App은 서버들을 spawn하고 준비된 federation/all 프로세스로 브라우저 요청을 로드밸런싱합니다.
Replica와 server 모드
브라우저는 컨테이너 안에서 게이트웨이이자 로드 밸런서인 Akan 앱에 닿습니다. Akan 앱은 페이지·API·웹소켓 트래픽을 federation 서버 세 개로 나누고, 큐·타이머·잡을 위한 batch 서버를 실행합니다.

정체성과 환경

루트 .env 파일은 앱이 실행될 때 사용할 조직, 도메인, 환경, 동작 모드, 로그 수준을 정합니다. 대부분의 프로젝트에서는 이 값을 자주 바꾸지 않지만, 값을 바꾸면 같은 앱을 로컬용, 디버그용, 개발 서버용, 운영에 가까운 형태로 실행할 수 있습니다.
.env
이 중 네 개는 이 앱이 누구이며 어디서 도는지에 답하며, 앞의 두 개는 필수입니다:
AKAN_PUBLIC_REPO_NAMEstring필수
조직 또는 저장소 네임스페이스이며, 보통 프로젝트 수명 내내 고정입니다.
AKAN_PUBLIC_SERVE_DOMAINstring필수
앱이 링크, 콜백, 도메인 기반 라우팅을 만들 때 쓰는 도메인입니다.
AKAN_PUBLIC_ENVlocal | debug | develop | main | testing기본값 debug
앱이 어떤 데이터 기준으로 도는지 정합니다. 로컬 테스트 데이터부터 운영에 가까운 main까지입니다.
AKAN_PUBLIC_OPERATION_MODElocal | edge | cloud | module기본값 ENV=local이면 local, 아니면 cloud
클라이언트가 연결할 곳입니다. 로컬 런타임, 클라우드, 엣지 경로 중 하나이며 module은 타입에만 있습니다.
실제로는 두 개를 같이 움직입니다. 기능을 만들 때는 ENV=local, OPERATION_MODE=local로 작업하고, 공용 데이터나 공용 서비스가 필요해지면 ENV를 debug나 develop으로 바꾸며, 배포할 때는 클러스터가 제공하는 operation mode에 맞춰 ENV=main으로 올립니다:
.env
두 개는 서버에 닿는 쪽을 좁힙니다. 데스크톱 앱에 싣는 서버처럼 자기 컴퓨터만 부르는 서버용입니다:
AKAN_LISTEN_HOSTstring기본값 모든 인터페이스
서버가 바인딩할 주소 하나입니다. 예: 127.0.0.1.
AKAN_ALLOWED_HOSTShost:port, …
응답할 Host 헤더입니다. 다른 요청은 소켓 업그레이드와 preflight까지 403을 받습니다.

데이터베이스 환경변수

배포가 어떤 데이터베이스 모드로 돌고 데이터가 어디에 있는지는 배포가 정합니다. 아래 변수는 env.server.ts에 적은 같은 값보다 우선하므로, 이미지 하나로 여러 배포를 할 수 있습니다:
AKAN_DATABASE_MODEsingle | multiple | cluster기본값 첫 번째로 선언한 모드
database.modes 중 하나이며, 여러 모드를 선언한 빌드의 배포는 반드시 설정합니다.
AKAN_SQLITE_DIRstring기본값 이미지에서는 /workspace/sqlite
경로를 따로 정하지 않은 SQLite 파일을 둘 디렉터리이며, 데이터베이스 파일과 single의 캐시·큐 파일이 여기에 놓입니다.
SQLITE_DATABASE_PATHstring
single과 multiple의 데이터베이스 파일 하나만 옮기며, AKAN_SQLITE_DIR보다 우선합니다.
AKAN_SOLID_DB_PATHstring
single이 캐시, 큐, PubSub을 두는 SQLite 파일입니다.
POSTGRES_URLstring
cluster의 데이터베이스이며(별칭 POSTGRES_URI), 풀 크기와 SSL은 쿼리 문자열에 적습니다.
POSTGRES_HOSTstring기본값 localhost
같은 URL을 나눠 적으며, POSTGRES_PORT, POSTGRES_DATABASE, POSTGRES_USER, POSTGRES_PASSWORD와 함께 씁니다.
POSTGRES_INSIGHT_URLstring
cluster에서 SQL 콘솔이 로그인할 URL이며, 기본 컬럼만 읽을 수 있는 role이어야 합니다.
REDIS_URIstringlocal 밖에서 필수
multiple과 cluster의 모든 인스턴스가 함께 쓰는 Redis이며, rediss://로 TLS를 켭니다.
AKAN_STORAGE_SHAREDtrue | 1
모든 인스턴스가 같은 업로드 볼륨을 마운트한다는 뜻이며, multiple과 cluster의 디스크 업로드에 필요합니다.
database: { modes: ["single", "cluster"] }를 선언한 앱은 이미지 하나로 아래 두 배포를 모두 실행합니다:
.env
  • REDIS_URI를 생략할 수 있는 곳은 로컬 개발뿐입니다. 개발자 PC에서는 localhost를 쓰고, akan start가 공용 환경에 붙어 실행될 때는 REDIS_HOST를 씁니다.
  • transaction 모드의 PgBouncer 뒤에서는 POSTGRES_URL에 prepare=false를 붙입니다. 드라이버가 이런 설정을 모두 쿼리 문자열에서 읽습니다.

로깅 환경변수

레벨 사다리는 trace, verbose, debug, info, warn, error이고, 세 목적지가 이를 각각 따로 읽습니다. 컨테이너 stdout, 회전 로그 파일, 그리고 앱이 등록한 sink입니다. 나머지 변수들은 레코드에 얼마나 많은 구조가 함께 실려 가는지, 그리고 누가 더 많은 것을 요구할 수 있는지를 정합니다.
AKAN_PUBLIC_LOG_LEVELtrace | verbose | debug | info | warn | error기본값 info
콘솔에 보낼 런타임 로그의 양입니다. 폐기된 log는 info를 뜻합니다.
AKAN_LOG_STDOUT_LEVELtrace | verbose | debug | info | warn | error기본값 AKAN_PUBLIC_LOG_LEVEL
형식과 무관하게 컨테이너 stdout으로 나가는 레벨입니다. 운영 권장은 info입니다.
AKAN_LOG_FILE_LEVELtrace | verbose | debug | info | warn | error기본값 trace
파일에 저장할 structured Logger 출력 범위이며, 터미널 로그 레벨과 별도로 동작합니다.
AKAN_LOG_FORMATtext | ndjson | ndjson-only기본값 text
text는 사람이 읽는 줄입니다. ndjson은 stdout을 한 줄에 JSON 레코드 하나로, ndjson-only는 회전 파일까지 JSON으로 씁니다.
AKAN_LOG_TO_FILE0 | 1기본값 1
gateway와 child 로그를 runtime/logs에 씁니다. 프로덕션 이미지에서는 꺼져 있습니다.
AKAN_LOG_DIRstring기본값 runtime/logs
볼륨이 기본 디렉터리에 마운트되어 있지 않을 때, 파일 로그가 쓸 경로입니다.
AKAN_LOG_MAX_SIZE_MBnumber기본값 50
프로세스별 로그 파일이 이 크기에 도달하면 다음 sequence 파일을 만듭니다.
AKAN_LOG_MAX_FILESnumber기본값 100
gateway 또는 child-0 같은 process key별로 보관할 회전 로그 파일 개수입니다.
AKAN_LOG_CONTEXT0 | 1기본값 1
각 호출의 레코드에 traceId, 엔드포인트, origin을 붙입니다. AKAN_TRACE와는 별개입니다.
AKAN_LOG_STREAM0 | 1기본값 0
1이면 akan logs나 .tail이 구독하지 않아도 child가 항상 gateway로 레코드를 올립니다.
AKAN_LOG_STREAM_TOKENstring기본값 미설정 — 라우트 없음
일치하는 bearer 토큰에게 링 버퍼를 SSE로 흘려 주는 GET /_akan/app/logs를 엽니다.
AKAN_LOG_CANONICAL0 | 1 | all | slow기본값 0
호출이 끝날 때 레코드 하나를 씁니다. 1·all은 모든 호출을, slow는 실패했거나 느린 호출만 씁니다.
AKAN_LOG_FLIGHT0 | 1기본값 0
호출마다 레벨 아래 레코드 최근 64건을 들고 있다가, 실패했거나 느리면 올립니다.
AKAN_LOG_FLIGHT_MSnumber기본값 1000
이 시간 이상 걸린 호출을 느린 호출로 봅니다. flight recorder와 canonical의 slow 모드가 함께 씁니다.
AKAN_LOG_FLIGHT_MAXnumber기본값 65536
프로세스가 동시에 들고 있을 레코드 상한이고, 넘치면 그 호출은 기록 없이 진행합니다.
AKAN_LOG_BUFFERnumber기본값 2000
akan logs와 SSE 스트림이 되돌려 보낼 수 있도록 메모리 허브가 들고 있는 레코드 수입니다.
AKAN_LOG_BUFFER_MBnumber기본값 4
같은 버퍼의 바이트 상한이며, 둘 중 먼저 걸리는 쪽이 적용됩니다.
AKAN_LOG_DEBUG_HEADERstring기본값 미설정 — local에서만
local 밖에서 x-akan-debug 헤더가 이 비밀값을 담아야 그 요청 하나를 trace로 기록합니다.
gateway(또는 단독 replica)가 akan logs --replay와 .trace를 위해 유지하는 링은 AKAN_LOG_BUFFER건 또는 AKAN_LOG_BUFFER_MB(기본 2,000건, 4MB) 중 먼저 차는 쪽까지 보관하고, 오래된 레코드부터 밀려납니다.

getEnv()

getEnv()는 .env 값을 앱이 실제로 사용할 런타임 정보로 정리해 주는 helper입니다. API URL이나 웹소켓 URL을 직접 조합하지 않고, 앱 코드에서는 getEnv()가 준비한 값을 읽어 사용할 수 있습니다.
Using getEnv()
로컬 모드
OPERATION_MODE가 local이면 getEnv()는 브라우저와 API 클라이언트가 내 로컬 Akan 런타임을 바라보도록 합니다. 보통 localhost:8282를 사용합니다.
local
클라우드 / 엣지 모드
OPERATION_MODE가 cloud 또는 edge이면 getEnv()는 앱 이름, 환경, 서비스 도메인을 조합해 서비스 URL을 만듭니다.
cloud / edge

OpenAPI JSON

Akan은 signal 파일에 선언된 HTTP query/mutation 표면을 OpenAPI 3.1 문서로 노출할 수 있습니다. Swagger, Redoc, 외부 클라이언트, SDK 생성 도구를 Akan이 이미 사용하는 API 형태에 연결할 때 유용합니다.
apps/myapp/main.ts
활성화한 뒤 앱 origin에서 /openapi.json을 요청하면 됩니다. 로컬 모드에서는 보통 localhost:8282/openapi.json에서 확인할 수 있습니다. 일반 API prefix는 /api를 유지하고, OpenAPI JSON은 프레임워크 메타데이터 route로 제공됩니다.
Read the OpenAPI document
앱 옵션
해당 앱 엔트리 포인트에서 항상 OpenAPI JSON을 노출해야 할 때 사용합니다.
new AkanApp("./server", { openapi: true })
환경변수
배포 환경이나 로컬 스크립트에서 endpoint 노출 여부를 결정해야 할 때 사용합니다.
AKAN_OPENAPI=true
서버 옵션
AkanApp을 거치지 않고 AkanServer를 직접 시작할 때 사용합니다.
new AkanServer("myapp", env, "all", lib, { openapi: true })

모듈 선택 실행

앱은 라이브러리가 선언한 모든 모듈을 마운트합니다. modules 옵션은 그 범위를 좁힙니다. 이 프로세스가 담당할 모듈을 지정하면 Akan은 그 모듈과 의존하는 모듈만 부팅하고 나머지는 컨테이너에 아예 올리지 않습니다. 빠진 모듈은 service, signal, route, 예약 작업이 모두 존재하지 않습니다. 하나의 코드베이스를 여러 개의 작은 프로세스로 나눠 실행하는 방법이며, 자기 도메인만 필요한 batch worker 같은 경우에 씁니다.
apps/myapp/main.ts
의존성은 프레임워크가 따라가므로 전체 그래프가 아니라 진입점만 적으면 됩니다. 지정한 모듈은 자신이 주입하는 service와 signal, 그리고 cascade로 삭제하는 model을 함께 끌어옵니다.
disableModules와 disableLibs는 반대편에서 좁힙니다. 지정한 대상과 그것을 참조하는 모듈만 빼고 전부 마운트합니다. disableLibs는 라이브러리 이름을 받아 그 라이브러리가 등록한 모듈 전부를 뜻합니다. 둘 다 modules를 쓰는 곳 어디서나 쓸 수 있고, 환경변수로는 AKAN_DISABLE_MODULES와 AKAN_DISABLE_LIBS입니다. modules와 제외 옵션에 같은 모듈을 적으면 빠집니다.
apps/myapp/main.ts
앱 옵션
이 엔트리 포인트가 담당할 모듈을 코드에서 정할 때 사용합니다. 여기서 생성되는 모든 replica가 같은 선택을 받습니다.
new AkanApp("./server", { modules: ["article"] })
환경변수
배포 환경에서 분리 방식을 정할 때 사용합니다. 엔트리 포인트를 새로 만들지 않고 같은 이미지를 다른 프로세스로 실행할 수 있습니다.
AKAN_MODULES=article,file
서버 옵션
AkanApp을 거치지 않고 AkanServer를 직접 시작할 때 사용합니다.
new AkanServer("myapp", env, "all", lib, { modules: ["article"] })

상태 확인, 메트릭, 로그

Akan 런타임은 앱이 살아있는지, 얼마나 바쁜지, 지금 무엇을 하고 있는지 확인할 수 있는 간단한 방법을 제공합니다. 로컬 개발에서는 페이지가 열리지 않거나 백그라운드 작업이 멈춘 것처럼 보일 때 유용합니다.
상태 확인
서버 프로세스가 실행 중이고 준비되었는지 확인할 때 사용합니다. solo replica는 gateway와 같은 형태로 직접 응답하므로, probe는 두 경우 모두 같은 형식을 읽습니다.
health
메트릭
활성 요청, 웹소켓 연결, room, 프로세스 지표 같은 런타임 수치를 확인할 때 사용합니다.
metrics
로그
터미널에 어느 정도 자세한 로그를 볼지는 AKAN_PUBLIC_LOG_LEVEL로 조절합니다. AkanApp은 기본적으로 gateway와 child process 출력을 runtime/logs에 저장하며, structured Logger 출력은 AKAN_LOG_FILE_LEVEL 기준으로 저장하고 날짜와 크기 기준으로 파일을 회전합니다.
logs
파일명에는 app name, environment, operation mode, 로컬 날짜, process key, sequence가 포함됩니다. child server의 직접 console.log 호출은 stdout/stderr pipe를 통해 저장되지만, gateway process의 직접 console.log 호출은 Logger sink 캡처 대상이 아닙니다.
런타임 점검
개발자
Akan 앱(게이트웨이 또는 솔로)
/_akan/app/health
/_akan/app/metrics
터미널 로그
실행 중 / 준비 완료
요청, 소켓, 메모리
디버그 상세

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

내 AI에 이 문서 연결하기

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