크고 작은 프로젝트의 코드를 작성하며 디자인 패턴의 중요성을 많이 느꼈다. 더군다나 다 같이 개발하는 장기간의 프로젝트에서는 더더욱이 신경써야할 부분이라고 생각한다.
디자인 패턴 중에서도 가장 많이 쓰이는 것은 Observer(옵저버) 패턴이라고 생각한다. 아직까지도 이 옵저버 패턴에대해 알기 이전에 짰던 코드들을 보면 '여기에 옵저버 패턴을 적용했더라면 좀 더 직관적이었을텐데...' 같은 생각이 들곤한다.
이글에서는 옵저버 패턴에 대해서 정리해보려고 한다.
옵저버 패턴에 대해 검색하면 대부분 위와 같은 이미지들이 많이 보인다. 정말로 옵저버 패턴은 위의 이미지 하나로 설명된다. 옵저버(관찰자)는 구독을 원하는 특정한 주제에 구독 신청을 하고, 주제는 새로운 내용이 갱신이 되면 그것을 자신을 구독한 구독자들에게 알린다.
여기서 주제라는 말이 애매하다고 느낄 수 있는데, 단순히 프로그램에서 다루고자하는 데이터 혹은 서비스 등 클래스로 만들어지는 대부분의 것들을 의미하는 포괄적인 의미이다. 안드로이드로 예를 들자면 서비스나 프래그먼트, 유니티로 예를 들자면 키보드 마우스 입력, 리소스 등 주제라고 불릴 수 있는것은 해석하기 나름이다.
public class InputManager
{
public Action KeyAction = null;
public void OnUpdate()
{
if (Input.anyKey == false)
return;
if (KeyAction != null)
KeyAction.Invoke();
}
}
유니티에서 예를 들어보자. 유니티에서 키보드의 입력을 하나의 주제로 보면, 위와 같이 InputManager라는 subject를 만들어 낼 수 있을 것이다. 이 subject는 단순히 키보드 입력이 일어나는 것을 감지하면 자신을 구독한 옵저버들에게 '키보드가 눌렸다!' 라는 의미로 Inovke()를 호출하여 구독자들에게 상황을 전한다.
그렇다면 이러한 키보드 입력 subject에는 어떤 구독자들이 있을까? 예를 들자면 키보드가 눌렸다면 플레이어 캐릭터가 이동을 할 수도 있고, 스킬을 사용했을수도 있고 그에 맞는 애니메이션을 재생할수도, 메뉴 UI를 호출해야 할 수도 있다. 앞서 말한것 처럼 하나의 subject에대해 여러가지 옵저버들이 있을 수 있고, 해당 subject가 업데이트 되었는지 궁금한 옵저버는 구독을 통해 그것을 받아 볼 수 있다.
void Start()
{
Managers.Input.KeyAction += Move;
}
예를 들어 플레이어 컨트롤을 위한 Move 함수를 원래는 update문에서 매 틱마다 호출하였으나 옵저버 패턴을 이용하여 위와 같이 KeyAction을 구독하는 형태로 만들면 update문에서 호출할 필요 없이 start가 호출 될때 한번만 구독을 해두면 된다.
옵저버 패턴을 사용하는 방법은 알겠으나 이것을 왜 사용하는 지 의문이 들 수 있다. 앞서 언급하였듯이 하나의 subject에는 여러개의 observer가 관심이 있어서 구독을 할 수가 있다고 하였다. 따라서 subject에 update해야할 내용이 있다면 구독자들에게 이벤트를 전파하는 방식으로 update내용을 전할 수 있다. 여기서 만약 옵저버 패턴이 없다면? 해당 내용을 원하는 모든 observer들을 하나하나 찾아서 update하는 함수를 일일이 호출해야 할 것이다.
위의 키보드 입력과 관련된 부분을 옵저버 패턴으로 처리하지 않는다면? 이동이나 스킬사용, 애니매이션 재생등의 observer들은 Update문에 일일이 함수를 호출하여 그것을 확인해야 하며, 더욱이 문제인것은 키보드 입력에 대해 버그가 터지면 어떤 옵저버에서 문제가 발생하였는 지 하나하나 확인해야 한다는 것이다. 옵저버 패턴으로 구현하여 새로운 입력에대한 업데이트 권한을 하나의 subject에서 가지기 때문에 디버깅에 어느정도 이점을 가진다는 것 또한 장점이다.
디자인 패턴에도 여러가지가 있지만 가장 자주 사용하고 중요한 것은 이 옵저버 패턴이라고 생각한다. 특히 코드가 길어질 수록 그 빛을 발하니 꼭 숙지해두자.
'디자인 패턴' 카테고리의 다른 글
[디자인 패턴] - 커맨드 패턴 (0) | 2023.02.28 |
---|