강의

멘토링

커뮤니티

Inflearn Community Q&A

lds37942177's profile image
lds37942177

asked

[Unity Level Up!] Modularly Developing Skill System

TargetSearcher for Target Search and Indicator for Skill Range Display

Indicator와 SelectionAction 및 SearchAction 간의 관계에 대해 질문있습니다.

Written on

·

49

0

좋은 강의 잘 듣고 있습니다. 감사합니다.

강의 코드를 면밀히 분석해보고 다양한 상황을 고려해봤습니다.

현재는 SelectionActionSearchAction들의 로직들이 Indicator의 로직에 제한된 느낌이 들었는데요.

 

현재 Indicator

[모양]: 원형 및 원뿔 검색

[방향]: 원뿔의 경우 isAttachIndicatorToRequester에 따라 스페이스를 누른 시점에 방향이 고정

이처럼 제한 되다 보니 SelectTarget이나 SearchArea들의 내부 로직을 작성할 때 현재의 Indicator를 고려해서 작성 해야 되는 상황이 나옵니다

 

즉, 예를들어 사각형, 캡슐, 또는 구 형태의 Indicator라던가 마우스를 따라 회전하는 Indicator 등 로직들이 서로 상이합니다.

이렇게 다양한 Indicator들을 구현한다고 했을 때 이미 만들어둔 SelectionAction이나 SearchAction에서 Indicator들에 맞춰 로직을 분기 처리하는 방식이 될거같더라구요.

 

그래서 생각을 해봤는데 어차피 Indicator에 따라서 체크 로직이 다르다면 Indicator 내에서 체크 로직을 담당하는게 좋을거같다고 생각했습니다.

1) SelectionActionSearchAction에서 각각 범위 체크를 해야 되는 시점에 Indicator에게 정보를 넘겨준다.

2) 각 Indicator들은 받은 정보를 토대로 해당 Indicator에 맞춰 실제 범위 체크를 처리하고 그 결과를 SelectionActionSearchAction에게 반환한다.

이렇게 하면 SelectionAction이나 SearchAction는 더 이상 수정할 것 없이 Indicator 만 구현해서 갈아 끼우면 되는 모듈로 사용할 수 있다고 생각이 듭니다.

 

하지만, SelectionActionSearchAction가 직접 범위를 체크 해야 하는 책임을 가지는 거였다면, 제가 말씀드린 설계는 책임 분리가 잘 못된 걸로 보여집니다.

 

따라서 질문 드릴 사항은

1) 위와 같은 설계 방식이 책임 분리나 다른 문제가 되는 방식일까요?

2) 또는 더 좋은 설계 방식이 있는지 궁금합니다.

감사합니다.

 

unitymodules

Answer 2

1

Developer G님의 프로필 이미지
Developer G
Instructor

수강해주셔서 감사합니다.

1) 제안하신 설계(Indicator가 범위 체크를 담당)가 책임 분리에 어긋나는가?
네, 단일 책임 원칙 관점에서는 조금 어긋납니다. Indicator의 본질적인 책임은 View/UI입니다. 플레이어에게 범위를 보여주는 역할이죠. 여기에 물리적인 충돌 체크나 거리 계산 같은 Logic를 넣게 되면, View와 Logic이 섞이게 됩니다. 거기다 이렇게 되면 나중에 '화면에 인디케이터는 안 띄우지만, 사각형 범위로 적을 찾는 스킬' 같은 것을 만들 때 곤란해집니다. 시각적 표현이 없는 데도 Indicator 객체를 생성해야 하는 모순이 발생하기 때문입니다.

2) 현재 방식
말씀하신 것처럼 "현재 코드가 원형/원뿔에 제한되어 있어서 새로운 형태를 추가하려면 로직이 꼬이지 않을까?"라고 충분히 우려하실 수 있습니다. 하지만 현재 강의의 구조는 이미 형태 확장을 고려하여 설계되어 있습니다.

IndicatorViewAction 클래스의 ShowIndicator(..., object range, ...) 함수를 보시면 매개변수 타입이 float가 아니라 object로 되어 있죠? 제가 이 값을 object로 선언해둔 이유가 특정 형태에 구애받지 않고 유연하게 데이터를 넘기기 위함입니다.

