
스팀 패치 및 핫픽스 동적 패키징 자동화 파이프라인
변경된 콘텐츠만 배포하도록 빌드 산출물을 분리하고 SteamPipe 업로드와 베타 브랜치 검증을 자동화하는 방법을 정리합니다. Unity와 Unreal 프로젝트에 공통으로 적용할 수 있는 구조와 운영 원칙을 다룹니다.
왜 패치 파이프라인을 분리해야 할까
출시 뒤의 배포는 새 실행 파일을 올리는 일만으로 끝나지 않습니다. 코드 한 줄 수정, 데이터 테이블 조정, 대용량 리소스 변경은 배포 위험도와 플레이어가 받는 다운로드 크기가 서로 다릅니다. 이를 하나의 전체 패키지로 다루면 작은 핫픽스에도 빌드 시간이 길어지고 검증 범위가 불필요하게 넓어집니다.
여기서 동적 패키징은 변경의 성격과 대상 플랫폼에 맞춰 배포할 파일 묶음과 Steam depot 구성을 빌드 과정에서 결정하는 방식을 뜻합니다. SteamPipe는 이전 빌드와 비교해 변경된 청크를 전송하므로 전체 설치 파일을 매번 내려받게 하지는 않습니다. 다만 실행 파일과 대형 아카이브의 작은 변경도 청크 재사용률을 크게 낮출 수 있으므로 산출물 구조를 안정적으로 유지하는 편이 중요합니다.

목표 구조
파이프라인의 입력은 소스 커밋과 배포 요청입니다. 출력은 플랫폼별 패키지, 업로드된 SteamPipe 빌드, 검증 결과 그리고 승인된 브랜치의 라이브 전환입니다. 라이브 전환 자체는 되돌리기 어려운 운영 작업이므로 일반적으로 자동 업로드와 분리하고 승인 단계를 둡니다.
flowchart LR
A[태그 또는 배포 요청] --> B[빌드 및 테스트]
B --> C[산출물 매니페스트 생성]
C --> D{변경 분류}
D -->|핫픽스| E[코드·설정 depot 패키징]
D -->|일반 패치| F[전체 대상 depot 패키징]
E --> G[SteamPipe 업로드]
F --> G
G --> H[비공개 베타 브랜치]
H --> I[설치·실행·회귀 검증]
I --> J{승인}
J -->|예| K[기본 또는 공개 브랜치 전환]
J -->|아니오| L[빌드 폐기 또는 수정]
먼저 정할 것: depot 경계와 산출물 규칙
Steam의 depot은 설치 단위입니다. Windows 실행 파일, Linux 실행 파일, 공용 데이터, 선택 DLC처럼 수명과 플랫폼이 다른 파일을 분리하기 좋습니다. 반대로 자주 함께 바뀌는 작은 파일을 지나치게 많은 depot으로 나누면 설정과 테스트만 복잡해집니다.
권장하는 출발점은 다음과 같습니다.
- 플랫폼별 실행 파일과 네이티브 플러그인은 플랫폼 depot에 둡니다.
- 여러 플랫폼이 공유하는 데이터는 공용 콘텐츠 depot에 둡니다.
- 서버 주소, 밸런스 수치, 원격 설정처럼 작고 긴급하게 바뀔 수 있는 데이터는 별도 핫픽스 depot 또는 원격 구성으로 분리합니다.
- 에셋 번들, Unreal pak 파일처럼 대형 아카이브는 가능한 한 묶음 순서와 파일 경계를 안정적으로 유지합니다.
핫픽스 depot은 모든 문제를 해결하는 만능 수단이 아닙니다. 네이티브 코드, 직렬화 포맷, 저장 데이터 호환성, 초기화 순서가 바뀌는 수정은 핫픽스라는 이름이어도 전체 회귀 검증이 필요합니다. 또한 게임이 별도 depot의 파일을 실제로 우선 읽도록 구현되어 있어야 합니다.
매니페스트로 변경을 판정하기
패키징 스크립트가 Git 변경 목록만 보고 배포 범위를 정하면 위험합니다. 생성된 파일은 소스와 일대일 대응하지 않을 수 있고 빌드 도구 버전이 달라지면 광범위한 변경이 생길 수 있습니다. 배포 판단은 최종 산출물을 기준으로 해야 합니다.
각 빌드가 끝난 뒤 파일 경로, 크기, SHA-256, 소속 depot을 기록한 매니페스트를 만듭니다. 이전 승인 빌드의 매니페스트와 비교하면 어떤 depot을 재검증해야 하는지 명확해집니다.
다음은 개념을 보여 주는 매니페스트 예시입니다.
{
"buildId": "1.4.2+ci.381",
"files": [
{
"path": "Game_Data/StreamingAssets/hotfix/balance.json",
"sha256": "a1b2...",
"depot": "hotfix"
},
{
"path": "Game.exe",
"sha256": "c3d4...",
"depot": "windows"
}
]
}
판정 규칙은 보수적으로 시작하는 편이 안전합니다. 예를 들어 hotfix/ 아래의 JSON과 검증된 스크립트 데이터만 핫픽스 후보로 인정하고 실행 파일이나 공용 리소스가 바뀌면 일반 패치 경로로 보냅니다. 핫픽스 후보라도 파일 크기, 스키마 버전, 서명 검증에 실패하면 일반 패치 또는 배포 중단으로 승격해야 합니다.
SteamPipe VDF를 빌드마다 생성하기
SteamPipe는 app build 스크립트와 depot build 스크립트로 업로드 대상을 정의합니다. 사람이 VDF를 직접 수정하는 방식은 App ID, depot ID, 경로 실수를 만들기 쉬우므로 템플릿과 환경 변수에서 생성하는 편이 낫습니다.
아래 예시는 Windows 실행 파일 depot과 핫픽스 depot을 함께 올리는 app build VDF입니다. 실제 ID와 경로는 Steamworks 설정에 맞게 바꿔야 합니다.
"appbuild"
{
"appid" "1234560"
"desc" "1.4.2 hotfix ci.381"
"setlive" "internal"
"contentroot" "D:\\agent\\work\\staging"
"buildoutput" "D:\\agent\\work\\steampipe-output"
"depots"
{
"1234561" "depot_windows.vdf"
"1234562" "depot_hotfix.vdf"
}
}
핫픽스 depot은 필요한 경로만 매핑합니다. 이 규칙이 넓어지면 의도하지 않은 파일까지 배포될 수 있으므로 와일드카드보다 명시 경로를 우선합니다.
"DepotBuildConfig"
{
"DepotID" "1234562"
"FileMapping"
{
"LocalPath" "Game_Data\\StreamingAssets\\hotfix\\*"
"DepotPath" "Game_Data\\StreamingAssets\\hotfix\\"
"recursive" "1"
}
"FileExclusion" "*.psd"
"FileExclusion" "*.log"
}
CI에서는 스테이징 디렉터리를 매번 새로 만들고 게임 패키징 결과 중 선택된 depot의 파일만 복사한 뒤 VDF를 생성합니다. 이전 작업의 파일이 남아 있으면 삭제된 파일이 다음 패치에 남는 문제가 발생할 수 있습니다. 이 때문에 작업 공간을 재사용한다면 스테이징 디렉터리의 정리와 매니페스트 검증을 반드시 함께 수행해야 합니다.
자동화 단계 예시
실제 CI 도구는 달라도 단계는 거의 같습니다.
steps:
- checkout: release-tag
- run: build-client --platform windows
- run: run-unit-tests
- run: package-to-staging
- run: create-manifest --input staging --output manifest.json
- run: classify-release --current manifest.json --previous approved-manifest.json
- run: generate-steampipe-vdf --release-kind "$RELEASE_KIND"
- run: steamcmd +login "$STEAM_BUILD_USER" +run_app_build scripts/app_build.vdf +quit
- run: install-from-branch --branch internal
- run: smoke-test --build "$BUILD_ID"
- approval: promote-to-public
빌드 계정의 비밀번호나 인증 정보는 저장소의 YAML에 쓰지 말고 CI의 비밀 저장소에서 주입합니다. 이 계정에는 해당 앱을 빌드할 최소 권한만 부여하고 사람의 개인 Steam 계정을 공유 계정처럼 사용하지 않는 편이 좋습니다. Steam Guard가 필요한 환경에서는 비대화형 빌드가 가능한 인증 방식을 사전에 점검해야 합니다.
베타 브랜치에서 검증하는 방법
업로드 성공은 배포 성공이 아닙니다. Steam 클라이언트가 실제로 빌드를 내려받고 기존 설치에서 올바르게 갱신하는지 확인해야 합니다. 내부 베타 브랜치를 하나 만들고 필요하면 비밀번호로 보호한 뒤 다음을 자동 또는 반자동으로 검증합니다.
- 빈 환경에 설치한 뒤 실행한다.
- 이전 빌드가 설치된 환경에서 업데이트한 뒤 실행한다.
- 저장 데이터가 있는 상태에서 로드와 저장을 확인한다.
- 핫픽스 파일이 게임의 기본 데이터보다 우선 적용되는지 확인한다.
- 크래시 보고 버전 문자열, 매니페스트 버전이 같은 빌드를 가리키는지 확인한다.
특히 핫픽스 파일은 시작 화면에서만 읽고 캐시하는 구조라면 업데이트 후에도 반영되지 않을 수 있습니다. 게임 안에 현재 적용된 데이터 버전과 해시를 표시하거나 로그로 남기면 현장 확인 시간이 크게 줄어듭니다.

