akan.config.ts 개요

모든 앱과 라이브러리는 루트에 akan.config.ts를 하나씩 둡니다. 이 파일에는 앱을 서비스하고 빌드하고 패키징하는 방법, 즉 도메인, 웹 표면, 네이티브 앱, 데이터베이스 모드, Docker 이미지를 적습니다.
빈 객체로 시작하면 됩니다. 적지 않은 키는 모두 프레임워크 기본값을 쓰므로, 기본값이 맞지 않을 때만 키를 추가합니다:
apps/myapp/akan.config.ts
전체 키 한눈에 보기
앱은 AppConfig로, 라이브러리는 LibConfig로 설정을 선언합니다. 키마다 아래 섹션에서 다루며, api, assets, plugins는 전체 레퍼런스에 있습니다.
키
앱
라이브러리
웹 서비스
routes
✓
어떤 도메인이 앱을 열고, 각 도메인이 어느 basePath로 이어지는지 정합니다.
web
✓
빌드가 만들 웹 표면을 정합니다. SSR 페이지, CSR 셸, 또는 API 전용입니다.
api
✓
엔드포인트와 웹소켓을 마운트할 경로입니다. 기본값은 /api와 /ws입니다.
i18n
✓
앱이 지원하는 locale 목록과 기본 locale입니다.
images
✓
이미지 최적화의 크기, 포맷, 허용 출처입니다.
syncPageLibs
✓
어떤 라이브러리의 page 폴더를 이 앱의 라우트로 서비스할지 정합니다.
네이티브 앱, 데이터, 환경변수
native
✓
iOS·Android·데스크톱 앱의 정보, 플랫폼 설정, target입니다.
database
✓
빌드가 실행될 수 있는 데이터베이스 모드이며, 배포는 AKAN_DATABASE_MODE로 그중 하나를 고릅니다.
publicEnv
✓
브라우저 코드용 추가 env 이름의 허용 목록입니다. 아직 빌드가 읽지 않습니다.
secrets
✓
akan upload-env로 함께 올리고 git에서는 빠지는 비공개 파일입니다.
빌드와 이미지
externalLibs
✓
✓
번들에서 빼고 프로덕션 이미지에 따로 설치할 패키지입니다.
barrelImports
✓
빌드가 정확한 파일 import로 바꿔 줄 추가 barrel입니다.
optimizeImports
✓
브라우저 빌드가 실제로 쓰는 부분만 읽을 추가 패키지입니다.
docker
✓
✓
프로덕션 이미지입니다. 라이브러리는 preRuns와 postRuns만 더합니다.
assets
✓
✓
빌드가 public/ 복사본에서 폰트를 덜어내는 방식입니다. 라이브러리는 keepFonts만 씁니다.
plugins
✓
✓
CLI가 런타임 패키지, 네이티브 설정, 에셋 생성에 쓰는 Akan 플러그인입니다.
✓선언할 수 있음받지 않음

설정 파일 형태

AppConfig와 LibConfig는 일반 객체나, 객체를 돌려주는 함수를 받습니다. 값이 앱 이름에 따라 달라지는 경우가 아니면 객체를 씁니다:
apps/myapp/akan.config.ts
함수 형태는 읽고 있는 앱이나 라이브러리의 { name, type }을 인자로 받습니다:
apps/myapp/akan.config.ts
  • 키는 같습니다. 함수는 객체 형태에 적었을 내용을 그대로 돌려줍니다.
  • 이름과 종류만 받습니다. 인자는 AppConfigContext(type: "app") 또는 LibConfigContext(type: "lib")입니다.
  • default export로 내보냅니다. Akan은 파일의 export default만 읽으며, 이름 있는 export는 무시합니다.

routes

