본문 바로가기
생각

PyTorch를 바꿨는데 vLLM을 다시 빌드해야 할까: Stable ABI의 호환 범위

vLLM의 Stable ABI 전환을 통해 Python·LibTorch 호환성을 구분하고, 가상 모듈 예시로 의존성의 최소 버전과 재빌드 생략 조건을 설명한다.

PyTorch를 바꿨는데 vLLM을 다시 빌드해야 할까: Stable ABI의 호환 범위 관련 이미지

추론 서버의 PyTorch 버전을 올릴 때 Python 코드는 그대로여도 컴파일된 확장 모듈은 다시 빌드해야 할 수 있다. 함수 이름이 같다는 것과 이미 만들어 둔 바이너리가 새 라이브러리에 연결된다는 것은 서로 다른 조건이기 때문이다.

2026년 11월 6일에 나온 vLLM의 Stable ABI 전환 발표 (새 창)는 CUDA wheel의 바이너리 호환성을 다룬다. 이 글에서는 “업그레이드해도 되는가”를 한 번에 판단하지 않고, 어떤 연결을 안정화했고 어떤 조건이 여전히 남는지 살펴본다. 아래의 A·B 모듈과 버전 계산은 이해를 돕기 위한 가상 예시이며, 실제 설치나 GPU 추론을 실행한 결과는 아니다.

LibTorch 전체가 아니라 연결 지점을 안정화한다

ABI는 컴파일된 코드끼리 함수 호출 방식과 데이터 표현을 맞추는 약속이다. 소스 코드 수준의 API가 같더라도 이 약속이 달라지면 기존 바이너리를 그대로 연결할 수 없다. 공식 구조 그림 (새 창)에서는 주황색으로 표시된 LibTorch 전체와 위쪽의 C shim을 구분해서 봐야 한다. Stable ABI는 일부 기능을 안정된 C 경계로 노출하고, C++ 래퍼가 이 경계를 통하도록 만든다. 헤더만으로 구현되는 유틸리티는 별도 영역에 놓인다.

예를 들어 확장 모듈 A가 텐서 연산을 요청한다고 해 보자. 기존 경로가 LibTorch 내부에서 바뀔 여지가 있는 심벌에 의존했다면, 새 라이브러리에서는 연결이 끊길 수 있다. 반면 안정된 경로에서는 A가 약속된 경계를 호출하고 그 뒤의 실제 구현은 라이브러리가 맡는다. 내부 구현이 바뀔 여지는 열어 두되 A가 의존하는 범위를 줄이는 방식이다. 모든 내부 기능을 그대로 쓰면서 안정성만 덧붙이는 것이 아니다.

주황색 LibTorch 위의 안정된 C shim과 이를 쓰는 C++ 래퍼, 왼쪽 헤더 전용 유틸리티를 구분한 구조 그림.
안정된 C 연결 경계와 LibTorch 내부를 구분한 원자료. 전체 라이브러리가 같은 호환 약속을 제공한다는 뜻은 아니다. 출처: vLLM·PyTorch 팀, 원그림 PTC 2025 Stable ABI 발표. 세부 영문은 확대해 확인한다.

abi3 표시와 PyTorch 호환성은 별개다

PyTorch의 C++ 연산자 튜토리얼 (새 창)은 CPython 호환성과 LibTorch 호환성을 독립된 두 축으로 설명한다. Python의 제한된 API를 쓰는 설정과 TORCH_TARGET_VERSION으로 LibTorch의 지원 범위를 정하는 설정이 따로 존재한다. 따라서 확장 파일 이름에 abi3가 붙어 있다는 이유만으로 PyTorch 버전까지 자유롭게 바꿀 수 있다고 단정해서는 안 된다.

가상 모듈 A가 CPython 쪽 조건은 만족하지만 LibTorch의 불안정한 심벌을 하나 사용한다고 해 보자. 이 경우 Python 버전을 바꾸는 문제와 PyTorch를 바꾸는 문제 중 후자는 여전히 남는다. 반대로 LibTorch 쪽만 안정화했더라도 Python의 비공개 API에 기대는 코드가 있다면 Python 호환성을 따로 확인해야 한다. 두 조건을 모두 확인해야 하는데 한쪽 표시만 보고 전체가 통과됐다고 읽는 셈이다.

