본문으로 건너뛰기

안동민 개발노트

본문 시작

플러그인 개발

언리얼 플러그인의 디렉터리와 모듈 구조를 이해하고 Build.cs와 모듈 인터페이스를 구성합니다.

이전 장에서 배포와 운영을 다뤘다면, 이번 장에서는 엔진 확장 관점으로 이동합니다.

언리얼 엔진은 기본 기능만으로도 강력하지만, 프로젝트가 커질수록 공통 기능 모듈화나 엔진 확장이 필요해집니다.

이때 가장 효과적인 방법이 플러그인(Plugin) 개발입니다.

플러그인을 잘 설계하면 재사용성, 유지보수성, 팀 협업 효율을 동시에 끌어올릴 수 있습니다.

이번 절에서는 언리얼 엔진 플러그인의 개념, 구조, 실제 개발 과정을 단계별로 정리합니다.

플러그인 모듈 확장

재사용 가능한 기능은 `.uplugin` 메타데이터, Source 모듈, Build.cs 종속성, 모듈 수명 주기로 묶인다.

  1. 1
    플러그인 폴더 구조

    플러그인 폴더는 메타데이터와 코드, 리소스, 콘텐츠를 분리한다. .uplugin 이름, 버전, 로딩 단계, 모듈 목록 Public / Private 외부 API와 내부 구현 분리 Build.cs 엔진 모듈 종속성 선언

  2. 2
    종류와 용도

    런타임 플러그인은 게임 실행 기능, 에디터 플러그인은 제작 도구 확장에 집중한다. 한 플러그인이 두 모듈을 함께 가질 수도 있다. Startup 모듈 로드 시 초기화 Runtime 게임 기능 제공 Shutdown 리소스 정리

  3. 3
    Startup

    모듈 로드 시 초기화

  4. 4
    Runtime

    게임 기능 제공

  5. 5
    Shutdown

    리소스 정리


플러그인이란 무엇인가?

플러그인은 언리얼 엔진의 기능을 확장하거나, 특정 기능 묶음을 재사용 가능한 형태로 캡슐화하기 위한 독립적인 모듈입니다.

엔진 자체를 수정하지 않고도 새로운 기능을 추가하거나 기존 기능을 대체할 수 있게 해줍니다.

플러그인 사용의 이점
  • 모듈화 및 재사용성: 특정 기능을 독립적인 단위로 분리하여 다른 프로젝트에서도 쉽게 재사용할 수 있습니다.
  • 쉬운 통합: 엔진 소스 코드를 직접 수정할 필요 없이, 프로젝트에 플러그인을 추가/제거하는 것만으로 기능을 통합하거나 비활성화할 수 있습니다.
  • 엔진 업그레이드 용이: 엔진 소스 코드를 수정하지 않으므로, 엔진 업데이트 시 충돌 위험이 적고 마이그레이션이 용이합니다.
  • 공유 및 판매: 개발한 기능을 언리얼 엔진 마켓플레이스를 통해 다른 개발자들과 공유하거나 판매할 수 있습니다.

플러그인의 종류

언리얼 엔진 플러그인은 기능에 따라 여러 가지 종류로 나눌 수 있습니다.

  • 런타임 플러그인 (Runtime Plugin): 게임이 실행되는 런타임 환경에서만 필요한 기능을 제공합니다. 주로 게임플레이 로직, 새로운 렌더링 기능, 네트워크 기능 등에 사용됩니다. 엔진에디터가 없어도 동작할 수 있는 모듈입니다.
  • 에디터 플러그인 (Editor Plugin): 언리얼 에디터의 기능을 확장하는 데 사용됩니다. 커스텀 에셋 에디터, 툴바 버튼, 메뉴 확장, 워크플로우 자동화 등에 활용됩니다. 게임 런타임에는 직접적인 영향을 주지 않습니다.
  • 개발 플러그인 (Developer Plugin): 개발 과정에 유용한 유틸리티 기능을 제공합니다.
  • 블루프린트 라이브러리 플러그인: 블루프린트에서 사용할 수 있는 새로운 노드나 함수를 제공합니다.
  • 하드웨어 통합 플러그인: 특정 하드웨어(VR 헤드셋, 입력 장치 등)와의 연동 기능을 제공합니다.