routes는 어떤 도메인이 앱을 여는지 서버에 알려 줍니다. 쇼핑몰과 관리자 화면처럼 앱 하나가 여러 클라이언트를 서비스한다면 route마다 basePath를 줍니다:
apps/shop/akan.config.ts
basePathstring
이 route가 여는 클라이언트이며 페이지는 page/<basePath> 아래에 둡니다. 클라이언트가 하나면 생략합니다.
domains{ [branch]: string[] }
이 route를 여는 호스트이며 branch를 키로 씁니다. debug, develop, main 또는 직접 정한 키입니다.
  • 호스트가 클라이언트를 고릅니다. 어떤 route에 적힌 호스트로 들어온 요청은 그 route의 basePath에서 응답합니다.
  • branch마다 기본 호스트가 생깁니다. debug, develop, main과 직접 추가한 branch 키마다, 각 basePath는 적은 호스트 외에 <basePath>-<branch>.<AKAN_PUBLIC_SERVE_DOMAIN>에서도 응답합니다.
  • basePath가 없으면 클라이언트는 하나입니다. 이때 앱은 <app>-<branch>.<AKAN_PUBLIC_SERVE_DOMAIN>에서 응답하고 page/ 아래 페이지를 모두 서비스합니다.

native

native는 @akanjs/native 런타임이 이 앱의 웹 화면으로 만드는 iOS·Android·데스크톱 앱을 정의합니다. 앱 이름, 번들 ID, 버전, 권한을 적고, 한 플랫폼만 읽는 값은 ios, android, desktop 아래에 둡니다.
네이티브 앱이 하나면 native에 바로 적습니다. 여럿을 내려면 targets를 더합니다. target은 같은 필드를 받아 native의 값을 필드별로 덮어쓰며, 객체는 키마다 합치고 목록과 나머지 값은 통째로 바꿉니다. targets가 없으면 앱에는 default라는 target 하나가 있습니다:
apps/shop/akan.config.ts
appNamestring기본값 앱 이름
네이티브 앱의 표시 이름입니다.
appIdstring기본값 com.<repo>.<app>
Android applicationId이자 iOS bundle id입니다.
versionstring기본값 0.0.1
사용자에게 보이는 버전이며, Android versionName과 iOS 마케팅 버전에 들어갑니다.
buildNumnumber기본값 1
스토어 빌드 번호이며, Android versionCode와 iOS 빌드 번호에 들어갑니다.
basePathstring
앱이 여는 클라이언트이며 routes에 선언된 basePath입니다. basePath가 없는 앱은 적지 않습니다.
permissions("camera" | "contacts" | "location" | "push" | "speech")[]기본값 []
네이티브 권한입니다. 값마다 해당 플러그인의 네이티브 설정이 켜집니다.
targetsRecord<string, AkanNativeSettings>기본값 { default: {} }
네이티브 앱마다 하나씩 두며, 키가 그 이름입니다. 각각 targets를 뺀 native의 필드를 받습니다.
  • 필드는 더 있습니다. indexPath, icon, splash, plugins, deepLinks, updates, 그리고 플랫폼 섹션인 ios(Info.plist, entitlements, 개인정보 매니페스트, 번들 파일), android(google-services.json, manifest XML, 파일), desktop(앱에 싣는 서버, 키오스크 설정)은 설정 레퍼런스에 있습니다.
  • 출시 전에 실제 appId를 정합니다. com.example.* 같은 임시 id는 Apple 포털에서 대개 이미 선점되어 있고, akan doctor --ios가 경고합니다.
  • CSR 셸은 켜 둡니다. 네이티브 앱이 이 셸을 싣고 나가므로, native 섹션은 web: { csr: false }와 함께 쓸 수 없습니다.
  • 플랫폼 설정. Firebase 파일, 서명, 스토어 빌드는 모바일 설정에서 다룹니다.

database

