다운로드는 끝났는데 왜 실행되지 않을까?
인터넷에 연결된 개발 PC에서 LLM을 실행했다. 모델도 정상적으로 내려받았고, 질문을 보내면 답변도 나온다. 이제 모델 폴더를 폐쇄망 서버로 옮기면 같은 서비스를 사용할 수 있을까?
다음과 같은 상황을 생각해보자.
- 가중치는 있는데 토크나이저 파일이 없어 로딩에 실패한다.
- Python 패키지는 설치했지만 GPU 연산에 필요한 라이브러리가 맞지 않는다.
- 실행할 때 추가 파일을 다운로드하려다 연결 시간 초과가 발생한다.
- 짧은 질문에는 답하지만 긴 문서와 동시 요청이 들어오면 메모리가 부족해진다.
- 새 모델로 교체한 뒤 답변 품질이 떨어졌는데 이전 설정을 찾을 수 없다.
이 문제들은 모델 파일의 존재 여부만으로 확인할 수 없다. 폐쇄망에서 운영해야 하는 대상은 모델 가중치 하나가 아니라, 모델을 사용하는 서비스 전체이기 때문이다.
이 글에서는 이미 학습된 LLM을 내부 서버에서 추론 서비스로 운영하는 경우를 기준으로, 외부망 준비부터 반입 검증, 서비스 배포와 복구까지 살펴본다.
아래 폴더 구조와 명령은 절차를 설명하기 위한 예시다. 특정 기관의 실제 구축 기록이나 성능 측정 결과는 아니다. Hugging Face Transformers 형식의 텍스트 모델을 중심으로 설명하며, 모델·추론 엔진·장비에 따라 필요한 파일과 검증 방법은 달라진다.
1. 반입 전에 운영 조건부터 정하기
모델을 고르기 전에 사용할 업무와 실행 환경을 적어본다.
| 구분 | 확인할 내용 |
|---|---|
| 업무 | 문서 질의응답, 정보 추출, 분류, Tool 호출 중 무엇을 수행하는가? |
| 입력과 출력 | 입력 길이, 최대 출력 길이, 한글·표·JSON 처리 요구사항은 무엇인가? |
| 부하 | 동시에 처리할 요청 수와 허용할 대기 시간은 얼마인가? |
| 하드웨어 | GPU 종류·수량·메모리, CPU, RAM, 디스크 여유 공간은 충분한가? |
| 실행 환경 | OS·CPU 아키텍처, GPU 드라이버, Python과 추론 엔진 버전은 무엇인가? |
| 내부 연결 | 내부 패키지 저장소·이미지 레지스트리·인증·DB에 접근할 수 있는가? |
| 운영 기준 | 서비스 담당자, 배포 시간, 장애 시 복구 목표는 정해졌는가? |
폐쇄망이라고 해서 모든 환경이 같은 것은 아니다. 인터넷만 차단되고 내부 저장소는 사용할 수 있는 환경도 있고, 필요한 파일을 서버에 직접 전달해야 하는 환경도 있다. 준비할 파일과 설치 경로는 이 조건에 따라 달라진다.
또한 모델을 GPU에 올리는 것과 목표 부하를 처리하는 것은 별도 조건이다. 가중치가 올라가더라도 긴 입력과 동시 요청을 위한 KV Cache 공간이 부족할 수 있다. 용량 산정은 앞선 LLM용 GPU 용량 산정 글과 연결해서 확인한다.
2. 가중치와 함께 가져와야 할 파일
모델 저장소에는 가중치 외에도 실행에 필요한 설정과 전처리 파일이 들어 있다.
| 구성 요소 | 역할 | 파일 예시 |
|---|---|---|
| 모델 가중치 | 학습된 파라미터 | model.safetensors, 분할된 가중치 파일 |
| 가중치 인덱스 | 분할 파일과 파라미터의 연결 정보 | model.safetensors.index.json |
| 모델 설정 | 모델 구조와 주요 설정 | config.json |
| 토크나이저 | 문자열과 토큰 사이의 변환 | tokenizer.json, tokenizer.model, 어휘 파일 |
| 토크나이저 설정 | 특수 토큰과 토크나이저 동작 설정 | tokenizer_config.json, special_tokens_map.json |
| 대화 템플릿 | 사용자·시스템·도구 메시지의 입력 형식 | 토크나이저 설정 내부 또는 별도 템플릿 파일 |
| 생성 설정 | 기본 생성 동작 | generation_config.json |
| 추가 코드·Processor | 사용자 정의 구조나 멀티모달 입력 처리 | Python 파일, Processor 설정 등 |
| 출처와 이용 조건 | 원본 확인과 사용 범위 검토 | 모델 카드, 라이선스 파일 |
위 파일이 모든 모델에 같은 이름으로 존재해야 한다는 뜻은 아니다. 모델 형식과 런타임에 따라 일부 정보가 합쳐져 있거나 다른 파일로 제공될 수 있다. GGUF처럼 별도의 배포 형식을 사용한다면 해당 런타임이 요구하는 구성으로 준비한다.
중요한 것은 선택한 런타임이 실제로 읽는 파일을 빠짐없이 준비하는 것이다. 특히 분할 가중치는 인덱스 파일만 있어도, 가중치 일부만 있어도 정상적으로 로딩되지 않는다.
대화 템플릿도 배포 설정의 일부로 다룬다. 가중치가 같아도 메시지를 구성하는 방식이 달라지면 답변이나 Tool 호출 동작이 달라질 수 있다.
3. 모델 이름 대신 정확한 Revision을 기록하기
같은 저장소 이름으로 다운로드하더라도 시점에 따라 파일이 달라질 수 있다. 배포 기록에 모델 이름만 남기면 나중에 같은 구성을 다시 준비하기 어렵다.
Hugging Face Hub에서는 snapshot_download()의 revision에 특정 커밋을 지정하고 local_dir에 파일을 내려받을 수 있다. 재현을 위해서는 이동할 수 있는 브랜치 이름보다 전체 커밋 해시를 기록하는 편이 명확하다. Hugging Face 다운로드 문서
다음은 외부망 준비 환경에서 실행하는 Python 예시다. 두 자리표시자는 실제 저장소 ID와 검토한 전체 커밋 해시로 바꾼다. 접근 제한 모델은 다운로드 계정의 권한과 이용 조건도 먼저 확인한다.
1
2
3
4
5
6
7
from huggingface_hub import snapshot_download
snapshot_download(
repo_id="<조직명>/<모델명>",
revision="<검토한 전체 커밋 해시>",
local_dir="./llm-release/model",
)
처음부터 확장자 몇 개만 허용하면 필요한 토크나이저나 코드 파일을 놓칠 수 있다. 반대로 저장소 전체를 받으면 사용하지 않는 형식의 가중치까지 포함해 용량이 커질 수 있다. 먼저 파일 구성을 확인하고, 실제 사용할 형식으로 범위를 줄인 다음 최종 반입 목록 그대로 다시 검증한다.
캐시 폴더를 직접 복사한다면 심볼릭 링크가 폴더 밖 파일을 가리키지 않는지도 확인한다. 폴더 이름과 목록이 보인다고 실제 데이터까지 모두 포함되었다고 판단하지 않는다.
원본 저장소에 필요한 파일이 모두 있다는 보장도 없다. 별도 저장소의 코드나 외부 리소스를 참조하는 모델은 그 의존성까지 확인해야 한다.
4. 실행 환경도 모델과 함께 고정하기
같은 모델 파일을 사용해도 실행 환경이 달라지면 로딩 가능 여부와 성능이 달라질 수 있다.
1
2
3
4
5
모델·토크나이저·대화 템플릿
↓
추론 엔진·Python 패키지·네이티브 라이브러리
↓
GPU 드라이버·컨테이너 실행 환경·하드웨어
버전 번호를 각각 적는 데서 끝내지 않고, 함께 검증한 조합으로 관리한다. PyTorch를 사용하는 경로라면 PyTorch와 CUDA 런타임의 조합을, 다른 엔진이라면 그 엔진이 요구하는 GPU와 드라이버 조건을 확인한다. 양자화 형식도 대상 GPU와 추론 엔진이 지원해야 한다.
Python 패키지로 구성하는 경우
최상위 패키지만 아니라 하위 의존성과 필요한 네이티브 라이브러리까지 준비한다. 대상과 같은 환경에서 설치한 버전 목록과 배포 파일을 함께 보관한다.
Python 패키지를 외부망에서 수집해 내부 Nexus로 배포하는 과정은 폐쇄망에서 Python 패키지 사용하기 글에서 다뤘다. 여기서도 다운로드 PC가 아니라 실제 실행 서버의 OS·아키텍처·Python 버전이 기준이다.
컨테이너로 구성하는 경우
이미지에는 검증한 실행 환경을 담고, 모델은 별도 볼륨이나 승인된 저장소로 제공할 수 있다. 이미지 태그와 함께 Digest를 기록하면 어떤 이미지를 검증했는지 구분하기 쉽다.
다만 GPU 드라이버까지 이미지 하나로 해결되는 것은 아니다. NVIDIA GPU 컨테이너를 사용하는 경우 호스트 드라이버와 NVIDIA Container Toolkit 등의 설정도 필요하다. NVIDIA Container Toolkit 설치 문서
운영 서버가 시작할 때 pip install이나 외부 이미지 다운로드를 수행하도록 두면, 배포가 실행 시점의 외부 의존성에 묶인다. 필요한 설치와 이미지 준비는 반입 전에 마치고, 내부 저장소만 사용하는 구성으로 검증한다.
5. 반입 단위를 하나의 Release로 묶기
모델 파일, 실행 이미지, 설정을 각각 다른 위치에서 관리하면 어느 조합을 검증했는지 놓치기 쉽다. 다음처럼 하나의 Release를 기준으로 연결 정보를 남길 수 있다.
1
2
3
4
5
6
7
8
llm-release/
├── manifest.yaml # 출처, 버전, 환경, 구성 요소 연결 정보
├── model/ # 모델과 토크나이저, 설정 파일
├── runtime/ # 실행 이미지 아카이브 또는 패키지 묶음
├── config/ # 실행 옵션, 대화 템플릿, 프롬프트
├── evaluation/ # 평가 입력, 판정 기준, 검증 결과
├── licenses/ # 모델·패키지 이용 조건
└── SHA256SUMS # 반입 파일의 해시 목록
실제 파일이 내부 레지스트리나 별도 저장소에 있다면 모두 한 폴더에 복제할 필요는 없다. Manifest에 해당 파일을 정확히 찾을 수 있는 경로·버전·Digest를 기록한다.
| 기록 항목 | 예시 또는 작성 내용 |
|---|---|
| Release ID | internal-llm-20261028-01 |
| 모델 출처 | 저장소 ID, 전체 커밋 해시, 원본·변환본 구분 |
| 모델 형식 | BF16, FP16, 특정 양자화 형식과 변환 설정 |
| 실행 환경 | 추론 엔진·패키지 버전 또는 이미지 Digest |
| 호스트 조건 | 검증한 GPU, 드라이버, OS·아키텍처 |
| 서비스 설정 | 최대 입력·출력 길이, 동시 처리 한도, 생성 옵션 |
| 검증 기록 | 평가 데이터 버전, 결과, 검증 일시와 담당자 |
| 복구 대상 | 이전 Release ID와 배포 방법 |
비밀번호와 접근 Token은 배포 묶음에 넣지 않는다. 외부망 다운로드용 자격증명을 그대로 반입하지 않고, 내부 서비스에 필요한 자격증명은 운영 환경에서 별도로 주입한다.
반입 전후의 파일 비교
다음은 Linux의 GNU 도구를 사용하는 예시다. 배포 묶음의 루트에서 실행하며, 파일명에 줄바꿈 같은 특수 문자가 없다고 가정한다.
1
2
3
4
5
6
7
# 외부망: 최종 반입 파일 구성을 확정한 뒤 생성
find . -type f ! -path './SHA256SUMS' -print0 \
| sort -z \
| xargs -0 sha256sum > SHA256SUMS
# 내부망: 같은 폴더 구조로 반입한 뒤 확인
sha256sum -c SHA256SUMS
이 검사는 목록에 기록된 파일의 누락과 내용 변경을 찾는 용도다. 목록에 없는 추가 파일이나 외부를 가리키는 심볼릭 링크까지 검사하지는 않는다. 반입 파일 목록과 링크 대상도 별도로 확인한다.
파일과 해시 목록을 함께 바꿀 수 있다면 해시 비교만으로 출처를 보증할 수 없다. 승인된 경로로 전달받은 목록과 대조하거나 조직의 서명·반입 검증 절차를 함께 사용한다.
6. 모델 파일과 실행 코드를 구분하기
모델 저장소에는 데이터 파일뿐 아니라 Python 코드가 포함될 수 있다. 사용자 정의 모델을 실행하기 위해 trust_remote_code=True가 필요하다면, 어떤 코드를 허용하는지 검토해야 한다.
이 옵션은 네트워크 차단을 해제하는 설정이 아니라 저장소에서 제공하는 사용자 정의 코드를 신뢰하고 실행하도록 허용하는 설정이다. 로컬로 반입한 코드도 실행 권한과 의존성을 검토할 대상이다.
Transformers의 보안 문서는 가중치 형식으로 safetensors 사용을 권장하고, 사용자 정의 코드는 내용을 확인하고 Revision을 고정하도록 안내한다. 다만 안전한 가중치 형식을 선택했다고 저장소의 다른 코드나 패키지까지 안전해지는 것은 아니다. Transformers 보안 정책
라이선스도 모델별로 확인한다. 다운로드할 수 있다는 사실만으로 모든 업무·배포 형태에 제한 없이 사용할 수 있는 것은 아니다. 원본 모델과 양자화·변환본의 출처 및 적용 조건을 함께 보관한다.
7. 캐시가 없는 환경에서 오프라인 검증하기
개발 PC에서는 이미 내려받은 파일과 패키지가 캐시에 남아 있을 수 있다. 반입 묶음에서 파일을 빠뜨려도 캐시가 대신 제공하면 실행이 성공한다.
따라서 검증 조건을 다음과 같이 잡는다.
- 대상과 호환되는 새 가상환경 또는 컨테이너를 준비한다.
- 반입할 패키지·이미지·모델만 제공한다.
- 기존 사용자 캐시가 연결되어 있지 않은지 확인한다.
- 실제 네트워크 정책으로 외부 통신을 차단한다.
- 설치, 모델 로딩, 첫 추론, 재시작을 차례로 확인한다.
Hugging Face Hub 접근은 프로세스를 시작하기 전에 다음 환경변수로 제한할 수 있다.
1
2
export HF_HUB_OFFLINE=1
export HF_HUB_DISABLE_TELEMETRY=1
HF_HUB_OFFLINE=1은 Hub에 대한 HTTP 호출을 막고 로컬 파일이나 캐시를 사용하도록 한다. Telemetry 비활성화도 해당 라이브러리의 기능 범위에 적용된다. 이 설정들이 사용자 정의 코드, 다른 SDK, 외부 API의 통신까지 막아주는 방화벽은 아니다. Hugging Face 환경변수 문서
Transformers에서는 모델 ID 대신 반입한 로컬 경로를 지정하고 local_files_only=True를 사용할 수 있다. 다음 예시는 로컬 설정과 토크나이저를 읽는 초기 점검이다. Transformers 오프라인 실행 문서
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from transformers import AutoConfig, AutoTokenizer
model_dir = "./llm-release/model"
config = AutoConfig.from_pretrained(
model_dir,
local_files_only=True,
trust_remote_code=False,
)
tokenizer = AutoTokenizer.from_pretrained(
model_dir,
local_files_only=True,
trust_remote_code=False,
)
tokens = tokenizer("폐쇄망 모델 로딩을 확인합니다.")
print(config.model_type)
print(len(tokens["input_ids"]))
이 예시는 가중치 로딩이나 GPU 추론까지 검증하지 않는다. 사용자 정의 코드가 필요한 모델은 여기서 실패할 수 있으므로, 옵션을 무조건 바꾸기보다 앞 단계의 코드 검토와 런타임 지원 여부부터 확인한다.
이후 실제 운영에 사용할 엔진과 실행 옵션으로 가중치를 로딩하고, API 요청을 보내 답변 생성을 확인한다. GPU 환경에서는 최초 기동 시 커널 컴파일이나 추가 캐시 생성이 필요한지도 살펴본다. 필요한 컴파일러·라이브러리와 쓰기 가능한 캐시 경로가 없다면 첫 실행에서 막힐 수 있다.
8. 실행 성공과 업무 품질을 따로 검증하기
서버가 켜졌다는 사실만으로 배포를 완료하지 않는다. 검증을 네 단계로 나누면 실패 위치를 구분하기 쉽다.
| 단계 | 확인할 내용 |
|---|---|
| 설치·기동 | 파일 검증, 패키지 설치, GPU 인식, 모델 로딩, 재시작 |
| 기능 | 일반 대화, 긴 입력, 스트리밍, JSON 출력, 필요한 Tool 호출 |
| 품질 | 실제 업무 질문의 정확성, 근거, 모르는 내용 처리, 형식·값 검증 |
| 부하·복구 | 동시 요청, 대기열, 타임아웃, 취소, 메모리 부족, 프로세스 재기동 |
예를 들어 문서에서 금액을 추출하는 서비스라면 “답변이 나왔다”보다 다음 항목이 중요하다.
- 원문에 있는 금액과 통화를 정확히 구분했는가?
- 값이 없는 경우 임의로 채우지 않았는가?
- JSON 형식뿐 아니라 업무 규칙도 만족하는가?
- 문서가 길어져도 필요한 항목을 놓치지 않는가?
성능도 입력 길이와 출력 길이, 동시 요청 수를 고정해서 비교한다. 첫 응답 시간, 전체 완료 시간, 처리량, 실패율을 함께 기록한다. 모델 교체 전후에는 같은 평가 입력과 판정 기준을 사용해야 변화의 의미를 판단할 수 있다.
초기 로딩·워밍업 시간과 준비된 서버의 요청 처리 시간도 구분한다. 자세한 지연 지표는 LLM 응답 속도 글과 연결해서 볼 수 있다.
평가 데이터는 반입·공유 가능한 합성 데이터나 비식별 자료로 준비한다. 외부망에서 수행한 검증 결과를 내부 GPU와 내부 서비스의 성능 결과로 대신하지 않는다.
9. RAG와 Agent는 연결된 구성 요소까지 확인하기
LLM 자체는 오프라인으로 동작해도, 전체 서비스는 외부 연결을 요구할 수 있다.
1
2
3
4
5
6
사용자 요청
→ 문서 파싱·OCR
→ Embedding·검색·Reranker
→ LLM
→ Tool·DB·내부 API
→ 결과 저장
각 단계가 모델 다운로드, 외부 API, 외부 인증 서버를 사용하는지 확인한다. Embedding 모델과 Reranker, OCR 모델도 별도의 가중치와 실행 환경이 필요할 수 있다.
특히 Embedding 모델을 바꾸면 검색 인덱스도 함께 검토해야 한다. 벡터 차원이 같아도 다른 모델의 벡터가 같은 의미 공간을 사용하는 것은 아니다. 모델과 전처리 방식이 달라진다면 기존 문서 재임베딩 및 인덱스 재구성이 필요한지 판단한다.
Agent는 Tool이 실제로 내부 주소를 호출하는지, 실행 계정에 필요한 권한만 있는지 점검한다. 폐쇄망은 외부 접속을 제한하지만 내부 데이터의 과도한 조회나 잘못된 수정까지 자동으로 막지는 않는다. 이 부분은 AI Agent 권한 관리 글에서 다뤘다.
10. 로그와 지표도 내부에서 확인할 수 있어야 한다
외부 관측 서비스에 의존하는 설정은 폐쇄망에서 동작하지 않거나 불필요한 재시도를 발생시킬 수 있다. 로그와 지표의 수집 위치, 보관 기간, 접근 권한을 내부 운영 조건에 맞춘다.
| 관측 대상 | 확인 목적 |
|---|---|
| 요청 수·오류율·타임아웃 | 서비스 실패와 부하 변화 확인 |
| 첫 응답 시간·완료 시간 | 사용자 지연과 성능 저하 확인 |
| 대기 요청 수·처리 중인 요청 수 | 처리 용량 부족과 대기열 증가 확인 |
| GPU 메모리·사용률·메모리 부족 오류 | 자원 포화와 실행 실패 진단 |
| 입력·출력 토큰 수 | 긴 요청이나 사용 패턴 변화 파악 |
| Release ID·요청 ID | 어떤 배포에서 문제가 발생했는지 추적 |
예를 들어 vLLM은 API 서버의 /metrics 경로로 운영 지표를 제공한다. 실제 지표 이름과 제공 항목은 배포한 버전의 문서를 기준으로 확인한다. vLLM 운영 지표 문서
요청 추적을 위해 원문 전체를 무조건 저장할 필요는 없다. 내부 문서와 개인정보가 로그에 남을 수 있으므로, 기본 로그에는 식별자·상태·처리 시간 중심으로 기록하고 본문 저장이 필요한 경우 범위와 접근 권한을 별도로 정한다.
프로세스가 살아 있다는 검사와 실제 요청을 처리할 준비가 되었다는 검사도 구분한다. 모델 로딩과 워밍업이 끝나기 전에 사용자 요청을 받지 않도록 하고, 별도의 소규모 추론 점검으로 응답 가능 여부를 확인한다.
11. 업데이트는 교체보다 되돌리기까지 설계하기
운영 중인 폴더에 새 가중치를 덮어쓰면 이전 파일과 새 파일이 섞이거나, 문제 발생 후 원래 구성을 복구하기 어려워질 수 있다.
Release별 경로를 분리하고 다음 순서로 배포한다.
- 새 Release를 별도 경로에 반입하고 파일을 검증한다.
- 격리된 검증 인스턴스에서 같은 평가를 실행한다.
- 품질과 부하 결과를 이전 Release와 비교한다.
- 진행 중 요청의 처리 방법을 정하고 트래픽을 전환한다.
- 오류율·지연·업무 품질을 확인하고 기준을 벗어나면 되돌린다.
GPU 여유가 없어 두 모델을 동시에 올릴 수 없다면, 사전 검증 후 점검 시간에 기존 모델을 내리고 교체하는 방식도 가능하다. 이때 모델을 다시 읽고 워밍업하는 시간까지 복구 시간에 포함한다. 모델 경로만 바꾼다고 실행 중인 프로세스가 자동으로 새 가중치를 사용하는 것은 아니다.
롤백 대상도 가중치 하나에 한정하지 않는다.
| 변경 항목 | 함께 복구할 수 있어야 하는 항목 |
|---|---|
| 생성 모델 | 토크나이저, 대화 템플릿, 생성 옵션, 호환되는 실행 환경 |
| 추론 엔진 | 이미지·패키지, 실행 옵션, API 호환 설정 |
| Embedding 모델 | 전처리 설정, 해당 모델로 생성한 인덱스와 검색 설정 |
| Agent 구성 | 프롬프트, Tool 정의, 권한 정책과 연결 설정 |
DB나 문서를 수정하는 Agent라면 배포 롤백만으로 이미 실행한 작업이 취소되지는 않는다. 실행 이력과 별도의 업무 복구 절차도 필요하다.
이전 Release를 보관하는 것에서 끝내지 않고, 그 Release로 서비스를 다시 시작해 요청을 처리하는 과정까지 검증한다.
자주 막히는 부분
| 증상 | 먼저 확인할 항목 |
|---|---|
| 실행 시 외부 Hub 연결을 시도함 | 로컬 경로 지정, 누락 파일, 다른 저장소 참조, 사용자 정의 코드 |
| 모델 폴더는 있는데 파일을 찾지 못함 | 분할 가중치·인덱스 누락, 깨진 링크, 마운트 경로·권한 |
| 토크나이저나 대화 템플릿 오류 | 모델과 같은 Revision의 파일인지, 런타임 지원 여부 |
| GPU를 인식하지 못함 | 호스트 드라이버, 컨테이너 GPU 연결, 런타임 호환 조건 |
| 짧은 질문은 되지만 긴 입력에서 실패 | 최대 길이 설정, KV Cache, 동시 요청과 메모리 여유 |
| 개발 PC에서만 정상 실행됨 | 기존 캐시, 패키지 버전, 외부 의존성, 하드웨어 차이 |
| 첫 기동에서만 오래 걸리거나 실패함 | 가중치 로딩, 커널 컴파일, 캐시 쓰기 권한, 워밍업 |
| 모델 교체 후 검색 품질이 떨어짐 | Embedding 변경, 전처리·인덱스·검색 설정의 조합 |
| 이전 모델로 되돌려도 동작이 다름 | 실행 이미지·템플릿·프롬프트·인덱스까지 복구했는지 |
반입 완료의 기준을 바꾸기
폐쇄망 LLM 운영에서 “모델을 가져왔다”는 것은 준비의 한 단계다. 운영 가능한 상태가 되려면 다음 질문에도 답할 수 있어야 한다.
- 반입한 파일만으로 새 환경에서 설치하고 실행할 수 있는가?
- 외부 통신이 차단되어도 필요한 업무를 끝까지 수행할 수 있는가?
- 목표 입력 길이와 동시 요청에서 품질·지연 기준을 만족하는가?
- 같은 구성으로 다시 배포하고, 문제가 생기면 이전 상태로 복구할 수 있는가?
반입의 단위를 파일에서 검증된 Release로 바꾸면, 모델을 실행하는 작업과 서비스를 운영하는 작업이 연결된다. 무엇을 가져왔는지뿐 아니라 어떤 조건에서 검증했고 어떻게 복구할지도 함께 남기는 것이 폐쇄망 LLM 운영의 출발점이다.