안녕하세요!
저는 현재 WPF를 사용해 테스트 자동화 프로그램을 만들고 있는 신입 WPF 개발자입니다.
자동화 프로그램을 개발하면서 어떻게 하면 UI 를 조금 더 체계적으로 관리/제어할 수 있을까라는 고민을 많이 했었습니다. 많이 부족하지만 스스로 한번 생각해본 UI 설계 방식이 있어 해당 내용을 공유하고 피드백을 받고 싶다는 생각에 이렇게 글을 작성합니다.
[개발 중인 테스트 자동화 프로그램]
[상태 기반 UI 관리 라이브러리 샘플 앱]
[비고]
저는 자바 SpringFramework 개발 1년, WPF 개발 3개월의 신입 개발자입니다. 기술적으로 아직 다른 분들과 비교했을 때 많이 부족하고 개발 경험도 정말 적습니다. 선배님들이 보시기에 많이 부족한 코드, 아이디어이겠지만 한번씩 피드백 해주시고 어떤 부분이 부족한지 지적해주신다면 저에게 정말 큰 도움이 될 것 같습니다. 많은 피드백 부탁드리겠습니다!
[문제 상황]
WPF로 하드웨터 부품에 대한 테스트 자동화 프로그램을 관리하면서 사실 가장 어려웠던 부분은 어떻게 하면 사용자 친화적인 UI 를 개발하는가였습니다. 가장 걱정했던 하드웨어 장치로부터 데이터를 가지고 오는 과정에 대한 로직은 이전 개발자분이 개발하신 Winform 코드와 API 문서들을 확인하며 생각보다 수월(?)하게 구현할 수 있었습니다. 하지만 사용자가 어떤 상황에서 어떤 선택을 할 수 있는지, 각 테스트 단계에서 사용자가 어떠한 선택을 할 수 있는지 제한하는 방식으로 UI 를 구성하는 것이 저 같은 초보 WPF 개발자에게는 꽤 어려운 일이었습니다.
제가 생각한 UI 구성 방식의 대원칙은 다음과 같았습니다.
" 사용자가 각 테스트 단계에서 어떠한 선택을 할 수 있는지 명확하게 제한함으로써 사용자가 테스트 단계에서 잘못된 선택을 하는 것을 방지한다"
가령, 테스트 장치들과 연결이 되지 않는 상태에서 사용자가 테스트 시작 버튼을 누르지 못하게 한다든가, 테스트 과정에서 사용자가 다른 버튼을 눌러 테스트 과정을 방해하는 것을 막는다든지 사용자가 각 단계에서 어떠한 행동을 할 수 있는지 명확하게 제공하는 것이 중요하다는 생각을 개발 초기에 많이 했었습니다. 꽤나 고가의 전자 부품을 테스트함에 있어 테스트 과정에서의 부주의함으로 인한 리스크를 최소화하고 싶었기 때문입니다.(사실 모르는 게 많아서 조금 불안했습니다…)
다만, 이러한 어떤 시나리오의 흐름 속에서 전체 UI를 관리한다는 것이 사실 쉽지 않았습니다. 다음은 제가 생각한 전체 프로그램의 실행 과정에 대한 간략한 흐름을 정리한 그림입니다.
이걸 실제 UI로 표현하면 이렇게 구현할 수 있었습니다.
이러한 어떤 시나리오, 절차를 가진 프로그램의 UI를 제작함에 있어 어려웠던 점은 시나리오의 특정 절차에 도달했을 때 개별적인 UI 요소들(여러 버튼, 여러 화면 구성)이 특정 UI 표현력을 가지게 하기 위해서 일괄적으로 관리할 수 있는 방법이 부재한다는 점이었습니다. 만약 위의 UI 흐름도에서 테스트 시나리오가 다음 단계로 이동하게 된다면, 각각의 UI 요소들을 직접적으로, 개별적으로 변경해주어야 한다는 점이 가장 문제였습니다. ViewModel 과 View 가 가능한한 일대일로 매핑될 수 있게 전체 프로그램 구조를 관리하고 싶었던 차에, 이러한 모든 UI 요소를 동시다발적으로 관리하는 것은 너무나 복잡하고 코드의 양이 증폭되게 하는 문제를 낳았습니다.(혹시 제가 놓치고 있는 방법들이 있다면 피드백 부탁드리겠습니다…!) 테스트 시나리오가 흘러가는 과정에서 각 테스트 단계에 일치되게끔 각각의 UI 요소들을 직접적으로 ‘하나하나’ 제어하기에는 너무 번거롭고 헷갈린다는 결론을 내리게 되었습니다. 실수로 ‘저장’ 버튼을 ‘시험 대기’ 상태에서 클릭할 수 없게 IsEnabled를 false로 변경하는 로직을 잊어버린다면, 심각한 버그가 발생할 수 있는 문제가 있는 구조라고 생각했습니다>
[해결 방안 모색]
제가 생각했던 해결 방안은 중앙집중적이고 일괄적인 UI 관리 방법을 제공하는 것이었습니다. 즉, 테스트 시나리오 속에서 현재 프로그램이 어떠한 단계에 도달한다면, 각각의 UI 요소들이 직접 해당 단계에 맞는 UI를 스스로 갖추도록 하게 하는 것입니다. 즉, ViewModel에서 개별적으로 UI 요소들의 UI 상태를 일일이 하나하나 변경하는 것이 아니라, ViewModel에서 테스트의 단계/상태만을 관리하고 이 상태가 변경된다면 이 ViewModel의 UI 요소들이 직접 자기 자신의 UI를 변경할 수 있도록 이벤트/구독 형식의 UI 관리 방법을 제공하는 것입니다.
저는 우선 이러한 특정 상태에 기반하여 전체 UI 요소를 관리하기 위해서는 테스트 시나리오의 흐름에 맞춘 명확한 상태에 대한 규정과 명칭이 필요하다고 생각을 하였고, 각 테스트 시나리오의 단계에 대해서 다음과 같은 이름을 지어주었습니다.
그리고 최종적으로 이러한 흐름을 관리할 수 있는 StateEventManager라는 객체를 사용하여 ViewModel 에서 전체 테스트의 흐름을 제어할 수 있게끔 해주었습니다. 그리고 각각의 UI 요소들은 StateEventManager의 각 테스트 단계로의 전환(NotReady, Ready, Waiting, Running, Paused, Completed)에 해당하는 이벤트에 자기 자신의 UI 수정 로직을 담은 이벤트 핸들러를 등록할 수 있습니다.
구체적인 절차는 다음과 같습니다.
- 각 UI 요소들의 이벤트 핸들러에 미리 UI 로직 정의
- 각 UI 요소들은 StateEventManger의 각 상태에 대한 이벤트에 자기 자신의 이벤트 핸들러를 연결
- 상위 관리자가 StateEventManger의 상태를 변경(특정 상태에 대한 이벤트를 Invoke)
- 이벤트에 등록된 이벤트 핸들러들이 일괄적으로 동작하면서 등록된 UI 요소들의 UI 로직을 일괄적으로 수행
- 이렇게 미리 정의해 놓은 UI 관리 이벤트 핸들러를 각 상태의 이벤트에 등록해놓는다면, 다음과 같이 특정 Command 를 사용하여 StateEventManager의 상태를 변경함으로써 모든 UI 요소의 UI를 일괄적으로 제어할 수 있습니다.
[2부에서 계속…]
처음에 글을 작성할 때는 한 게시물에 전체적인 내용을 다 담을 수 있을 거라고 생각했는데, 제 표현력이 좋지 않아 아이디어를 다 담지는 못했습니다. 전체적인 개념에 대해서는 나름대로 표현했다고 생각하나 어디까지나 초안 수준의 아이디어로 개선해야 할 점이 많습니다. 앞으로 올릴 2부에서 조금 더 구체적이고 상세한 내용을 담을 수 있도록 하겠습니다. 긴 글 읽어주셔서 정말 감사합니다. 많은 피드백 부탁드리겠습니다. 감사합니다!