LLM 엔지니어링11장 · 폐쇄망 문서 파이프라인과 폐쇄형 RAG5 / 23← 이전목차다음 →MetaContents

11장. 폐쇄망 문서 파이프라인과 폐쇄형 RAG

바깥으로 나가는 연결 막기

집 전화에 발신 제한을 걸면 정해 둔 번호로만 전화가 걸립니다. 폐쇄망의 프로그램도 사내 주소로만 연결되어야 합니다. 그런데 라이브러리 가운데에는 우리가 모르는 사이에 바깥으로 연결하려는 것이 있습니다.

허브에서 모델 받기, 사용 통계 보내기, 외부 API 부르기, 업데이트 묻기의 네 가지 바깥 연결을 견준 카드

네 카드는 몰래 바깥으로 나가려는 연결입니다. 없는 모델을 허브에서 찾는 것, 라이브러리가 사용 통계를 보내는 것, 코드가 외부 LLM API 를 부르는 것, 새 판이 있는지 묻는 것입니다. 폐쇄망에서는 이 연결이 막혀 오류가 나거나 한참 기다리다 실패합니다. 여기서 발신 제한이 오프라인 설정과 방화벽, 정해 둔 번호가 사내 주소(이 장에서는 localhost)입니다.

끄는 법

바깥 연결끄는 법이 장에서
Hugging Face 허브HF_HUB_OFFLINE=1, TRANSFORMERS_OFFLINE=1실습 1에서 켠다
Chroma 사용 통계Settings(anonymized_telemetry=False) 또는 ANONYMIZED_TELEMETRY=False실습 1, 4에서 켠다
외부 LLM API코드에서 부르지 않고 사내 Ollama 주소만 쓴다http://localhost:11434/v1
pip 저장소PIP_NO_INDEX=1 또는 --no-index안내만 한다

나가는 연결 막아 보기

파이썬에서는 주소를 IP 로 바꾸는 socket.getaddrinfo 를 바꿔 끼워, localhost 가 아닌 주소를 막을 수 있습니다. 실습 1에서 이것을 파일로 만들어 모든 실습에 씁니다.

Python
import socket

real = socket.getaddrinfo                      # 원래 함수를 챙겨 둔다

def only_local(host, *args, **kwargs):
    """localhost 가 아니면 연결하기 전에 오류를 낸다"""
    if host not in ("localhost", "127.0.0.1", "::1"):
        raise OSError(f"폐쇄망: {host} 로 나가는 연결을 막았습니다")
    return real(host, *args, **kwargs)

socket.getaddrinfo = only_local                # 바꿔 끼운다
try:
    socket.getaddrinfo("huggingface.co", 443)
except OSError as e:
    print(e)
socket.getaddrinfo = real                      # 예시가 끝나면 되돌린다

코드에 나오는 함수

코드쉬운 뜻
socket네트워크 연결을 다루는 표준 라이브러리다. socket 은 "전기 콘센트, 꽂는 구멍"이라는 뜻이다
socket.getaddrinfoget address information(주소 정보 얻기)의 줄임이다. huggingface.co 같은 이름을 IP 주소로 바꾼다
real = socket.getaddrinfo원래 함수를 부르지 않고 이름표만 챙겨 둔다. 괄호가 없으면 실행하지 않는다
*args, **kwargs나머지 인자를 몇 개든 받아 그대로 넘긴다. args 는 arguments(인자), kwargs 는 keyword arguments(이름 붙인 인자)다
raise OSError(...)운영체제(OS) 쪽 오류를 일부러 일으킨다. 연결 실패와 같은 종류의 오류다
socket.getaddrinfo = only_local라이브러리의 함수 자리에 우리 함수를 끼운다. 이렇게 바꿔 끼우는 일을 몽키 패칭(monkey patching)이라고 한다
except OSError as e:오류가 나면 그 오류를 e 로 받아 멈추지 않고 이어 간다

이 코드가 뜻하는 것

회사의 전화 교환원으로 읽어 봅니다. 직원이 바깥에 전화하려면 교환원에게 번호를 물어야 합니다. 교환원 자리에 "사내 번호만 알려 주는" 새 교환원을 앉히면, 바깥 번호를 물을 때 "연결할 수 없습니다"라는 답만 돌아옵니다. 여기서 교환원 자리가 socket.getaddrinfo, 새 교환원이 only_local, 원래 교환원이 real 입니다.

줄하는 일쉽게 말하면
real = socket.getaddrinfo원래 함수를 챙겨 둔다원래 교환원의 연락처를 적어 둔다
def only_local(...)localhost 가 아니면 오류를 낸다사내 번호만 알려 주는 새 교환원
return real(host, ...)localhost 면 원래 함수에 넘긴다사내 번호는 원래 교환원에게 넘긴다
socket.getaddrinfo = only_local함수를 바꿔 끼운다새 교환원을 자리에 앉힌다
socket.getaddrinfo("huggingface.co", 443)바깥 주소를 물어본다바깥 번호를 물어본다
socket.getaddrinfo = real원래 함수로 되돌린다원래 교환원을 다시 앉힌다

교안을 만든 PC 에서는 폐쇄망: huggingface.co 로 나가는 연결을 막았습니다 가 찍혔습니다. 주소를 IP 로 바꾸기 전에 막았으므로 실제로 바깥에 묻는 일은 일어나지 않았습니다. 443 은 HTTPS(HyperText Transfer Protocol Secure, 암호화한 웹 통신)가 쓰는 포트 번호입니다.

주의할 점

  • 이 방법은 같은 파이썬 프로그램 안의 연결만 막습니다. 다른 프로그램이나 IP 를 바로 쓰는 연결은 막지 못합니다. 실제 폐쇄망의 차단은 방화벽과 네트워크 장비가 합니다. 여기서는 "우리 코드가 바깥을 찾는지" 확인하는 시험 도구로 씁니다.
  • 오프라인 설정은 라이브러리를 불러오기(import) 전에 켭니다. 라이브러리가 불러올 때 설정을 읽어 두는 경우가 있기 때문입니다.
← 이전 절11장 · 모델과 패키지 들여오기다음 절 →11장 · 문서 수집