예를 들어, 사각형(Box) 범위 스킬을 새로 추가한다고 가정해 보겠습니다.

  • BoxSearchAction (로직): 내부에서 사각형 크기(Vector3 extents)를 가지고 Physics.OverlapBox 같은 물리 연산을 알아서 처리합니다. 그리고 Indicator를 띄울 때는 자신이 가진 Vector3 값을 Range Property의 반환값으로 넘겨줍니다. (SelectTarget class 참고)

  • BoxIndicatorViewAction (뷰): 넘어온 object 매개변수를 다시 Vector3로 캐스팅해서 화면에 사각형을 그려주기만 하면 끝입니다. 꼭 BoxSearchAction이아니라도 Range로 Vector3를 return하는 SearchAction은 이 IndicatorView와 호환이 되는겁니다. 물론 View에 설정하는 Indicator 자체도 박스 형태를 구현할 수 있는 Indicator Prefab을 설정해야겠죠.

이렇게 하면 Action은 물리 연산만, Indicator는 시각 효과만 완벽하게 분리되어 담당하게 됩니다(Action - IndicatorView - Indicator 구조). 기존 코드를 뜯어고칠 필요 없이, 새로운 Action과 View 클래스를 파생시키는 것만으로 무한히 확장할 수 있는 구조인 것이죠. 좀 더 타입 안정성을 지키고 싶다하면 object가 아니라 IndicatorData 같은 구조체나 클래스를 만들어 넣기는 것도 괜찮습니다.

감사합니다.

lds37942177님의 프로필 이미지
lds37942177
Questioner

상세한 답변 감사합니다!

현재 강의 코드에서 SearchAreaSearch 함수에서 로직이 CircleIndicatorViewAction에 맞춰져 있는데, TargetSearchAction 자체가 IndicatorViewAction 모듈을 자유롭게 선택하는 방식이라고 생각을 해서 (제가 잘못 이해했을 수 있습니다.), SearchArea에서 말씀해주신 BoxIndicatorViewAction같은 것도 선택 가능한 부분이라 생각했습니다. 그런데 답변주신 내용처럼 BoxIndicatorViewActionSearchArea에는 적합하지 않아 적합한 BoxSearchAction를 새로 만들어야 된다는 거 같습니다.

 

그렇다면 TargetSearchAction을 구현할 때 모든 IndicatorViewAction 모듈을 사용 할 수 있는게 아니라 적합한 것만 사용할 수 밖에 없을 거 같다고 생각이 듭니다.

이는 당장은 아니지만, 나중에 TargetSelectionAction이나 TargetSearchAction도 많아지고 IndicatorViewAction도 많아지는 경우를 고려 했을 때 에디터에서 서로 적합한 것을 고르는 것이 관리 상 어렵지 않을까 조심스럽게 생각이 듭니다.

 

만약 이런 경우라면 차라리 최상위 클래스인 TargetSearchAction 에서 IndicatorViewAction을 선택할 수 있게 하기보다 TargetSearchAction을 상속 받는 클래스들을 1차 분류로 정의하고 각 분류에 해당하는 IndicatorViewAction들을 만들고 필드로 추가해서 제한하도록 하는 것이 어떨까 생각이 듭니다.

그렇게 되면 1차 분류된 TargetSearchAction들은 에디터에서도 그에 맞는 IndicatorViewAction들만 고를 수 있게 되어 관리 측면에서도 좋을 거 같다는 생각이 듭니다.

설계라는 것이 항상 고민이 많이 되는 일인 거 같습니다. 이러한 설계 방식도 괜찮은지 답변 주시면 감사하겠습니다!

Developer G님의 프로필 이미지
Developer G
Instructor

수강해주셔서 감사합니다.

타입이나 어트리뷰트를 통해 연결 가능한 모듈을 제한하여 휴먼 에러를 방지하는 것은 현업에서도 많이 쓰이는 아주 흔하고 좋은 접근법입니다.

하지만 이 시점에서 아키텍처를 설계할 때 반드시 명심해야 할 아주 중요한 원칙을 하나 짚어드리고 싶습니다. 오버 엔지니어링을 경계하는 것과 YAGNI(필요하지 않은 기능은 미리 구현하지 마라) 원칙입니다.

질문해주신 내용에 대해 제 시각에서 피드백을 드리겠습니다.

1. 실무적인 현실 (정말로 종류가 수십 가지로 늘어날까?)
수강생분께서 Action과 Indicator가 많아져서 에디터에서 짝을 맞추기 어려워질 '미래'를 우려하셨습니다. 하지만 실제 상용 게임 프로젝트의 사례를 보면, 타겟팅 범위의 형태는 기껏해야 원형(Sphere), 사각형(Box), 원뿔(Cone) 정도가 대부분입니다. 간혹 특이한 형태가 들어가더라도 수십 가지로 기하급수적으로 늘어나는 일은 거의 발생하지 않습니다. 즉, 오지 않을 미래의 복잡도를 미리 걱정하고 계신 것에 가깝습니다.

