UI에 작게 보이는 빨간 점은 유저에게 이것을 따라 가보라는 작은 넛지를 준다. 카카오톡에서도 내 친구들이 프로필을 업데이트했을때의 빨간 점을 못이기고 클릭했던 경험도 있을것이다. 빨간 점 시스템을 가장 잘 만들고 사용하고있는 쪽이 어딜까? 바로 게임이다!
게임덕후이자 개발자로서 평소에 게임을 하면서도 이건 어떻게 구현했을까, 상태관리 어떻게 하는걸까 감탄/고민을 자주한다. 요즘은 원신을 정말 재미있게 즐기고있는데, 원신은 유저가 빨간 점을 누르면 "원석"(게임 내 중요 재화)이 생긴다는걸 정말 잘 훈련시켜서 은근슬쩍 원신에서 일어나는 모든 이벤트들을 선전한다.
이런 빨간 점 시스템을 안드로이드에서 구현해보기위해, 내가 게임 개발자다...생각하고 자료를 찾아보았다. 유니티 에셋스토어에 올라온 Unity Red Dot Notify System과 레딧 포스트가 특히 도움되었다. 빨간 점 시스템에서 다루는 데이터는 트리처럼 계층적 구조로 되어있고, 이벤트는 노드의 알림 수에 변화가 생겼을 경우 이를 전파하는 형태다. 그리고 이 알림을 숫자로 보이게 할 것인가, 그냥 느낌표로 띄울 것인가는 별도의 UI 레이어에서 처리한다.
원신을 예시로 구현해보기
앞에서 살짝 원신에 대해서 얘기했으니, 원신을 예시로 빨간 점 시스템을 안드로이드에서 직접 만들어보도록하자. 일반적인 게임들처럼 퀘스트 메뉴에는 메인 퀘스트, 일일 퀘스트가 있다. 메인 퀘스트에는 "페이몬을 도와줘!"라는 퀘스트가 새로 떠서 진행중이라고 해보자.
다음의 계층구조가 그려지게 된다.
.
└── 퀘스트
├── 메인 퀘스트
│ └── 페이몬을 도와줘!
└── 일일 퀘스트
이런 계층적 관계를 표현하기 위해서 `DotNode`라는 인터페이스를 준비했다. Node는 다른 `DotNode`들을 자식으로 가질 수 있고, `LeafNode`는 자식이 없다. `match`는 나중에 사용할것이지만, 어떤 `LeafNode`가 자신 또는 자식이 맞는지 체크하는 함수다.
그러면 원신의 빨간점 시스템을 방금 정의한 `DotNode`로 표현해보자.
이렇게 선언해두면 다음에 `HelpPaimon`에 대한 빨간 점을 조작하고 싶을때 `GenshinRedDot.Quest.MainQuest.HelpPaimon`로 접근해서 쓸 수 있다.
object GenshinRedDot {
data object Quest : DotNode.Node(
MainQuest,
DailyQuest
) {
data object MainQuest : DotNode.Node(
HelpPaimon
) {
data object HelpPaimon : DotNode.LeafNode
}
data object DailyQuest : DotNode.LeafNode
}
}
다음은 `DotNode`들을 관리하고, 업데이트를 처리하는 `DotSystem`의 구현이다.
빨간 점의 숫자는 `LeafNode`만 가질 수 있도록 설계되었다. 일반 노드는 자식들의 합으로만 빨간 점 숫자를 표현가능하다. 숫자를 읽는 것은 어느 노드든 가능하지만, 숫자를 할당하는 것은 `LeafNode`로만 가능하다. 그리고 어떤 `LeafNode`든 업데이트가 일어날 경우 모든 리스너들에게 이 변화를 알린다.
유저가 "페이몬을 도와줘" 퀘스트를 완료할 수 있을 경우, 이 값을 1로 만들어주면 될 것이다.
DotSystem.setCount(GenshinRedDot.Quest.MainQuest.HelpPaimon, 1)
이것으로 빨간 점 시스템은 완성되었다.
이제 이것을 어떻게 표현하면 좋을지 Compose 함수를 작성해보자.
핵심은 `OnDotChangedEffect`다.
`DisposableEffect`를 이용해 컴포저블이 떨어졌을때 리스너도 깔끔하게 제거될 수 있도록 만들었다. 어떤 `LeafNode`의 숫자에 대한 업데이트가 일어날때, 내가 관찰해야하는 변화인지 `match` 함수를 통해 체크하고, 새로운 `count` 변화를 상위 컴포저블에게 알려준다.
이제 이 모든 코드를 합쳐서 Preview로 직접 확인해보자.
Daily Quest의 [+] 버튼을 눌러 3으로 만들면 상위 계층인 Group: Quest에도 해당 숫자가 반영된다.
유저가 "페이몬을 도와줘" 퀘스트를 완료할 수 있는 상태가 됨을 가정하고 HelpPaimon 옆의 [+] 버튼을 눌러서 숫자를 올려보면 상위 계층인 MainQuest와 Quest각각에 일어난 변화를 관찰 할 수 있다.
'프로그래밍 > Android' 카테고리의 다른 글
Github Package를 이용한 라이브러리 배포방법 (0) | 2024.11.04 |
---|---|
[안드로이드] IllegalStateException: Storage for [...] is already registered 오류 해결방법 (0) | 2024.10.27 |
ManifestPlaceholder : 매니페스트에서 빌드 변수 사용하기 (1) | 2024.10.09 |
Android Room은 어떻게 Flow를 지원할 수 있었을까? (0) | 2024.09.14 |
Mastering Android ViewModels: init {} 블록에서 상태를 초기화하는 것을 피하라 (0) | 2024.06.23 |