[GPU] CVD로 AI 에이전트 GPU 워크스페이스 구축하기
개요
고객 지원용 AI 봇에 "웹사이트에서 자료를 받아 표로 정리해줘" 같은 작업을 맡기려면, 언어 모델이 답을 문장으로 만드는 것만으로는 부족합니다. 브라우저를 열고, 프로그램을 실행하고, 결과 파일을 어딘가에 저장할 실제 컴퓨터가 필요합니다. 이 글에서는 그 컴퓨터 역할을 Tencent Cloud Desktop(CVD)으로 구축하면서 겪은 과정을 정리합니다.
핵심 질문은 세 가지였습니다. 이 구조에서 LLM, 에이전트, CVD는 각각 무슨 일을 하는가, GPU는 정확히 어디에 필요한가, 그리고 GPU가 필요하다고 결론 나면 실제로 얼마나 크게 잡아야 하는가입니다. 아래는 이 질문에 답하기 위해 직접 인스턴스를 만들고 접속해본 기록입니다.
1. 역할을 세 조각으로 나눠서 본다
이 구조는 LLM, AI 에이전트, CVD 세 개의 역할로 나눠서 봐야 정확합니다.
| 구성 요소 | 하는 일 |
|---|---|
| LLM / 판단 | 목표와 현재 상태를 읽고 다음 행동을 제안합니다. 외부 모델 API 또는 직접 배포한 모델을 쓸 수 있습니다. |
| AI 에이전트 / 조율 | 모델 호출, 도구 실행, 권한 확인, 재시도와 완료 판단을 관리하는 봇 프로그램입니다. |
| CVD / 실행 공간 | 브라우저, 업무 프로그램, 터미널과 파일을 실행/보관합니다. GPU 구성에서는 모델 추론/영상 처리도 여기서 실행됩니다. |
요청 한 건이 처리되는 흐름도 이 역할 분담을 그대로 따라갑니다.
- 요청 접수: 사용자가 작업을 맡기면 에이전트가 대상, 저장 위치, 허용된 계정/권한을 먼저 확인합니다.
- 다음 행동 판단: 에이전트가 작업 목표와 현재 화면/실행 결과를 모델에 전달하고, 모델은 다음 행동을 제안합니다.
- CVD에서 실행: 에이전트가 연결 도구로 CVD의 브라우저를 조작하거나 명령을 실행합니다.
- 결과 확인과 반복: 바뀐 화면, 명령 종료 상태, 생성 파일을 받아 성공 여부를 확인하고, 실패하면 횟수와 제한시간을 두고 재시도합니다.
- 완료와 전달: 실제 파일 내용과 저장 여부를 검증한 뒤에야 사용자에게 결과를 전달합니다. 모델이 "완료"라고 답했다는 사실만으로 작업을 성공 처리하지 않습니다.
여기서 "화면 조작(Computer Use)"이라는 방식이 나오는데, 이건 에이전트가 화면 상태를 확인하고 마우스/키보드를 제어하는 방식을 가리킵니다. 프로그램이 API나 CLI를 제공한다면 화면을 클릭하는 대신 그 인터페이스를 바로 쓸 수도 있습니다. 모델과 에이전트 사이에 오가는 것도 단순한 프롬프트가 아니라 작업 목표, 이전 실행 결과, 허용된 도구와 입력 형식까지 포함된 맥락 전체입니다.
2. GPU는 정확히 어디에 필요한가
여기서 실무적으로 가장 자주 헷갈리는 지점이 나옵니다. "봇이 컴퓨터를 조작하는 것"과 "모델을 그 컴퓨터에서 직접 실행하는 것"은 완전히 별개의 선택입니다. 세 역할을 나눠서 그렸다고 반드시 서버 세 대가 필요하다는 뜻도 아닙니다. 에이전트는 CVD 내부에서 돌 수도, 별도 서버에서 돌 수도 있습니다.
구성별로 GPU가 실제로 필요한지 정리하면 이렇습니다.
| 구성 | CVD의 역할 | GPU 판단 기준 |
|---|---|---|
| 외부 LLM API + CVD | 모델 판단은 외부 API에 맡기고 CVD에서 브라우저/업무 프로그램만 실행 | 외부 모델의 추론 때문에 CVD GPU가 필요한 건 아닙니다. 화면 렌더링/영상 편집 같은 실행 프로그램 자체의 요구사항만 확인하면 됩니다. |
| 직접 배포한 LLM + CVD | CVD의 GPU에서 모델을 실행하고 봇이 그 모델 API를 호출 | 모델 가중치, 대화 길이, 동시 요청 수에 맞춰 VRAM을 산정해야 합니다. 모델과 데스크톱 작업이 GPU를 공유하면 서로 느려질 수 있습니다. |
| AI 봇 + 영상/이미지 생성 모델 | 봇이 생성 요청을 조율하고 GPU 모델이 결과를 생성 | 해상도/프레임 수/동시 실행에 따라 메모리와 처리시간이 달라집니다. 작업 대기열과 결과 보관도 함께 설계해야 합니다. |
즉 "AI 에이전트를 쓴다 = GPU가 필요하다"가 아닙니다. 판단을 외부 API에 맡기는 구성이라면 CVD는 그냥 브라우저와 업무 프로그램을 실행하는 일반 데스크톱이면 충분합니다. GPU가 실제로 필요해지는 시점은 모델 가중치를 CVD 자체에 올려서 돌리기로 결정한 순간부터입니다.
CVD 인스턴스를 만들었다고 해서 업무를 이해하고 스스로 조작하는 봇이 자동으로 완성되는 것도 아닙니다. 모델 연결, 에이전트 프로그램, 화면/명령 제어 도구, 프로그램 설치와 로그인, 작업 검증과 운영 정책은 전부 따로 구성해야 합니다.
3. GPU 메모리 산정
GPU가 필요하다고 결론 나면 다음 질문은 크기입니다. GPU 메모리는 단순히 "가중치 크기"가 아니라 세 요소의 합입니다.
GPU 메모리 = 가중치 + KV cache/중간 텐서 + 실행 버퍼LLM은 대화가 길어질수록 KV cache가 커지고, 영상 모델은 해상도/프레임 수/참조 입력에 따라 중간 텐서가 커집니다. 파일 크기가 VRAM보다 작다는 사실만으로는 실행을 보장할 수 없습니다. 양자화 모델도 로딩 순간에는 더 높은 정밀도의 텐서를 먼저 올릴 수 있어서, 실행 중보다 시작할 때 메모리가 더 필요할 수 있다는 점을 실측 과정에서 확인했습니다.
파라미터 수와 정밀도별 대략적인 가중치 용량은 다음과 같습니다.
| 모델 크기 | FP16/BF16 | 8비트 | 4비트 |
|---|---|---|---|
| 7B | 약 14GB | 약 7GB | 약 3.5GB |
| 27B | 약 54GB | 약 27GB | 약 13.5GB |
| 70B | 약 140GB | 약 70GB | 약 35GB |
이 값은 파라미터 수 × 비트 수로 계산한 가중치 용량의 대략적인 십진 GB 값이며, 양자화 메타데이터/일부 고정밀 계층/KV cache/실행 버퍼는 포함하지 않습니다. 70B를 INT8로 낮춰도 가중치만 약 70GB라 여유가 거의 없고, INT4로 더 낮추거나 여러 GPU로 나누되 목표 품질과 동시 요청 수를 함께 검증해야 합니다. CPU offload로 용량 문제를 완화할 수는 있지만, CPU↔GPU 전송 때문에 지연이 커질 수 있다는 트레이드오프가 붙습니다.
G6와 G6s 구성
실제 인스턴스 사양은 G6(장당 48GB)와 G6s(장당 72GB) 두 계열로 갈립니다.
| vCPU | 시스템 RAM | GPU 수 | G6 합계 (48GB/장) | G6s 합계 (72GB/장) |
|---|---|---|---|---|
| 32 | 96GB | 1 | 48GB | 72GB |
| 96 | 288GB | 1 | 48GB | 72GB |
| 64 | 192GB | 2 | 96GB | 144GB |
| 192 | 576GB | 2 | 96GB | 144GB |
| 128 | 384GB | 4 | 192GB | 288GB |
| 384 | 1,152GB | 4 | 192GB | 288GB |
| 256 | 768GB | 8 | 384GB | 576GB |
| 384 | 1,536GB | 8 | 384GB | 576GB |
| 768 | 2,304GB | 8 | 384GB | 576GB |
이 표는 PRO 5000 기반 구성이고, 선택 가능한 리전/재고/이미지는 계정과 시점에 따라 달라집니다. 여기서 짚어야 할 함정이 하나 있습니다. "4 × 72GB"는 72GB 메모리 공간 네 개라는 뜻이지, 아무 설정 없이 하나의 288GB GPU처럼 동작한다는 뜻이 아닙니다. 여러 GPU를 하나처럼 쓰려면 아래 병렬화 방식 중 무엇을 쓸지 별도로 정해야 합니다.
| 방식 | 어떻게 나누는가 | 실무 판단 |
|---|---|---|
| TP (Tensor Parallel) | 한 모델의 행렬 연산과 가중치를 GPU에 분할 | 큰 모델 적재와 단건 지연 개선에 유리하지만 GPU 간 통신이 잦습니다. |
| EP (Expert Parallel) | MoE의 전문가를 GPU에 분산 | 전문가 라우팅과 통신 비용을 함께 봐야 합니다. |
| Ulysses / USP | 영상/시퀀스 처리를 나누는 병렬 경로 | 해상도/길이 및 다른 병렬 차수와 맞아야 합니다. |
| FSDP | 모델 상태를 분할하고 필요할 때 모음 | 학습뿐 아니라 특정 영상 모델의 BF16 추론 경로에도 씁니다. |
| 독립 복제 인스턴스 | 모델 실행기를 여러 개 띄우고 요청을 분산 | 단건은 느려져도 전체 처리량이나 장애 격리는 좋아질 수 있습니다. |
이 구성에는 NVLink가 없다는 점도 실측 전에 미리 확인해야 하는 부분입니다. RDMA 사용 가능 여부는 별도 확인이 필요하고, PCIe 세대/P2P 경로/NUMA 배치는 실제 인스턴스에서 직접 봐야 합니다. GPU 수만 곱해서 처리량을 예상하면 통신 비용을 놓칩니다. 인스턴스에 접속한 뒤 가장 먼저 돌린 명령이 이 구조를 확인하는 것이었습니다.
nvidia-smi
nvidia-smi topo -m
nvidia-smi --query-gpu=index,name,memory.total,memory.used,driver_version --format=csv
free -h
df -h4. 인스턴스와 이미지 구성
GPU 크기를 정했다면 다음은 실제 인스턴스 생성입니다. 이번 구축에서는 이후 시리즈의 기준이 될 MiniMax H3 예제를 기준으로 구성했습니다.
- 서비스와 리전 확인: CVD 사용 가능 여부, GPU 재고, 모델 이미지 제공 여부를 먼저 확인합니다. 시험 단계는 사용량 기반, 지속 운용은 약정/월 단위 조건을 비교하는 게 맞습니다.
- VPC와 서브넷 선택: API를 호출할 서버, 점프 호스트, 이후 TKE/TI-ONE을 연결할 위치까지 함께 정해야 합니다. 나중에 네트워크를 옮기면 주소와 접근 정책도 다시 맞춰야 하는 번거로움이 생깁니다.
- GPU형 G6s 선택: H3 시작 구성은 128 vCPU, RAM 384GB, PRO 5000 72GB 4장입니다.
- 모델 이미지 선택: H3는 일반 Ubuntu 22.04가 아니라
[G6] Ubuntu Server 22.04 LTS 64-bit MiniMax H3 Base에 해당하는 전용 이미지를 찾아야 합니다. - 디스크 구성: H3 시스템 디스크는 650GB 이상 SSD 또는 고성능 유형으로 준비합니다. 모델 패키지, Docker 계층, 캐시와 영상 출력까지 담을 공간이 필요합니다.
- 인터넷 경로 설정: 다운로드나 외부 후처리가 필요하면 NAT 연결과 라우팅을 함께 구성합니다.
- CVD 사용자 생성 및 인스턴스 연결: CVD 접속용 사용자와 Linux SSH 사용자는 별개일 수 있다는 점을 유의해야 합니다.
650GB는 어디까지나 H3 예제의 시작 조건입니다. 뒤에서 다룰 GLM은 가중치만 약 328GB라 이미지와 캐시까지 더하면 훨씬 여유가 필요합니다. 시스템 디스크, 출력용 디스크, NAT/EIP, 네트워크와 후처리(MPS) 비용은 따로 계산해야 하고, 모델 라이선스와 상업적 사용 조건도 배포 전에 확인이 필요합니다.
이미지를 선택한 뒤에는 실제로 필요한 명령과 경로가 준비돼 있는지 읽기 전용으로 점검했습니다.
command -v nvidia-smi
command -v h3-use
command -v ds4
command -v glm53
docker image ls
# 선택한 이미지에 해당하는 경로만 확인
ls -ld /srv/minimax-h3 /opt/deepseek-v4-flash /opt/glm-5.3-flash세 모델의 명령이 모두 있어야 하는 건 아닙니다. 선택한 이미지에 해당하는 명령과 경로만 확인하면 됩니다. 명령이 없다고 무작정 패키지를 추가하기보다, 이미지 종류와 초기화 상태부터 다시 확인하는 편이 안전합니다.
5. 접속 경로: 콘솔, 사설망 SSH, 공인망 SSH
로컬 PC와 CVD는 서로 다른 컴퓨터입니다. 당연한 말처럼 들리지만, 127.0.0.1은 명령을 실행하는 컴퓨터 자기 자신을 가리킨다는 점을 실제로 터널을 걸다가 한 번씩 헷갈리게 됩니다. 접속 방식은 세 가지로 나뉩니다.
| 접속 방식 | 접속 경로 | 추가 준비 |
|---|---|---|
| 콘솔 | CVD 콘솔 → 연결된 사용자 → 로그인 | CVD 사용자 연결 |
| 사설망 SSH | 같은 VPC의 CVM → CVD 사설 IP | Linux 사용자, SSH, 사설망 통신 |
| 공인망 SSH | 로컬 PC → NAT의 EIP → DNAT → CVD | NAT/EIP, 포트 매핑, 접근 제한 |
콘솔에서 GPU 확인
CVD 콘솔에서 인스턴스에 로그인하고 터미널을 연 뒤, 관리자로 전환해서 GPU를 확인합니다.
sudo su -
nvidia-smiLinux 사용자 생성 후 사설망 SSH
이후 예제는 Ubuntu 기준입니다. testcvd는 예시 사용자이고, sudo 그룹은 관리자 권한이라 업무에 필요한 범위인지 먼저 확인해야 합니다.
# root 계정으로 전환
sudo su -
# testcvd 사용자 생성
sudo useradd -m -s /bin/bash testcvd
# testcvd 비밀번호 설정
sudo passwd testcvd
# testcvd에 sudo 권한 부여, 운영 환경에서는 최소 권한 검토
sudo usermod -aG sudo testcvd같은 VPC에 있는 CVM 콘솔에서 로그인한 뒤 사설 IP로 접속합니다.
ssh testcvd@CVD_PRIVATE_IP
# 주소 예시
ssh testcvd@10.0.2.12공인망에서는 NAT의 DNAT을 씁니다
로컬 PC에서 바로 CVD로 붙는 구조가 아닙니다. EIP는 CVD에 직접 붙이지 않고 NAT 게이트웨이에 연결하는 방식입니다. CVD의 외부 통신은 NAT 경로를 쓰고, 외부에서 들어오는 SSH 연결은 DNAT 규칙으로 전달합니다. 외부로 나갈 수 있다고 해서 외부에서 들어오는 접속까지 자동으로 허용되는 건 아닙니다.
| 설정 | 예시 |
|---|---|
| 프로토콜 | TCP |
| 공인 IP / 외부 포트 | NAT EIP / 22 |
| 사설 IP / 대상 포트 | 10.0.2.12 / 22 |
| 접근 허용 | 관리자 공인 IP 또는 필요한 CIDR만 |
| 라우팅 | CVD 서브넷과 NAT 경로 및 반환 경로 확인 |
ssh testcvd@NAT_EIP
# 주소 예시
ssh testcvd@203.0.113.10여기서 NAT_EIP는 실제 NAT 공인 IP로 바꿔야 하고, 외부 포트를 22가 아닌 다른 값(예: 2222)으로 정했다면 -p 2222를 명시해야 합니다. NAT의 EIP 연결 개수 한도는 계정/리전별 할당량을 미리 확인하는 게 좋습니다.
로컬 브라우저와 API는 SSH 터널로 연결
DeepSeek, H3, 초해상도 Agent는 기본 예제에서 인증이 없고, GLM도 별도 설정 전에는 인증이 없습니다. 사설망에서도 접근 대상을 제한해야 하고, 외부로 노출하려면 TLS/인증/요청 제한이 있는 게이트웨이를 거쳐야 합니다. 실제로 CVD 위의 웹 UI와 API를 로컬 브라우저에서 열기 위해 쓴 포트 포워딩은 다음과 같습니다.
ssh -N \
-L 127.0.0.1:8189:127.0.0.1:8189 \
-L 127.0.0.1:8000:127.0.0.1:8000 \
-L 127.0.0.1:7002:127.0.0.1:7002 \
-L 127.0.0.1:30010:127.0.0.1:30010 \
testcvd@NAT_EIP터널을 유지한 채 로컬 브라우저에서 http://127.0.0.1:8189를 열면 CVD의 ComfyUI에 연결됩니다. 다른 모델 인스턴스는 별도 SSH 연결이 필요하고, 로컬 포트가 이미 다른 프로그램에 쓰이고 있다면 왼쪽 포트만 바꾸면 됩니다. 예를 들어 18000:127.0.0.1:8000으로 연결하면 로컬에서는 18000을 쓰게 됩니다.
이후 시리즈의 모든 API 예제에서 등장하는 127.0.0.1은 CVD에서 직접 실행하거나, 해당 CVD로 SSH 터널이 연결된 로컬 PC에서 실행한다는 걸 전제로 합니다. 별도 사설망 애플리케이션에서 호출한다면 이 주소를 CVD 사설 IP로 바꿔야 합니다.
6. 서비스 운영 전에 확인해야 했던 것들
인스턴스를 띄우고 접속까지 마쳤다고 바로 서비스를 열 수 있는 건 아닙니다. 실제로 다음 항목을 하나씩 짚어봤습니다.
- 접근 권한: 봇 전용 계정과 최소 권한을 쓰고, 외부 전송/삭제/결제처럼 영향이 큰 동작은 별도 승인 대상으로 둡니다. 화면이나 웹페이지에 보이는 지시를 신뢰된 사용자 명령으로 취급하지 않는 것도 포함됩니다.
- 작업 격리: 여러 사용자가 같은 로그인 세션/다운로드 폴더를 공유하지 않도록 설계해야 합니다. CVD 한 대를 마련했다고 사용자별 격리가 자동으로 되는 게 아닙니다.
- 재시도와 복구: 화면 변경, 팝업, 네트워크 끊김에 대비하고, 동일 작업을 다시 실행해도 중복 제출/중복 결제가 나지 않도록 관리해야 합니다.
- 지연과 비용: 모델 응답 대기 + 화면 전송/프로그램 실행 + 반복 횟수가 전체 작업시간을 결정합니다. GPU를 늘려도 외부 API 응답이나 웹사이트 대기시간은 그대로일 수 있다는 걸 감안해야 합니다. CVD 사용료 외에 모델 API/저장/전송 비용도 함께 봐야 합니다.
- 데이터 보호: 화면/문서가 외부 모델로 전달되는지 확인하고 계정/비밀정보를 가려야 하며, 실행 기록과 결과 파일의 보관 기간, 실패 시 정리 절차도 미리 정해야 합니다.
정리
- 이 구조는 LLM(판단), AI 에이전트(조율), CVD(실행) 세 역할로 나눠서 봐야 하고, 서버 대수와 역할 개수가 반드시 일치하지는 않습니다.
- GPU는 "에이전트를 쓴다"고 무조건 필요해지는 게 아니라, 모델 가중치를 CVD 자체에서 직접 돌리기로 한 순간부터 필요해집니다.
- GPU 메모리는 가중치 + KV cache/중간 텐서 + 실행 버퍼의 합이고, 특히 로딩 시점에 실행 중보다 더 큰 메모리가 필요할 수 있습니다.
- "4 × 72GB"는 72GB 공간 네 개이지 288GB GPU 하나가 아닙니다. TP, EP, Ulysses/USP, FSDP, 독립 복제 인스턴스 중 실제 워크로드에 맞는 병렬화 방식을 따로 정해야 합니다.
- 이 구성에는 NVLink가 없어서 GPU 수만 곱해 처리량을 예상하면 통신 비용을 놓칩니다.
nvidia-smi topo -m으로 실제 연결 구조를 먼저 확인하는 게 안전합니다. - 접속은 콘솔, 사설망 SSH, 공인망 SSH(NAT의 DNAT 경유) 세 경로로 나뉘고, 로컬 브라우저/API 접근은 SSH 터널로 연결하는 걸 기본으로 삼았습니다. 기본 예제 상태에서는 대부분 인증이 없다는 점도 놓치면 안 됩니다.
워크스페이스 구축과 접속 경로가 정리됐으니, 이어지는 실측은 이 환경 위에 실제로 DeepSeek을 배포하고 API를 검증하는 과정입니다. 다음 글에서 다룹니다.