GPU 클러스터 대신 Job 하나: Gemma 4 커스터마이징이 서버리스로 넘어가는 순간
Gemma 4 같은 대형 open model을 다루는 일은 더 이상 거대한 GPU 클러스터의 전유물이 아니다. Cloud Run Jobs와 RTX 6000 Pro 조합은 fine-tuning의 진입장벽을 낮추지만, 메모리 전략·LoRA 설정·체크포인트 운영 같은 실무 함정은 더 선명하게 드러낸다.
대형 open model의 미세조정은 오랫동안 인프라 조직의 일처럼 보였다. GPU를 몇 장 묶을지, 드라이버와 CUDA 버전을 어떻게 맞출지, 학습이 멈췄을 때 어느 노드에서 체크포인트가 손상됐는지부터 확인하는 풍경이 너무 익숙했기 때문이다. 그런데 Gemma 4 같은 최신 계열을 다루는 이야기가 Cloud Run Jobs와 RTX 6000 Pro 한 장으로 흘러가기 시작하면, 바뀌는 것은 비용 구조만이 아니다. 학습의 진입장벽이 내려가는 대신, 그동안 클러스터 복잡도에 가려져 있던 더 본질적인 문제가 앞으로 튀어나온다. 어떤 파라미터를 정말 학습시킬 것인가, 메모리는 어디서 새고 있는가, 재시도와 체크포인트는 어떤 실패를 가정해야 하는가 같은 질문들이다.
클러스터를 없앴더니 오히려 설계가 더 선명해졌다
서버리스 GPU가 주는 첫인상은 간단하다. 오래 켜 두는 머신 대신, 배치 단위의 학습 작업이 필요할 때만 Job을 올리고 끝나면 내린다. 관리해야 할 VM 풀도 없고, 오토스케일 정책을 따로 설계하지 않아도 된다. 학습이 웹 요청처럼 짧지 않더라도, “한 번 실행해서 끝나는 일”이라는 점에서는 오히려 서버리스와 잘 맞는 편이다.
흥미로운 지점은 여기서부터다. 인프라가 단순해지면 모델 자체의 제약이 더 적나라하게 보인다. 이전에는 분산 학습, 스토리지 병목, 쿠버네티스 스케줄링 같은 문제가 전면에 있었다. 이제는 “이 모델을 이 정밀도로 올리면 실제로 남는 VRAM이 얼마인지”, “LoRA target을 어디까지 넓혀야 멀티모달 적응이 되는지”, “이미지와 텍스트가 섞인 입력에서 label masking이 어긋나지 않는지”가 훨씬 중요한 질문이 된다. 서버리스는 학습을 쉽게 만든다기보다, 무엇이 진짜 어려운지 숨기지 않게 만든다.
96GB라는 숫자는 여유가 아니라 선택지를 뜻한다
RTX 6000 Pro급 메모리를 보면 많은 팀이 곧바로 “그럼 이제 full fine-tuning도 가능하겠네”라고 생각한다. 하지만 대형 모델에서 메모리 계산은 단순히 가중치 크기만 보는 문제가 아니다. 학습 시점의 VRAM은 모델 weight, optimizer state, gradient, activation이 동시에 잡아먹는다. 여기에 멀티모달이면 이미지 토큰과 그에 따른 activation 부담이 더해진다. 긴 context나 큰 batch를 살짝만 욕심내도 체감은 순식간에 달라진다.
그래서 실제 선택지는 대체로 두 갈래로 갈린다. 품질 최대화를 노리되 메모리를 압축하는 QLoRA 경로, 혹은 정밀도 손실을 줄이는 대신 더 작은 계열이나 더 얕은 adapter 범위를 택하는 경로다. 96GB는 “무조건 넉넉하다”는 뜻이 아니라, “이제부터는 무엇을 보존하고 무엇을 포기할지 선택할 수 있다”는 뜻에 가깝다. 이전 세대의 24GB, 48GB 환경에서는 선택이라기보다 체념에 가까웠다.
이 차이는 운영 현실에서도 크게 느껴진다. 메모리가 빠듯한 환경에서는 OOM이 사고처럼 온다. 96GB급 단일 GPU에서는 OOM이 사고라기보다 설계의 피드백이 된다. batch를 조금 줄이거나 gradient checkpointing을 켜는 선에서 끝날 수도 있고, 아예 vision tower까지 학습시키려던 생각을 접어야 할 수도 있다. 중요한 것은 이 피드백이 훨씬 빠르고 명확해졌다는 점이다.
멀티모달 미세조정은 텍스트 LoRA의 습관으로 접근하면 자주 삐끗한다
Gemma 4 계열의 매력은 reasoning과 긴 문맥만이 아니다. 이미지, 경우에 따라서는 오디오까지 같은 계열 안에서 다룰 수 있다는 점이 실무적으로 크다. 문제는 이 순간부터 텍스트 전용 SFT 감각이 함정이 된다는 것이다.
텍스트 중심 작업에서는 대개 q_proj, v_proj 같은 익숙한 target만 잡아도 그럭저럭 결과가 나온다. 하지만 멀티모달에서는 “언어 쪽만 건드려도 되겠지”라는 가정이 자주 틀린다. 분류처럼 보이는 과제라도 실제로는 vision representation과 language head 사이의 연결부를 같이 조정해야 성능이 움직인다. 이미지가 들어오는데 눈은 그대로 두고 말하는 방식만 바꾸는 셈이기 때문이다.
이 지점에서 all-linear 같은 넓은 target 전략이 다시 등장한다. 예전에는 이런 선택이 다소 투박하게 보였다. 메모리를 아끼기 위해 최대한 surgical하게 target을 좁히는 것이 미덕처럼 여겨졌기 때문이다. 그런데 멀티모달 대형 모델에서는 오히려 반대가 된다. 너무 좁게 잡으면 “학습은 도는데 결과는 안 좋아지는” 상태가 생긴다. 특히 custom wrapper가 들어간 projection layer, vision tower 내부 선형층, modality bridge 같은 부분이 빠지면 손실 곡선만 보고는 이유를 알아채기 어렵다.
즉, 서버리스 GPU가 가져온 변화는 단지 더 싼 실행 환경이 아니라, adapter 설계의 기준 자체를 바꿔 놓는 쪽에 가깝다. 이제 질문은 “얼마나 적게 학습시킬까”가 아니라 “어디를 빼면 실제 적응이 깨지는가”가 된다.
품종 분류 예제가 사소해 보이지만, 사실은 꽤 좋은 시험대다
반려동물 품종 분류는 얼핏 보면 데모용 과제처럼 보인다. 더 거창한 비즈니스 문제, 예를 들어 의학 이미지 판독 보조나 산업 설비 이상 탐지 같은 장면과 비교하면 너무 가볍게 들린다. 그런데 이런 예제가 가지는 장점이 있다. 시각적 구분이 미묘하고, 정답이 비교적 명확하며, 성능 변화가 수치로 드러나기 쉽다는 점이다.
이런 과제는 멀티모달 미세조정의 세 가지 층위를 동시에 드러낸다. 첫째, base checkpoint 자체가 이미 상당한 분류 능력을 가지고 있는지. 둘째, adapter를 얹었을 때 vision 쪽 적응이 실제로 일어나는지. 셋째, prompt template, masking, 데이터 정렬 같은 사소해 보이는 구현 차이가 결과를 얼마나 흔드는지. 품종 분류는 그래서 “모델이 똑똑한가”보다 “파이프라인이 정렬되어 있는가”를 검증하기 좋은 과제다.
실무에서 이 감각은 그대로 이어진다. 문서 이미지 분류, 상품 사진 태깅, 결함 탐지처럼 겉보기에는 단순한 과제들도 대부분 동일한 함정에 빠진다. baseline이 이미 높기 때문에 gains는 작아 보이지만, 작은 gain이 실제 서비스에서는 false positive와 false negative의 분포를 꽤 바꿔 놓는다. 특히 카테고리 수가 많고 클래스 간 시각적 차이가 미세할수록 더 그렇다.
자주 터지는 문제는 학습 코드가 아니라 입력 경계에서 시작된다
멀티모달 학습이 생각보다 자주 실패하는 이유는 대개 거창하지 않다. 모델 구조를 몰라서가 아니라, 입력을 만드는 방식이 아주 조금 어긋났기 때문이다. 이미지가 먼저 와야 하는 템플릿인데 텍스트를 앞에 둔다든지, chat template를 적용한 뒤 assistant 응답의 시작 위치를 잘못 계산한다든지, label masking을 문자열 길이 기준으로 단순 처리한다든지 하는 실수다.
이런 문제는 손실이 폭발하는 식으로만 나타나지 않는다. 더 위험한 경우는 학습이 멀쩡히 도는 것처럼 보이는데 실제로는 프롬프트 일부까지 정답으로 학습하고 있는 상태다. 로그만 보면 step도 진행되고 eval도 숫자가 나온다. 그런데 정작 결과는 설명이 안 되는 방향으로 흔들린다. 예측이 장황해지거나, 분류 문제인데 문장 스타일만 과하게 따라 하거나, 특정 라벨에 비정상적으로 쏠린다.
원인은 단순하다. 멀티모달 템플릿에서는 눈에 보이지 않는 special token과 media token이 텍스트 길이 감각을 쉽게 배반한다. 특히 이미지 토큰이 가변적으로 들어가면 “프롬프트 길이를 미리 계산해 잘라내는 방식”이 깨지기 쉽다. 이때 필요한 것은 더 복잡한 수식이 아니라, 실제 input_ids 안에서 assistant span의 시작을 역으로 찾아 label을 거는 식의 보수적인 처리다. 학습은 화려한 optimizer보다 이런 경계 처리에서 품질이 갈린다.
Cloud Run Jobs는 편리한 런타임이 아니라 실패 모델이 다른 런타임이다
배치 학습을 Job으로 올리는 방식은 실행 경험을 바꾼다. 하지만 더 중요한 변화는 실패를 해석하는 방식이다. 상시 서버 환경에서는 프로세스가 살아 있는 동안 많은 것을 당연하게 여긴다. 로컬 디스크에 중간 결과를 두고, 재시작 없이 epoch를 길게 끌고 가며, 장애를 “그 노드가 불안정했다” 정도로 이해한다.
반면 Job 중심 환경에서는 매 실행이 독립 사건이다. 컨테이너 파일시스템은 영속 저장소가 아니고, 재시도는 이전 상태를 이어받지 못할 수 있으며, 중간 체크포인트를 언제 어디에 flush할지 명확히 설계해야 한다. 이 때문에 서버리스 GPU 학습은 인프라가 아니라 체크포인트 철학을 바꾸게 만든다. epoch 끝에 한 번 저장하는 습관은 위험해지고, “잃어도 되는 step 수”를 먼저 정한 뒤 저장 간격을 계산하는 편이 더 현실적이 된다.
짧은 예시는 이런 식이 된다.
gcloud run jobs create gemma4-ft \ --image=REGION-docker.pkg.dev/PROJECT/repo/train:latest \ --region=REGION \ --gpu=1 \ --gpu-type=nvidia-rtx-pro-6000 \ --cpu=20 \ --memory=80Gi \ --no-gpu-zonal-redundancy \ --add-volume name=ckpt,type=cloud-storage,bucket=MODEL_BUCKET \ --add-volume-mount volume=ckpt,mount-path=/mnt/checkpoints
이 설정에서 중요한 것은 GPU를 붙였다는 사실보다, 체크포인트의 생존 위치를 컨테이너 밖으로 강제했다는 점이다. 학습 환경이 ephemeral할수록 저장 전략은 선택이 아니라 기본 조건이 된다.
LoRA rank는 성능 레버인 동시에 비용 레버다
실무에서 많이 놓치는 대목은 LoRA 설정이 단지 품질 관련 hyperparameter가 아니라는 사실이다. r, alpha, dropout, target 범위는 곧바로 메모리 사용량과 학습 안정성, 실행 시간을 건드린다. 특히 멀티모달에서 rank를 조금만 올려도 “표현력이 늘었다”는 장점과 “학습 surface가 커져 과적합과 메모리 압박이 빨라진다”는 단점이 같이 온다.
그래서 단일 GPU 환경에서 현실적인 출발점은 대개 극단이 아니다. 너무 낮은 rank는 vision adaptation이 잘 안 붙고, 너무 높은 rank는 서버리스의 장점인 빠른 실험 회전을 해친다. 더구나 baseline이 이미 높은 최신 open model에서는 gain의 크기보다 gain의 방향이 중요하다. 정확도 평균이 조금 오르는 것보다, 특정 class에서 반복되던 오판 패턴이 사라지는지가 더 의미 있을 수 있다.
여기서 설계 판단은 자연스럽게 “최고 점수”보다 “가장 덜 놀라운 운영 결과”를 향하게 된다. 즉, 검증 데이터에서 한 번 반짝하는 설정보다, 다른 샘플 분포와 다른 배치 크기에서도 결과가 덜 흔들리는 설정이 낫다. 클러스터가 아닌 Job 하나로 학습할 수 있게 되면, 오히려 이런 보수적인 판단이 더 중요해진다. 누구나 쉽게 실행할 수 있기 때문에, 누구나 쉽게 과신할 수도 있기 때문이다.
운영에서 먼저 보이는 신호는 정확도가 아니다
학습이 끝난 뒤 운영에서 가장 먼저 눈에 들어오는 것은 보통 accuracy가 아니다. 컨테이너 시작 시간이 길어졌는지, 모델 로딩이 매 실행마다 흔들리는지, 체크포인트 쓰기 시간이 step 시간보다 길어졌는지, GPU 메모리 사용량이 특정 구간에서 비정상적으로 솟는지 같은 신호들이다. 이 신호들은 나중에 품질 문제로 번진다.
예를 들어 startup 시간이 길어지면 작은 실험 반복이 느려지고, 이는 결국 hyperparameter 탐색 폭을 줄인다. 체크포인트 flush가 병목이면 저장 간격을 넓히게 되고, 그 순간 재시도 비용이 커진다. GPU 메모리 사용량이 step 후반부에서만 급증하면 데이터셋 특정 샘플의 해상도나 토큰 길이가 분포를 깨고 있을 가능성이 있다. 이런 패턴은 “모델이 느리다”가 아니라 “데이터와 런타임 가정이 충돌한다”는 신호다.
서버리스 환경은 이런 신호를 더욱 또렷하게 만든다. 인스턴스를 오래 붙잡아 두지 않기 때문에 평균으로 흐려지는 것이 적다. 한 번의 실행이 하나의 실험이고, 실패도 더 discrete하게 관찰된다. 그래서 운영 지표를 보면 모델의 품질보다 파이프라인의 성숙도가 먼저 드러난다.
결국 바뀌는 것은 미세조정의 민주화가 아니라 의사결정의 위치다
Gemma 4 같은 계열을 단일 서버리스 GPU로 다룰 수 있다는 사실은 분명 상징적이다. 이제 대형 open model의 커스터마이징이 특정 규모의 인프라를 가진 조직만의 영역은 아니다. 하지만 더 중요한 변화는 다른 곳에 있다. 과거에는 “할 수 있느냐”가 문제였다면, 이제는 “어디에 적응을 걸고 무엇을 운영 위험으로 볼 것이냐”가 문제다.
이 변화는 좋은 소식이면서 불편한 소식이기도 하다. 좋은 이유는, 진입장벽이 인프라에서 설계 감각으로 이동했기 때문이다. 불편한 이유는, 설계 감각은 GPU를 더 사는 것으로 해결되지 않기 때문이다. 멀티모달 입력 순서, masking 경계, LoRA target, checkpoint 전략, 재시도 모델 같은 문제는 모두 작은 차이로 보이지만 결과를 크게 가른다.
서버리스로 넘어가는 순간은 결국 “클러스터가 필요 없어진다”는 선언이 아니다. 오히려 그 반대다. 거대한 인프라가 대신 숨겨주던 복잡성이 사라지면서, 어떤 모델을 어떤 방식으로 조정해야 하는지가 더 선명해진다. 그래서 Job 하나로 끝내는 시대의 경쟁력은 GPU 개수가 아니라, 단일 실행 안에 어떤 판단을 담아내느냐에서 나온다. Gemma 4의 미세조정이 흥미로운 이유도 바로 거기에 있다. 이제 어려운 것은 장비를 구하는 일이 아니라, 단순해진 런타임 위에서 복잡한 선택을 제대로 하는 일이다.
같이 읽으면 좋은 글
같은 주제이거나 태그가 겹치는 글을 연결해 탐색 흐름을 강화했습니다.
GPU 한 대로 끝내는 멀티모달 미세조정의 현실
Gemma 4와 serverless GPU 조합은 대형 멀티모달 모델 fine-tuning의 진입장벽을 낮춘다. Cloud Run Jobs, QLoRA, LoRA 타깃 전략, VRAM 관리까지 함께 짚으며 실전 적용 시의 기대와 함정을 균형 있게 풀어낼 글에 어울리는 메타데이터다.
Q, Slim LLM CLI를 실무에 붙이는 법: 터미널 AI 보조도구를 작게 시작해 크게 쓰기
터미널에서 바로 쓰는 slim LLM CLI는 개발자의 질문, 에러 분석, 최근 세션 컨텍스트 활용을 빠르게 묶어준다. 이 글은 최소한의 설정으로 도입하는 방법, redaction과 provider 분리, 로그 범위 조절, 흔한 보안 함정까지 실무 관점에서 정리하는 deep dive 가이드다.
netdata/netdata: lean team을 위한 AI-powered observability, 어디까지 바로 쓸 수 있나
`netdata/netdata` 신호를 바탕으로, 복잡한 구축 없이 실시간 full stack observability를 시작하려는 개발팀 관점에서 도입 포인트를 정리한 글이다. per-second metrics, auto discovery, edge 기반 분석, 운영 함정과 체크리스트까지 FAQ 형식으로 다룬다.
이전 글
GPU 한 대로 끝내는 멀티모달 미세조정의 현실
댓글
불러오는 중…