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

앱 설정

akan.config.ts는 앱 단위 설정 파일입니다. 처음부터 모든 옵션을 이해할 필요는 없습니다. 빈 파일로 시작하고, 앱에 필요한 필드만 하나씩 추가하면 됩니다.
apps/minimal/akan.config.ts
설정 가능한 키는 아래가 전부입니다. 모두 앱이 그대로 동작하는 기본값을 갖고 있으며, 그중 자주 바꾸게 되는 것들을 이어지는 슬라이드에서 다룹니다:
routesAkanRouteConfig[]
앱이 사용할 공개 도메인이며, basePath로 클라이언트를 나눌 수 있습니다.
api{ prefix, websocketPrefix }기본값 /api, /ws
signal 엔드포인트와 웹소켓 업그레이드가 마운트될 경로입니다. 모든 클라이언트 번들에 구워집니다.
webboolean | { csr: boolean }기본값 true
빌드가 만들고 앱이 부팅 때 마운트하는 웹 표면을 정합니다.
i18n{ defaultLocale, locales }기본값 en, ["en", "ko"]
모든 라우트가 놓이는 locale 세그먼트입니다. defaultLocale은 locales 안에 있어야 합니다.
nativeAkanNativeAppConfig
iOS·Android·데스크톱 앱의 정보, 플랫폼 설정, target입니다.
imagesAkanImageConfig기본값 webp, quality 75
이미지 최적화의 허용 목록·크기·제한입니다. 목록에 없는 원격 호스트는 거부됩니다.
publicEnvstring[]기본값 []
기본 AKAN_PUBLIC_* 패턴 외에 브라우저 빌드가 인라인해도 되는 process.env 이름입니다.
secretsstring[]기본값 []
env.server.*.ts 안에 담을 수 없는 파일의 glob입니다. upload-env가 함께 보내고 git-ignore됩니다.
assets{ pruneFonts, keepFonts }기본값 true, []
akan build가 배포용 public/ 복사본을 어떻게 줄일지 정합니다. 원본 트리는 건드리지 않습니다.
syncPageLibsstring[] | boolean기본값 false
이 앱이 자기 라우트로 마운트할 라이브러리 page 폴더를 정합니다.
pluginsAkanPlugin[]기본값 []
이 앱이 등록하는 Akan 플러그인이며, CLI가 실행 시점에 읽습니다.
pipelineAppPipelineConfig기본값 build → docker → deploy
Akan Cloud가 이 앱을 빌드하고 배포할 때 순서대로 실행하는 stage입니다.
dockerstring | DockerImageConfig기본값 oven/bun:1-slim
Dockerfile 전체 문자열이거나, akan build가 Dockerfile을 조립할 재료입니다.
database{ modes: DatabaseMode[] }기본값 { modes: ["single"] }
빌드가 실행될 수 있는 모드 목록이며, 배포마다 AKAN_DATABASE_MODE로 그중 하나를 고릅니다.
externalLibsstring[]기본값 []
번들에 넣지 않고 프로덕션 런타임 의존성으로 유지할 패키지입니다.
trustedDependenciesstring[]기본값 []
bun install --production이 설치 스크립트를 실행할 패키지이며, 이미지와 데스크톱 앱의 서버 모두에 적용됩니다.
binRecord<string, { [platform]: AkanBinSource }>기본값 {}
모든 데스크톱 빌드가 싣고 가는 실행 파일이며 플랫폼마다 적고, PATH 맨 앞에 놓입니다. 이미지는 읽지 않습니다.
barrelImportsstring[]기본값 akanjs + workspace
스캔과 번들링에서 Akan이 펼치는 barrel 경로입니다.
optimizeImportsstring[]기본값 built-in list
클라이언트 빌드가 정확한 원본 파일 import로 바꿔 줄 추가 패키지입니다.
작게 시작: 대부분의 기본값은 준비되어 있으므로 빈 config도 유효합니다.
필요한 것만 추가: 앱에서 실제로 바꿔야 하는 부분만 선언하면 됩니다.
하나의 기준점: CLI 명령, 프로덕션 빌드, 네이티브 앱 명령이 모두 이 파일을 기준으로 동작합니다.

설정 파일 형태

default export는 일반 객체이거나 함수일 수 있습니다. 대부분의 앱은 객체로 충분합니다. config를 읽는 시점에 앱 메타데이터가 필요할 때만 함수를 사용합니다.
객체 설정
함수 설정

애플리케이션 환경설정

