사람함께에이전트▾
사람 — 직접 정하고 책임지는 비즈니스 규칙과 흐름. 직접 읽어보세요.
함께 — 개념은 알아두고, 세부 규칙은 에이전트가 따릅니다.
에이전트 — 에이전트가 따르는 규칙과 레퍼런스. 필요할 때 찾아보세요.
상태와 메트릭
앱이 느리거나 응답하지 않을 때는 추측하기 전에 실행 중인 앱에게 먼저 물어보세요. 설정 없이 바로 쓸 수 있는 endpoint 두 개가 들어 있습니다.
볼 곳답해 주는 질문
GET /_akan/app/health
살아 있나요? replica마다 떠 있는지, 요청을 받을 준비가 됐는지 보여 줍니다.
GET /_akan/app/metrics
얼마나 바쁜가요? 처리 중인 요청, WebSocket 부하, 메모리, 렌더링 대기열을 보여 줍니다.
akan logs <app>
왜 그런가요? 그 숫자를 만든 endpoint, 큐, 렌더링 경로를 로그에서 찾습니다.
- 설정도 토큰도 필요 없습니다. 둘 다 앱 포트(기본
8282)의 루트에 있는 GET 경로이고, API prefix 아래에 있지 않습니다. - gateway가 있든 없든 형태가 같습니다. solo replica도 gateway와 같은 형태로 답하고
"solo": true를 덧붙입니다. - 포트만 확인하려면
/_akan/bench/ping을 부르세요.ok한 단어로 답합니다.
이 페이지에서 쓰는 말
용어설명
gateway
요청을 replica에게 나눠 주는 앞단 프로세스입니다.
akan start로 띄우거나 replica가 둘 이상일 때 생깁니다.replica
요청이나 작업을 처리하는 서버 프로세스입니다. 응답의
children 배열에 하나씩 들어갑니다.solo
gateway 없이 replica 하나만 도는 형태로, 컨테이너의 기본값입니다. replica가 두 endpoint에 직접 답합니다.
RSC worker
페이지를 렌더링하는 별도 프로세스입니다. 웹을 서빙하는 replica마다 하나씩 붙습니다.
Health 확인
앱이 열리지 않으면 health부터 보세요. 서버가 응답하는지, replica마다 요청을 받을 준비가 됐는지 알려 줍니다.
앱 포트로 호출합니다. 두 번째 줄은 replica 요약만 뽑아 보며,
jq가 필요합니다:Terminal
akan start에서는 gateway가 replica 하나를 띄우고, 응답은 다음과 같습니다(일부 생략):응답
필드 읽기
필드설명
status
평소에는
running이고, 서버가 내려가는 동안에는 stopping입니다.children[].role
all은 요청과 작업을 모두, federation은 요청을, batch는 백그라운드 internal만 맡습니다.children[].ready
replica가 부팅을 마치고 요청이나 작업을 받을 수 있게 되면
true가 됩니다.children[].status
replica가 지금 어느 단계에 있는지입니다. 아래 표를 보세요.
restartCountlastRestartReasonlastErrorMessage
replica가 몇 번, 왜 재시작했는지 알려 주므로 계속 재시작된다면 여기부터 봅니다.
solo
solo일 때만 붙고, 이때 replica 항목에는 재시작 필드가 없습니다.
replica 상태값
| status | 뜻 |
|---|---|
| starting | 프로세스가 떴고 아직 부팅 중입니다. |
| ready | 요청을 받을 수 있지만, gateway가 보낸 첫 health ping의 응답은 아직 오지 않았습니다. |
| healthy | 2초마다 오는 gateway의 health ping에 응답하고 있습니다. |
| unhealthy | 5초(akan start에서는 15초) 동안 ping에 답하지 않았거나 연결할 수 없어서, gateway가 재시작합니다. |
| exited | 프로세스가 종료됐고, gateway가 다시 띄웁니다. |
| crashed | akan start 전용입니다. 부팅이 세 번 연속 실패해 다음 코드 저장을 기다립니다. |


