본문으로 바로가기

SafeTensors 형식: 안전한 ML 모델 직렬화를 위한 가이드

SafeTensors는 2026년 4월 PyTorch Foundation에 합류했으며, Hugging Face Hub의 기본 체크포인트 형식입니다. 헤더-데이터 구조가 모델 로딩을 어떻게 안전하게 지키는지 알아보세요.
업데이트됨 2026년 6월 15일  · 10분 읽다

최근에 Hugging Face에서 모델을 다운로드해 보셨다면 .bin이나 .pkl 대신 .safetensors 파일이 보였을 겁니다. 겉보기보다 훨씬 큰 변화입니다.

수년간 대부분의 ML 프레임워크는 모델 체크포인트 저장에 피클 기반 직렬화에 의존해 왔습니다. 그럭저럭 잘 작동했지만 숨은 대가가 있었습니다. 체크포인트를 로드하는 동안 역직렬화 과정에서 임의의 Python 코드가 실행될 수 있어, 겉보기엔 무해한 모델 파일 속에 숨겨진 공급망 공격과 악성 페이로드에 노출될 위험이 있었습니다.

SafeTensors는 그 격차를 메우기 위해 만들어졌습니다. 로딩 중 어떤 코드도 실행하지 않고 원시 텐서 가중치만 저장하여, 현재 Hugging Face Hub 전반의 기본 형식이 되었습니다. 2026년 4월에는 PyTorch, vLLM, DeepSpeed, Ray와 함께 Linux Foundation 산하 PyTorch Foundation에 공식 합류했습니다. 

이 형식이 내부적으로 어떻게 작동하는지, 다른 형식들과는 어떻게 다른지 계속 읽어보세요.

SafeTensors란 무엇인가요?

SafeTensors는 모델 가중치를 안전하게 저장하도록 특별히 설계된 파일 형식입니다. 

이 형식은 실행 가능한 코드와 원시 수치 텐서 데이터를 분리하여 가중치만 저장합니다. 이것이 피클 기반 형식과 다른 점입니다.

이 형식은 대부분의 체크포인트가 이미 담고 있는 핵심에 집중하기 때문에 현대 ML 파이프라인에도 자연스럽게 들어맞습니다: 

  • 텐서
  • 셰이프
  • 데이터 타입
  • 가중치 값

범용 Python 직렬화 시스템처럼 동작하는 대신, SafeTensors는 모델 파라미터를 위한 전용 스토리지 계층처럼 동작합니다.

비록 Hugging Face가 처음에 자사 생태계를 위해 SafeTensors를 개발했지만, 형식 자체는 프레임워크에 구애받지 않습니다. 최근(2026년 4월) PyTorch Foundation에 합류했으며 PyTorch, TensorFlow, JAX, Flax, NumPy 및 기타 ML 프레임워크를 지원합니다.

피클의 문제: 왜 새로운 형식이 필요했나

Python의 Pickle 형식은 일반 Python 애플리케이션을 위해 만들어졌습니다. 개발자가 내부 상태, 메서드, 복원 로직과 함께 전체 Python 객체를 저장하고 복원해야 하는 경우가 많기 때문입니다.

머신러닝 체크포인트는 대개 그 수준의 저장이 필요하지 않습니다. 대부분의 모델 파일은 가중치 행렬, 임베딩, 바이어스 등 수치 파라미터인 텐서를 주로 저장합니다. 실제로는 체크포인트가 대부분 구조화된 수치 데이터라는 뜻입니다.

하지만 .pkl 파일은 데이터를 저장하는 것 이상을 합니다. 로딩 시 Python이 객체를 어떻게 재구성할지에 대한 지시를 담을 수도 있습니다. 즉, 역직렬화는 단순한 읽기 작업이 아니라 코드를 실행할 수 있습니다. 그리고 그 코드가 악성이라면 심각한 보안 문제가 됩니다. 

피클이 임의 코드 실행을 가능하게 하는 방식

Python은 피클 역직렬화 중에 __reduce__() 같은 특수 메서드를 사용해 객체를 재구성합니다. 클래스는 이 메서드를 정의하여, 메모리로 다시 불러올 때 객체를 정확히 어떻게 재구성할지 피클에 알려줄 수 있습니다.