akan.config.ts가 앱을 어떻게 빌드하고 라우팅할지 설명한다면, env/ 폴더는 앱이 실행 중 사용할 실제 값을 설명합니다. 공개 가능한 클라이언트 키, 서버 전용 옵션, 환경별 서비스 설정 같은 값이 여기에 들어갑니다.
env/env.client.local.ts
env/env.server.local.ts
env.client.*
클라이언트 코드가 쓰는 공개 가능한 값입니다. 지도 키, 사이트 키, 기능 스위치 같은 값입니다.
env.server.*
서버 모듈에서만 쓰는 값입니다. 서버 옵션, 연결 설정, 비공개 서비스 설정을 둡니다.
localtestingdebugdevelopmain
AKAN_PUBLIC_ENV로 고르는 suffix이며, 순서대로 내 PC, 테스트, 공유 개발 단계 둘, 운영 환경입니다.
env.*.type.ts
env 값의 형태를 정의해, 빠지거나 이름이 틀린 설정을 코딩 중에 잡습니다.

서버 옵션

lib/option.ts는 앱이 서버를 설정하는 자리입니다. env/는 값을, akan.config.ts는 빌드를 담고, 이 파일은 그것을 런타임에 연결합니다. use 객체, signal middleware, adaptor override, web proxy에 더해 MCP 서버, agent relay 접근 정책, 그 relay가 말을 거는 LLM까지 여기서 정합니다. 앱이 의존하는 모든 라이브러리도 각자 option.ts를 가지며, 마운트 순서대로 읽고 앱의 것을 마지막에 얹습니다. 그래서 앱은 라이브러리가 선언한 값을 다시 쓰지 않고 조일 수 있습니다.
lib/option.ts
setLlm
LlmAdaptorRole을 차지한 어댑터가 쓸 apiKey·model·host입니다.
setAgentAccess
runAgentTurn으로 LLM 키를 쓰려면 통과해야 할 가드이며 AND로 묶입니다. 없으면 모든 호출이 거절됩니다.
setMcp
instructions·readOnly·auth 같은 MCP 서버 설정입니다.
useapplyMiddlewareapplyAdaptorapplyWebProxy
service가 use<T>()로 잡는 env 기반 싱글턴, signal middleware, adaptor override, web proxy를 등록합니다.

Route와 Domain

routes는 앱에서 사용할 공개 도메인을 적는 곳입니다. 앱에 여러 클라이언트가 있다면 각 route에 basePath로 클라이언트 이름도 적을 수 있습니다. 다중 클라이언트 구조 자체는 Multi Client 페이지에서 자세히 다루고, 여기서는 설정 필드에 집중합니다.
apps/myapp/akan.config.ts
basePathstring
이 route가 여는 클라이언트이자 첫 page 폴더입니다. basePath가 없는 route는 앱 자체입니다.
domainsRecord<branch, string[]>기본값 {}
이 route를 여는 호스트이며 branch를 키로 씁니다. debug·develop·main은 항상 있고, 다른 키는 branch를 추가합니다.

웹 표면과 경로 접두사

web은 빌드가 어떤 웹 표면을 만들지 정하고, api는 서버가 엔드포인트를 어디에 마운트할지 정합니다. 둘 다 main.ts만이 아니라 여기에 선언합니다. 두 값 모두 클라이언트 번들에 구워지며, 미리 빌드된 CSR 셸이나 네이티브 앱은 이를 알려 줄 서버에 닿지 못하기 때문입니다.
apps/myapp/akan.config.ts
webboolean | { csr: boolean }기본값 true
true는 SSR과 CSR을 모두 빌드하고, false는 API 전용이며, { csr: false }는 CSR 셸만 뺍니다.
api.prefixstring기본값 /api
signal 엔드포인트가 마운트될 경로이며, akanjs/base의 getApiPrefix()로 읽습니다.
api.websocketPrefixstring기본값 /ws
웹소켓 업그레이드가 놓이는 경로이며, getWsPrefix()로 읽습니다.
두 접두사를 문자열로 직접 적지 마세요. new AkanApp({ prefix, websocketPrefix })는 서버와 그 서버가 렌더링하는 모든 페이지에서 두 값을 여전히 덮어씁니다.
AKAN_SSR과 AKAN_CSR은 같은 선택을 부팅 시점에 좁히며, 좁히기만 합니다. 빌드가 빼놓은 표면을 배포가 다시 켤 수는 없습니다. akan start는 web을 무시하므로 개발 화면은 그대로 유지됩니다.

네이티브 앱