database.modes는 앱의 빌드가 실행될 수 있는 데이터베이스 모드를 나열합니다. 모드는 저장소, 큐, 캐시를 맡을 엔진을 고르며, 대부분의 앱은 이 키를 생략하고 single로 동작합니다:
모드데이터베이스, 큐, 캐시
single셋 모두 SQLite라 별도 서버가 필요 없습니다.
multiple데이터는 호스트 볼륨의 SQLite 파일 하나, 큐와 캐시는 Redis가 맡습니다.
cluster데이터는 Postgres, 큐와 캐시는 Redis가 맡습니다.
앱의 배포가 쓸 수 있는 모드를 모두 선언합니다. 첫 번째가 기본값입니다:
apps/enterprise/akan.config.ts
  • 배포는 그중 하나를 고릅니다. AKAN_DATABASE_MODE는 선언된 모드 중 하나만 고를 수 있습니다. 선언이 하나면 생략해도 되고, 여럿이면 배포마다 하나를 적어야 합니다.
  • CLI도 같은 방식으로 고릅니다. akan start, akan build, akan script, akan console은 셸에 AKAN_DATABASE_MODE가 있으면 그 모드를, 없으면 첫 번째로 선언한 모드를 씁니다.
  • 연결 값은 배포 환경이 정합니다. SQLITE_DATABASE_PATH, POSTGRES_URL 같은 연결 환경변수는 env.server.ts에 적은 같은 값보다 우선하며, REDIS_URI는 환경변수에서만 읽습니다.
  • 드라이버는 선언한 모드를 따라갑니다. akan build는 선언한 모든 모드의 드라이버를 프로덕션 package.json에 넣으며, multiple은 bullmq와 ioredis를, cluster는 postgres까지 더합니다.
  • 실제로 필요할 때만 올립니다. 로컬에서 multiple은 Redis가, cluster는 Redis와 Postgres가 필요하며, akan start가 이를 띄우고 akan dbup은 앱들이 선언한 것을 띄웁니다. 언제 바꿀지는 데이터베이스 모드를 참고하세요.

web

web은 빌드가 만들고 서버가 마운트할 브라우저 표면을 정합니다. API는 항상 서비스되고, 페이지 표면만 켜고 끕니다.
API
signal 엔드포인트와 웹소켓입니다. 항상 서비스되며 web으로 끄지 않습니다.
SSR
서버에서 그리는 페이지입니다. 라우트 렌더러, pages·client 번들, RSC worker를 포함합니다.
CSR
네이티브 모바일 빌드가 싣고 나가는 단일 파일 SPA 셸입니다.
값
API
SSR
CSR
값마다 만드는 것
web: true
✓
✓
✓
기본값입니다. 페이지와 모바일 셸을 모두 만들며, 네이티브 앱도 내는 앱에 맞습니다.
web: { csr: false }
✓
✓
모바일 셸 없이 페이지만 만들며, 웹 전용 앱에 맞습니다.
web: false
✓
API 전용입니다. page/, public/, 동기화된 라이브러리 라우트를 모두 서비스하지 않습니다.
✓빌드하고 서비스함빠짐
네이티브 빌드가 없는 웹 전용 앱은 이렇게 모바일 셸을 뺍니다:
apps/myapp/akan.config.ts
  • CSR만 켜는 옵션은 없습니다. CSR 셸은 SSR 빌드가 컴파일한 스타일시트를 인라인하므로, SSR 없이는 스타일 없는 앱이 됩니다.
  • 환경변수는 좁히기만 합니다. AKAN_SSR=false나 AKAN_CSR=false로 배포마다 표면을 끌 수 있지만, 빌드에서 빠진 표면을 다시 켤 수는 없습니다.
  • 개발 서버는 전부 켭니다. akan start는 web을 무시하고 모든 표면을 서비스합니다.

images