하나의 플러그인이 여러 종류의 기능을 동시에 포함할 수도 있습니다.

예를 들어, 런타임에 작동하는 기능과 이를 설정하는 에디터 UI를 함께 제공할 수 있습니다.


플러그인 생성 및 구조

언리얼 에디터에서 플러그인을 쉽게 생성할 수 있습니다.

플러그인 생성

언리얼 에디터에서 프로젝트를 엽니다.

Edit (편집) 메뉴에서 Plugins (플러그인)를 선택합니다.

Plugins 창에서 New Plugin (새 플러그인) 버튼을 클릭합니다.

플러그인 템플릿을 선택합니다.

  • Blank: 가장 기본적인 빈 플러그인.
  • Content Only: 콘텐츠만 포함하는 플러그인.
  • Third Party Library: 외부 라이브러리를 통합하기 위한 플러그인 템플릿.
  • Editor Standalone Window: 에디터에 독립적인 창을 추가하는 플러그인.
  • Etc.: 다른 유용한 템플릿들이 있습니다.

플러그인 이름과 위치를 지정하고 Create Plugin을 클릭합니다.

새로 생성된 플러그인 폴더는 일반적으로 프로젝트 루트 디렉터리의 Plugins 폴더 또는 엔진 설치 디렉터리의 Engine/Plugins 폴더에 위치합니다.

플러그인 기본 구조

생성된 플러그인 폴더는 다음과 같은 기본 구조를 가집니다.

MyPlugin.uplugin (플러그인 메타데이터 파일)
MyPlugin.cpp
MyPluginModule.cpp
MyPlugin.h
IMyPluginModule.h
MyPlugin.Build.cs (빌드 설정 파일)
MyPluginEditor.Build.cs
Icon128.png
  • .uplugin 파일: 플러그인의 메타데이터를 담고 있는 JSON 파일입니다. 플러그인 이름, 버전, 설명, 로딩 단계(LoadingPhase), 그리고 포함된 모듈 목록 등이 정의됩니다.
  • Source/[PluginName]/ 폴더: 플러그인의 C++ 코드와 빌드 설정을 포함하는 모듈 폴더입니다.
    • Public/: 다른 모듈에서 접근할 수 있는 공개 헤더 파일. 플러그인의 API 정의.
    • Private/: 플러그인 내부 구현 파일.
    • [PluginName].Build.cs: 플러그인 모듈의 빌드 설정 파일입니다. 종속성(PublicDependencyModuleNames, PrivateDependencyModuleNames), 매크로 정의, 라이브러리 포함 경로 등을 지정합니다.
플러그인 로딩 시점

`.uplugin`은 어떤 모듈을 언제 불러올지 설명하고, `Source` 아래의 Public, Private, Build.cs는 코드 경계와 종속성을 고정합니다.

  1. 외부 모듈에 노출되는 API

    Public 외부 모듈에 노출되는 API 다른 코드가 include할 수 있는 타입과 인터페이스만 둡니다.

  2. 구현 세부사항을 숨기는 공간

    Private 구현 세부사항을 숨기는 공간 내부 클래스, 헬퍼, 실제 로직은 여기서 변경 가능하게 유지합니다.

  3. 종속성과 빌드 규칙

    Build.cs 종속성과 빌드 규칙 `Core`, `Engine`, `UMG`, `Slate` 같은 모듈 의존성을 선언합니다.

  4. 아이콘과 콘텐츠 자산

    Resources 아이콘과 콘텐츠 자산 마켓플레이스 배포나 에디터 표시용 리소스를 분리합니다.


플러그인 개발 과정

Build.cs 파일 설정

플러그인의 핵심은 Build.cs 파일입니다.

이 파일에서 다른 언리얼 엔진 모듈과의 종속성을 정의합니다.

MyPlugin.Build.cs
using UnrealBuildTool;

