Sparta Unreal 부트캠프 75일차

정찬호·2026년 3월 19일

모듈

모듈은 언리얼에서 코드를 기능 단위로 쪼갠 “빌드/로딩의 최소 단위”입니다.

게임을 "한 채의 건물"이라고 하면, 모듈은 전기실/기계실/엘리베이터실처럼 설비를 구획별로 분리해 둔 느낌입니다.

모듈은 다음과 같은 이유로 유용합니다.

  • 컴파일 단위 분리: 전체를 다시 빌드하지 않고 바뀐 구역만 다시 빌드
  • 의존성 통제: “이 모듈은 저 모듈에 의존한다”를 명시해서 참조가 무분별해지는 걸 방지
  • 로드/언로드 가능: 상황에 따라 모듈이 로드되는 시점을 관리 가능

엔진도 Engine, UMG, Renderer 같은 수많은 모듈로 구성됩니다.

모듈의 문제점

기본적으로 “프로젝트 소스가 포함된 모듈”은 코드가 드러납니다. (소스가 배포/공유되면 당연히 보임)
모듈의 Public/Private 폴더 구조는 “접근/의존성 제어(컴파일 관점)”에 가깝고, “탐색기에서 못 보게 해서 보안” 같은 목적을 달성하진 못합니다.
코드를 숨기려면 보통 라이브러리 (.lib / .dll) 형태로 바이너리로 배포하거나, 엔진/플러그인 배포 정책을 따라야합니다.
모듈 당 생성 가능한 오브젝트 제한이 존재해

모듈과 컴포넌트

모듈(Module): 빌드/링크/로딩의 단위 (코드를 “프로젝트 구조” 관점에서 쪼갬)
→ “바뀐 기능만 다시 빌드”, 의존성 격리, 런타임/에디터 코드 분리

컴포넌트(Component): 게임플레이 구성 단위 (액터에 붙는 기능 조각)
→ 체력 컴포넌트, 인벤토리 컴포넌트처럼 “런타임 동작을 조립”하는 목적

모듈과 플러그인

모듈: 가장 작은 “코드 빌드 단위”

플러그인(Plugin): 배포/공유 가능한 “패키지 단위”이고, 내부에 하나 이상의 모듈을 포함합니다.

각 확장자는

  • 프로젝트: .uproject (프로젝트 전체 정의)
  • 플러그인: .uplugin (플러그인 정의)
    이며 둘 다 JSON 형식입니다.
    프로젝트는 실행 앱의 주체, 플러그인은 프로젝트/엔진에 "끼워 넣는 확장"입니다.
    플러그인 자체만으로는 실행이 불가능한 것입니다.

모듈과 서드파티(ThirdParty) 모듈

일반 모듈(Runtime/Editor 등): 보통 UE C++ 소스(헤더/CPP)로 구성되고 엔진 규칙대로 빌드됩니다.
ThirdParty 모듈: 외부 SDK/라이브러리 연동을 위해 .lib/.dll(윈도우), .a/.so(리눅스) 같은 “미리 컴파일된 바이너리”를 감싸서 UE 빌드 시스템에 연결하는 목적이 큽니다.
코드를 공개하기 싫을 때의 전형적인 선택지가 바로 이런 바이너리 배포라고 합니다.
(즉, UE 모듈 구조가 보안을 만들어준다기보다 배포 형태(소스 vs 바이너리)가 핵심입니다.)

애착 모듈이 위험한 이유

여기서 말하는 “애착 모듈”을 개인 이름/개인 취향으로 모듈을 남발하거나, 개인이 소유한 모듈처럼 운영하는 문화입니다.
여기서 위험 포인트를 설명하자면

  • 의존성 난립: 아무나 갖다 쓰게 되면 Public 의존이 퍼져서 프로젝트가 끈끈해짐
  • Ownership 불명확: 담당자가 빠지면 유지보수 공백
  • *모듈 경계 붕괴: “잡동사니 모듈”이 되어 재사용도/테스트도 어려움
  • LoadingPhase/Type 오남용까지 섞이면 패키징/런타임 문제로 이어질 수 있음

애착 카테고리는 안전하다?

여기서 “카테고리”가 로그 카테고리(UE_LOG 카테고리)를 말합니다.
애착 브랜치, 애착 모듈 때문에 애착 카테고리라고 임시로 표현하는 것입니다. 실제 있는 표현인지는 모릅니다.

  • 보통은 모듈 구조/빌드에 영향을 거의 안 주는 ‘이름표’라서 “상대적으로 안전”한 편입니다.
  • 다만 “안전”의 의미가 보안이 아니라 협업/운영이라면, 개인 닉네임 카테고리가 난립하면 로그 필터링이 어려워지고 로그 정책(레벨/포맷)이 제각각이 될 수 있어 → 팀 규칙이 없으면 유지보수성이 떨어질 수는 습니다.