200이 곧 준비 완료는 아닙니다. gateway가 있으면 replica가
starting이거나 재시작 중이어도 health는 200으로 답합니다. 상태 코드가 아니라 children[].ready를 보세요.Metrics 확인
앱은 응답하는데 바빠 보이면 metrics를 보세요. 트래픽, WebSocket 부하, 메모리, 렌더링 대기열을 프로세스마다 보여 줍니다.
호출 방법은 같습니다. 두 번째 줄은 replica마다 숫자 두 개만 골라 봅니다:
Terminal
gateway가 있을 때의 응답입니다(일부 생략):
응답
- 최상위는 gateway가 본 값입니다.
rooms는 구독자가 있는 pubsub room 수,sockets는 room을 하나 이상 구독한 소켓 수입니다. children에는 replica마다 항목이 하나씩 있습니다. 그 안의metrics에 해당 replica의 트래픽, 메모리, 렌더링 수치가 담깁니다.- 요청과 소켓 수는 실시간 값입니다.
activeRequests,totalRequests,activeWebSockets는 gateway가 트래픽을 넘기면서 바로 셉니다. 메모리, 지연, 렌더링 수치는 주기적인 샘플입니다.
gateway가 있을 때와 solo일 때
solo에는 대신 세어 줄 gateway가 없어서, 몇몇 필드는 비어서 옵니다:
필드
gateway
solo
최상위
rooms · sockets
✓
구독자가 있는 pubsub room 수와, 그 room을 구독한 소켓 수입니다.
gateway
✓
gateway 프로세스 자신의 메모리와 이벤트 루프 샘플입니다.
proxyHop
✓
gateway가 요청을 replica로 넘기는 데 걸린 시간입니다.
AKAN_TRACE=1일 때만 채워집니다.replica별 (children[] 안)
activeRequests · totalRequests
✓
지금 처리 중인 요청과, replica가 뜬 뒤 받은 전체 요청 수입니다.
activeWebSockets
✓
이 replica로 이어진 WebSocket 연결 수입니다.
restartCount · lastRestartReason
✓
replica가 재시작한 횟수와 마지막 이유입니다.
rssBytes · heapUsedBytes
✓
✓
마지막 샘플 시점의 replica 메모리입니다.
rscWorkerRssBytes
✓
✓
replica에 딸린 RSC worker의 메모리입니다. 별도 프로세스라 따로 잡힙니다.
eventLoopLagP99Ms
✓
✓
직전 구간에서 타이머가 늦게 실행된 정도입니다. 높으면 무언가 프로세스를 막고 있습니다.
rscPendingRenderCount
✓
✓
RSC worker에 보냈지만 아직 돌아오지 않은 렌더링 수입니다.
trace
✓
✓
endpoint별 소요 시간과 쿼리 수입니다.
AKAN_TRACE=1일 때만 붙습니다.✓값이 있음null, 0 또는 없음
숫자 읽는 법
스냅샷 하나로 알 수 있는 것은 많지 않습니다. 1분 간격으로 몇 번 받아 보고, 숫자마다 무엇을 알려 주는 값인지 따져 읽으세요.
수치알 수 있는 것
activeRequests
지금 처리 중인 요청입니다. 계속 높다면 느린 endpoint가 작업을 붙잡고 있을 수 있습니다.
activeWebSocketsroomssockets
실시간 부하입니다. 열린 연결 수와, 그 연결이 구독한 room 수를 봅니다.
rssBytesheapUsedBytes
메모리 크기입니다. 값 하나보다 여러 샘플에 걸친 추세를 보세요.
rscWorkerRssBytes
replica의
rssBytes에 더해서 보세요. 그 합이 replica가 실제로 쓰는 메모리입니다.rscPendingRenderCount
RSC worker를 기다리는 서버 렌더링입니다. 값이 오르면 렌더링 작업이 밀리고 있습니다.
eventLoopLagP99Ms
이벤트 루프가 타이머를 얼마나 늦게 돌렸는지입니다. 높으면 어떤 작업이 요청을 막고 있습니다.
restartCountlastRestartReason
replica 재시작 횟수와 마지막 이유입니다. 계속 오르면 replica가 반복해서 죽고 있습니다.
rscWorkerRecycleCountrscWorkerLastRecycleReason
RSC worker가
rss>…MiB 같은 한도에 닿아 교체된 횟수와 이유입니다. 잦다면 렌더링 메모리를 의심하세요.

대부분의 수치는 실시간 값이 아니라 샘플입니다. 메모리, 지연, 렌더링 수치는
AKAN_MEMORY_LOG_INTERVAL_MS(기본 60초)마다 새로 잡히고, 언제 잡혔는지는 reportedAt에 있습니다. 비교할 응답은 최소 한 주기 간격을 두고 받으세요.메모리 로그
metrics 응답 하나로 메모리 문제를 잡기 어렵다면, 샘플마다 로그를 남기고 값이 어떻게 움직이는지 보세요.
서버가 시작할 때 읽는 환경변수에 넣습니다. 로컬에서는 워크스페이스의
.env에, 배포에서는 컨테이너 env에 둡니다:.env
AKAN_MEMORY_LOG"1"기본값 꺼짐
샘플마다 프로세스당
memory role=… 줄 하나를 로그로 남깁니다.AKAN_MEMORY_LOG_INTERVAL_MSnumber (ms)기본값 60000
이 로그 줄과
/_akan/app/metrics 수치가 함께 쓰는 샘플 주기입니다.AKAN_MEMORY_GC_ON_REPORT"1"기본값 꺼짐
샘플마다 먼저 전체 GC를 돌려 heap 수치가 살아 있는 메모리만 보이게 하고,
gcDurationMs를 더합니다.그러면 샘플마다 프로세스당 한 줄이 찍힙니다. 실행 중인 앱에서
akan logs로 이 줄만 골라 봅니다:Terminal
rss와rscWorkerRss는 서로 다른 프로세스입니다. 둘을 더해야 replica가 실제로 쓰는 메모리가 됩니다.elLag는 평균/p99/최대입니다. 직전 샘플 이후 구간의 이벤트 루프 지연을 밀리초로 보여 줍니다.- gateway 자신의 줄은 verbose 레벨입니다. 기본값
info보다 낮으므로 콘솔에서 보려면AKAN_PUBLIC_LOG_LEVEL=verbose로 둡니다.


진단이 끝나면
AKAN_MEMORY_GC_ON_REPORT를 끄세요. 강제 GC는 샘플마다 프로세스를 멈추게 하고, AKAN_MEMORY_LOG가 꺼져 있어도 실행됩니다.확인 순서
가장 가벼운 질문부터 자세한 질문 순으로 확인하고, 원인을 찾으면 거기서 멈추세요.
- health를 봅니다. replica가
ready가 아니거나unhealthy라면 시작 문제부터 해결합니다. 이유는lastErrorMessage와lastRestartReason에 있습니다. - metrics를 봅니다.
activeRequests,activeWebSockets,rooms, 메모리,eventLoopLagP99Ms를 확인합니다. - 메모리가 계속 늘면 메모리 로그를 켜고 여러 샘플을 비교합니다.
- 원인은 로그에서 찾습니다. 어떤 endpoint, 큐, 렌더링 경로가 그 숫자를 만들었는지
akan logs <app>으로 확인하고,AKAN_TRACE=1을 켜면 metrics에 endpoint별 소요 시간이 붙습니다.
이어서 볼 문서