기사

Unity 워크플로 확장: 중대형 프로젝트에서 얻은 교훈

MATTHEW WOJTECHKO / MEGA CAT STUDIOSLead Game Developer
Mar 31, 2026
Mega Cat Studios와 Playground Productions의 Backyard Baseball
이 웹페이지는 이해를 돕기 위해 기계 번역으로 제공됩니다. 기계 번역으로 제공되는 콘텐츠에 대한 정확도나 신뢰도는 보장되지 않습니다. 번역된 콘텐츠의 정확도에 관해 의문이 있는 경우 웹페이지의 공식 영어 원문을 참고해 주시기 바랍니다.

이 블로그 게시물은 Mega Cat Studios에서 Unity 전문 지식과 실제 상업용 게임 개발 과제에 대한 솔루션을 공유하는 시리즈의 첫 번째 글입니다. 입력, 레벨 및 환경 디자인을 다루는 이 시리즈의 다른 게시물도 확인해 보세요:

좋은 팁을 많이 얻어가시길 바랍니다!

멋진 아이디어가 떠오르고, 코드가 타이핑하는 속도만큼 빠르게 작성됩니다. 커밋할 때마다 새로운 기능이 구체화됩니다. 하지만 아이디어가 형성되는 바로 그 속도 때문에 곧 크고 버그가 많은 엉망진창인 상태를 마주하게 될 수도 있습니다.

Mega Cat Studios에서는 모든 프로젝트를 열정으로 시작하기 때문에, 빠르게 진행하며 가능한 한 빨리 작업을 완료하려는 유혹을 잘 이해하고 있습니다. 프로토타입 단계에서는 이러한 접근 방식이 괜찮으며, 사실 저희는 이를 권장합니다! 현명한 개발자는 반복 속도를 우선시해야 할 때와 안정성을 우선시해야 할 때를 알고 있습니다. 프로토타입 단계를 벗어나면 그러한 "빠르고 자유로운" 접근 방식은 부채가 되기 때문입니다.

저희는 Mega Cat Studios에서 이러한 전환을 여러 번 겪었으며, 모든 프로젝트를 통해 새로운 것을 배웁니다. 최근 프로젝트인 Backyard Baseball를 실행 준비하는 과정에서 얻은 교훈 중 일부를 공유하고자 합니다.

교훈 1: 확장을 위한 구조

씬의 프리팹 계층 구조는 명확하게 정의된 그룹과 부모 프리팹으로 구성되어 있어, 내비게이션이 쉽고 효율적인 수정이 가능합니다.
씬의 프리팹 계층 구조는 명확하게 정의된 그룹과 부모 프리팹으로 구성되어 있어, 내비게이션이 쉽고 효율적인 수정이 가능합니다.

확장성 문제는 잘못된 코드보다는 계획되지 않은 아키텍처로 인해 발생하는 경우가 더 많습니다. 개발자나 아티스트가 10초 안에 에셋을 찾을 수 없다면 워크플로를 변경해야 합니다. 프로젝트를 확장하기 위해 설정하는 몇 가지 팁은 다음과 같습니다:

  • 유형 및 목적별 정리: 유형별로 그룹화한 다음 목적별로 그룹화합니다. 유형에는 아트, 코드, 오디오와 같은 범주가 포함됩니다. 목적은 그것들이 사용되는 용도입니다. 직관적인 정리는 온보딩 마찰을 줄여줍니다. 새로운 아티스트는 "캐릭터 대기 상태" 스프라이트가 어디에 속하는지 질문할 필요 없이 정확히 알아야 합니다.
  • 씬을 단순하게 유지: 우리는 "메가 씬"을 버리고 대신 더 작은 씬을 선택합니다. 예를 들어, 저장 데이터와 중요 시스템을 보관하는 메인 씬과 함께 타이틀 화면, 그리고 플레이어가 경기 중인지 여부에 따라 가산적으로 로드되는 야구장 씬 등이 있습니다. 마찬가지로, 독립형 기능에는 프리팹을 사용하여 변경 사항이 해당 기능을 포함하는 씬 파일에 직렬화될 가능성을 줄입니다. 이를 통해 아티스트는 환경 작업을 수행하고 디자이너는 동일한 "레벨"에서 게임플레이를 조정할 수 있어 파일 충돌이 발생하지 않습니다(자세한 내용은 나중에 설명).
  • Addressables 시스템 설정: 기존의 리소스 폴더 대신 Addressables 시스템을 사용하여 필요할 때만 에셋을 로드함으로써 메모리 사용량을 적게 유지합니다. 또한, Addressables 키로 에셋을 로드하는 것이 리소스 폴더의 특정 위치에 대한 파일 경로를 통해 로드하는 것보다 더 명확하고 오류가 발생할 가능성이 적습니다.