native는 Android·iOS·데스크톱 명령이 이 앱의 CSR 클라이언트로 만드는 앱을 설명합니다. 이름, 패키지 ID, 버전, 권한, 플러그인을 적고, 한 플랫폼만 읽는 값은 그 플랫폼의 섹션인 ios, android, desktop에 둡니다.
Native config
basePath가 없는 앱은 basePath를 적지 않고, 네이티브 앱을 하나만 내는 앱에는 targets가 필요 없습니다. 그래서 앱의 서버를 싣는 데스크톱 앱의 가장 짧은 설정은 이렇습니다:
native without basePath
첫 페이지가 /가 아니면 그 옆에 indexPath를 더합니다: native: { indexPath: "/board", desktop: { server: true } }. 한 플랫폼만 다른 곳에서 시작하면 그 플랫폼 섹션에 indexPath를 따로 적습니다: native: { indexPath: "/mobile", desktop: { indexPath: "/", server: true } }는 폰 앱을 /mobile로, 데스크톱 앱을 /로 엽니다.
Target
targets는 Akan 앱 하나로 네이티브 앱 여러 개를 만듭니다. 각자 자기 basePath를 여는 스토어 앱과 관리자 앱 같은 경우입니다. target은 targets를 뺀 native의 모든 필드를 받고, target이 적은 값이 이깁니다. 객체(deepLinks, updates, ios, android, desktop과 그 안의 객체)는 키마다 합치고, 목록, icon, splash와 나머지 값은 통째로 바꿉니다. 그래서 target의 permissions는 native의 목록에 더해지지 않고 그 목록을 대신합니다. targets가 없으면 앱에는 default라는 target 하나가 있고, routes에 앱 이름과 같은 basePath가 있으면 그 target은 앱 이름을 갖고 그 basePath를 엽니다.
native.targets
basePathstring
앱이 여는 클라이언트이며 routes에 선언된 basePath입니다. basePath가 없는 앱은 적지 않습니다.
indexPathstring기본값 /
시작 경로이며, 딥링크로 열 때 아래에 쌓는 화면이자 기록 없는 뒤로 가기가 돌아가는 곳입니다. ios.indexPath, android.indexPath, desktop.indexPath는 그 플랫폼에서 이 값보다 우선합니다.
appNamestring기본값 the app name
네이티브 앱 표시 이름입니다.
appIdstring | { default?, ios?, android?, macos?, windows?, linux? }기본값 com.<repo>.<app>
Android applicationId이자 iOS bundle id이며, 스토어마다 id가 이미 다르면 플랫폼별로 적습니다.
fileNamestring기본값 the app folder name
실행 파일과 아카이브의 이름이며, 영문자, 숫자, ., _, -만 씁니다.
versionstring기본값 0.0.1
사용자에게 보이는 앱 버전이며, Android versionName과 iOS MARKETING_VERSION에 기록됩니다.
buildNumnumber기본값 1
스토어 제출 빌드 번호이며, Android versionCode와 iOS CURRENT_PROJECT_VERSION에 기록됩니다.
iconstring | { image, backgroundColor? }
앱 폴더 기준의 정사각형 PNG이거나, 그 이미지와 투명한 부분 뒤에 칠할 색입니다.
splashstring | { image?, backgroundColor?, autoHide?, timeout? }
실행할 때 가운데에 보이는 PNG이거나, 시작 화면의 이미지, 색, 숨기는 시점입니다.
backgroundColorstring | { light, dark }기본값 white / black
창과 external view가 페이지를 그리기 전에 보이는 색이며, splash의 기본 색입니다.
permissionscamera | contacts | location | push | speech기본값 []
네이티브 권한 힌트이며, 각 값이 해당 플러그인의 네이티브 설정을 켭니다.
pluginsstring[]기본값 []
권한이 가져오는 것 외에 더 싣는 런타임 플러그인이며, 내장 id(iap)나 절대 경로 폴더로 적습니다.
deepLinks.schemesstring[]
example:// 같은 커스텀 URL scheme입니다.
deepLinks.domainsstring[]
app link·universal link 호스트이며, 호스트만 남도록 정규화됩니다.
updates{ url, publicKeys, revokedKeys?, channel?, readyTimeout?, report? }
설치된 앱이 새 릴리스를 찾는 곳이며, 폰은 스스로, 데스크톱 앱은 updates를 부를 때 업데이트합니다.
updates.urlstring
akan publish-update가 쓴 파일을 두는 정적 기본 URL(스토리지 버킷 등)이며, 릴리스 빌드에서는 https입니다.
updates.publicKeysstring[]
akan update-keygen이 출력한 키 1~3개로, 서명 키를 맨 앞에 둡니다. 키는 앞의 키만 폐기하고, 데스크톱 앱은 첫 키만 믿습니다. 키가 하나면 publicKey로 쓰며, 둘을 함께 쓰지는 않습니다.
updates.revokedKeysstring[]
모든 폰 릴리스가 폐기할 keyId(최대 16개)이며, 여기 두어 새 체크아웃에서 게시한 릴리스도 폐기를 이어 갑니다. 폰 빌드는 이 키들을 믿지 않습니다.
updates.channelstring기본값 the --env it is built with
앱이 따르는 채널이며, 적지 않으면 빌드할 때의 env로 게시한 릴리스만 받습니다. pilot 타깃은 자기 채널을 적습니다.
updates.readyTimeoutnumber기본값 10000
시험 실행 중인 릴리스가 첫 페이지를 마운트하기까지의 시간(ms)이며, 넘기면 되돌립니다.
updates.report{ url: string }
폰이 릴리스마다 어떻게 됐는지(되돌림 등) 보내는 주소이며, 되돌림 비율을 볼 수 있습니다. 적지 않으면 보내지 않습니다.
devtoolsboolean기본값 false
릴리스 빌드에서도 웹 인스펙터를 엽니다. 내부 테스트 타깃에만 씁니다.
ios.teamIdstring
apple-app-site-association에 쓰는 Apple Developer Team ID이며, universal link에 필요합니다.
ios.infoPlistRecord<string, AkanNativeValue>
iOS 앱의 Info.plist에 더할 키입니다.
ios.entitlementsRecord<string, AkanNativeValue>
iOS 앱에 더할 entitlements입니다.
ios.privacy{ tracking?, trackingDomains?, collectedDataTypes?, accessedApis? }
App Store 업로드에 필요한 개인정보 매니페스트(PrivacyInfo.xcprivacy) 중 앱의 몫입니다.
ios.filesRecord<string, string>
앱 번들에 복사할 파일이며, 키는 번들 안 경로, 값은 앱 폴더 기준 경로입니다.
android.sha256CertFingerprintsstring[]
assetlinks.json에 쓰는 서명 인증서 fingerprint이며, debug는 로컬 빌드, release는 Play Store 빌드용입니다.
android.googleServicesstring
FCM 푸시가 읽는 google-services.json의 앱 폴더 기준 경로입니다.
android.push{ channel?, smallIcon?, color? }
푸시가 들어갈 알림 채널, 상태 표시줄 아이콘(앱 폴더 기준 PNG), 강조 색입니다.
android.autoplayboolean기본값 false
iOS·데스크톱처럼 소리 있는 미디어가 터치 없이 재생됩니다.
android.manifeststring[]
<manifest> 수준에 넣을 XML이며, applicationId 자리표시자를 채워 넣습니다.
android.applicationstring[]
<application> 안에 넣을 XML입니다.
android.activitystring[]
앱의 activity 안에 넣을 XML입니다.
android.filesRecord<string, string>
앱에 복사할 파일이며, 키는 res/<type>/<file>이나 assets/<path>, 값은 앱 폴더 기준 경로입니다.
desktop.serverboolean | { omit?, profile?, modules?, env?, restart?, watchdog? }기본값 false
앱의 서버를 loopback으로 싣고, 페이지는 그 서버만 부릅니다. 켜고 끄려면 다시 설치해야 합니다. 객체로 주면 아래 키대로 바꿔서 싣습니다.
desktop.server.omitstring[]
이미지에만 필요한 패키지이며, 그것만 끌어오는 패키지와 함께 뺍니다. 서버 번들 자체가 이 패키지를 import하면 안 됩니다.
desktop.server.profilestring
환경 자신의 파일 대신 env/env.server.<env>.<profile>.ts를 번들합니다. 비밀 이름의 값이 든 파일은 빌드가 거부합니다.
desktop.server.modulesstring[]
서버가 마운트할 것이며 AKAN_MODULES로 전달됩니다. 모듈 이름이나, serve()에 edge를 적은 모든 모듈을 뜻하는 @edge를 씁니다.
desktop.server.envRecord<string, string>
이미지의 값보다 우선해 서버가 시작할 때 받는 환경 변수이며, 그 컴퓨터의 누구나 읽을 수 있습니다. 비밀 이름의 변수와 stage가 정하는 변수는 거부합니다.
desktop.server.restart"forever" | number기본값 5
앱이 서버를 포기하기 전까지 연달아 허용하는 크래시 횟수입니다. 아무도 지켜보지 않는 화면이면 "forever"를 씁니다.
desktop.server.watchdogboolean | { intervalMs?, failures? }기본값 false
intervalMs(10000)마다 서버의 health route에 묻고, failures(3)번 답이 없으면 서버를 다시 띄웁니다.
desktop.recovery"errorPage" | "reload"기본값 "errorPage"
"reload"는 멈춘 페이지를 매번 다시 불러오고 앱을 다시 띄우며, 페이지가 대화상자·공유 시트·다운로드·링크를 열지 못하게 합니다. "errorPage"는 오류 화면을 보여 줍니다.
desktop.window{ fullscreen?, skipTaskbar?, frameless? }
주 창을 첫 프레임부터 전체화면으로, 작업 표시줄 버튼 없이(Windows, Linux), 또는 제목 표시줄과 테두리 없이(frameless) 엽니다.
desktop.screenCapture"picker" | "auto"기본값 "picker"
"auto"(Windows)는 선택 창 없이 첫 화면을 공유합니다. 카메라를 요청하는 앱에서는 켜지 않습니다.
desktop.webview2"bootstrapper" | "standalone"기본값 "bootstrapper"
Windows 설치 프로그램입니다. "bootstrapper"는 WebView2 Runtime이 없는 PC에서 내려받고, "standalone"은 설치 때 오프라인인 PC를 위해 런타임 전체(약 200 MB)를 싣습니다.
desktop.publisherstring기본값 the app name
Windows에서 앱을 배포하는 주체이며, 설치된 앱의 게시자와 실행 파일의 회사 이름으로 쓰입니다.
targetsRecord<string, AkanNativeSettings>기본값 { default: {} }
Akan 앱 하나에서 만드는 여러 네이티브 앱이며, 각각 targets를 뺀 위 필드를 받습니다.