images는 내장 이미지 최적화기를 설정합니다. 제공할 폭, 포맷, quality와 가져올 수 있는 출처를 정하며, 바꿀 필드만 적습니다:
apps/catalog/akan.config.ts
remotePatterns{ protocol?, hostname?, port?, pathname?, search? }[]기본값 []
최적화기가 가져올 수 있는 원격 출처입니다. 목록에 없는 호스트는 거부됩니다.
localPatterns{ pathname?, search? }[]기본값 [{ pathname: "/**" }]
제공할 수 있는 로컬 public/ 경로입니다.
deviceSizesnumber[]기본값 [640, 750, 828, 1080, 1200, 1920, 2048, 3840]
화면 너비 이미지용 폭입니다. 두 크기 목록 어디에도 없는 폭은 거부됩니다.
imageSizesnumber[]기본값 [32, 48, 64, 96, 128, 256, 384]
아바타나 아이콘처럼 작은 고정 크기 이미지용 폭입니다.
formats("image/webp" | "image/avif")[]기본값 ["image/webp"]
출력 포맷의 선호 순서입니다. 브라우저가 받는 첫 번째 포맷이 쓰입니다.
qualitiesnumber[]기본값 [75]
허용할 quality 값입니다. 그 밖의 quality 요청은 거부됩니다.
minimumCacheTTLnumber기본값 14400
초 단위 최소 캐시 유지 시간입니다. 원본이 더 짧게 요구해도 이 값을 지킵니다.
dangerouslyAllowSVGboolean기본값 false
SVG 원본을 제공합니다. SVG에는 스크립트가 들어갈 수 있어 기본으로 꺼져 있습니다.
maximumRedirectsnumber기본값 3
원격 원본을 가져올 때 따라갈 리다이렉트 횟수입니다.
fetchTimeoutMsnumber기본값 7000
원격 원본을 가져오는 제한 시간이며 밀리초 단위입니다.
maxRemoteBytesnumber기본값 26214400 (25 MB)
내려받을 수 있는 원격 원본의 최대 크기입니다.
maxConcurrencynumber기본값 0
동시에 인코딩할 이미지 수입니다. 0이면 서비스하는 머신 CPU 수의 절반(최소 1)을 씁니다.
  • 목록은 기본값을 대체합니다. formats나 remotePatterns를 적으면 그 목록이 통째로 바뀌고, 적지 않은 목록은 기본값을 유지합니다.
  • 원격 이미지는 기본으로 막혀 있습니다. remotePatterns는 빈 목록에서 시작하므로, 앱이 이미지를 가져오는 CDN을 모두 적습니다.
  • AVIF는 OS 코덱이 있어야 합니다. image/avif는 macOS와 Windows에서만 인코딩되며, Linux에서는 빠지고 image/webp로 제공됩니다.

i18n

i18n은 앱이 지원할 언어를 적습니다. 모든 라우트는 /ko/… 같은 locale 경로 아래에 놓입니다:
apps/global/akan.config.ts
localesstring[]기본값 ["en", "ko"]
앱이 지원하는 locale 경로입니다. 각 값이 모든 라우트 앞에 붙습니다.
defaultLocalestring기본값 "en"
브라우저 언어가 하나도 맞지 않을 때 쓰는 값입니다. locales 중 하나여야 합니다.
  • locale 없는 경로는 리다이렉트됩니다. 브라우저의 Accept-Language에 가장 맞는 locale로 보내고, 맞는 것이 없으면 defaultLocale로 보냅니다.
  • 여기에는 지원 언어만 둡니다. 실제 번역 문구는 그 문구를 가진 dictionary나 page에 둡니다.

publicEnv

publicEnv는 브라우저 코드가 읽어도 되는 추가 환경변수 이름의 허용 목록입니다. 여기에는 이름만 적고, 값은 환경변수에 그대로 둡니다:
apps/landing/akan.config.ts
  • AKAN_PUBLIC_*는 항상 공개됩니다. 이 접두사를 가진 변수는 목록에 적지 않아도 브라우저 번들에 인라인됩니다.
  • 현재 빌드는 그 접두사만 읽습니다. 여기에 적은 이름은 아직 인라인되지 않으므로, 브라우저에서 읽을 변수에는 AKAN_PUBLIC_ 접두사를 붙입니다.

secrets

secrets는 service-account JSON, 인증서, 키 파일처럼 env.server.*.ts 안에 담을 수 없는 비공개 파일을 적습니다. 이 파일들은 env 파일과 함께 전송되고 git에서는 빠집니다:
apps/api/akan.config.ts
  • 앱 폴더 기준 glob입니다. secrets/**/*는 apps/<app>/secrets/ 아래의 모든 파일입니다.
  • env 파일과 함께 전송됩니다. akan upload-env는 매칭된 파일을 기본 env/env.client.*.ts, env/env.server.*.ts 파일과 함께 묶고, akan download-env는 같은 경로로 되돌려 놓습니다.
  • 업로드할 때 git에서 제외됩니다. akan upload-env를 실행할 때마다 이 패턴이 워크스페이스 .gitignore의 관리 블록에 기록됩니다.

