M2 MacBook Air 16GB에서 Microsoft Learn 검색, Edge0 스트리밍, 문장 단위 한국어 번역을 연결한 에이전트를 실행했습니다. 2026년 9월 13일 확인한 샘플 Gist에는 전체 코드와 함께 TTFT 53.47초를 기록한 실행 결과를 공개했습니다.

마지막 글은 측정에 사용한 질문, 검색과 첫 응답까지의 시간, 생성 답변의 근거, 출력 속도의 해석, 후속 최적화와 사내 PoC 확장 조건을 다룹니다. 4편에서 설명한 클라이언트 계측을 기준으로 결과를 읽습니다.

실행 로그와 측정값부터 살펴보겠습니다. 각 단계의 시간을 비교한 뒤 현재 결과로 판단할 수 있는 범위와 추가 실험이 필요한 범위를 나눠 설명합니다.

수치를 비교할 때의 기준은 다음과 같습니다.

문서는 2026년 9월 13일에 확인했습니다. 아래 수치는 특정 질문과 검색 결과를 사용한 한 번의 실행에서 기록했습니다. 실행 당시의 모든 버전, 캐시 상태와 반복 측정 결과는 이 기록만으로 확인되지 않습니다. tok/s로 표시한 값은 콘텐츠가 있는 SSE 이벤트 수로 계산했습니다.

Native AOT 질문을 사용한 단일 실행

실험에는 M2 MacBook Air 16GB와 Edge0-35B-A3B-preview를 사용했습니다. Python 호스트가 Microsoft Learn을 검색하고 Apple Translation으로 입력과 출력을 번역하는 구성은 Gist의 실행 안내와 같습니다.

질문은 다음과 같이 입력했습니다.

NativeAOT에서 Reflection.Emit을 사용할 수 있는지도 설명해주세요.

모델의 일반 지식을 평가하기보다 검색한 공식 문서를 읽고 런타임 코드 생성의 지원 여부를 판정하는지 확인했습니다. 이 한 번의 결과를 장비의 평균 성능이나 다른 질문의 응답 품질로 일반화하지는 않습니다.

검색 완료와 첫 응답 사이의 대기 시간

요청 처리 단계별 기록을 정리하겠습니다. 샘플 코드의 상태 메시지는 입력 처리 시작을 기준으로 경과 시간을 표시하고, TTFT는 Edge0 요청을 시작하는 별도 시각을 기준으로 계산합니다.

질문 변환과 검색에 걸린 약 2.6초

실험 당시 한국어 안내문을 사용한 로그에서는 다음과 같은 순서로 검색을 마쳤습니다. 현재 Gist는 같은 안내를 영어로 표시합니다.

[   0.0s] 한국어 질문 정규화
[   1.3s] 영어 검색 질의 생성 완료
[   1.3s] Microsoft Learn 검색
[   2.6s] 관련 문서 3개 검색 완료

근거 자료
  [1] Native AOT deployment
  [2] Introduction to AOT warnings
  [3] ASP.NET Core support for Native AOT

약 2.6초에는 한국어 질문 정규화, 영어 질의 생성과 Microsoft Learn 검색이 포함됩니다. 이 실행에서 해당 구간은 뒤이어 발생한 첫 응답 대기보다 짧았습니다.

Edge0 요청 이후 기록한 TTFT 53.47초

검색 결과를 전달한 뒤에는 첫 콘텐츠를 받을 때까지 대기 상태를 출력했습니다.

[   2.6s] Edge0-35B에 요청 전달
[   7.6s] Edge0 처리 중, 첫 토큰 대기 5초
[  12.6s] Edge0 처리 중, 첫 토큰 대기 10초
[  17.7s] Edge0 처리 중, 첫 토큰 대기 15초
[  22.7s] Edge0 처리 중, 첫 토큰 대기 20초
[  27.7s] Edge0 처리 중, 첫 토큰 대기 25초
[  32.7s] Edge0 처리 중, 첫 토큰 대기 30초
[  37.7s] Edge0 처리 중, 첫 토큰 대기 35초
[  42.8s] Edge0 처리 중, 첫 토큰 대기 40초
[  47.8s] Edge0 처리 중, 첫 토큰 대기 45초
[  52.8s] Edge0 처리 중, 첫 토큰 대기 50초
[  56.1s] 첫 토큰 수신 (TTFT 53.5초)

입력 처리 시작부터 첫 콘텐츠 수신까지는 약 56.1초였고 Edge0 요청 기준 TTFT는 53.47초였습니다. 두 값은 시작 시점이 다릅니다.

TTFT에는 클라이언트 처리, 서버 대기열, 토큰화, 프리필과 첫 생성 단계가 함께 들어갈 수 있습니다. 서버 내부 계측이 없으므로 53.47초 전체를 프리필 시간으로 해석하지는 않습니다. 이 기록에서는 Edge0 요청 이후 첫 콘텐츠를 기다리는 구간이 가장 길었습니다.