이미지와 공개 환경변수

images는 최적화할 수 있는 원격 이미지의 허용 목록을 정합니다. publicEnv는 기본 AKAN_PUBLIC_* 패턴 외에 브라우저에 노출할 환경변수 패턴을 추가하는 허용 목록입니다.
images
publicEnv

시크릿 파일

service-account JSON, TLS 인증서, private key 파일처럼 env.server.*.ts 안에 담을 수 없는 비공개 값이 있습니다. secrets 필드는 이런 파일의 glob 패턴을 나열해 Akan이 env/ 폴더와 함께 전송하도록 합니다.
akan upload-env는 매칭된 모든 파일을 아카이브하고, akan download-env는 이를 복원합니다. 패턴은 앱 디렉터리 기준으로 resolve되며, 한 번의 선언으로 배포와 git-ignore가 함께 처리됩니다.
secrets

빌드와 런타임

나머지 설정은 빌드 시스템과 프로덕션 이미지를 위한 것입니다. 대부분의 앱은 건드릴 일이 없지만, 특정 패키지를 외부 의존성으로 남기거나, 폰트를 정리 대상에서 빼거나, 라이브러리 라우트를 앱에 합치거나, 이미지에 시스템 의존성을 더할 때 사용합니다.
Build and runtime fields
externalLibsstring[]기본값 []
번들하지 않는 패키지이며, 프로덕션에서 워크스페이스가 고정한 버전으로 설치됩니다.
trustedDependenciesstring[]기본값 []
설치 스크립트 실행을 허용할 패키지이며, 설치하면서 스스로 빌드하는 애드온에 씁니다.
binRecord<string, { [platform]: AkanBinSource }>기본값 {}
플랫폼마다 { url, sha256, file? } 또는 { path, file? }이며, 데스크톱 앱에 실려 그 PATH 맨 앞에 놓입니다.
optimizeImportsstring[]기본값 built-in list
클라이언트 빌드가 정확한 원본 파일로 import할 추가 패키지이며, 아이콘 세트를 통째로 싣지 않게 합니다.
barrelImportsstring[]기본값 akanjs + workspace
스캔과 번들링에서 펼칠 추가 barrel 경로이며, 워크스페이스 밖의 barrel에만 씁니다.
database.modes("single" | "multiple" | "cluster")[]기본값 ["single"]
선언한 모든 모드의 드라이버가 함께 설치됩니다. multiple은 bullmq·ioredis를, cluster는 postgres까지 더합니다.
assets.pruneFontsboolean기본값 true
참조되지 않는 폰트를 dist의 public/ 복사본에서 제거합니다. optimize가 켜진 폰트의 원본도 제거됩니다.
assets.keepFontsstring[]기본값 []
스캔 결과와 무관하게 남길 폰트 glob이며, 런타임에 조립되는 URL 같은 경우에 씁니다.
syncPageLibsstring[] | boolean기본값 false
true는 page 폴더가 있는 모든 의존 라이브러리를, 배열은 적은 것만 마운트하고, false는 기존 링크를 모두 제거합니다.
pluginsAkanPlugin[]기본값 []
CLI가 실행 시점에 읽어 런타임 패키지, 네이티브 프로젝트 설정, public/ 에셋을 처리합니다.
dockerstring | DockerImageConfig기본값 oven/bun:1-slim
Dockerfile 전체이거나 그 재료입니다. image, bun install 앞뒤의 preRuns·postRuns, command입니다.
라이브러리가 이 중 다섯에 값을 더합니다. 라이브러리 자신의 externalLibs, trustedDependencies, docker.preRuns·docker.postRuns, assets.keepFonts는 그 라이브러리를 마운트하는 모든 앱에, bin은 그 라이브러리에 의존하는 앱에 적용됩니다. 생성되는 이미지에는 ca-certificates와 tzdata만 설치되므로, ffmpeg나 헤드리스 브라우저가 필요한 앱은 직접 선언해야 합니다.
  • 이미지 하나로 여러 배포를 합니다. ["single", "cluster"]로 선언하면 같은 이미지가 엣지 사이트와 클라우드 클러스터를 모두 실행하고, 배포마다 AKAN_DATABASE_MODE로 모드를 정합니다.
  • 데스크톱 앱은 실행 파일을 직접 싣고 갑니다. 데스크톱 앱에는 이미지의 docker 단계가 하나도 들어가지 않습니다. 그래서 bin이 ffmpeg처럼 서버나 네이티브 플러그인이 실행하는 파일을 빌드하는 컴퓨터용으로 모든 데스크톱 빌드에 넣고, 앱의 PATH 맨 앞과 플러그인의 ctx.binDir에 둡니다. 정적 LGPL 빌드를 넣으세요. --enable-nonfree로 빌드한 것은 재배포할 수 없습니다.