public class MyPlugin : ModuleRules
{
    public MyPlugin(ReadOnlyTargetRules Target) : base(Target)
    {
        PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;

        PublicIncludePaths.AddRange(
            new string[] {
                // ... add public include paths required here ...
            }
            );

        PrivateIncludePaths.AddRange(
            new string[] {
                // ... add other private include paths required here ...
            }
            );

        PublicDependencyModuleNames.AddRange( // 다른 모듈에서 이 플러그인의 public 헤더를 사용할 때 필요한 종속성
            new string[] {
                "Core",
                "CoreUObject",
                "Engine",
                "UMG" // UMG 위젯을 사용한다면 추가
                // ... add other public dependencies that you statically link with here ...
            }
            );

        PrivateDependencyModuleNames.AddRange( // 이 플러그인 내부에서만 사용하는 종속성
            new string[] {
                // "Slate", // 에디터 플러그인이 UI를 사용한다면
                // "SlateCore",
                // ... add private dependencies that you statically link with here ...
            }
            );

        DynamicallyLoadedModuleNames.AddRange( // 런타임에 동적으로 로드될 모듈 (예: 에디터 모듈)
            new string[] {
                // ... add any modules that your module may dynamically load here ...
            }
            );
    }
}

모듈 인터페이스 정의 (IModuleInterface)

각 플러그인 모듈은 IModuleInterface를 상속받아 구현됩니다.

이 인터페이스는 모듈이 로드될 때 (StartupModule)와 언로드될 때 (ShutdownModule) 호출되는 함수를 정의합니다.

Public/IMyPluginModule.h
#pragma once

#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"

// 플러그인 모듈 인터페이스를 선언합니다.
class MYPLUGIN_API IMyPluginModule : public IModuleInterface
{
public:
    /**
     * 모듈의 인스턴스를 가져옵니다.
     */
    static inline IMyPluginModule& Get()
    {
        return FModuleManager::LoadModuleChecked<IMyPluginModule>("MyPlugin");
    }

    /**
     * 모듈이 로드되었는지 확인합니다.
     */
    static inline bool IsAvailable()
    {
        return FModuleManager::Get().IsModuleLoaded("MyPlugin");
    }

    // 여기에 플러그인이 외부에 노출할 함수를 선언합니다.
    virtual void MyCustomFunction() = 0;
};
Private/MyPluginModule.cpp
#include "MyPluginModule.h" // 먼저 모듈 헤더 포함
#include "MyPlugin.h"       // 플러그인에서 제공할 주요 기능 헤더 포함

#define LOCTEXT_NAMESPACE "FMyPluginModule"

// 모듈을 구현하고 등록합니다.
void FMyPluginModule::StartupModule()
{
    // 모듈 시작 시 수행할 초기화 로직
    UE_LOG(LogTemp, Log, TEXT("MyPlugin Module Started!"));
    // Add custom functionality here
}

void FMyPluginModule::ShutdownModule()
{
    // 모듈 종료 시 수행할 정리 로직
    UE_LOG(LogTemp, Log, TEXT("MyPlugin Module Shut Down!"));
    // Clean up any resources here
}

void FMyPluginModule::MyCustomFunction()
{
    UE_LOG(LogTemp, Warning, TEXT("My Custom Function called from MyPlugin!"));
}

#undef LOCTEXT_NAMESPACE

// 언리얼 엔진에 모듈을 등록하는 매크로
IMPLEMENT_MODULE(FMyPluginModule, MyPlugin)

플러그인 기능 구현

플러그인의 실제 기능은 이 모듈 내부에서 구현됩니다.

예를 들어, 새로운 액터 컴포넌트, 블루프린트 라이브러리 함수, 커스텀 에디터 모드 등을 만들 수 있습니다.

블루프린트 라이브러리 함수 추가 예시
Public/MyPluginBPLibrary.h
#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "MyPluginBPLibrary.generated.h"

UCLASS()
class MYPLUGIN_API UMyPluginBPLibrary : public UBlueprintFunctionLibrary
{
    GENERATED_BODY()

public:
    UFUNCTION(BlueprintCallable, Category = "MyPluginFunctions")
    static void PrintMyPluginMessage(FString Message);
};
Private/MyPluginBPLibrary.cpp
#include "MyPluginBPLibrary.h"

void UMyPluginBPLibrary::PrintMyPluginMessage(FString Message)
{
    UE_LOG(LogTemp, Warning, TEXT("MyPlugin Message: %s"), *Message);
}

MyPlugin.Build.csUMG와 같은 종속성을 추가해야 할 수도 있습니다.

에디터 확장 (선택 사항)