롤백과 운영 기준
문제가 확인되면 새 파일을 급히 다시 올리기보다 마지막 정상 빌드를 어느 브랜치에 연결할지 먼저 결정합니다. Steamworks의 빌드 관리 화면에서 검증된 이전 빌드를 브랜치에 다시 연결할 수 있도록 빌드 번호, Git 커밋, 콘텐츠 매니페스트, 배포 시각을 함께 보관합니다.
운영 기준도 코드로 남겨 두는 것이 좋습니다.
- 기본 브랜치 전환은 승인된 파이프라인만 수행한다.
- 핫픽스는 허용 경로와 데이터 스키마를 검사한다.
- 모든 업로드에는 사람이 읽을 수 있는 설명과 변경 목록을 남긴다.
- 배포 뒤에는 설치 성공, 실행 성공, 크래시 지표를 정해진 시간 동안 확인한다.
- 롤백은 새 빌드 생성보다 이전 검증 빌드의 브랜치 전환을 우선한다.
마무리
좋은 스팀 패치 자동화의 핵심은 업로드 명령 하나가 아니라 산출물의 경계와 검증 가능한 판단 근거입니다. 파일 해시 기반 매니페스트, 생성형 VDF, 내부 베타 검증, 승인된 브랜치 전환을 연결하면 작은 데이터 수정은 빠르게 처리하면서도 실행 파일과 대형 콘텐츠 변경에는 필요한 검증 시간을 확보할 수 있습니다.
SteamPipe의 정확한 VDF 키와 브랜치 운영 권한은 Steamworks 설정 및 SDK 버전에 따라 달라질 수 있으므로 배포 파이프라인을 적용하기 전에는 Steamworks의 Uploading to Steam 문서와 현재 앱의 depot 설정을 함께 확인하는 것이 안전합니다.