syncPageLibs

syncPageLibs는 라이브러리가 자기 page/ 폴더에 둔 라우트를 앱이 서비스하게 합니다. 라우트 파일은 라이브러리가 소유하고, 앱은 사용 여부만 정합니다.
값앱이 서비스하는 라우트
false기본값입니다. 라이브러리 라우트를 쓰지 않고, 이전 동기화로 생긴 링크도 지웁니다.
truepage/ 폴더가 있는 모든 의존 라이브러리의 라우트입니다.
["shared"]나열한 라이브러리의 라우트만 가져옵니다.
libs/shared의 라우트만 서비스하려면 이렇게 적습니다:
apps/myapp/akan.config.ts
  • 라우트는 원래 경로를 그대로 씁니다. libs/shared/page/login/_index.tsx는 앱에서 /login으로 서비스됩니다.
  • 링크가 아니라 라이브러리를 고칩니다. 앱은 생성되고 git에서 제외된 폴더를 통해 이 라우트를 보므로, 수정은 libs/<lib>/page에서 합니다.
  • 경로 하나에 라우트 하나입니다. 동기화된 두 라우트가 같은 경로로 풀리면 안 됩니다.

externalLibs

externalLibs는 패키지를 번들에서 빼고, 프로덕션 빌드의 실제 의존성으로 설치합니다. 네이티브 패키지나 런타임에 민감한 패키지에 필요하며, 일반 TypeScript 헬퍼에는 필요 없습니다:
apps/media/akan.config.ts
라이브러리도 자기 런타임에 필요한 패키지를 같은 방식으로 선언합니다:
libs/report/akan.config.ts
  • 워크스페이스 전체가 합쳐집니다. 앱 목록이 먼저 오고 모든 라이브러리 목록이 중복 없이 뒤에 붙으므로, apps/media는 ["shiki", "puppeteer"]가 됩니다.
  • 모든 라이브러리가 포함됩니다. 앱의 의존 라이브러리만 읽는 것이 아니므로, 라이브러리가 한 번 선언하면 어느 앱도 다시 적을 필요가 없습니다.

barrelImports

barrel은 여러 파일을 다시 export하는 index 파일입니다. barrelImports에 있는 barrel에서 X를 import하면, 빌드가 그 import를 X를 정의한 파일로 바로 연결하므로 barrel의 나머지는 불러오지 않습니다.
akanjs/webkitakanjs/commonakanjs/uiakanjs/server
프레임워크 facet입니다.
@apps/<app>/{ui,webkit,common,client,server}
이 앱 자신의 facet입니다.
@libs/<lib>/{ui,webkit,common,client,server}
워크스페이스에 있는 모든 라이브러리의 같은 facet입니다.
이 facet 밖의 barrel만 추가합니다. 예를 들면 디자인 시스템 패키지입니다:
apps/admin/akan.config.ts
  • import처럼 찾습니다. 빌드는 barrel을 tsconfig paths에서 먼저 찾고, 그 다음 node_modules에서 찾습니다.
  • 덧붙기만 합니다. 적은 값은 위 기본 목록 뒤에 더해집니다.

optimizeImports