에디터 플러그인을 만들 경우, MyPluginEditor와 같은 별도의 모듈을 생성하고 Build.cs에서 UnrealEd, Slate, SlateCore 등 에디터 관련 모듈에 종속성을 추가해야 합니다.

  • FExtensibilityManager, FMenuBuilder, FToolBarBuilder 등을 사용하여 에디터 메뉴, 툴바, 컨텍스트 메뉴를 확장할 수 있습니다.
  • IAssetTypeActions를 구현하여 커스텀 에셋 타입을 등록하고 에디터를 확장할 수 있습니다.

플러그인 컴파일 및 활성화

플러그인을 생성하거나 수정했다면, 언리얼 엔진 프로젝트의 Visual Studio/Xcode 솔루션 파일을 다시 생성해야 합니다.

프로젝트 폴더에서 .uproject 파일을 마우스 오른쪽 버튼으로 클릭합니다.

Generate Visual Studio project files (또는 Generate Xcode project)를 선택합니다.

솔루션 파일(.sln)을 열고, 프로젝트를 빌드합니다.

빌드가 성공하면 에디터의 Plugins 창에서 새로 만든 플러그인을 찾아 활성화할 수 있습니다.

활성화 후에는 에디터를 재시작해야 변경 사항이 적용됩니다.


외부 라이브러리 통합 (Third-Party)

플러그인을 통해 SDL, OpenCV, FFMPEG 등 외부 C++ 라이브러리를 언리얼 엔진 프로젝트에 통합할 수 있습니다.

핵심 흐름: ThirdParty 구조를 먼저 고정한 뒤 Build.cs 링크 설정과 플랫폼별 패키징 검증을 반복하면 통합 실패를 빠르게 줄일 수 있습니다.

Build.cs 설정: PublicAdditionalLibraries, PublicDelayLoadDLLs, PublicIncludePaths, RuntimeDependencies 등을 사용하여 라이브러리의 .lib, .dll, .h 파일 경로를 지정합니다.

라이브러리 파일 배치: 일반적으로 플러그인 폴더 내부에 ThirdParty/[LibraryName]/ 폴더를 만들고, 플랫폼별로 (Win64, Linux, Android 등) 라이브러리 파일들을 배치합니다.

플랫폼별 분기: Target.Platform을 사용하여 플랫폼에 따라 다른 라이브러리 파일을 로드하도록 Build.cs에서 분기 처리를 합니다.

플러그인은 코드가 컴파일되는 것만으로 끝나지 않습니다.

런타임/에디터 모듈 분리, 플랫폼별 패키징, 예제 프로젝트, 문서와 버전 호환성을 함께 검수해야 실제 재사용 가능한 배포물이 됩니다.

플러그인 패키징 검수

재사용 가능한 배포물은 모듈 분리, 플랫폼 파일, 예제 프로젝트, 문서화가 한 흐름으로 맞아야 안정적으로 공유됩니다.

  1. 1
    런타임과 에디터 분리

    module 게임 빌드에 에디터 전용 모듈이 섞이지 않도록 경계를 확인합니다. ✓ Runtime 모듈은 패키징 가능 ✓ Editor 모듈은 에디터에서만 로드

  2. 2
    플랫폼별 의존성 확인

    build Build.cs의 라이브러리 경로와 RuntimeDependencies가 플랫폼마다 맞아야 합니다. ✓ Win64, Linux, Android 분기 ✓ DLL, SO, DYLIB 배치

  3. 3
    예제 프로젝트로 재검증

    verify 새 프로젝트에 플러그인을 넣고 활성화, 빌드, 실행까지 다시 확인합니다. ✓ 깨끗한 프로젝트에서 활성화 ✓ 패키징 결과물 실행

  4. 4
    문서와 버전 정보 고정

    publish 사용법, 샘플, 지원 엔진 버전, 변경 로그를 함께 배포합니다. ✓ README와 예제 맵 ✓ 지원 버전과 제한 사항


플러그인 마켓플레이스 배포

