사람함께에이전트▾
사람 — 직접 정하고 책임지는 비즈니스 규칙과 흐름. 직접 읽어보세요.
함께 — 개념은 알아두고, 세부 규칙은 에이전트가 따릅니다.
에이전트 — 에이전트가 따르는 규칙과 레퍼런스. 필요할 때 찾아보세요.
일반▾
인터페이스▾
관측성▾
성능▾
네이티브▾
개발▾

엣지 컴퓨팅

Akan에서 엣지 컴퓨팅은 한 Akan 서버가 앱에서 이미 쓰는 생성된 fetch로 다른 Akan 서버를 호출하는 것입니다. { origin } 옵션 하나만 더하면 호출이 다른 서버로 갑니다.
클라우드 서버
무엇을 할지 결정하고 엣지에 명령을 보냅니다.
엣지 서버
장비나 사용자 가까이에서 일을 처리하고, 상태를 돌려보냅니다.
fetch + { origin }
양쪽을 타입이 있는 signal 호출로 잇고, 로컬 호출과는 { origin } 옵션 하나만 다릅니다.

다른 서버 호출하기

생성된 fetch 호출은 모두 마지막 인자로 옵션 객체를 받습니다. 여기에 { origin }을 넣으면 호출이 내 서버가 아니라 그 서버로 갑니다.
  • origin은 API prefix로 끝나야 합니다. fetch는 origin 뒤에 endpoint 경로를 그대로 붙입니다. 예를 들면 https://edge-01.example.com/api입니다.
  • prefix는 직접 적지 말고 읽어 옵니다. 설정으로 바뀔 수 있으므로 /api를 문자열로 적지 말고 akanjs/base의 getApiPrefix()로 origin을 만듭니다.
  • 호출하는 쪽도 그 endpoint를 알아야 합니다. fetch에는 자기 앱과 lib이 선언한 endpoint만 있으므로, 엣지가 제공하는 endpoint는 두 앱이 함께 쓰는 lib에 두거나 한 앱을 양쪽에서 돌립니다.
엣지 서버 하나에 ping을 보내 살아 있는지 확인하는 코드입니다:
apps/myapp/lib/_edge/edge.service.ts
  • fetch.ping()은 기본 제공됩니다. 모든 Akan 서버가 "ping"으로 답하므로 따로 endpoint를 선언하지 않습니다.
  • 닿지 않는 서버는 에러를 던집니다. 연결 거부나 timeout은 Err로 도착하므로, 확인 코드는 이를 잡아 false로 답합니다.
  • 확인용 호출에는 짧은 timeout을 줍니다. 없으면 죽은 엣지 때문에 호출이 기본값인 30초 동안 붙잡힙니다.
원격 호출에 쓰는 옵션
originstringquery · mutation · pubsub
호출을 받을 서버로, scheme과 host에 API prefix까지 적습니다.
timeoutnumber | false기본값 30000query · mutation
호출자가 포기하기까지의 ms로, endpoint에 선언된 timeout보다 우선하고 false면 계속 기다립니다.
tokenstringquery · mutation
Authorization: Bearer <token>으로 보내므로, 원격 서버의 guard가 그 계정으로 판단합니다.
onResync() => voidpubsub
끊긴 연결이 복구되어 room을 다시 구독한 뒤에 실행됩니다.

명령 보내기

클라우드가 엣지에게 일을 시킬 때는 평범한 query나 mutation을 같은 { origin }으로 호출합니다. 인자와 반환값의 타입도 그대로입니다. origin은 한 번 만들어 두고 호출마다 넘깁니다:
apps/myapp/lib/_edge/edge.service.ts
  • 오래 걸리는 작업에는 더 긴 제한 시간이 필요합니다. endpoint가 { timeout }을 선언하거나 호출할 때 넘기지 않으면, 호출은 30초 뒤에 포기합니다.
  • 제한 시간은 엣지 endpoint에 선언합니다. 펌웨어 업데이트나 프로비저닝처럼 느린 작업에 선언해 두면 모든 호출자가 같은 제한 시간을 씁니다.

에러는 그대로 돌아옵니다

원격 endpoint가 던진 Err는 이쪽에도 같은 Err로 도착합니다. key와 data가 같고 instanceof Err도 참입니다. 그대로 흘려보내면 내 호출자도 같은 에러를 받으므로, 브라우저는 원격 서버가 고른 문장을 toast로 띄웁니다.
에러 하나가 서버 두 대를 건너는 모습입니다:
에러 하나, 서버 둘
호출한 쪽이 받는 에러
상황
↳ 호출한 쪽에서 던져지는 것
원격 endpoint가 Err를 던짐
key, data, 상태 코드가 그대로인 같은 Err
연결이 거부되었거나 host를 찾지 못함
base.error.serverUnreachable (503)
timeout 안에 응답이 없음
base.error.gatewayTimeout (408)
앞단 프록시가 자체 페이지로 502, 503, 504를 응답함
base.error.serverUnavailable · base.error.gatewayTimeout

상태 듣기

