Git LFS 비용 폭탄과 언리얼 에셋 충돌을 해결하는 Lore VCS 이행 가이드
TuBrief 편집팀
2026년 7월 14일
0
컴퓨터/소프트웨어원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
커뮤니티의 다른 글
댓글 (0)
Log in to leave a comment
아직 작성된 글이 없습니다
원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
Log in to leave a comment
아직 작성된 글이 없습니다
프로젝트가 커지면 Git LFS는 재앙으로 변합니다. 소스코드 몇 줄 고치는 건 순식간인데, 기가바이트 단위의 아트 에셋이 섞이기 시작하면 커밋 한 번에 수십 초씩 모래시계가 돕니다. 대형 파일을 통째로 복사해서 쌓아두는 LFS의 둔한 구조 탓에, 저장소 용량은 금세 테라바이트를 넘기고 대역폭 과금 고지서에는 무서운 숫자가 찍힙니다.
에픽게임즈가 오픈소스로 공개한 Lore는 이진 파일을 최우선으로 다룹니다. 파일을 블록 단위로 쪼개 중복을 제거하는 FastCDC 방식을 사용해 패키지 용량과 전송 대역폭을 획기적으로 줄여줍니다. 데브옵스 전문 인력이 없는 소규모 팀이라도 당장 적용할 수 있는 Lore 실무 마이그레이션과 최적화 방법을 정리했습니다.
기존 Git 저장소에 쌓인 소스코드 커밋 히스토리를 굳이 버릴 필요는 없습니다. 가벼운 코드는 Git에 그대로 두고, 무거운 이진 에셋만 Lore 저장소로 떼어내는 하이브리드 전략이 현실적입니다.
아래 스크립트는 Git LFS가 추적하던 파일 목록을 식별해 대칭 디렉터리 구조를 만들고, 복사본의 SHA-256 해시를 대조해 데이터 누락 없이 Lore로 이전합니다.
#!/usr/bin/env bash
set -euo pipefail
GIT_REPO_DIR="$HOME/projects/my-game-git"
LORE_REPO_DIR="$HOME/projects/my-game-lore"
LORE_SERVER_URL="lore://127.0.0.1:41337/my-project"
echo "[1/5] Lore 저장소 초기화 및 원격 바인딩..."
if [ ! -d "$LORE_REPO_DIR" ]; then
mkdir -p "$LORE_REPO_DIR"
cd "$LORE_REPO_DIR"
lore repository create "$LORE_SERVER_URL"
else
cd "$LORE_REPO_DIR"
fi
echo "[2/5] Git LFS 추적 파일 목록 수집..."
cd "$GIT_REPO_DIR"
LFS_FILES=$(git lfs ls-files -n | grep -E "\.(uasset|umap|fbx|png|psd)$" || true)
if [ -z "$LFS_FILES" ]; then
echo "이전할 LFS 파일이 없습니다."
exit 0
fi
echo "[3/5] 파일 복사 및 검증용 매니페스트 생성..."
echo "$LFS_FILES" | while read -r filepath; do
if [ -f "$filepath" ]; then
dest_dir="$LORE_REPO_DIR/$(dirname "$filepath")"
mkdir -p "$dest_dir"
cp -p "$filepath" "$LORE_REPO_DIR/$filepath"
source_hash=$(openssl dgst -sha256 "$filepath" | awk '{print $2}')
echo "$filepath:$source_hash" >> "$LORE_REPO_DIR/.lore_migration_manifest"
fi
done
echo "[4/5] Git LFS 해제 및 Lore 스테이징..."
cd "$GIT_REPO_DIR"
echo "$LFS_FILES" | while read -r filepath; do
git rm --cached "$filepath"
done
sed -i.bak -E 's/filter=lfs diff=lfs merge=lfs//g' .gitattributes
cd "$LORE_REPO_DIR"
echo "$LFS_FILES" | while read -r filepath; do
lore stage "$filepath"
done
lore commit -m "Migration: Transfer heavy assets from Git LFS to Lore"
lore push
echo "[5/5] 데이터 무결성 검증..."
lore repository verify state
lore repository verify fragment
if [ -f ".lore_migration_manifest" ]; then
migration_errors=0
while IFS=":" read -r file sha; do
if [ -f "$file" ]; then
current_hash=$(openssl dgst -sha256 "$file" | awk '{print $2}')
if [ "$sha" != "$current_hash" ]; then
echo "오염된 파일 감지: $file"
migration_errors=$((migration_errors + 1))
fi
fi
done < .lore_migration_manifest
if [ $migration_errors -eq 0 ]; then
echo "이전 완료. 모든 데이터가 100% 무결하게 복구되었습니다."
rm .lore_migration_manifest
else
echo "검증 실패: $migration_errors 건의 파일 무결성에 문제가 있습니다."
exit 1
fi
fi
터미널을 열고 위 내용을 migrate.sh로 저장합니다. chmod +x migrate.sh 명령어로 실행 권한을 준 뒤, 본인의 로컬 경로에 맞게 변수를 수정해 실행하면 됩니다.
이 작업을 마치면 원격 클라우드 LFS 스토리지 사용량이 즉각 줄어듭니다. 에픽게임즈의 자체 도입 사례에 따르면 이 블록 수준 중복 제거 기술을 통해 인프라 유지 비용을 50% 수준으로 절감할 수 있습니다.
매 빌드 주기마다 수백 기가바이트짜리 전체 게임 에셋을 새로 내려받는 파이프라인은 네트워크 카드와 디스크 입출력을 망가뜨리는 주범입니다. Lore는 빌드 시간을 단축하기 위해 가상 파일 시스템 기반의 지연 복구(On-demand Hydration)를 지원합니다.
최초 클론 단계에서는 메타데이터 구조 체인과 디렉터리 트리만 껍데기 형태로 복제하고, 컴파일러가 조리(Cook) 과정에서 실제 에셋을 읽어 들일 때 필요한 바이너리 청크만 동적으로 스트리밍해 디스크에 채우는 방식입니다.
name: Game Project On-Demand Production Build
on:
push:
branches: [ release-candidate ]
env:
LORE_SERVER: "lore://10.0.1.50:41337/game-depot"
SHARED_STORE_PATH: "/var/lib/lore_shared_chunk_store"
WORKSPACE_PATH: "game_build_workspace"
jobs:
assemble-assets:
runs-on: self-hosted
steps:
- name: Persistent Shared Store 준비
run: |
if [ ! -d "${{ env.SHARED_STORE_PATH }}" ]; then
sudo mkdir -p "${{ env.SHARED_STORE_PATH }}"
sudo chmod 777 "${{ env.SHARED_STORE_PATH }}"
lore shared-store create "${{ env.SHARED_STORE_PATH }}"
fi
- name: Shared Cache를 경유한 Sparse Bare Clone
run: |
lore clone \
--bare \
--use-shared-store \
--shared-store-path "${{ env.SHARED_STORE_PATH }}" \
"${{ env.LORE_SERVER }}" \
"${{ env.WORKSPACE_PATH }}"
- name: 뷰 필터를 통한 불필요한 시네마틱 소스 제외
run: |
cd "${{ env.WORKSPACE_PATH }}"
echo "+ /SourceCode/**" > .lore/view
echo "+ /Config/**" >> .lore/view
echo "+ /Content/Core_Assets/**" >> .lore/view
echo "- /Content/Cinematic_RAW/**" >> .lore/view
- name: 필수 청크만 로컬 디스크에 동기화
run: |
cd "${{ env.WORKSPACE_PATH }}"
lore sync
- name: Unreal Engine Cooker 실행
run: |
cd "${{ env.WORKSPACE_PATH }}"
./RunUAT.sh BuildCookRun \
-project="$(pwd)/GameProject.uproject" \
-platform=Win64 \
-clientconfig=Development \
-cook -stage -pak -archive
빌드 전용 서버에 /var/lib/lore_shared_chunk_store 같은 영구 캐시 저장소를 마련해 두면 효과가 극대화됩니다. lore clone --bare 명령어로 인덱스 정보만 빠르게 가져온 뒤, .lore/view 필터 파일에 꼭 필요한 경로만 남겨 두고 lore sync를 때립니다. 이 구조를 정착시키면 빌드 노드로 전송되는 트래픽이 평소 대비 85% 이상 사라집니다. 전체 빌드 시간은 평균 30%가량 단축됩니다.
언리얼 엔진의 .uasset이나 레벨 맵 파일 같은 바이너리 에셋은 텍스트 코드처럼 메인 브랜치에서 자동으로 병합할 수 없습니다. 두 아티스트가 같은 에셋을 동시에 수정하면, 나중에 푸시한 아티스트가 앞사람의 작업을 덮어씌워 날리거나 타임라인이 꼬이는 사고가 일어납니다.
Lore는 원격 서버의 변경 불가능한 원장을 기준으로 배타적 제어를 수행하는 잠금(Lock) 기능을 직접 제공합니다.
# 특정 바이너리 캐릭터 모델 파일에 단독 편집 권한 요청
lore lock acquire Content/Characters/HeroMesh.uasset --branch main
# 특정 폴더 하위 리소스들의 잠금 소유 상태 확인
lore lock status Content/Characters/HeroMesh.uasset
# 원격 저장소에서 특정 작업자가 잠근 전체 파일 검색
lore lock query --branch main --owner developer_artist_03
# 작업 완료 및 푸시 후 권한 반납
lore lock release Content/Characters/HeroMesh.uasset --branch main
아티스트가 파일을 손대기 전에 lore lock acquire 명령어로 락을 점유하게 만드는 규칙을 세워야 합니다. 수정이 끝나고 커밋과 푸시가 원격지에 무사히 반영되면 lore lock release로 락을 풀어 다음 작업자에게 넘깁니다.
기획자와 아티스트들이 터미널 명령어를 어색해한다면 Anchorpoint 같은 데스크톱 GUI 툴에 해당 경로를 연동해 마우스 우클릭 버튼 클릭만으로 이 잠금 명령어들이 실행되도록 환경을 꾸며주면 됩니다.
작업 환경의 사양에 맞춰 클라이언트 설정을 조정해야 파일 입출력 병목 현상을 방지할 수 있습니다.
--direct-file-write 및 --direct-file-io 플래그를 켜고, 가비지 컬렉션 스케줄 간격을 늘려서 작업 중 뜬금없는 디스크 선점 현상을 방지합니다.Lore 아키텍처 결정 회의(ADR-00016) 결과를 참고하면, 기본 압축 엔진으로 Zstandard Level 6 규격을 설정하는 것이 효율성 면에서 균형이 가장 잘 맞습니다.
| 압축 알고리즘 종류 | 데이터 최종 압축률 (%) | 압축 연산 속도 (MiB/s) | 압축 해제 속도 (MiB/s) | 이식성 및 특징 |
|---|---|---|---|---|
| LZ4 Default | 47.6% | 718.7 | 2494.5 | 속도는 빠르나 스토리지 용량 낭비가 큼 |
| Zstd Level 1 | 34.5% | 602.0 | 1363.1 | 속도와 용량 보존의 준수한 타협점 |
| Zstd Level 6 (권장) | 28.9% | 136.5 | 1284.9 | 공간 절약 대비 최상의 처리 효율 유지 |
| Oodle Kraken 3 (Fast) | 28.2% | 95.6 | 1413.1 | 에픽게임즈 독점 Oodle 종속 라이브러리 필요 |
| Oodle Kraken 6 (기존 기본) | 23.9% | 2.2 | 1312.6 | 기가바이트 단위 이전 시 속도가 심하게 저하됨 |
기존에 자주 쓰이던 Oodle Kraken Level 6는 백엔드 직렬화 과정에서 압축 처리 속도가 초당 2.2 MiB 수준으로 내려앉아 아티스트들의 퇴근 전 커밋 대기 시간을 늘리는 주원인이었습니다.
반면 Zstd Level 6는 Oodle Kraken 6에 육박하는 압축률을 내면서도 로컬 청크 블록 압축 속도가 136.5 MiB/s로 약 62배 빠릅니다. 해외 지사나 재택근무자가 많아 대역폭 간섭이 심하다면 로컬 네트워크 내에 프록시 에지 캐시 노드를 구성하는 2계층 서버 토폴로지 구성을 검토해 보길 바랍니다.