어려운 점은 이러한 모범 사례를 이해하는 것이 아닙니다. 시작할 때 이를 약속하고 몇 년이 지난 후에도 그 원칙을 유지하는 것입니다.

현재 개발의 어느 단계에 있는지, 그리고 그 단계에서 무엇을 우선시하고 있는지 파악하십시오.

Backyard Baseball의 개발자인 Paolo Roxas는 "프로토타이핑 단계에서는 코드가 거의 없기 때문에 모듈식으로 만들기 전에 먼저 기능을 구현하는 것이 괜찮습니다"라고 말합니다. "우리는 프로젝트를 더 복잡하게 만들기 전에 어떻게 진행되는지 확인하고 싶습니다."

playable 캐릭터, 게임 모드, 생동감 넘치는 환경 등 Backyard Baseball의 방대한 규모로 인해 훌륭한 아키텍처가 필수적이었습니다.
playable 캐릭터, 게임 모드, 생동감 넘치는 환경 등 Backyard Baseball의 방대한 규모로 인해 훌륭한 아키텍처가 필수적이었습니다.

레슨 2: Unity와 대립하지 말고 협력하세요

작고 집중된 고려 사항과 작업이 결합되어 복잡한 필딩 결정을 형성합니다. \"갓\" 스크립트는 없으며, 조화롭게 작동하는 구성 가능한 빌딩 블록만 있을 뿐입니다.
작고 집중된 고려 사항과 작업이 결합되어 복잡한 필딩 결정을 형성합니다. \"갓\" 스크립트는 없으며, 조화롭게 작동하는 구성 가능한 빌딩 블록만 있을 뿐입니다.

Mega Cat Studios의 엔지니어링 헤드인 David Chávez Armenteros는 \"집중적이고 간결하며 독립적인 빌딩 블록(컴포넌트, ScriptableObjects, 또는 커스텀 클래스 등)을 만드는 것보다 더 강력한 것은 없습니다\"라고 말합니다. Unity는 핵심적으로 모듈성을 수용합니다. 유연성을 유지하기 위해 우리는 세 가지 클래식 원칙을 따릅니다:

1. 단일 책임: 각 스크립트나 클래스는 명확하게 정의된 하나의 역할을 가져야 합니다.

2. 느슨한 결합: 시스템은 직접적인 참조보다는 인터페이스나 이벤트를 통해, 그리고 적절한 경우에만 상호 작용해야 합니다. 순환적이거나 복잡한 아키텍처를 피하기 위해 코드로 구현하기 전에 시스템 간의 의존성을 그래프로 그려보는 것을 권장합니다.

3. 플러그 앤 플레이: 방대한 \"갓\" 스크립트를 작성하는 대신 작고 집중된 단위를 결합하여 복잡한 동작을 만드세요.

레슨 3: 제한을 활용하여 자유를 얻으세요

Assembly Definition 파일은 특정 시스템에 대한 로직을 포함하며 의존성을 명확하게 지정합니다. 보시다시피 Mega Cat Studios에서는 모듈화와 체계적인 관리를 위해 많은 작은 어셈블리를 사용합니다. 단, \"순환 의존성\"이 발생하지 않도록 주의하세요.
Assembly Definition 파일은 특정 시스템에 대한 로직을 포함하며 의존성을 명확하게 지정합니다. 보시다시피 Mega Cat Studios에서는 모듈화와 체계적인 관리를 위해 많은 작은 어셈블리를 사용합니다. 단, \"순환 의존성\"이 발생하지 않도록 주의하세요.

Assembly Definitions(AsmDefs)는 코드를 그룹화하는 C# 구문입니다. 이들의 알려진 장점은 컴파일 시간 단축이지만, 진정한 숨겨진 능력은 모듈화를 강제하는 것입니다.