2. 엄격한 제약이 가져오는 유지보수의 족쇄
만약 수강생분의 제안대로 1차 분류를 만들어 사용할 수 있는 Indicator의 타입을 제한해두었다고 가정해 봅시다. 나중에 범용적으로 쓸 수 있는 전혀 새로운 형태의 'C'라는 Indicator를 하나 개발했습니다. 그렇다면 개발자는 기존에 만들어둔 수많은 Action 클래스들을 일일이 열어서 "이 Action에는 C Indicator를 허용해줄까?"를 전부 검토하고 매칭 코드를 수정해야 합니다. 결과적으로 에디터에서의 휴먼 에러를 막으려다, 새로운 뷰 모듈을 추가할 때마다 시스템 전체를 건드려야 하는 새로운 유지보수 비용을 낳게 됩니다. 타입을 자유롭게 풀어두는 것보다 이게 정말로 더 편하고 좋은 설계일까요? 모를 일입니다.

3. 문제가 발생했을 때 고쳐도 늦지 않습니다 (KISS 원칙)
설계는 완벽한 방어벽을 미리 치는 것이 아니라, 현재의 요구사항에 맞는 가장 단순하고 유연한 형태(Simple is Best / KISS)를 유지하는 것입니다. 특히 요즘은 AI의 발전으로 본인의 설계 능력만 확실하다면 코드를 대대적으로 리팩토링하는 것은 순식간에 끝납니다. 따라서 처음부터 무거운 제약 구조를 짜기보다는, 일단 열린 구조로 개발을 진행하다가 "기획자/프로그래머가 에디터에서 잘못된 Indicator를 연결하는 실수가 정말로 빈번하게 발생해서 작업에 지장이 생길 때" 해당 제약 로직을 도입해도 절대 늦지 않습니다.

4. 정답은 없습니다. 고민할 시간에 일단 부딪혀보고 고치세요.
수강생분이 제안하신 설계가 강의의 방식보다 결과적으로 더 나을지 아닐지는 저조차도 모릅니다(다만, 강의의 코드는 강의를 위해 단순화된 형태이긴 합니다.). 제가 아무리 열심히 설계를 하고 구현을 해도, 프로젝트/버전 롤아웃이 끝나고 포스트모템을 진행해 보면 반성할 점, 개선할 점은 계속 나옵니다. A가 좋은 줄 알았는데 사실 B가 더 좋았다던가 하는 일도 비일비재하죠.

너무 깊게 생각할 필요 없이, 일단은 '확장 가능한 형태'에 주안을 두고 만드는 것에 집중해 보세요. 그리고 수강생분이 느끼기에 본인이 생각하는 방식이 나아 보이는 확실한 근거가 있으시다면, 주저하지 말고 직접 그 방식대로 구현해 보세요, 틀리면 반성하고 그때 가서 고치면 되니까요.

저도 경험이 적을 때는 'A로 할까, B로 할까' 설계 때문에 정말 많은 개발 시간을 잡아먹었습니다. 저거 하나 선택하자고 코드를 계속 엎으면서 하루 종일을 날린 적도 있어요. 물론 그런 시간들 덕분에 지금 제 나름의 코딩 철학이 잡힌 거지만, 돌이켜보면 너무 많은 시간을 날려먹었다는 건 부정할 수 없습니다. 수강생분은 저처럼 우둔한 방향으로 시간을 허비하지 않으셨으면 합니다.

결론적으로 수강생분이 고민하신 '타입을 통한 제약과 안전성 확보'라는 방향성 자체는 객체지향 설계에서 매우 훌륭한 시각입니다.

감사합니다.

0

lds37942177님의 프로필 이미지
lds37942177
Questioner

답변 감사합니다. 충분히 와 닿고 공감 되는 내용들이네요.

처음부터 완벽한 설계는 없다. 그리고 제가 고민한 사항이 사실 다가오지 않을 미래일 수도 있는데 고민했다는 부분도 공감 됩니다. 아예 모르는 부분은 아니었지만, 매번 그렇게 해야지 해도 또 고민을 한 거 같습니다. 답변 주신 내용들을 읽고 한번 더 곱씹어 보게 되네요.

이후에도 설계를 할 때 말씀해주신 원칙과 피드백을 상기하겠습니다.

마지막으로 '타입을 통한 제약과 안전성 확보'가 좋은 시각이라는 점 말씀 해주셔서 감사합니다.

매번 이렇게 상세한 답변 주셔서 정말 감사합니다!

lds37942177's profile image
lds37942177

asked

Ask a question