파이프라인

pipeline은 Akan Cloud가 이 앱에 대해 순서대로 실행할 stage 목록입니다. 선언하지 않으면 build, docker, deploy를 실행합니다. 선언하면 그 목록이 파이프라인 전부이므로 이 액션들도 목록에 적습니다.
apps/web/akan.config.ts
stagesAppPipelineStageInput[]
이 앱의 stage를 순서대로 적으며, 내장 액션도 여기에 넣습니다.
envRecord<string, string>
이 앱의 모든 step에 줄 환경변수입니다.
afterstring[]
이 앱보다 먼저 배포할 앱입니다. 빌드에 없는 앱은 무시합니다.
  • stage는 바로 앞 액션 뒤에 실행됩니다. 어떤 액션보다 앞에 적은 stage는 앱들이 빌드하기 전에, build 뒤에 적은 stage는 모든 앱의 빌드가 끝난 뒤에 실행됩니다.
  • 액션은 순서를 지킵니다. 이미지는 그 빌드 결과로 만들기 때문에 docker 앞에는 build가 있어야 합니다. 앱의 액션 하나가 건너뛰어지거나 실패하면 그 뒤의 액션은 실행하지 않습니다.
  • 함수형은 빌드 정보를 받습니다. pipeline: (ctx) => ({ … })는 ctx.app, ctx.branch, ctx.trigger 같은 빌드 정보를 읽습니다.