예를 들어 __reduce__()는 호출 가능한 함수와 그 인수를 반환할 수 있습니다. 역직렬화 중 Python은 그 호출 가능한 객체를 실행해 객체를 재구성합니다. 예시 코드:

import pickle
import os

class Demo:
    def __reduce__(self):
        return (os.system, ("echo 'Code executed during deserialization'",))

payload = pickle.dumps(Demo())

pickle.loads(payload)

pickle.loads()가 실행되면, Python은 __reduce__()가 반환한 함수를 실행합니다. 이 예에서는 역직렬화가 os.system()을 통해 셸 명령을 촉발합니다.

문제는 셸 명령 그 자체가 아닙니다. __reduce__()는 로직에 따라 임의의 인수와 함께 어떤 호출 가능한 객체든 반환할 수 있습니다. 즉, Pickle 파일은 다른 함수를 호출하고, 파일을 다운로드하고, 환경을 수정하거나, 로딩 중 악성 코드를 실행할 수 있습니다. 그래서 Python 문서도 신뢰할 수 없는 소스의 피클 데이터를 로드하지 말라고 명시적으로 경고합니다.

모델 공유 시대의 위험

Hugging Face Hub 같은 플랫폼에는 이제 연구자, 스타트업, 취미 개발자, 익명 기여자들이 공유한 백만 개가 넘는 모델이 호스팅됩니다. 개발자가 모델을 즉시 다운로드해 테스트할 수 있어 생태계가 빠르게 움직입니다. 하지만 대부분의 업로드된 체크포인트는 배포 전에 개별적으로 감사를 거치지 않습니다.

많은 PyTorch 체크포인트는 여전히 .pt.bin 같은 형식을 통해 피클 기반 직렬화에 의존합니다. 이 파일을 로드하면, Python은 체크포인트 내부에 내장된 역직렬화 로직을 실행할 수 있습니다. 체크포인트가 악성이라면, 그 로직이 자격 증명을 훔치거나 환경 변수를 읽고, 페이로드를 다운로드하거나, 로딩 중 원격 코드를 실행할 수 있습니다.

Pickle vs SafeTensors

SafeTensors는 바로 이 문제를 해결하기 위해 만들어졌습니다. 임의의 Python 객체를 직렬화하는 대신, 텐서 데이터와 해당 텐서를 올바르게 로드하는 데 필요한 메타데이터만 저장합니다. .safetensors 파일을 로드할 때는 Python의 재구성 로직을 실행할 필요가 없으므로 공격 표면이 크게 줄어듭니다.

SafeTensors 형식은 어떻게 작동하나요

SafeTensors가 무엇이고 왜 존재하는지 알았으니, 이제 구조와 동작 방식을 살펴보겠습니다.

헤더-데이터 구조

SafeTensors 파일은 JSON 헤더와 그 뒤를 잇는 원시 텐서 데이터, 두 부분으로 이루어집니다.

헤더 각 텐서의 메타데이터를 저장합니다. 예를 들면 

  • 텐서 이름
  • 셰이프
  • 데이터 타입
  • 바이트 오프셋

헤더 뒤에는 파일이 텐서의 원시 바이트를 연속적으로 저장합니다.

헤더는 일종의 목차처럼 작동합니다. 파일에 어떤 텐서가 있는지, 어디에 위치하는지를 로더에 알려 주는데, 이는 데이터베이스 인덱스가 저장된 레코드를 가리키는 방식과 유사합니다. SafeTensors는 과도하게 큰 메타데이터 페이로드를 막기 위해 헤더 크기를 100MB로 제한합니다.

SafeTensors File Anatomy

제로-카피 및 메모리 매핑 로딩

SafeTensors는 메모리 매핑 로딩을 통해 로딩 속도를 높입니다. 역직렬화 중 Python 객체를 재구성하는 대신, 프레임워크가 디스크의 텐서 데이터를 메모리에 직접 매핑할 수 있습니다. 불필요한 메모리 복사를 줄이고 로딩 중 CPU 오버헤드를 낮춥니다.

Hugging Face의 벤치마크에 따르면, SafeTensors는 CPU에서 PyTorch 대비 약 76배, GPU 작업에서는 약 2배 더 빠르게 가중치를 로드했습니다. 물론 정확한 가속 비율은 하드웨어와 체크포인트 크기에 따라 달라지지만, Python 역직렬화를 피하면 일관되게 로드 성능이 향상됩니다.