튜토리얼의 TORCH_TARGET_VERSION은 최소 지원 PyTorch 버전을 지정한다. 그렇다고 이 설정이 필요한 모든 기능을 과거 버전에 만들어 주지는 않는다. 필요한 연산이 안정 API에 없다면 설계를 바꾸거나, 비안정 API를 그대로 쓰면서 지원할 PyTorch 버전별로 빌드를 유지하는 선택지가 남는다.

모듈 하나가 남으면 패키지 전체의 조건도 남는다

전환 RFC (새 창)를 보면 커널을 나눠 점진적으로 옮길 수는 있어도, 관련 파일 전체가 안정된 API를 써야 최종 wheel을 안정화할 수 있다. 전환 단계 그림 (새 창) 가운데에는 안정 라이브러리와 비안정 라이브러리가 함께 놓여 있다. 이는 전환 작업이 진행 중이라는 뜻이지 최종 패키지가 모두 안정화됐다는 뜻은 아니다.

이를 A와 B 두 모듈의 이야기로 좁혀 보자. A는 안정된 심벌만 쓰고 최소 버전이 2.11이라고 가정한다. 반면 B에는 비안정 심벌이 남아 있다. A를 성공적으로 바꿨다고 해서 B의 연결 방식까지 저절로 바뀌지는 않는다. 만약 B까지 안정화했지만 필요한 심벌이 2.13에서야 추가됐다면, 이 관점에서 두 모듈을 함께 쓰는 패키지의 최소 버전은 max(2.11, 2.13)=2.13이 된다.

이 계산은 지원 범위를 평균 내는 문제가 아니라, 필요한 조건을 모두 만족하는 버전을 찾는 문제다. A의 최소 버전만 보고 2.11을 고르면 B가 요구하는 연결 지점을 찾을 수 없다. 여기 쓰인 숫자는 설명을 위한 예시일 뿐 특정 wheel의 실제 설치 가능 버전을 뜻하지는 않는다.

왼쪽의 비안정 라이브러리가 줄고 안정 라이브러리가 커지며, 가운데 공존 단계를 지나 오른쪽 안정 라이브러리로 전환된다.
vLLM의 점진적 전환 과정. 가운데 공존 단계와 오른쪽 완료 단계를 구분한다. 도형 면적은 성능·진행률의 측정값이 아니다. 출처: vLLM·PyTorch 팀.

심벌 검사로 알 수 있는 것과 실행해야 아는 것

torch-abi-audit (새 창)는 바이너리 심벌을 검사해 안정·비안정 PyTorch 의존성을 구분하고, 안정 심벌이 추가된 버전 정보를 바탕으로 최소 torch 버전을 계산한다. 확장 모듈뿐만 아니라 함께 묶인 라이브러리도 판정 대상에 포함한다. 앞선 A·B 예시로 치면 B의 비안정 의존성을 찾아내거나 B 때문에 최소 요구 버전이 높아지는 이유를 확인하는 작업에 해당한다.

다만 심벌 검사가 모델 출력이 동일한지, 요청 지연이 허용 범위 안에 드는지까지 측정해 주지는 않는다. 최소 버전 이상이라는 조건 역시 CUDA·드라이버·Python API·다른 의존성이 모두 맞아떨어진다는 결론을 대신하지 않는다. 따라서 배포 여부를 판단할 때는 먼저 해당 wheel의 전체 심벌 검사 결과와 지원 환경을 맞춘 뒤, 실제로 쓰는 모델·연산·입력으로 결과와 성능을 비교해 볼 수 있다. 이는 이 글에서 제안하는 적용 방식이며 실제 환경에서 검증을 수행한 결과는 아니다.

결국 Stable ABI가 덜어 주는 것은 호환되는 라이브러리가 바뀔 때마다 같은 확장을 다시 컴파일해야 하는 부담이다. 지원 범위 밖의 기능이 필요하다면 여전히 버전별 빌드가 더 적합할 수 있다. 다시 빌드하지 않아도 되는지는 바이너리 연결 조건으로, 실제 운영에 투입할 수 있는지는 실행 결과로 나눠 판단해야 한다.

채용 제안 보내기

함께 해결할 LLM 과제와 기대하는 역할을 알려 주세요.

연락하기