stage 키
stage는 내장 액션(use)이거나 셸 stage(name과 sh 또는 steps)입니다. 태그는 각 키를 어느 쪽이 받는지 나타냅니다.
use"build" | "docker" | "deploy" | "ota"use
내장 액션입니다. 앱마다 각각 한 번까지, 이 순서로 씁니다. ota는 적었을 때만 돕니다.
targetsstring[]use
ota 전용: 업데이트를 묶을 네이티브 타깃입니다. 기본값은 native.updates가 있는 타깃 전부입니다.
platforms("ios" | "android")[]use
ota 전용: 업데이트를 묶을 휴대폰 플랫폼입니다. 기본값은 둘 다입니다.
namestringshelluse
stage에 표시할 이름으로, 셸 stage에는 꼭 필요합니다.
shstringshell
step 하나로 실행할 bash 스크립트입니다. sh와 steps 중 하나만 씁니다.
steps(string | PipelineStepInput)[]shell
차례로 실행할 명령으로, 각각이 step 하나입니다.
envRecord<string, string>shell
이 stage의 step에 줄 환경변수로, 앱과 워크스페이스의 값보다 우선합니다.
secretsstring[]shell
step이 같은 이름의 환경변수로 받을 파이프라인 시크릿입니다.
whenPipelineWhenshelluse
적은 조건이 모두 맞을 때만 stage를 실행합니다.
timeoutPipelineDurationshelluse
stage 전체의 제한 시간으로, 초 단위 숫자나 30s, 10m, 2h로 씁니다.
retrynumber | { attempts, delay? }shell
자기 retry가 없는 step마다 적용하는 총 시도 횟수이며, 시도 사이의 delay를 줄 수 있습니다.
retrynumberuse
액션의 총 시도 횟수입니다. 숫자만 받고 delay는 없습니다.
allowFailureboolean기본값 falseshelluse
이 stage가 실패해도 빌드를 실패로 만들지 않습니다.
milestonePipelineMilestoneshelluse
진행 표시용 이름으로 prepare, build, verify, package, deploy, finish 중 하나입니다.
idstringshelluse
고정 id로, 기본값은 이름을 바꾼 slug나 액션 이름입니다.
descriptionstringshelluse
stage와 함께 보여 줄 긴 설명입니다.
step 키
steps의 항목은 명령 문자열이거나, 아래 키를 가진 객체입니다:
shstring
실행할 bash 명령입니다. steps에 문자열만 쓰면 이것만 적은 것과 같습니다.
namestring
step에 표시할 이름입니다.
cwdstring
실행할 디렉터리로, 워크스페이스 루트 기준이며 루트 밖으로 나갈 수 없습니다.
envRecord<string, string>
이 step의 환경변수로, stage의 값보다 우선합니다.
secretsstring[]
stage의 시크릿에 더해 이 step이 받을 시크릿입니다.
timeoutPipelineDuration
이 step의 제한 시간입니다.
retrynumber | { attempts, delay? }
총 시도 횟수이며, 시도 사이의 delay를 줄 수 있습니다.
allowFailureboolean기본값 false
이 step이 실패해도 stage를 실패로 만들지 않습니다.
skipExitCodesnumber[]
이 코드로 끝나면 step을 건너뜀으로 처리하고, stage의 나머지도 건너뜁니다.
idstring
stage 안에서 쓰는 고정 id입니다.
stage를 실행하는 조건
branchstring | string[]
빌드 브랜치가 맞아야 하는 패턴입니다.
triggerPipelineTrigger | PipelineTrigger[]
빌드를 시작한 계기로 push, redeploy, initial, rebuild, manual 중에서 고릅니다.
changedstring | string[]
브랜치의 마지막 성공 빌드 이후 바뀐 경로 중 하나가 맞아야 하는 패턴입니다.
  • 패턴. *는 경로 한 마디 안에서, **는 여러 마디에 걸쳐, ?는 한 글자에 맞습니다. 앞에 !를 붙이면 제외하고, 대소문자를 구분합니다.
  • 판정 시점. branch와 trigger는 plan을 만들 때, changed는 stage를 실행하기 직전에 판정합니다. 비교할 이전 성공 빌드가 없으면 모든 경로가 바뀐 것으로 봅니다.