지연 로딩과 부분 역직렬화

SafeTensors는 전체 체크포인트를 한 번에 메모리로 읽어들이는 대신, 이름으로 지정한 특정 텐서만 로드합니다.

이는 여러 GPU에 걸쳐 실행되는 대규모 분산 모델에서 유용합니다. 예를 들어 BLOOM의 176B 파라미터 모델의 경우, 표준 PyTorch 체크포인트에서는 먼저 전체 모델 가중치를 역직렬화한 뒤 디바이스 간에 분할해야 했고, 이 과정에 약 10분이 걸렸습니다. 

SafeTensors를 사용하면 각 GPU는 실제로 필요한 텐서 샤드만 로드했습니다. 그 결과 8개 GPU에서 모델 시작 시간이 약 45초로 단축되었습니다.

SafeTensors와 다른 직렬화 형식 비교

SafeTensors는 모델 가중치를 안전하고 효율적으로 저장하고 로드하는 데 매우 적합하지만, 그렇다고 모든 형식을 대체하는 범용 해법은 아닙니다. 올바른 선택은 무엇을 저장하는지, 그리고 모델이 파이프라인의 어디에 위치하는지에 달려 있습니다.

피클 이야기는 충분히 했으니, 이제 다른 형식에 집중하겠습니다.

SafeTensors vs GGUF

SafeTensorsGGUF는 서로 다른 문제를 해결합니다. 

GGUF는 GGML Unified Format의 약자로, llama.cpp 같은 런타임에서 양자화된 추론 워크로드를 위해 만들어졌습니다. 이 형식은 특히 CPU 추론과 엣지 디바이스를 위해 압축 모델의 효율적 배포에 초점을 맞춥니다. 

SafeTensors는 파이프라인의 더 이른 단계에 위치합니다. 대부분의 SafeTensors 체크포인트는 학습, 파인튜닝, 머징, 분산 추론 워크플로우에 사용되는 전체 정밀도 또는 학습 준비가 된 텐서를 저장합니다. 이 형식은 안전한 로딩, PyTorch 같은 프레임워크와의 호환성, 학습 및 서빙 중 효율적인 텐서 액세스를 우선합니다.

서로 직접 경쟁하기보다 상호 보완적으로 사용할 수 있습니다. 예시 워크플로우: 

  • PyTorch와 SafeTensors 체크포인트로 모델을 학습하거나 파인튜닝
  • 최종 모델을 양자화
  • 배포를 위해 llama.cpp 또는 엣지 추론 런타임용으로 GGUF로 내보내기

SafeTensors vs ONNX

SafeTensors는 PyTorch 같은 프레임워크 내부에서 모델 가중치를 안전하게 저장하고 효율적으로 로드하는 데 초점을 맞춥니다. 텐서와 메타데이터만 저장하므로, 체크포인트 공유, 파인튜닝, 학습 워크플로우에서 가볍고 빠릅니다.

ONNX는 더 넓은 접근을 취합니다. 모델 파라미터와 함께 전체 계산 그래프를 저장합니다. 덕분에 한 프레임워크에서 모델을 내보내 다른 환경에서 완전히 달리 실행하고자 할 때 유용합니다.

예를 들어, 팀이 PyTorch를 사용해 LLM을 학습하고 파인튜닝한다면, 빠르게 로드되고 기존 워크플로우에 바로 통합되는 SafeTensors 체크포인트를 선호할 가능성이 큽니다. 하지만 동일한 팀이 모델을 TensorRT, ONNX Runtime, 또는 엣지 추론 엔진에 배포해야 한다면 ONNX로 내보내는 것이 더 적합합니다.

실전에서 SafeTensors 사용하기

SafeTensors가 PyTorch 생태계 전반으로 빠르게 확산된 이유 중 하나는 API가 익숙하게 느껴지기 때문입니다. 여전히 평소처럼 state dict과 텐서로 작업합니다.

텐서 저장과 로딩

기본 워크플로우는 표준 PyTorch 체크포인트 처리와 동일해 보입니다. 예시는 다음과 같습니다:

import torch
from safetensors.torch import save_file, load_file

tensors = {
    "weights": torch.randn(2, 2),
    "bias": torch.zeros(2)
}

save_file(tensors, "model.safetensors")

loaded_tensors = load_file("model.safetensors")

print(loaded_tensors["weights"])

save_file()은 텐서를 .safetensors 형식으로 기록하고, load_file()은 이를 메모리로 다시 로드합니다.

SafeTensors는 safe_open()을 통한 선택적 로딩도 지원합니다. 일부 텐서만 필요할 때 유용한, 대형 체크포인트에서 특히 효과적입니다.

from safetensors import safe_open

with safe_open("model.safetensors", framework="pt") as f:
    weights = f.get_tensor("weights")

print(weights)

전체 체크포인트를 로드하는 대신, get_tensor()는 요청한 텐서만 읽습니다.

기존 모델을 safetensors로 변환

표준 패턴은 다음과 같습니다:

  1. 기존 모델 로드
  2. state dict 추출
  3. save_file()로 저장
from transformers import AutoModel
from safetensors.torch import save_file

model = AutoModel.from_pretrained("bert-base-uncased")

save_file(model.state_dict(), "model.safetensors")

state_dict()는 모델 가중치를 텐서로 반환하며, SafeTensors는 이를 바로 저장할 수 있습니다. 

모델이 이미 Hugging Face Hub에 있다면 로컬 변환 코드가 필요하지 않을 수도 있습니다. Hugging Face는 Hub 인터페이스를 통해 호스팅된 모델의 체크포인트 변환을 기본 지원합니다.

직렬화 형식: 비교 표

기능 SafeTensors Pickle (.pkl/.bin/.pt) GGUF ONNX
임의 코드 실행 아니요 아니요 아니요
주요 사용 사례 학습, 파인튜닝, 체크포인트 공유 범용 Python 직렬화 양자화된 엣지/CPU 추론 크로스 프레임워크 배포
계산 그래프 저장 아니요 아니요 아니요
메모리 매핑 로딩 아니요 아니요
지연/부분 텐서 로딩 아니요 아니요
프레임워크 지원 PyTorch, TF, JAX, Flax, NumPy Python(모든 프레임워크) llama.cpp, 엣지 런타임 ONNX Runtime, TensorRT, 엣지
양자화 지원 확대 중(FP8, GPTQ, AWQ) 아니요 예(네이티브)
Hugging Face Hub 기본값 아니요 아니요 아니요

2026년의 SafeTensors: PyTorch Foundation 합류와 다음 단계

2026년 4월, Hugging Face는 SafeTensors를 Linux Foundation 산하 PyTorch Foundation에 기여했습니다. 이 프로젝트는 이제 PyTorch, vLLM, DeepSpeed, Ray와 함께 재단의 거버넌스를 따릅니다.

이는 SafeTensors가 더 이상 Hugging Face만의 프로젝트가 아니라, ML 생태계를 위한 공유 인프라가 되어가고 있음을 의미합니다. 

발표에서는 형식의 향후 방향성도 다룹니다.

디바이스 인지 로딩

주요 초점 중 하나는 디바이스 인지 로딩입니다. 오늘날 많은 워크플로우가 여전히 텐서를 CPU 메모리로 로드한 뒤 CUDA나 ROCm 디바이스로 전송합니다. 이 추가 스테이징 단계는 특히 대규모 분산 시스템에서 시작 지연을 키웁니다. 

SafeTensors의 메인테이너들은 불필요한 CPU 복사를 줄이고 텐서를 가속기 쪽으로 직접 옮기는, 직접 디바이스 로딩 경로를 개선하고 있습니다. 

분산 로딩

분산 로딩 지원도 진화하고 있습니다. 현대 추론 시스템은 더 이상 단일 GPU에서만 모델을 실행하지 않습니다. 텐서 병렬화와 파이프라인 병렬화가 대형 모델의 표준 배포 패턴이 되었지만, 프레임워크 전반의 체크포인트 로딩 API는 아직 분절되어 있습니다. 

SafeTensors는 샤드 인지 로딩과 분산 텐서 레이아웃 지원을 확대하여, 프레임워크가 디바이스 전반에서 체크포인트 로딩을 더 효율적으로 조율할 수 있도록 하고 있습니다. 