모듈을 분리해야 하는 이유

  • 빌드/링크 한계(크기, 시간, 메모리): 한 모듈(=한 덩어리 코드)이 너무 커지면 컴파일/링크가 느려지고 실패 가능성이 올라가서 쪼갭니다.
  • 의존성 폭발: 기능이 한 모듈에 뭉치면 include/참조가 얽혀 “조금 고치면 다 다시 빌드”가 되어 분리합니다.
  • 에디터/런타임 분리 필요: Editor 전용 코드가 Runtime에 섞이면 패키징/배포에서 문제가 나서 모듈을 분리합니다.
  • 플랫폼/도구 제약(드물지만 존재): 특정 툴체인에서 심볼 수, 섹션 크기 같은 제한을 맞을 때 “단위를 쪼개라”는 해법이 나오기도 합니다.

모듈을 분리하는 이유에 대해 설명할 때 한 튜터님이 "모듈별로 최대 오브젝트 갯수가 정해져 있어, 개수가 초과되어서 모듈을 쪼개야 하는 경우도 있었다."라고 경험담을 말씀하셨는데 AI 튜터에게 해당 필기가 넘어나기 계속 그걸 물고 늘어지는 상황이 발생했습니다.
채팅 2~3번으로 해결된 이야기이긴 하지만 자꾸 이야기를 과하게 해석해서 단정 짓는 것 같아 보였습니다.
어디까지나 경험담이라는 이야기인데 자꾸 위의 사례를 함축해서 설명했을 가능성이 크다고 주장을 하더군요. 그냥 그런 경우도 있구나라고 넘어갈 것을 과하게 해석해서 엉뚱하게 나아가는 느낌을 받았습니다. 덕분에 모듈 분리 이유에 대해 한 번 더 확인하게 되는 시간이 되었습니다.

.dll / .lib

.dll: 보통 우리가 말하는 동적 라이브러리(Dynamic Library)입니다.
공용 설비실(엘리베이터/보일러)처럼, 여러 프로그램이 같은 DLL을 공유해서 쓰거나 실행 중에 불러와요.

.lib: “동적”이 아니라 링킹을 위한 라이브러리 파일입니다.
.lib에는 보통 2가지 종류가 있습니다.
1. 정적 라이브러리(static .lib): 코드가 프로그램에 포함돼서 최종 exe에 같이 들어가요.
2. 임포트 라이브러리(import .lib): 실제 코드는 DLL에 있고, 이 .lib는 “이 DLL의 이런 함수/심볼을 쓸 거야”라는 연결용 표지판 역할을 해요.

추가로 현실에서는 다음과 같이 함께 오는 것이 보통이라고 합니다

  • .h(헤더): “어떤 함수/클래스가 있는지 설명서”
  • .lib: “링커가 연결하는 데 필요한 정보/또는 코드”
  • .dll: “실제 구현이 들어있는 파일(동적일 때)”

동적 라이브러리(Dynamic Library)의 의미와 역할
동적 라이브러리는 한마디로 “실행 파일(exe) 바깥에 분리되어 있다가, 실행 시점에 로딩되어 함께 동작하는 코드 묶음”을 의미합니다.
exe가 매장(프로그램)이라면 동적 라이브러리는 필요할 때 가져다 쓰는 공용 부품 창고(공용 기능 팩) 같은 느낌입니다.

“동적”이라는 말의 핵심 의미

  • 정적 링크: 필요한 코드가 exe 안에 미리 포함되어 출발해요(매장이 부품을 전부 들고 출근).
  • 동적 링크: 필요한 코드가 exe 밖(.dll 등)에 따로 있고, 실행 중에 OS 로더가 붙여 줍니다(매장이 필요할 때 창고에서 부품을 가져옴).

동적 라이브러리의 주요 역할(왜 쓰나)

  • 코드 공유: 여러 프로그램/모듈이 같은 DLL을 함께 쓰면, 공통 기능을 중복으로 들고 있지 않아도 됩니다.
  • 업데이트/교체 용이: exe를 다시 빌드/배포하지 않고도(조건이 맞으면) DLL 교체로 기능 수정이 가능합니다.
  • 플러그인 구조에 유리: 기능을 “필요할 때만” 로딩하거나, 선택적으로 탑재하는 구조를 만들기 좋습니다.
  • 의존성 분리: 큰 기능 덩어리를 분리해 빌드/배포/관리 단위를 나누는 데 도움될 때가 많습니다.

대신 생기는 주의점(동적의 비용)

  • 버전/호환성 문제: DLL 버전이 맞지 않으면 실행이 실패하거나(로드 실패), 동작이 달라질 수 있습니다.
  • 배포 누락 위험: 필요한 DLL을 같이 전달하지 않으면 실행이 안 됩니다.
  • 런타임 오류 가능성: 정적보다 문제가 “실행할 때” 터지는 경우가 늘 수 있습니다.
profile
게임 개발 지망생입니다.

0개의 댓글