icon
3장 : 클래스와 객체 지향 설계

블루프린트 인터페이스 활용


지금까지 액터와 컴포넌트, 그리고 상속을 통해 객체 지향의 기본 원리를 블루프린트에서 어떻게 적용하는지 알아보았습니다. 이번 절에서는 객체 지향 설계의 또 다른 강력한 도구인 블루프린트 인터페이스(Blueprint Interface) 에 대해 설명드리겠습니다. 인터페이스는 상속과는 또 다른 방식으로 블루프린트 간의 유연한 통신을 가능하게 하며, 느슨한 결합(Loose Coupling)을 통해 확장성과 유지보수성을 크게 향상시킵니다.


인터페이스란 무엇인가?

일상생활의 비유를 들어 설명해 볼까요? 여러분이 스마트폰 충전기(인터페이스)를 가지고 있다고 생각해봅시다. 이 충전기는 어떤 종류의 스마트폰이든 상관없이 특정 포트(USB-C, 라이트닝 등)만 가지고 있다면 충전할 수 있습니다. 충전기는 '충전한다'는 기능만 정의할 뿐, 그 기능을 어떤 스마트폰이 어떻게 구현하는지는 신경 쓰지 않습니다.

블루프린트 인터페이스도 이와 유사합니다. 인터페이스는 특정 기능의 이름만 정의하고, 그 기능을 어떻게 구현할지는 해당 인터페이스를 '구현(Implement)'하는 블루프린트 클래스에 맡깁니다. 인터페이스 자체는 어떠한 로직이나 변수도 포함하지 않습니다. 오직 '이러한 기능이 존재한다'는 약속만을 담고 있습니다.


인터페이스가 왜 필요한가?

상속은 "A는 B이다 (A is a B)"라는 '부모-자식' 관계를 형성합니다. 예를 들어, BP_SportsCarBP_Car이다. 이는 매우 강력하지만, 한 가지 제약이 있습니다. 블루프린트는 단일 상속(Single Inheritance) 만을 지원합니다. 즉, 하나의 블루프린트는 오직 하나의 부모 블루프린트만 가질 수 있습니다.

하지만 게임 개발에서는 여러 블루프린트가 서로 다른 종류의 '기능'을 공유해야 하는 경우가 많습니다. 예를 들어, BP_Door (문), BP_Lever (레버), BP_Button (버튼)과 같은 액터들이 모두 '상호작용'이라는 공통된 기능을 가져야 한다고 가정해봅시다. 이들을 모두 같은 부모 클래스로 묶는 것은 논리적으로 맞지 않을 수 있습니다. 문은 레버가 아니고, 레버는 버튼이 아니니까요.

이럴 때 인터페이스가 해결책이 됩니다. 이 세 가지 액터(문, 레버, 버튼)는 모두 BPI_Interactable (상호작용 가능 인터페이스)를 '구현'할 수 있습니다. 각 액터는 BPI_Interactable이 정의한 Interact (상호작용) 기능을 자신만의 방식으로 구현합니다. 문은 열리고, 레버는 작동하고, 버튼은 눌리는 식으로 말이죠.

인터페이스는 "A는 B를 할 수 있다 (A can do B)"라는 '능력' 관계를 정의합니다. 이를 통해 블루프린트 간의 느슨한 결합을 가능하게 합니다. 특정 블루프린트가 어떤 인터페이스를 구현했는지 확인만 하면, 그 블루프린트가 해당 인터페이스에 정의된 기능을 가지고 있다고 확신하고 호출할 수 있습니다. 이는 시스템의 유연성을 극대화하고, 나중에 새로운 상호작용 가능한 오브젝트를 추가할 때 기존 코드를 수정할 필요 없이 인터페이스만 구현하면 되므로 확장성에도 매우 유리합니다.


블루프린트 인터페이스 생성 및 정의

인터페이스 생성하기

  • 콘텐츠 브라우저(Content Browser) 에서 마우스 오른쪽 버튼을 클릭합니다.
  • 블루프린트(Blueprints) > 블루프린트 인터페이스(Blueprint Interface)를 선택합니다.
  • 이름을 지정합니다. (예: BPI_Interactable - 일반적으로 'BPI_' 접두사를 사용합니다.)
  • 생성된 인터페이스 에셋을 더블클릭하여 인터페이스 에디터를 엽니다.

인터페이스 함수 정의하기

  • 인터페이스 에디터의 좌측 함수(Functions) 패널에서 + 버튼을 클릭하여 새로운 함수를 추가합니다.
  • 함수 이름을 지정합니다. (예: Interact)
  • 이 함수에 필요한 입력(Inputs)출력(Outputs) 매개변수를 디테일 패널에서 추가합니다. (예: Interact 함수는 InteractingActor (Actor Reference 타입)이라는 입력 핀을 가질 수 있습니다.)
  • 참고: 인터페이스 함수에는 로직을 구현할 수 있는 그래프가 없습니다. 오직 함수의 이름과 입출력 매개변수만 정의합니다.