현대적 양자화 워크플로우

이 형식은 최신 양자화 워크플로우에도 적응하고 있습니다. 추론 시스템은 점점 더 FP8, GPTQ, AWQ 형식에 의존하여 메모리 사용량을 줄이고 서빙 비용을 낮춥니다. 

프레임워크가 이를 커스텀 직렬화 로직으로 처리하도록 강제하는 대신, SafeTensors는 저정밀 및 블록 양자화 텐서 형식에 대한 정식 지원을 형식 자체에 추가하고 있습니다. 

현재로서는 개발자가 저장과 로드 워크플로우를 전환해 SafeTensors를 수동으로 선택해야 합니다. 하지만 PyTorch의 기본 직렬화 시스템과 더 깊은 통합을 위한 작업이 진행 중입니다. 이것이 구현되면, SafeTensors는 대체 체크포인트 형식이 아니라 PyTorch가 모델을 저장하는 기본 방식이 될 수 있습니다.

맺음말

오랫동안 개발자들은 로딩 중 임의의 Python 코드를 실행할 수 있는 직렬화 시스템을 사용해 모델 체크포인트를 공유해 왔습니다. 공개 모델 허브가 수백만 개의 체크포인트를 호스팅하기 시작하자, 보안 위험을 외면하기가 훨씬 어려워졌습니다.

SafeTensors는 형식의 범위를 좁힘으로써 상황을 바꾸었습니다. 전체 Python 객체를 직렬화하려는 대신, 텐서와 이를 로드하는 데 필요한 메타데이터만 저장하는 데 집중합니다. 이 단순한 설계는 피클 기반 체크포인트에서 발생하던 역직렬화 위험을 제거하는 동시에, 로딩 속도와 메모리 효율도 개선합니다.

따라서 모델 가중치만 필요하다면, 역직렬화 중 임의 코드를 실행할 이유가 없습니다. 그런 경우에는 SafeTensors를 사용하는 편이 낫습니다.

최신 ML 도구, 모델 형식, Hugging Face 워크플로우를 더 깊이 다뤄보고 싶으시다면, Deep Learning in PythonWorking with Hugging Face 과정을 추천합니다. 오늘날의 AI 생태계 전반에서 사용하는 도구로 모델을 학습, 파인튜닝, 배포하는 실전 워크플로우를 다룹니다.

SafeTensors 자주 묻는 질문

기존 .bin 또는 .pt 모델을 SafeTensors로 변환할 수 있나요?

예. PyTorch 또는 Transformers에서 모델을 일반적으로 로드한 뒤 state_dict()를 추출하고, safetensors 라이브러리의 save_file()로 저장하면 됩니다. Hugging Face Hub는 다수의 호스팅 모델에 대해 자동 변환도 지원합니다.

SafeTensors로 양자화된 모델을 저장할 수 있나요?

예. SafeTensors는 이미 여러 저정밀 텐서 타입을 지원하며, 양자화 추론이 보편화됨에 따라 FP8, GPTQ, AWQ 같은 형식에 대한 지원도 확대되고 있습니다.

모델 전체를 로드하지 않고 SafeTensors 파일 내용을 살펴볼 수 있나요?

예. 형식은 텐서 메타데이터를 헤더에 별도로 저장하므로, 체크포인트 전체를 메모리에 로드하지 않고도 텐서 이름, 셰이프, 데이터 타입을 확인할 수 있습니다.

SafeTensors를 사용하면 모델 정확도에 영향이 있나요?

아니요. SafeTensors는 가중치가 저장·로드되는 방식을 바꿀 뿐, 수치 값 자체는 바꾸지 않습니다. 로딩 후 모델의 동작은 동일합니다.

SafeTensors는 추론 워크로드에만 유용한가요?

개발자들은 추론뿐 아니라 학습, 파인튜닝, 체크포인트 공유, 분산 로딩 워크플로우에서도 이를 사용합니다.

주제

추천 머신러닝 코스

tracks

머신 러닝 기초 in Python

16
머신 러닝의 기술을 익히고 예측, 패턴 인식, 그리고 딥 러닝과 강화 학습의 기초에 능숙해지세요.
자세히 보기Right Arrow
강좌 시작
더 보기Right Arrow