리드 개발자이자 스파게티 코드 혐오자인 Nico Gaudenzi는 그것들을 맹신합니다.

"Backyard Baseball에서 입력 레이어와 게임플레이 레이어는 서로 다른 DLL에 있습니다." 게임플레이는 입력 세부 정보와 완전히 무관합니다."

이는 각 종속성을 계산된 결정으로 만듦으로써 엔지니어들이 스스로의 실수를 방지하도록 합니다. 정말 필요하다면, 플레이어 물리나 AI 동작을 망가뜨릴 위험 없이 게임패드 처리부터 Netcode까지 전체 Input System을 다시 작성할 수 있습니다. 더 가능성 있는 것은, 한 엔지니어가 실수로 다른 시스템에 연쇄적인 변경을 일으키지 않고 코드베이스의 단일 도메인에서 작업할 수 있게 해주며, 개발자가 기능 구현 및 버그 수정을 위해 파악해야 하는 코드의 양을 줄여준다는 점입니다.

레슨 4: 더 열심히가 아니라 더 똑똑하게 테스트하세요

프로젝트가 커짐에 따라 "도미노 효과"가 나타날 수 있습니다: 이곳의 작은 변경 사항이 저곳의 무언가를 망가뜨립니다. 좋은 아키텍처는 큰 도움이 되지만, 만능 해결책은 아닙니다.

기능 변경 사항이 품질 보증 담당자의 매뉴얼 테스트를 거치기 전에, 게임은 일련의 자동화된 단위 테스트를 통해 엄격하게 분석됩니다.

"테스트는 요구 사항 목록처럼 작동합니다"라고 Nico는 말합니다. "테스트는 기대되는 바를 설명하고 주요 사용 사례를 제공합니다."

Backyard Baseball의 캐릭터가 직구를 던지거나, 지지대를 훔치거나, 홈런을 칠 때, 공이 투구에 적합한 속도로 이동하도록 보장하거나, 주자의 타이밍이 지지대 도루 메커니즘과 일치하거나, 수비수가 타구에 올바르게 반응하도록 하는 등 우리가 달성하고자 하는 구체적인 게임플레이 결과가 있습니다. 캐릭터는 지면과 올바르게 충돌해야 하고, 공은 적절한 속도로 움직여야 하며, 와인드업, 스윙, 지지대 간 질주와 같은 동작을 추적하는 플레이어 컨트롤러 플래그와 같은 더 세분화된 시스템이 작동해야 합니다.

Pablo Sanchez의 파워를 미세 조정하거나, 더 중요하게는 배트 스윙을 제어하는 공유 코드를 조정할 때, 접촉 타이밍부터 공의 궤적까지 모든 상호 작용이 전체 게임에서 일관되게 동작하도록 보장해야 합니다.

종종 예상치 못한 부분이 망가지곤 하는데, 이것이 바로 테스트가 중요한 이유입니다.

이 시스템이 워크플로에 통합되면 특정 요구 사항이 깨지는 순간 바로 알 수 있으므로, 건초 더미에서 바늘을 찾는 것만큼 시간이 많이 걸리는 테스트 및 문제 해결 세션을 줄일 수 있습니다.

Unity의 Test Runner는 시스템이 모듈화되어 있을 때 가장 효과적으로 작동하며, 이것이 우리가 Assembly Definitions를 사용하는 또 다른 이유입니다.

레슨 5: 에셋을 기어에 맞추기

이와 같은 시각적 스케일링 오류는 종종 워크플로가 손상되었다는 징후입니다. 인적 오류를 방지하기 위해 개발자는 에셋이 씬에 들어오기 전부터 프로젝트 표준을 강제하는 자동화 시스템을 구현합니다.
이와 같은 시각적 스케일링 오류는 종종 워크플로가 손상되었다는 징후입니다. 인적 오류를 방지하기 위해 개발자는 에셋이 씬에 들어오기 전부터 프로젝트 표준을 강제하는 자동화 시스템을 구현합니다.

"실수는 인간의 몫이고, 용서는 신의 몫이다."

하지만 애초에 인적 오류를 방지하는 시스템을 구축하는 것은 그야말로 전설적인 일입니다.