개발한 플러그인을 언리얼 엔진 마켓플레이스에 배포하여 수익을 창출할 수 있습니다.

  • 마켓플레이스 가이드라인 준수: 에픽 게임즈의 마켓플레이스 제출 가이드라인(코드 표준, 문서화, 테스트 등)을 엄격히 준수해야 합니다.
  • 문서화: 사용자가 플러그인을 쉽게 사용할 수 있도록 상세한 문서화와 예제 프로젝트를 제공해야 합니다.
  • 테스트: 다양한 언리얼 엔진 버전, 플랫폼, 그리고 다양한 프로젝트 환경에서 철저히 테스트해야 합니다.

재사용 가능한 플러그인은 코드가 빌드되는 것만으로 충분하지 않고, 설명 파일과 모듈 경계, 패키징 증거, 사용자 문서까지 함께 제출 가능한 상태여야 합니다.

재사용 플러그인 검수

`.uplugin`, 모듈 경계, ThirdParty 파일, 문서, 예제 프로젝트가 맞물려야 다른 프로젝트에서도 안전하게 켜고 끌 수 있습니다.

  1. 메타데이터 정리

    descriptor 버전, 설명, 지원 엔진, 모듈 LoadingPhase를 제출 기준에 맞춥니다.

  2. 런타임/에디터 분리

    modules 게임 빌드에 에디터 의존성이 섞이지 않도록 `Build.cs`를 나눕니다.

  3. 플랫폼 패키징

    package Win64, Linux, Android 등 대상별 라이브러리와 RuntimeDependencies를 확인합니다.

  4. 예제 프로젝트

    sample 사용자가 첫 기능을 바로 실행할 수 있는 맵과 블루프린트 예시를 둡니다.

  5. 설치 문서

    docs 활성화, 종속성, 제한 플랫폼, 문제 해결 절차를 짧게 정리합니다.

  6. 호환성 검증

    tests 지원 엔진 버전과 새 프로젝트에서 빌드·패키징이 통과하는지 확인합니다.


플러그인을 오래 재사용하려면 기능 구현과 함께 공개 API, 에디터 전용 의존성, 외부 라이브러리 배치, 샘플 검증이 서로 엇갈리지 않도록 관리해야 합니다.

모듈 경계와 재사용성

플러그인은 기능 파일 묶음이 아니라 공개 API, 에디터 의존성, 외부 라이브러리, 샘플 프로젝트가 맞물린 배포 단위입니다.

  1. 노출 범위 제한

    PUBLIC API Public 헤더에는 다른 모듈이 실제로 호출할 타입과 함수만 둡니다.

  2. 에디터 의존성 분리

    EDITOR ONLY UnrealEd, Slate, ToolMenus는 에디터 모듈에 두어 패키징을 보호합니다.

  3. 플랫폼 파일 고정

    THIRD PARTY 라이브러리, DLL, RuntimeDependencies를 플랫폼별 폴더로 정리합니다.

  4. 사용 예시 검증

    SAMPLE 새 프로젝트에서 활성화, 컴파일, 예제 실행까지 반복 확인합니다.


플러그인 개발은 언리얼 엔진의 기능을 확장하고 재사용성을 높이는 강력한 방법입니다.

플러그인의 구조를 이해하고, Build.cs 파일을 올바르게 설정하며, 모듈 인터페이스를 통해 기능을 노출하는 방법을 익히는 것은 매우 중요합니다.

에디터 확장, 외부 라이브러리 통합, 그리고 마켓플레이스 배포까지 고려한다면, 언리얼 엔진 개발자로서 더 넓은 영역으로 역량을 확장할 수 있을 것입니다.

플러그인은 모듈 경계, 의존성, 에디터 노출, 배포 가능성까지 갖춰야 재사용된다

내 프로젝트에서 동작하는 상태를 넘어 다른 프로젝트에서도 예측 가능하게 동작하는 상태가 목표다.

영역확인 기준위험 신호
Module BoundaryRuntime, Editor, Developer 모듈 책임 분리런타임 빌드가 Editor API를 참조
DependenciesBuild.cs와 uplugin 의존 목록이 실제 API와 일치빌드 머신에서만 누락 오류 발생
Editor Exposure설정, 메뉴, Details 확장이 찾기 쉬운 위치에 있음기능은 있지만 사용자가 진입점을 못 찾음
Packaging비활성화, 샘플, 문서, 버전 호환성 테스트패키징 또는 다른 프로젝트 설치 실패