optimizeImports는 브라우저 빌드가 실제로 쓰는 부분만 읽을 패키지를 적습니다. 아이콘 하나를 import하면 아이콘 세트 전체가 아니라 그 아이콘만 불러옵니다:
apps/dashboard/akan.config.ts
기본 포함 패키지
lucide-reactdate-fnslodash-esramdaantdreact-bootstrapahooks@ant-design/icons@headlessui/react@headlessui-float/react@heroicons/react/20/solid@heroicons/react/24/solid@heroicons/react/24/outline@visx/visx@tremor/reactrxjs@mui/material@mui/icons-materialrechartsreact-use@material-ui/core@material-ui/icons@tabler/icons-reactmui-corereact-icons/*
  • 기본 목록에 더해집니다. 적은 값은 위 목록에 합쳐집니다.
  • sideEffects: false면 적지 않아도 됩니다. package.json에 이 값을 선언한 패키지는 자동으로 최적화됩니다.
  • 직접 만든 barrel은 깔끔하게 유지합니다. 파일 하나에 export 하나를 지키면 결과를 예측하기 쉽습니다.

docker

docker는 akan build가 만드는 프로덕션 이미지를 조정합니다. 이미지에 시스템 패키지나 다른 시작 명령이 필요할 때만 선언합니다.
생성되는 이미지는 ca-certificates와 tzdata만 설치하므로, ffmpeg, 헤드리스 브라우저, 네이티브 툴체인은 preRuns에 적습니다:
apps/worker/akan.config.ts
imagestring | { amd64?, arm64? }기본값 oven/bun:1-slim
베이스 이미지입니다. 객체 형태로 아키텍처마다 다른 이미지를 고릅니다.
preRuns(string | { amd64?, arm64? })[]기본값 []
bun install --production 전에 실행하는 단계라, 네이티브 빌드가 필요한 도구를 찾을 수 있습니다.
postRuns(string | { amd64?, arm64? })[]기본값 []
설치가 끝난 뒤, 앱 파일을 복사하기 전에 실행하는 단계입니다.
commandstring[]기본값 ["bun", "main.js"]
컨테이너의 CMD입니다.
생성되는 Dockerfile 순서
  1. 이미지로 FROM한 뒤 ca-certificates, tzdata, Asia/Seoul 타임존을 설정합니다.
  2. preRuns: 라이브러리 단계가 먼저, 앱 단계가 그다음입니다.
  3. package.json을 복사하고 bun install --production을 실행합니다.
  4. postRuns도 같은 순서로 실행합니다.
  5. 앱 파일을 복사하고 PORT, NODE_ENV, AKAN_PUBLIC_* 값과 AKAN_LOG_TO_FILE=0을 설정한 뒤 CMD를 둡니다.
  • apt-get update로 시작합니다. 기본 단계가 apt 패키지 목록을 지우므로, preRuns의 설치 명령은 목록부터 갱신합니다.
  • 아키텍처별 단계. { amd64, arm64 } 항목은 멀티 아키텍처 빌드에서 각 명령을 해당 아키텍처에서만 실행합니다.
Dockerfile 전체 작성
이미지를 완전히 직접 제어해야 한다면 Dockerfile 전체를 문자열로 쓰고, 위 순서를 그대로 지킵니다:
apps/custom-runtime/akan.config.ts
  • 생성된 파일에서 시작합니다. akan build는 원래 쓸 Dockerfile을 dist/apps/<app>/Dockerfile에 쓰며, 여기에는 config에 맞는 ENV 줄이 들어 있습니다.
  • config에 따라 달라지는 줄이 있습니다. 생성된 파일은 routes에 basePath가 있으면 AKAN_PUBLIC_BASE_PATHS를, web으로 표면을 껐다면 AKAN_SSR=false / AKAN_CSR=false를 추가합니다.

라이브러리 설정 필드

라이브러리의 akan.config.ts도 앱과 같은 객체 또는 함수 형태입니다. 여기에 선언한 값은 워크스페이스의 앱에 더해지므로, 라이브러리가 필요로 하는 것을 앱마다 다시 적지 않아도 됩니다:
libs/report/akan.config.ts
키
의존하는 앱
나머지 앱
라이브러리가 더하는 값
externalLibs
✓
✓
앱 자신의 목록 뒤에 중복 없이 붙습니다.
docker.{preRuns,postRuns}
✓
✓
앱이 docker를 문자열로 쓰지 않았다면 앱 자신의 단계보다 먼저 실행됩니다.
assets.keepFonts
✓
정리 대상에서 빼 둘 폰트를 라이브러리 자신의 public/ 기준 glob으로 적습니다.
plugins
✓
CLI가 런타임 패키지, 네이티브 설정, 에셋 생성에 씁니다.
✓적용됨적용 안 됨
  • 이미지와 명령은 정하지 않습니다. 라이브러리는 단계만 더하고, 베이스 이미지와 CMD는 앱이 정합니다.
  • 실제 예시. libs/util은 모바일 기능을 이렇게 제공합니다: plugins: [pushNotificationPlugin, cameraPlugin, …].

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

내 AI에 이 문서 연결하기

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