수많은 코딩과 디버깅 후에는 눈이 침침해진 개발자가 몇 번의 잘못된 클릭을 하거나 임시로만 사용하려던 변경 사항을 실수로 리포에 푸시하는 일이 불가피하게 발생합니다. 용서할 수 있는 일이지만(가끔 눈이 침침해지는 사람 중 한 명으로서 말합니다), 임포트 설정이 잘못 구성된 에셋은 엄청난 결과를 초래할 수 있습니다. 많은 개발자가 고성능 머신에서 작업하기 때문에, 캐릭터, 애니메이션, 효과가 포함된 스타디움 씬이 저사양 하드웨어에서 느려지거나 불안정해지기 시작할 때까지 성능 문제가 눈에 띄지 않는 악몽 같은 시나리오가 발생할 수 있습니다.

이 위험을 완화하기 위해 에셋에 대한 액세스를 제한할 수도 있지만, 게임 콘텐츠를 조정해야 하는 여러 이유로 인해 병목 현상이 발생합니다:

  • 모델이 너무 커서 카메라 설정에 맞지 않습니다.
  • 이 오디오 클립은 영역이 작아서 특정 효과가 필요합니다.
  • 셰이더가 변경되었으므로 모든 텍스처를 조정해야 합니다.

Backyard Baseball과 같이 시각적 정체성이 중요한 게임에서는 출시를 앞두고 디자인(look and feel)을 완벽하게 다듬기 위해 모델과 VFX를 수백 번 수정합니다.

"아무리 기술 사양이 뛰어나도 콘텐츠의 다양성이 존재하면 에셋 간의 미세하지만 중요한 차이를 다뤄야 한다는 사실은 변하지 않습니다"라고 Nico는 말합니다.

자동화는 이 부분에서도 도움이 됩니다:

  • AssetPostprocessor: 프로젝트 표준을 강제하는 커스텀 임포트 로직을 작성합니다.
  • OnValidate: OnValidate 메서드를 사용하여 에디터에서 누락된 참조를 리포트하며, 이는 빌드 전에 항상 실행됩니다.

하지만 마지막으로, 자동화에 대한 모든 이야기가 단순한 매뉴얼 수정이 더 빠를 때 이를 방해하지 않도록 하십시오.

"10분이면 수동으로 할 수 있는 작업을 자동화하는 데 10일을 쓰지 마세요"라고 David는 경고합니다.

레슨 6: 인적 요소(협업)를 마스터하세요

Mega Cat Studios의 개발자들은 게임 작업 중 충돌을 피하기 위해 버전 관리와 간단한 가이드라인을 사용하여 부서 간에 협업합니다.
Mega Cat Studios의 개발자들은 게임 작업 중 충돌을 피하기 위해 버전 관리와 간단한 가이드라인을 사용하여 부서 간에 협업합니다.

버전 관리 시스템(예: Git)은 매일 수십 명의 개발자로부터 발생하는 수백 가지 변경 사항을 조정할 때 가장 먼저 떠오르는 것 중 하나입니다. David는 Mega Cat의 모든 프로젝트에 대해 다음과 같은 검증된 방법론을 권장합니다:

  • 작고 원자적인 변경 사항: 한 번에 많은 시스템에 영향을 주는 "메가 커밋"을 피하세요. 개별 기능 브랜치에서의 작업이 안정화되고 검토될 때까지 격리하세요. 필요할 때 체리 픽(cherry picking)이나 다른 Git 마법을 더 쉽게 사용할 수 있도록 잘 문서화된 버전 관리 기록을 위해 개별 변경 사항을 개별 커밋으로 유지하세요.
  • 메인에서 매일 병합: 기능, 부서 및 장기 브랜치를 메인 브랜치와 최신 상태로 유지하세요. 이렇게 하면 최종 병합의 크기와 복잡도를 줄여 대규모 충돌을 방지하는 데 도움이 됩니다.
  • 병합 요청 검토: 이는 품질 보증의 첫 번째 단계로, 여기서 버그를 잡고, 프로젝트 표준을 적용하며, 전체 시스템과의 응집력을 보장합니다.

"대규모 Unity 프로젝트에서 코드 리뷰는 단순한 형식이 아닙니다"라고 David는 조언합니다. "이는 충돌 방지와 전반적인 프로젝트 품질의 핵심 부분입니다."

