| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
- 게임 디자인 패턴
- 오브젝트 풀
- 의존성 주입
- 테이블 데이터
- github desktop
- 개발
- Abstract Factory Pattern
- Di
- Object Pool
- Dependency Injection
- 데이터 형식
- 기술면접
- Render Mode
- Canvas Scaler
- 이벤트 버스
- 구글 스프레드 시트
- C#
- 상태 패턴
- 프로젝트 생성
- unity
- 콘솔 앱
- 유니티
- New Input System
- 구글플레이콘솔
- 스타일 지침
- 추상 팩토리 패턴
- Visual Studio Installer
- Unity 기술면접
- MVP 패턴
- event bus
- Today
- Total
DevDino
[게임 디자인 패턴] 의존성 주입 패턴(Dependency Injection Pattern) 본문
의존성 주입 패턴(Dependency Injection Pattern)
게임을 개발하다 보면 플레이어가 데미지를 입었을 때 소리를 내기 위해 AudioManager.Instance.PlaySound()처럼 싱글톤(Singleton)을 호출하는 경우가 아주 흔합니다.
하지만 이렇게 작성하면 플레이어 클래스는 특정 오디오 매니저에 '강하게 결합(Tight Coupling)'되어버립니다. 만약 테스트를 위해 소리를 끄고 싶거나, 다른 씬에서 다른 오디오 매니저를 사용해야 한다면 플레이어의 내부 코드를 직접 수정해야 하는 문제가 발생합니다.
이처럼 객체가 스스로 필요한 부품(의존성)을 찾거나 만들어 쓰는 대신, 외부에서 조립해서 넣어주는(주입하는) 방식인 '의존성 주입(DI)'패턴에 대해 알아보겠습니다.
의존성 주입 패턴(Dependency Injection)이란?
객체가 내부에서 필요한 의존 객체를 직접 생성하거나 전역 변수(싱글톤 등)를 통해 가져오는 대신, 외부로부터 필요한 객체를 전달(주입)받아 사용하는 디자인 패턴입니다. 일반적으로 인터페이스(Interface)를 활용하여 구체적인 구현체에 대한 의존도를 낮춥니다.
의존성 주입 패턴의 장점
- 결합도 감소: 객체는 자신이 사용할 부품이 어떻게 만들어졌는지 알 필요 없이, 주어진 인터페이스만 보고 작동하므로 코드 간 결합도가 크게 낮아집니다.
- 유연성 및 재사용성: 상황에 따라 다른 동작을 하는 객체(예: 모바일용 오디오, PC용 오디오)를 쉽게 갈아 끼울 수 있습니다.
- 테스트 용이성: 실제 게임 매니저 대신, 테스트용 가짜 객체(Mock)를 주입할 수 있어 유닛 테스트(Unit Test)를 작성하기가 매우 쉬워집니다.
구현 예제
1. 인터페이스 및 다양한 구현제 정의하기
플레이어가 사용할 오디오 시스템의 추상적인 규칙(인터페이스)을 만들고, 상황에 맞는 구체적인 클래스들을 구현합니다.
// 오디오 시스템 인터페이스
public interface IAudioService
{
void PlaySound(string clipName);
}
// 실제 게임에서 작동할 일반 오디오
public class GameAudioService : IAudioService
{
public void PlaySound(string clipName) => Debug.Log($"{clipName} 소리 재생!");
}
// 테스트용 혹은 소음 방지용 무음 오디오
public class MuteAudioService : IAudioService
{
public void PlaySound(string clipName) { /* 아무 소리도 나지 않음 */ }
}
2. 의존성을 주입받는 클라이언트 만들기
플레이어 클래스는 GameAudioService라는 구체적인 클래스를 몰라도 됩니다. 단지 IAudioService를 외부에서 생성자를 통해 주입받아 사용하기만 하면 됩니다.
public class Player
{
// 구체적인 클래스가 아닌 인터페이스에 의존
private IAudioService _audioService;
// 외부에서 의존성을 '주입' 받음 (생성자 주입 방식)
public Player(IAudioService audioService)
{
_audioService = audioService;
}
public void TakeDamage()
{
// 내부에서는 주입받은 객체를 그대로 사용만 함
_audioService.PlaySound("Damage_Ouch");
}
}
3. 주입자(Injector) 만들기
게임을 시작하는 최상위 클래스에서 부품을 생성하고 조립하여 플레이어에게 넣어줍니다.
public class GameManager : MonoBehaviour
{
private void Start()
{
// 1. 일반적인 게임 상황
IAudioService normalAudio = new GameAudioService();
Player normalPlayer = new Player(normalAudio);
normalPlayer.TakeDamage(); // "Damage_Ouch 소리 재생!" 출력
// 2. 조용히 테스트해야 하는 상황 (플레이어 코드 수정 없이 부품만 교체!)
IAudioService muteAudio = new MuteAudioService();
Player testPlayer = new Player(muteAudio);
testPlayer.TakeDamage(); // 아무 일도 일어나지 않음
}
}
싱글톤 패턴이 직접 접근하는 거라면 의존성 주입(DI) 패턴은 필요한 매니저를 주입받는 사고의 전환입니다.
유니티 환경에서는 MonoBehaviour의 특성상 생성자를 직접 다루기 까다로워 메서드 주입을 사용하기도 합니다. 프로젝트의 규모가 커진다면 이런 주입 과정을 자동으로 처리해 주는 VContainer나 Zenject같은 DI 전용 프레임워크를 도입하는 것을 적극 권장합니다.
'Unity > 디자인 패턴' 카테고리의 다른 글
| [게임 디자인 패턴] MVC / MVP 패턴 (0) | 2026.07.15 |
|---|---|
| [게임 디자인 패턴] 오브젝트 풀 패턴(Object Pool Pattern) (0) | 2026.07.15 |
| [게임 디자인 패턴] 추상 팩토리 패턴(Abstract Factory Pattern) (0) | 2026.07.14 |
| [게임 디자인 패턴] 전략 패턴(Strategy Pattern) (0) | 2026.07.14 |
| [게임 디자인 패턴] 옵저버 패턴(Observer Pattern) (0) | 2026.07.14 |