엣지가 상태를 계속 보낸다면 엣지의 pubsub endpoint를 같은 { origin }으로 구독합니다. 구독 호출은 구독 해제 함수를 돌려주므로, 보관해 두었다가 다 쓰면 호출합니다:
apps/myapp/lib/_edge/edge.service.ts
  • 엣지 서버마다 소켓은 하나입니다. origin을 준 첫 구독이 그 서버로 websocket을 열고, 이후 구독은 그 소켓을 함께 씁니다.
  • 연결이 끊긴 동안 보낸 이벤트는 사라집니다. onResync를 넘기면 room을 다시 구독한 뒤 현재 상태를 다시 불러올 수 있습니다.
  • 엣지의 pubsub에는 guards를 직접 선언합니다. slice의 guard map은 pubsub에 적용되지 않으므로, guards가 없는 room은 어떤 소켓이든 구독할 수 있습니다.

원격 노드 감싸기

같은 엣지 서버와 여러 번 통신한다면, origin과 구독 해제 함수를 기억하는 작은 class로 감싸면 편합니다:
apps/myapp/srvkit/RemoteEdge.ts
  • origin은 한 곳에만 있습니다. 모든 메서드가 #origin을 재사용하므로 { origin }을 빠뜨리는 호출이 생기지 않습니다.
  • close() 한 번으로 모든 구독을 해제합니다. 엣지가 오프라인이 되거나 worker가 멈출 때 호출합니다.
  • adapt()가 아닌 평범한 class입니다. 프로세스마다 하나가 아니라 엣지 서버마다 하나이므로, 필요한 곳에서 new RemoteEdge(host)로 만듭니다.

아주 빠른 데이터

명령과 상태는 Akan fetch로 유지하세요. 텔레메트리나 영상 프레임 같은 바이트는 pubsub(Binary)로 보낼 수 있고, 그것으로도 감당하지 못하는 스트림에만 별도 통로를 둡니다.
fetch.startJob(...)
명령. 인자와 결과에 타입이 있는 query나 mutation입니다.
fetch.subscribeJobStatus(...)
상태. 엣지가 발행하는 pubsub room입니다.
pubsub(Binary)
텔레메트리, 영상 프레임. websocket binary frame으로 보내고, 느린 구독자는 가장 최신 frame을 받습니다.
별도 통로
아주 큰 스트림. pubsub(Binary)로 부족할 때만 추가합니다.
  • 바이트는 JSON을 거치지 않습니다. 반환 타입 전체가 Binary이면 payload가 websocket binary frame으로 나가고 Uint8Array로 도착합니다.
  • 느린 구독자는 가장 최신 frame만 받습니다. 기준값에 대한 델타처럼 모든 frame이 도착해야 한다면 pubsub 옵션에 { backpressure: "queue" }를 선언합니다.
  • 바이트를 Any로 보내지 마세요. Any 안의 Buffer는 약 3.6배 큰 JSON 숫자 배열이 됩니다.

엣지 사이트 띄우기

엣지 사이트는 보통 데이터를 SQLite 파일에 두는 컨테이너 하나입니다. 클라우드는 같은 이미지로 같은 앱을 클러스터로 돌릴 수 있습니다.
akan.config.ts에 두 데이터베이스 모드를 모두 선언합니다:
apps/myapp/akan.config.ts
그다음 이미지를 배포할 때마다 어디서 도는지, 데이터가 어디 있는지를 정합니다:
설정엣지 사이트클라우드 클러스터
AKAN_PUBLIC_OPERATION_MODEedgecloud (이미지 기본값)
AKAN_DATABASE_MODEsinglecluster
데이터AKAN_SQLITE_DIR가 가리키는 마운트 볼륨의 SQLite 파일POSTGRES_URL과 REDIS_URI
인스턴스컨테이너 하나여러 서버
  • 운영 모드와 데이터베이스 모드는 서로 따로입니다. edge나 cloud는 서버가 어디서 도는지를, single이나 cluster는 데이터가 어디 있는지를 정합니다.
  • 운영 모드를 따르는 것은 internal뿐입니다. cron("0 4 * * *", { operationMode: ["cloud"] })처럼 선언한 internal은 엣지에서 돌지 않고, endpoint는 모두 양쪽에서 제공됩니다.
  • 배포마다 모드를 적습니다. 모드를 두 개 선언했다면 AKAN_DATABASE_MODE가 꼭 필요하고, 첫 번째 모드로 넘어가는 것은 개발 기기뿐입니다.

팁

  • 평범한 signal로 시작하세요. 로컬에서 잘 동작하면 보통 { origin }만 바꿔 원격으로 호출할 수 있습니다.
  • 엣지 서버 host는 DB에 저장하세요. origin을 getApiPrefix()로 조립해야 prefix가 바뀌어도 모든 origin에 반영됩니다.
  • 구독은 항상 정리하세요. 그러지 않으면 오래 도는 worker에서 연결이 샙니다.
함께 볼 페이지

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

내 AI에 이 문서 연결하기

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