코드를 검토하는 사람이 구현되는 영역에 대한 전문 지식을 갖추고 코딩 모범 사례를 숙지하고 있는지 확인하여, 정확성과 유지보수성을 정확하게 평가할 수 있도록 하세요.

Unity에서 버전 관리를 최대한 원활하게 만들기 위한 구체적인 유용한 팁이 있습니다. 씬과 프리팹은 프로젝트의 기반을 구성하므로, CPU 성능뿐만 아니라 개발자 협업을 위해서도 최적화하세요.

우리는 항상 거대한 씬이나 모놀리식 프리팹보다 더 작고, 추가적이며, 중첩된 컴포넌트를 선호합니다. 이런 방식으로 개발자는 충돌 없이 병렬로 작업할 수 있습니다.

씬과 프리팹의 병합 충돌은 데이터가 개발자가 읽기 쉽지 않아 결정하기 가장 어렵기 때문에 이는 중요합니다. 이 과정을 원활하게 하기 위해 우리는 이러한 파일을 바이너리가 아닌 텍스트로 직렬화하고 YAML 파일에 대한 Git 구성의 자동 병합 기능을 활성화합니다. 이렇게 하면 Git이 병합 충돌을 스스로 결정할 가능성이 높아지며, 개발자가 새로운 기능을 만드는 중요한 작업에 시간을 할애할 수 있게 됩니다.

하지만 이 모든 것에도 불구하고:

“충돌을 예방하는 것이 보통 충돌을 결정하려고 노력하는 것보다 더 나은 전략입니다”라고 Nico는 말합니다.

명확한 에셋 소유권은 이를 위해 큰 도움이 될 수 있습니다.

“특정 씬이나 프리팹을 누가 수정할 수 있는지 정의하십시오”라고 David는 말합니다. “그러면 팀원들은 에셋을 직접 편집하는 대신 소유권 밖의 변경 사항을 요청하게 됩니다.”

Nico는 유사한 절차를 “세마포어 시스템”이라고 설명합니다. 이는 기본적으로 개발자가 에셋을 변경할 때 기록하여 사실상 해당 에셋을 “잠그는” 스프레드시트입니다. 다른 개발자가 해당 파일을 변경해야 하는 경우, 파일을 잠근 개발자가 변경 사항을 저장소에 푸시하고 “잠금을 해제”할 때까지 기다려야 합니다.

언제나 그렇듯, 팀에 가장 적합한 절차를 찾으십시오.

미래를 위한 구축

상징적인 Pablo Sanchez와 Mr. Clanky가 여기 있으며, 경기를 시작할 준비가 되었습니다.
상징적인 Pablo Sanchez와 Mr. Clanky가 여기 있으며, 경기를 시작할 준비가 되었습니다.

Mega Cat Studios에서 우리는 Unity 프로젝트의 규모를 확장하는 것은 “더 열심히 코딩하는 것”보다 아키텍처 규율에 더 큰 비중을 둔다는 것을 배웠습니다. Unity의 컴포넌트 기반 특성을 존중하고, Assembly Definitions로 경계를 강화하며, 미래를 대비하여 에셋을 구성함으로써, 우리는 실행 전에 프로젝트가 기술 부채로 무너지지 않으면서 프로토타입 단계의 창의적인 흐름을 상당 부분 유지합니다.

이러한 교훈이 중요하지만, 완벽한 코드베이스는 없다는 점을 기억하십시오. 소프트웨어 개발은 권장되는 프로그래밍 패턴과 실용적인 고려 사항이 매일 충돌하는 거대한 전투입니다. 이러한 원칙 중 하나를 따르는 것이 유익한 절충안을 얻지 못한 채 개발을 지연시킨다면, 이는 교과서적인 권장 사항이 아닌 팀의 특성에 더 민감해져야 한다는 신호입니다. 결국 모든 프로젝트, 팀, 사람은 각기 다릅니다.

Mega Cat Studios는 매일 그 균형을 맞추기 위해 노력합니다. 새로운 프로젝트를 진행할 때마다 게임 라이브러리가 계속 성장함에 따라, 저희는 더 나은 Unity 개발자이자 더 나은 협업자가 되기를 희망합니다.