๐ Unity ์ด์ ๋ธ๋ฆฌ ์ํ ์ฐธ์กฐ, ์ด๋ป๊ฒ ํด๊ฒฐํ ๊น?
EventBus ๊ธฐ๋ฐ ๊ตฌ์กฐ๋ก ์์ ํ ๋์ปคํ๋งํ๋ ๋ฐฉ๋ฒ
๐งฉ ๋ฌธ์ ๋ฐฐ๊ฒฝ Unity ํ๋ก์ ํธ์์ .asmdef(Assembly Definition) ํ์ผ์ ์ฌ์ฉํ๋ฉด, ๋ชจ๋ ๊ฐ ์์กด์ฑ์ ๋ช ํํ ๋๋ ์ ์์ต๋๋ค. ํ์ง๋ง ๊ท๋ชจ๊ฐ ์ปค์ง๊ณ ๋ชจ๋์ด ๋๋๋ค ๋ณด๋ฉด ํ์ฐ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค:
โ A ๋ชจ๋์์ B๋ฅผ ์ฐธ์กฐํ๊ณ ์ถ์๋ฐ, โ B๋ A๋ฅผ ์ฐธ์กฐํ๊ณ ์์ด ์๋ฌ๊ฐ ๋ฐ์ํ๋ ์ํฉ
๋ํ์ ์ธ ์๊ฐ **Core์ Services ๊ฐ์ ์ํ ์ฐธ์กฐ ๋ฌธ์ **์ ๋๋ค.
- Core ์ด์ ๋ธ๋ฆฌ: ์ ์ฒด ์์คํ ์ ์ค์ฌ ๋ก์ง, ๊ด๋ฆฌ ํด๋์ค
- Services ์ด์ ๋ธ๋ฆฌ: ๊ฐ๋ณ ๊ธฐ๋ฅ ๋ชจ๋ (์: UserService, GameLogicService)
- App ์ด์ ๋ธ๋ฆฌ: ์ด๊ธฐ ์คํ, UI, ์ฌ ์ ์ด ๋ฑ
1
2
CS0234: The type or namespace name 'Services' does not exist in the namespace 'MyProject'
๐ฏ ํด๊ฒฐ ์ ๋ต: EventBus๋ฅผ ํตํ ์์ ํ ๋์ปคํ๋ง ์๋น์ค๋ค์ ์ง์ ํธ์ถํ์ง ์๊ณ , ์ด๋ฒคํธ ๊ธฐ๋ฐ ๋ฉ์์ง ์ ๋ฌ ๋ฐฉ์(EventBus)** ์ ์ฌ์ฉํด** ๋ชจ๋ ๊ฐ์ ์ง์ ์ ์ธ ์์กด์ฑ์ ์ ๊ฑฐํฉ๋๋ค.
๐งฑ ๊ตฌ์กฐ ์ ํ ์ /ํ ๋น๊ต
| ๊ตฌ์กฐ | Before | After (EventBus ๋ฐฉ์) |
|---|---|---|
| ์์กด์ฑ | Core โ Services ์ง์ ์ฐธ์กฐ | Core โ EventBus, Services โ EventBus |
| ํธ์ถ ๋ฐฉ์ | ์ง์ ๋ฉ์๋ ํธ์ถ | ์ด๋ฒคํธ ๋ฐํ ๋ฐ ๊ตฌ๋ |
| ํ ์คํธ์ฑ | ์ด๋ ค์ | ์ฌ์ (๋ชจ๋ ๋ ๋ฆฝ) |
| ํ์ฅ์ฑ | ๋ฎ์ (์์กด์ฑ ์ฆ๊ฐ) | ๋์ (๊ตฌ๋ ๋ง ํ๋ฉด ๋จ) |
๐ง ํต์ฌ ๊ตฌํ ์์ โ 1. EventBus ์์คํ
1
2
3
4
5
6
7
8
public static class EventBus {
private static Dictionary _handlers = new();
public static void Subscribe(Action listener) { ... }
public static void Unsubscribe(Action listener) { ... }
public static void Publish(T evt) { ... }
}
โ 2. ์๋น์ค ๊ด๋ จ ์ด๋ฒคํธ ์ ์
1
2
3
4
public struct ServiceInitializeRequestEvent {}
public struct ServiceInitializedEvent {}
public struct ServiceQueryRequestEvent { public Action callback; }
๐งฉ ๊ตฌ์กฐ ํ๋ฆ ์์ โถ ์๋น์ค ์ด๊ธฐํ ์์ฒญ
1
2
3
// Core์์ ๋ฐํ
EventBus.Publish(new ServiceInitializeRequestEvent());
1
2
3
4
5
6
// ๊ฐ ์๋น์ค์์ ๊ตฌ๋
EventBus.Subscribe(() => {
InitializeSelf();
EventBus.Publish(new ServiceInitializedEvent());
});
โถ ํน์ ์๋น์ค ์กฐํ ์์ฒญ
1
2
3
4
5
// App์์ ์๋น์ค ์์ฒญ
EventBus.Publish(new ServiceQueryRequestEvent {
callback = service => { _userService = service; }
});
1
2
3
4
5
// ์๋น์ค์์ ๊ตฌ๋
ํ ์๋ต
EventBus.Subscribe>(evt => {
evt.callback?.Invoke(this);
});
โ ์ต์ข ๊ตฌ์กฐ
1
2
3
4
5
6
7
Assets/
โโโ Core/ โ Core.asmdef
โโโ Services/ โ Services.asmdef
โโโ UI/ โ UI.asmdef
โโโ EventBus/ โ EventBus.asmdef
โโโ App/ โ App.asmdef
| ์ด์ ๋ธ๋ฆฌ | ์ฐธ์กฐ ๋์ |
|---|---|
| Core | โ EventBus |
| Services | โ EventBus |
| UI | โ EventBus |
| App | โ EventBus |
| EventBus | โ ์๋ฌด ๊ฒ๋ ์ฐธ์กฐ ์ ํจ |
- Core โ Services โ UI ์ฌ์ด ๋ณต์กํ ํธ์ถ์ด ์ฝํ๊ธฐ ์์ํ ๋
- ์ฌ๋ฌ ์๋น์ค๊ฐ ํ ๊ด๋ฆฌ์์ ํธ์ถ์ ๋ฐ์์ผ ํ ๋
- ์๋น์ค ๊ฐ ์ง์ ํธ์ถ ์์ด ์ ์ฐํ ์ฐ๊ฒฐ์ด ํ์ํ ๋
- ๊ตฌ์กฐ์ ์ผ๋ก ํ์ฅ์ฑ๊ณผ ํ ์คํธ์ฑ์ ์ค์ํ๊ฒ ์๊ฐํ ๋
- Uber์ RIBs ์ํคํ ์ฒ: ์ด๊ธฐ์๋ ๋ชจ๋ ํต์ ์ ์ด๋ฒคํธ๋ก ํ๋ ค๊ณ ํ์ผ๋, ๊ฒฐ๊ตญ ์ง์ ์ฐธ์กฐ๋ ํ์ฉํจ.
- FaceBook์ Flux: โ๋ชจ๋ ๊ฒ์ด ์ด๋ฒคํธโ์์ ์์ํ์ง๋ง, Redux์์๋ ์ง์ ์ ๊ทผ๋ ์ง์ํ๊ธฐ ์์ํจ.
- Unity์ ECS: ์์ ์ด๋ฒคํธ ์์คํ ์ ์๋ํ์ง๋ง, ComponentSystem์์ ์ง์ ์ ๊ทผ์ ํ์ฉํจ.
- ํผํฉ ์ ๊ทผ๋ฒ(Hybrid Approach)ํ์ ์ด ๋ช ํํ๊ณ ๊ฐ๊ฒฐํฉ์ด ํ์ํ ๊ฒฝ์ฐ ์ธํฐํ์ด์ค๋ก ๊ฐํ๊ฒ ๊ฒฐํฉ.
- ๋์จํ ๊ฒฐํฉ์ด ํ์ํ ๊ฒฝ์ฐ ์ด๋ฒคํธ๋ฒ์ค๋ฅผ ์ฌ์ฉํด์ ๋์จํ๊ฒ ๊ฒฐํฉ.
1
2
3
4
5
6
7
8
// ์ง์ ์ฐธ์กฐ: ํ์
์ด ๋ช
ํํ๊ณ ๊ฐ๊ฒฐํฉ์ด ํ์ํ ๊ฒฝ์ฐ
public class GameManager : IGameService
{
public GameState CurrentState { get; set; }
}
// EventBus: ๋์จํ ๊ฒฐํฉ์ด ํ์ํ ๊ฒฝ์ฐ
EventBus.Publish(new PlayerDiedEvent(player));
2. ๊ณ์ธต๋ณ ์ญํ ๋ถ๋ด(Hierarchical Approach)
| ๊ณ์ธต | ๋ชจ๋ | ์ค๋ช | ์ฐธ์กฐ ๋์ |
|---|---|---|---|
| โ | EventBus | ์ด๋ฒคํธ ๋ฉ์์ง ํต์ ํ๋ธ | ์์ โ |
| โก | Core | ๊ณตํต ์ ํธ, ์ธํฐํ์ด์ค, ๋ชจ๋ธ | โ EventBus |
| โข | Services | ๊ฒ์ ์์คํ (ํ๋ ์ด์ด, ๋งค์น ๋ฑ) | โ Core, EventBus |
| โฃ | UI | ํ๋ฉด ์ปดํฌ๋ํธ, ์ธํ ์ฒ๋ฆฌ | โ Services, Core, EventBus |
| โค | App | Bootstrap, EntryPoint | โ ๋ชจ๋ ๊ฒ |