모든 step이 받는 환경변수
AKAN_CI_BRANCHAKAN_CI_ENVAKAN_CI_TRIGGERAKAN_CI_BUILD_NUMAKAN_CI_COMMIT
빌드의 브랜치, env, 계기, 번호, 커밋입니다.
AKAN_CI_APPSAKAN_CI_APP
빌드가 다루는 앱들과, stage가 실행되는 앱입니다.
AKAN_CI_PHASEAKAN_CI_STAGEAKAN_CI_STEP
지금 실행 중인 것의 id입니다.
AKAN_CI_RESULT
post step에 알려 주는 빌드 결과입니다.
CIAKAN_CI
모든 step에 있어서, 스크립트가 빌드 안에서 실행되는지 알 수 있습니다.
  • 좁은 쪽 값이 이깁니다. step의 env가 stage보다, stage가 앱보다, 앱이 워크스페이스보다 우선합니다.
  • 예약된 이름이 있습니다. CI, 모든 AKAN_CI_*, PATH나 HOME 같은 셸 이름은 env에 쓰거나 시크릿 이름으로 쓸 수 없습니다.

워크스페이스 설정

워크스페이스 루트의 akan.config.ts에는 모든 앱에 걸치는 설정, 곧 모든 앱의 앞뒤에 실행할 stage, 빌드를 마무리할 step, CLI가 연결할 클라우드, 앱을 미러링할 저장소(subspace)를 둡니다. 타입은 WorkspaceConfig이고, 앱과 라이브러리 설정은 각자의 파일에 둡니다.
akan.config.ts
beforeWorkspacePipelineStageInput[]
어느 앱 stage보다 먼저 실행할 stage로, 각각이 phase 하나입니다.
afterWorkspacePipelineStageInput[]
모든 앱의 마지막 stage 뒤에 실행할 stage입니다.
post{ success, failure, canceled, always }
빌드를 마무리하는 step으로, 끝난 결과에 따라 고르고 always는 마지막에 실행합니다.
envRecord<string, string>
앱 stage를 포함해 빌드의 모든 step에 줄 환경변수입니다.
timeoutPipelineDuration
빌드 전체의 제한 시간입니다.
앱의 것처럼 루트 pipeline도 빌드 정보를 받는 함수 (ctx) => ({ … })로 쓸 수 있으며, ctx.app만 없습니다.
cloud.hoststring기본값 Akan Cloud
--host 없이 실행한 클라우드 명령이 연결할 클라우드입니다. 직접 운영하는 클라우드 등을 씁니다.
subspace.pushableBranchesstring[]기본값 main, develop, debug
akan subspace push가 미러링하는 브랜치입니다. 다른 브랜치는 거부하므로 기능 브랜치가 미러 저장소로 가지 않습니다.
루트 stage의 종류
모양실행
{ name, sh | steps }앱의 것과 같은 셸 stage로, 한 번 실행합니다.
{ name, parallel: [...] }셸 stage를 나란히 실행합니다. maxParallel로 수를 제한하고, failFast면 하나가 실패할 때 나머지를 멈춥니다.
{ name, matrix: "apps", sh }빌드의 앱마다 하나씩 AKAN_CI_APP을 정해 실행합니다. when.app으로 앱을 좁힙니다.
내장 액션은 앱의 것이므로, 루트 stage는 use를 받지 않습니다.
빌드 순서
phase는 차례로 실행되며, 각 phase는 앞 phase의 stage가 모두 끝날 때까지 기다립니다:
phase실행
before루트 before의 stage마다 phase 하나입니다.
before-buildbuild보다 앞에 적은 앱 stage입니다.
build모든 앱의 빌드를 나란히 실행합니다.
after-buildbuild와 docker 사이에 적은 앱 stage입니다.
docker모든 앱의 이미지를 만듭니다.
after-dockerdocker와 deploy 사이에 적은 앱 stage입니다.
deploy모든 앱을 after 순서에 따라 하나씩 배포합니다.
after-deploydeploy 뒤에 적은 앱 stage입니다.
otaota를 적은 앱의 OTA 업데이트를 묶습니다.
after-otaota 뒤에 적은 앱 stage입니다.
after루트 after의 stage입니다.
post끝난 결과에 맞는 step을 실행하고, 이어서 always를 실행합니다.