컴파일 및 저장: 인터페이스를 정의한 후에는 반드시 컴파일하고 저장해야 합니다.


인터페이스 구현 및 활용

이제 생성한 인터페이스를 실제 액터 블루프린트에서 '구현'하고 '호출'해 봅시다.

액터 블루프린트에 인터페이스 구현하기

  • 인터페이스 기능을 추가하고 싶은 액터 블루프린트(예: BP_Door)를 엽니다.
  • 블루프린트 에디터의 상단 툴바에서 클래스 세팅(Class Settings) 버튼을 클릭합니다.
  • 디테일 패널의 인터페이스(Interfaces) 섹션에서 Implemented Interfaces 옆의 + 추가(+ Add) 버튼을 클릭합니다.
  • 목록에서 여러분이 만든 인터페이스(예: BPI_Interactable)를 검색하여 선택합니다.
  • 이제 블루프린트를 컴파일하면 좌측 함수(Functions) 패널인터페이스(Interfaces) 섹션이 새로 생기고, 그 아래에 Interact 함수가 나타난 것을 볼 수 있습니다.

인터페이스 함수 오버라이드(구현)하기

  • 좌측 함수 패널의 인터페이스 섹션 아래 Interact 함수 위에서 마우스 오른쪽 버튼을 클릭하고 이벤트 구현(Implement Event)을 선택합니다.
  • 이벤트 그래프에 Event Interact 노드가 생성됩니다. 이제 이 이벤트 노드의 실행 핀 뒤에 이 액터가 Interact 되었을 때 수행할 실제 로직을 구현합니다.
  • 예시: Print String 노드를 연결하여 "문이 상호작용되었습니다!"라고 출력하도록 설정하고, 문을 열리는 애니메이션을 재생하는 로직을 추가할 수 있습니다.
  • 블루프린트를 컴파일하고 저장합니다.

인터페이스 메시지 호출하기

  • 이제 다른 블루프린트(예: 플레이어 캐릭터 블루프린트)에서 이 Interact 기능을 호출해봅시다.
  • 플레이어 캐릭터 블루프린트의 이벤트 그래프에서, 예를 들어 E 키를 눌렀을 때 특정 액터와 상호작용하는 로직을 만든다고 가정합니다.
  • Event E 키 입력 노드를 추가합니다.
  • 플레이어가 보고 있는 액터나 겹쳐진 액터를 가져오는 로직을 만듭니다. (예: Line Trace By Channel 또는 Get Overlapping Actors 사용)
  • 가져온 액터 레퍼런스 핀에서 드래그하여 마우스 오른쪽 버튼을 클릭하고, 여러분의 인터페이스 함수 이름(예: Interact)을 검색합니다. 이때, Message가 붙은 노드를 선택해야 합니다. (예: Interact (Message))
  • Interact (Message) 노드는 대상 액터가 BPI_Interactable 인터페이스를 구현했는지 자동으로 확인하고, 구현했다면 해당 액터의 Event Interact 로직을 실행시킵니다.
  • Target 핀에는 상호작용할 액터 레퍼런스를 연결하고, 필요한 경우 입력 매개변수를 연결합니다.

이 방식의 장점은, Interact (Message) 노드를 연결할 때 대상 액터가 BP_Door인지, BP_Lever인지, BP_Button인지 명시적으로 알 필요가 없다는 것입니다. 그저 BPI_Interactable 인터페이스를 구현했는지 여부만 중요합니다.


인터페이스 사용의 이점 정리

  • 다형성(Polymorphism) 구현: 하나의 인터페이스 메시지 호출로, 다양한 종류의 블루프린트가 각자 자신만의 방식으로 기능을 수행할 수 있게 합니다.
  • 느슨한 결합(Loose Coupling): 블루프린트 간의 의존성을 줄여줍니다. 호출하는 쪽은 특정 클래스에 묶이지 않고, 인터페이스만 알면 되므로 시스템 변경에 유연하게 대처할 수 있습니다.
  • 확장성: 새로운 기능이 필요할 때, 기존 인터페이스에 함수를 추가하거나, 새로운 클래스가 기존 인터페이스를 구현하기만 하면 됩니다.
  • 협업 효율성: 팀원 간에 기능의 '계약'을 명확히 정의할 수 있어, 각자 독립적으로 개발하고 나중에 쉽게 통합할 수 있습니다.

블루프린트 인터페이스는 복잡한 게임 시스템을 설계하고, 여러 블루프린트가 서로 유기적으로 상호작용하게 만들 때 매우 유용한 고급 도구입니다. 처음에는 어렵게 느껴질 수 있지만, 인터페이스를 활용하기 시작하면 블루프린트 코드의 유지보수성과 확장성이 크게 향상되는 것을 경험하실 수 있을 것입니다.


이번 절에서는 블루프린트 인터페이스의 개념, 생성 및 활용 방법, 그리고 상속과의 차이점에 대해 알아보았습니다. 인터페이스는 블루프린트의 객체 지향적 설계를 한 단계 더 발전시키는 중요한 요소입니다.