공식 문서와 대조한 생성 답변

모델의 답변에서 핵심 판정을 짚어보겠습니다. 첫 영어 콘텐츠를 받은 뒤 호스트가 문장을 모아 번역하면서 한국어 답변을 출력했습니다. 실험 당시의 생성 결과를 다음과 같이 그대로 옮겼습니다.

전문가> 아니요, 네이티브 AOT 애플리케이션에서는
`System.Reflection.Emit`를 사용할 수 없습니다.

네이티브 AOT는 `System.Reflection.Emit`를 포함하는
런타임 코드 생성을 명시적으로 금지합니다 [1].

컴파일러는 `RequiresDynamicCodeAttribute`를 사용하는
메서드에 대해 네이티브 코드를 생성할 수 없습니다.

이러한 경고는 해당 멤버가 AOT와 근본적으로 호환되지
않음을 나타냅니다.

가장 좋은 해결 방법은 네이티브 AOT로 빌드할 때 메서드를
호출하지 않고 AOT와 호환되는 다른 것을 사용하는 것입니다 [2].

핵심 판정인 System.Reflection.Emit 미지원은 Native AOT 제한 사항과 일치합니다. 개별 AOT 경고의 의미와 대응은 AOT 경고 문서를 기준으로 해당 호출부를 살펴볼 수 있습니다. 생성 답변의 나머지 설명까지 이 한 가지 판정으로 검증한 것으로 보지는 않습니다.

호스트는 위 두 문서와 ASP.NET Core의 Native AOT 지원 문서를 함께 출력했습니다. 독자는 답변의 출처 번호를 해당 문서와 대조할 수 있습니다.

콘텐츠 이벤트로 계산한 출력 속도

실행 로그에 기록한 값을 계측 코드의 실제 계산 기준에 따라 해석하면 다음과 같습니다.

  • 질문 처리와 검색, 약 2.6초: 입력 처리를 시작한 시점부터 자료 선택까지 걸린 시간을 기록했습니다.

  • TTFT, 53.47초: Edge0 요청 기준 시각부터 첫 콘텐츠 수신까지 걸린 시간을 기록했습니다.

  • 총 생성 시간, 82.11초: Edge0 요청 기준 시각부터 스트림 수신 종료까지 걸린 시간을 기록했습니다.

  • 콘텐츠 이벤트 수, 119개: 샘플의 completion_tokens 필드가 콘텐츠를 포함한 이벤트를 세었습니다.

  • 첫 응답 이후 시간, 28.64초: 첫 콘텐츠 수신부터 스트림 수신 종료까지 걸린 시간을 기록했습니다.

  • 이벤트 기준 출력 속도, 약 4.15회/초: 콘텐츠 이벤트 수 119를 첫 응답 이후 시간 28.64초로 나누어 계산했습니다. 기존 로그에서는 이 값을 tok/s로 표시했습니다.

첫 응답이 시작된 뒤에는 번역한 문장이 점진적으로 나타났습니다. 다만 TTFT는 첫 영어 콘텐츠를 받은 시점까지의 시간이며 첫 한국어 문장이 화면에 나타나는 데에는 문장 완성과 번역 시간이 더해집니다. 총 생성 시간도 한국어 번역과 출력이 모두 끝난 시점까지를 재는 지표는 아닙니다.

이 계측은 같은 구성의 변화를 비교하는 데 사용할 수 있습니다. 다른 모델이나 서버와 토큰 처리율을 비교하려면 실제 토큰 수와 측정 구간을 맞추면 됩니다. 현재 수치만으로 서버의 순수 디코드 성능을 단정하지는 않습니다.

그라운딩 길이와 캐시 상태의 후속 비교

입력량과 캐시 상태의 후속 비교 조건을 검토하겠습니다. 별도 실험에서 그라운딩을 약 6.7KB에서 약 1.7KB로 축소했을 때 전체 처리 시간이 약 94초에서 약 48초로 줄었고 핵심 답변을 유지했습니다. 1편의 비교 기록과 Gist의 입력량 제한을 함께 보면 후속 실험의 변수를 정할 수 있습니다.

긴 입력을 처리하는 비용이 대기 시간에 영향을 줄 수 있지만 앞선 비교는 캐시 상태와 반복 횟수를 통제한 결과가 아닙니다. 실제 원인을 더 좁히려면 다음과 같이 조건을 맞춰 비교할 수 있습니다.

  1. 같은 질문과 검색 결과를 고정해 기준 실행을 기록합니다.
  2. 자료를 재정렬하고 그라운딩 크기를 줄인 뒤 답변의 핵심 근거를 비교합니다.
  3. 프리픽스 캐시의 지원 여부와 적용 조건을 확인하고 적용 전후를 측정합니다.
  4. 프로세스 시작 직후와 반복 요청에서 캐시 상태를 구분해 기록합니다.
  5. 동일한 입력과 생성 길이를 사용해 다른 Apple Silicon 장비에서 반복 측정합니다.
  6. 추가 백엔드가 공개되면 같은 요청과 계측 기준으로 비교합니다.