기본값과 규칙

Akan은 사용자가 작성한 파일과 프레임워크 기본값을 합쳐 최종 앱 설정을 만듭니다. 처음 앱을 만들 때는 고급 옵션을 추가하기 전에 아래 규칙만 기억하면 됩니다.
환경별 값: config 필드를 추가하기 전에 런타임 값은 env/에 둡니다. 공개 값은 client env에, 서버 전용 비공개 옵션은 server env에 둡니다.
라우트: 커스텀 도메인이나 여러 클라이언트가 필요해지기 전까지는 routes를 생략해도 됩니다.
네이티브 앱: appName은 앱 이름, appId는 com.<repoName>.<appName>, version은 0.0.1, buildNum은 1이 기본값입니다. 출시 전에는 조직의 실제 reverse-DNS appId를 지정해야 합니다. com.example.app 같은 placeholder id는 Apple 포털에서 이미 선점되어 있는 경우가 대부분입니다.
이미지: remotePatterns가 허용하지 않은 원격 이미지는 차단됩니다. 기본 포맷은 WebP이고 기본 quality는 75입니다.
다국어: locale 기본값은 en과 ko이며 기본 locale은 en입니다. 기본 locale을 옮기거나 다른 목록을 제공할 때만 바꿉니다. defaultLocale은 locales 안에 있어야 합니다.

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

내 AI에 이 문서 연결하기

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