이 순서는 앞으로 비교할 항목을 제시합니다. 현재 샘플에 재정렬 모델이나 프리픽스 캐시를 구현했다는 뜻은 아닙니다. 우선 입력 자료를 줄일 때 답변 근거를 유지하는지와 첫 응답 대기 시간이 어떻게 달라지는지를 함께 관찰할 수 있습니다.

사내 PoC와 다른 백엔드의 확장 조건

사내 서비스와 다른 백엔드로의 확장 조건을 다루겠습니다. M2 MacBook Air 실험에서는 한 사용자의 질문이 검색, 추론과 번역을 거쳐 끝까지 처리되는지 확인했습니다. Edge0 아키텍처는 추론 코어와 백엔드를 분리하지만 여러 사용자의 세션을 운영하는 서비스 계층은 별도로 구성할 수 있습니다.

Mac mini와 Mac Studio의 요청 제어

장비를 옮기는 후속 PoC에서는 클라이언트와 추론 서버 사이에 인증, 세션, 검색과 정책을 관리하는 호스트를 둘 수 있습니다. 아래 구조는 확장 구상이며 현재 CLI에 구현한 기능을 나타내지는 않습니다.

사내 클라이언트
    ↓
사용자 인터페이스와 API 어댑터
    ↓
에이전트 호스트
    ├─ 인증과 세션
    ├─ 문서 검색과 접근 권한
    ├─ 요청 수 제한과 대기열
    └─ 상태 및 응답 이벤트
    ↓
Edge0 서버

현재 35B 서버 문서는 생성 요청을 FIFO 대기열에서 하나씩 처리한다고 설명합니다. 이 동작을 여러 세션의 토큰 생성을 함께 처리하는 연속 배칭과 구분하면 동시 요청 수와 응답 대기 시간을 판단하기 쉽습니다.

사내 기술 문서 검색, 제품 매뉴얼 질의응답, 운영 절차 안내처럼 범위를 정한 업무를 후속 실험 대상으로 선택할 수 있습니다. 현재 CLI는 인증, 문서별 권한 필터링과 다중 사용자 세션을 구현하지 않았으므로 사내 서비스 구성에서는 해당 계층을 별도로 다룹니다. Responses API 형식이나 AG-UI를 제공하는 어댑터도 같은 후속 범위에 포함됩니다.

CUDA 백엔드 공개 이후의 비교

Edge0의 공개 지원 범위는 MLX 기반 Apple Silicon을 대상으로 하며 CUDA 백엔드는 로드맵에 포함합니다. 따라서 NVIDIA GPU에서 같은 결과를 얻었다고 해석할 수는 없습니다.

추가 백엔드가 공개되고 호환 API를 제공하면 Python 호스트의 검색과 번역 흐름을 재사용하는 방향으로 검토할 수 있습니다. 동일한 질문, 그라운딩 자료, 생성 길이와 계측 기준을 유지하면 장비와 백엔드 차이에 따른 결과를 비교하기 쉽습니다.

한정된 업무에서 확인한 로컬 에이전트의 범위

여기까지 정리하면 16GB 노트북에서 35B급 모델과 공식 문서 검색, 온디바이스 번역을 연결한 에이전트가 한 요청을 끝까지 처리했습니다. 모델에는 문서 해석과 답변 생성을 맡기고 호스트에는 검색과 상태 관리를 맡기는 구성이 성립했습니다.

현재 장비에서 기록한 53.47초의 TTFT는 대화형 사용에 직접 영향을 줍니다. 입력 자료를 줄이고 캐시 상태를 나눠 측정하는 작업을 먼저 비교할 수 있으며 다중 사용자 운영과 다른 백엔드는 후속 검증 범위로 남습니다. 빠른 응답이 중요한 서비스와 대기 시간을 허용하는 기술 문서 실험은 서로 다른 기준으로 평가할 수 있습니다.

전체 실행 코드와 설치 절차는 연재 Gist에 있습니다. 한정된 질문과 근거 자료로 재현을 시작하면 모델 크기뿐 아니라 답변의 출처, 첫 출력까지의 시간과 운영 범위를 함께 평가할 수 있습니다.

연재의 다른 글은 다음 순서로 읽을 수 있습니다.

  1. 16GB Mac의 35B 로컬 LLM과 근거 기반 에이전트
  2. Microsoft Learn과 Apple Translation 실행 환경
  3. Microsoft Learn 검색을 연결한 로컬 RAG 에이전트
  4. 스트리밍 응답의 TTFT와 출력 속도 계측
  5. 현재 글