비동기 함수를 사용한 MVVM 형태의 모듈화된 UI 소프트웨어의 시각적 동기화 기법
Visually Synchronizing Modular UI Software Using Asynchronous Function
Article information
Trans Abstract
As the modern warfare continuously evolves into one that is network-centric, the amount of data a weapon system has to handle is rapidly growing, which applies not just to the internal data processing software but also to the UI software. Not only is the amount of data growing, but also is the complexity of handling such data, which when combined together creates a significant delay in updating relevant components in a UI software. In the context of the defense industry, split-second delay in visual component update can lead to catastrophic failure in making strategic decisions. This paper presents a novel method that utilizes asynchronous functions to control the program flow and reduce the delay in updating multiple visual components of a modular software. We apply this method to our modular UI software which uses MVVM pattern, where we were able to reduce the delay by an average of 78.4 %.
1. 서 론
현대 전쟁은 더 이상 단순하게 더 좋은 무기와 더 많은 병력이 승리를 가져다주지 않는다. 육군, 해군, 공군 모두가 각각의 무기 체계들에서 획득한 정보를 공유함을 통해 시너지 효과를 내고 있다. 아무리 좋은 무기를 갖고 있어도 전쟁 상황에 대한 정보가 없으면 어느 지점을 타격할지 모르고, 아무리 안 좋은 무기를 가지고 있어도 정보가 있다면 큰 효과를 낼 수 있다. 이와 같이 전쟁이 점점 더 네트워크 기반의 전쟁으로 진화하고 무기 체계들이 더 많고 다양한 정보를 주고 받으면서 이런 정보들을 보관하고 처리하는 소프트웨어적 부담 또한 많이 증가했다.
받으면서 이런 정보들을 보관하고 처리하는 소프트웨어적 부담 또한 많이 증가했다. 이에 따라 무기체계의 소프트웨어도 복잡한 정보처리 과정을 체계적으로 관리해야 하므로, 소프트웨어를 기능별로 모듈화하는 사례가 늘고 있다[1,2]. 소프트웨어 모듈화의 다양한 장점 중 첫 번째로 꼽을 수 있는 것은 우선 업무 분담이 명확해진다는 점이 있다[3,4]. 모듈화하지 않은 단일 형태의 소프트웨어일 경우, 여러 개발자가 하나의 코드를 수정해야 하므로 업무 분담에 지장이 생긴다. 그뿐만 아니라 기존의 개발자가 아닌 새로운 개발자가 업무를 맡게 되면 한 번에 너무 방대한 양의 코드를 분석해야 하므로 개발에 소모되는 시간이 비약적으로 증가할 수 있다. 그리고 기존의 개발자라도 시간이 지나고 코드를 수정할 일이 생겼을 때 내용을 다시 파악해야 하는 가능성이 있기 때문에 유지보수성이 떨어진다.
모듈화의 또 다른 장점은 새로운 무기 체계의 소프트웨어를 개발할 때 코드를 재사용하기 쉬워진다는 점이다[4]. 단일 형태의 소프트웨어를 재사용하려면 코드 내 결합도가 높아서 필요한 부분만 분리하기 쉽지 않고, 오히려 새롭게 코드를 작성하는 게 더 효율적일 때가 많다. 그 반면에 모듈화된 소프트웨어를 사용한다면, 필요한 기능의 모듈만 재활용할 수 있고, 모듈 간 의존성이 명확하게 정리되어 있어 추가적인 구현이나 수정을 최소화할 수 있다.
모듈화에는 장점이 많지만, 단점 또한 존재한다. 소프트웨어의 복잡도 증가, 오버헤드 발생 등 여러 가지 문제점들이 있지만 본 논문에서는 모듈화에 따르는 동기화 문제에 중점을 둔다. 모듈화를 하게 되면 하나의 정보처리 요청에 대해서도 여러 개의 모듈, 그리고 UI 소프트웨어의 경우 여려 화면 영역들이 해당 요청에 대해 반응하고 갱신해야 한다. 하지만 모듈마다 정보처리 요청에 대해서 수행해야 할 작업의 양이 다르고 이에 따라 각 영역이 갱신되는데 걸리는 시간이 다르다. 화면 영역 간 갱신 시간의 차이는 아무리 미세하더라도 사용자에게 불편함을 줄 뿐만 아니라 업무 수행 시간 증가 및 조작실수를 할 확률을 증가시킨다[5,6]. 만약에 실제 전쟁 상황에서 이러한 문제를 가진 무기체계 운용 UI 인터페이스를 사용하다가 잘못된 판단을 하거나 조작 실수로 인해 의도하지 않은 명령을 내리게 된다면 낭비된 무기 자산에서 오는 금전적인 손실, 실제 위협을 제거하는 데 사용될 무기가 줄어드는 데서 오는 전략적 불리함, 그리고 최종적으로 이러한 실수들로 인해 인명 피해까지 생길 수 있다.
기존 연구에서는 시각적 동기화를 위해 두 가지 방법을 사용한다[7]. 하나는 흐름 동기화로서 단순한 순차적인 작업을 통해 인터페이스를 갱신한다. 사용자가 정보를 입력하거나 혹은 외부에서 정보를 갱신했을 때 해당 정보를 읽어오는 함수가 있고, 함수에서는 특정 인터페이스 부분을 갱신한다. 이 방식은 정보 처리 함수에서 정보를 저장하고 있는 도메인도 갱신하고 관련된 인터페이스를 동시에 갱신해서 코드가 단순하고 이해하기 쉽다는 장점이 있다. 두 번째 방법은 관찰자 동기화로서 정보 갱신에 대해 알림을 보내고 인터페이스 구성 요소들은 이런 알림에 구독하는 방식을 사용한다. 이 방식은 도메인 관련 처리와 인터페이스 관련 처리를 완전히 분리할 수 있어서 여러 인터페이스 구성 요소를 동시에 갱신시킬 때 유용하다. 하지만 흐름 동기화는 도메인 관련 처리와 인터페이스 갱신이 서로 얽혀있어서 복잡한 프로그램일수록 코드의 유지보수성이 떨어지고, 관찰자 동기화는 정보 처리를 하는 모듈이 여러 개일 때를 고려하지 않아서 인터페이스 구성요소 간 갱신 시각의 차이가 생길 수 있다.
이에 따라 본 논문에서는 비동기 함수를 활용해서 흐름 동기화와 관찰자 동기화의 장점을 합친 새로운 동기화 기법을 제시한다. 이 기법은 흐름 동기화 기법처럼 특정 정보 갱신에 관련된 모든 인터페이스 구성 요소를 동시에 갱신시켜서 구성 요소 간 갱신 시각 차이를 최소화하면서 관찰자 동기화 기법의 알림과 구독 방식을 유지해서 도메인 처리와 인터페이스 처리를 분리한다. 제시한 새로운 기법을 MVVM (Model - View - ViewModel) 형태의 모듈화된 UI 소프트웨어에 적용해서 시각적 오차가 얼마나 줄었는지 측정하는 실험을 해서 시각적 오차를 78.4 % 줄이는 데 성공했다. 2장에서는 MVVM 패턴의 주요 구성 요소와 개념을 설명하고, 3장에서는 타깃 소프트웨어를 분석해서 시각적 동기화가 안 되는 부분과 그 원인을 찾는다. 4장에서는 타깃 소프트웨어에 새로운 동기화 기법을 구현하는 방법을 설명하고 동기화 효과를 측정하기 위한 설정들을 소개한다. 5장에서는 동기화 기능을 사용해서 구간마다 처리되는 시간 차이를 측정하여 실험 결과를 정리하고, 마지막으로 6장에서는 실험 결과를 바탕으로 결론을 내린다.
2. MVVM 패턴
새로운 동기화 기법을 소개하기에 앞서 타깃 소프트웨어의 구조인 MVVM 패턴을 소개하겠다. MVVM 패턴에는 3개의 주요 구성 요소가 있다: 정보들을 저장하고 비즈니스 로직을 수행하는 모델(model)과, 화면의 디자인적 구조를 정의해놓은 뷰(view)와, 마지막으로 모델과 뷰 사이에서 모델의 정보를 가공해서 뷰가 가져갈 수 있게 준비하거나, 뷰의 입력을 받아 모델에 정보처리 요청을 보내는 뷰모델(viewmodel)이 있다. 각 요소는 앞서 서론에서 소개한 관찰자 동기화 기법을 사용해 동기화한다. 모델은 데이터를 갱신해서 해당 데이터에 구독한 뷰모델들에 알림을 보내고, 알림을 받은 뷰모델은 정보를 모델에서 가져와서 처리하고 비슷하게 뷰에 알림을 보낸다. 사용자가 인터페이스를 사용해 뷰에 입력하게 되면 뷰는 직접적으로 뷰모델의 데이터를 수정하고, 뷰모델은 이에 반응해 모델의 데이터를 수정한다. Fig. 1은 MVVM의 형태를 나타내는 그림이다.
모델과 뷰모델의 차이를 간단히 표현하자면 모델은 더 큰 단위의 데이터베이스이고 뷰모델은 다른 말로 ‘뷰의 모델’로서 특정 뷰에서 필요한 데이터만 모델에서 가져오고 가공해서 갖고 있다[7-9]. 하지만 그렇다고 해서 뷰모델과 뷰가 1:1의 관계를 이루고 있는 것은 아니다. 하나의 뷰모델에 대해 여러 개의 뷰가 존재해서 하나의 뷰모델에 대해서 여러 개의 뷰를 사용해 다양한 방식으로 표현할 수가 있는 것이다. 마찬가지로 하나의 모델에 대해 여러 개의 뷰모델이 존재할 수 있다. 예를 들면 동물원 관리 소프트웨어라고 하면 모델에 모든 동물들에 대한 데이터가 담겨있고, 두 개의 뷰모델에는 각각 육식동물하고 초식동물에 대한 데이터를 갖고, 육식동물/초식동물의 위치를 나타내는 그래프의 뷰와 목록을 나타내는 뷰를 구현하면 위 설명대로 모델과 뷰모델의 관계도 1:N이고 뷰모델과 뷰의 관계도 1:N이 된다.
모델은 자신의 데이터를 갱신하고 알림만 보내는 요소로서 뷰모델과 뷰의 존재를 모르고, 오직 정보처리 요청이 들어왔을 때 데이터를 저장 및 수정하고 비즈니스 로직을 수행하기만 한다. 따라서 Fig. 1이 표현하는 것은 모델이 뷰모델에 데이터를 건네주는 것이 아니라 뷰모델이 모델의 데이터를 가져간다고 봐야 한다. 뷰모델은 모델을 관찰하면서 모델의 데이터가 변경됐을 때 모델의 데이터를 가져와서 가공하고 자신의 데이터를 갱신한다. 마지막으로 뷰도 비슷하게 뷰모델을 관찰하면서 뷰모델의 데이터가 변경됐을 때 뷰모델의 데이터를 가져와서 화면의 내용을 갱신한다.
MVVM 패턴은 이렇게 양방향 결합이 아닌 단방향 결합을 사용해 느슨한 결합을 이루고 있다[4,7-9]. 느슨한 결합에는 많은 장점들이 있는데 그중 하나는 관심사를 분리할 수 있어서 디자이너가 뷰를 담당하고 프로그래머가 모델과 뷰모델을 담당해서 흔히 말하는 프론트앤드와 백앤드가 분리된다. 이렇게 명확하게 분리가 된다는 것은 모델과 뷰가 서로 개별적으로 검증이 가능하다는 것이고, 만약 모델이나 뷰에 변경 사항이 생겨도 서로 영향을 주지 않는다. 뷰에서 UI를 완전히 새롭게 디자인한다 해도 모델은 변경할 필요가 없고, 모델에서 데이터를 가공하는 방식을 전부 바꿔도 뷰를 새롭게 만들 필요가 없다.
다음 장에서는 시각적 동기화가 안 되는 부분을 찾기 위해 타깃 소프트웨어를 분석하는 과정에 대해 설명한다.
3. 타깃 소프트웨어 분석
타깃 소프트웨어는 WPF 프레임워크에 C# 언어를 사용하고, 여러 개의 모듈이 존재하며 각 모듈은 MVVM 패턴을 따른다. 따라서 하나의 정보처리 요청에 대해 여러 개의 모델이 비즈니스 로직을 수행하게 되고 이에 대해 여러 뷰모델과 뷰들이 갱신된다. 타깃 소프트웨어를 가지고 실험하기 위해 Fig. 2와 같이 여러 모듈에 영향을 주는 임의의 정보처리 요청을 선택하였다.
선택한 정보처리 요청으로 2개의 모델이 갱신되고 그에 반응해 3개의 뷰모델과 뷰들이 갱신되는데, 각 모델, 뷰모델, 뷰가 알림을 받고 갱신이 완료되는 시각이 다르다. 이를 비교하기 위해 Table 1에 측정할 시각의 변수명을 선언하고 의미를 정의한다.
Table 1을 보면 뷰에서는 시각을 기록하지 않는데 그 이유는 WPF 프레임워크 상 뷰에서 시각을 기록하는 코드를 작성하는 데 어려움이 있기 때문이다. WPF 프레임워크에서 모델과 뷰모델은 앞서 서술한 것처럼 C# 언어를 사용하지만, 뷰는 HTML과 비슷한 XAML 이라는 마크업 언어를 사용해서 구현되기 때문에 뷰 내부에서 해당 정보처리 요청에 대한 갱신만 골라서 시각을 기록하는 것은 간단하지 않다. 이에 따라 데이터를 분석하고 시각을 기록하기 용이한 모델과 뷰모델에만 Fig. 3과 같이 코드를 추가했다.
시각을 기록하는 코드를 추가하고 데이터를 수집하기 위해 앞서 선택한 정보처리 요청을 30번 보내봤다. Table 2는 기록된 시각들을 모두 tm1s 기준으로 지난 시간을 계산한 차트고, Fig. 4는 30번의 정보처리 중 첫 번째 5개의 정보처리 요청에 대해 프로그램이 각 위치를 지나는 시간을 tm1s 기준으로 그린 그래프다. 평균이 아닌 첫 번째 5개를 표현한 이유는 모든 개별적인 정보처리 요청이 똑같은 순서로 시각 기록 위치들을 지나는 것을 중요하게 생각해서이다. 실제로 Table 2를 보면 프로그램 흐름이 각 위치를 지나는 순서가 항상 같은 것을 볼 수 있다. 선택한 정보처리 요청에 대해 모델 1이 가장 먼저 갱신하고, 모델 1을 보고 있는 뷰모델 1과 뷰모델 2가 순차적으로 갱신한다. 그리고 모델 2가 다음으로 정보처리 요청에 대해 갱신하고 모델 2를 보고 있는 뷰모델 3이 마지막으로 갱신된다. Fig. 5에서 이 정보처리가 모듈들의 각 부분을 지나는 순서를 표현했다. 각 뷰가 처리되는 순서를 보면 3, 5, 8번째로서 뷰들이 갱신되는 시각의 차이가 생길 수밖에 없다.
위 현상은 WPF 프레임워크의 설계상 하나의 정보처리 요청(이벤트)에 대한 갱신은 끝까지 하나의 스레드가 담당하게 돼서 그런 것으로 파악된다. 해당 정보처리를 담당하는 스레드는 일단 모델 1에서 정보 갱신을 완료하고, 이에 대한 알림을 보낸다. 모델 1에 구독을 하고 있는 뷰모델 1과 뷰모델 2는 알림을 받고 각각 정보처리를 시작하는데 이 역시 같은 스레드가 순차적으로 진행하게 된다. 하지만 뷰모델 1의 처리가 끝나면 바로 다음에 뷰모델 2의 처리가 시작되는 것이 아니라 뷰 1이 뷰모델 1에 구독하고 있기 때문에 뷰 1의 처리가 먼저 진행된다. 마찬가지로 모델 2는 스레드가 모델 1, 뷰모델 1, 뷰모델 2에 대한 갱신을 하고 나서 정보처리를 하게 된다.
다음 장에서는 타겟 소프트웨어에서 동기화 기능을 만들기 위해 구현한 코드 구조와 기능을 구현한 위치에 대해 설명한다.
4. 동기화 기능 구조
앞서 사용했던 프로그램 흐름도를 원하는 대로 수정할 수 있다면 Fig. 6처럼 수정할 수 있다. 모델과 뷰모델들의 처리 순서가 어떻게 되는지는 상관없고 최종적으로 뷰들이 순서대로 갱신되는 것이 목표라 할 수 있다. 이 목표를 달성하기 위해 선행 연구들[10,11]이 제안한 것처럼 타깃 소프트웨어의 프로그램 흐름이 특정 위치를 지날 때 잠시 정지했다가 다른 주요 위치들도 지났다는 것을 확인하고 재개하는 방법으로 동기화 기능을 구현하였다. 만약 이를 구현하게 되면 Fig. 7처럼 각 뷰를 갱신하기 직전에 동기화 체크를 해서 모든 뷰모델이 뷰를 갱신시킬 준비가 됐는지 확인하고 나서 최종적으로 뷰들을 순차적으로 갱신시키는 형태가 된다. Fig. 8은 뷰모델 3에서 동기화 기능을 구현한 코드를 보여준다.
먼저 동기화가 필요한 위치에 있는 함수를 비동기 함수로 선언해서 이벤트를 발생시킨 스레드가 아닌 별도의 스레드가 이 함수를 수행하게 만들어야 한다. 그리고 해당 함수 안에서 동기화가 필요한 위치에 도달하면 동기화 모듈에 현재 위치에 도달했다는 것을 알리고, await 키워드를 사용해서 동기화 모듈이 동기화가 필요한 다른 위치들도 도달됐는지 알려주기를 기다린다. 이런 방식으로 구현하면 프로그램 흐름이 동기화 기능을 구현한 모든 위치에 도달해야지만 실행을 계속하게 돼서 프로그램 흐름 순서를 제어할 수 있게 된다.
Table 1에서 정의한 시각 중 각 모델 혹은 뷰모델이 정보처리 요청을 받은 시각을 동기화하거나 데이터 갱신을 끝낸 시각을 동기화할 수 있는데 이 중 뷰모델이 데이터 갱신을 끝내는 지점은 동기화 하면 동기화 효과를 측정할 수가 없다. 왜냐하면 뷰모델이 데이터 갱신을 하면 뷰에 알림을 보내는데 앞서 설명한 대로 뷰 쪽에 시각을 기록하는 코드를 넣기 어려워서 뷰가 화면 갱신을 했다는 것을 알 수 없기 때문이다. 따라서 Table 3과 같이 4가지 상황에서 시간을 측정하였다.
다음 장에서는 앞서 3장에서 한 것처럼 상황마다 정보 갱신 요청을 30번 해서 프로그램 흐름을 기록하는 실험을 한다. 이 결과를 가지고 어떤 소프트웨어 구조가 동기화 효과가 제일 크고 그 원인에 대해 알아본다.
5. 실험 결과
Cnone은 동기화 기능이 없는 구조로서 앞서 이미 데이터를 모았으니 추가적으로 Cms, Cme, Cvms를 구현해서 데이터를 기록했다.
Table 4, Table 5, Table 6은 각각 Cms, Cme, Cvms를 구현해서 tm1s를 기준으로 각 기록 위치를 지난 시간을 계산한 차트고 Fig. 10, Fig. 11, Fig. 12도 비슷하게 첫 5개의 정보처리가 tm1s를 기준으로 각 기록 위치를 지난 시간을 표현한 그래프다. 이 데이터를 가지고 동기화의 효과를 계산하기 위해 몇 가지 공식을 다음과 같이 정의한다.
먼저 (1)은 프로그램이 모델 1이 정보 갱신을 받은 시각과 모델 2가 정보 갱신을 받은 시각 중 먼저 지나간 시각에서 나중에 지나간 시각을 빼서 모델 간 정보 갱신 요청을 받은 시각의 최대 차이를 구하는 것이다.
마찬가지로 (2)는 프로그램이 모델 1이 정보 갱신을 마친 시각과 모델 2가 정보 갱신을 마친 시각 중 먼저 지나간 시각에서 나중에 지나간 시각을 빼서 모델 간 정보 갱신을 마친 시각의 최대 차이를 구하는 것이다. (1), (2)를 계산하는 이유는 이 두 값을 가지고 모델 쪽에서 프로그램이 동기화가 얼마나 됐는지 측정하기 위함이다.
다음으로 (3)은 프로그램이 뷰모델 1, 뷰모델 2, 뷰모델 3 중 가장 먼저 정보 갱신 알림을 받은 시각과 가장 늦게 정보 갱신 알림을 받은 시각의 차이를 구하는 공식이다.
마지막으로 (4)는 프로그램이 뷰모델 1, 뷰모델 2, 뷰모델 3 중 가장 먼저 정보 갱신을 마친 시각과 가장 늦게 정보 갱신을 마친 시각의 차이를 구하는 공식이다. (3), (4)를 계산하는 이유는 이 두 값을 가지고 뷰모델 쪽에서 프로그램이 동기화가 얼마나 됐는지 측정하기 위함이다.
Table 7은 앞서 모은 데이터를 가지고 (1) ∼ (4) 공식대로 시간을 계산한 수치들의 평균을 나열한 표다. 먼저 Cnone을 보면 다른 상황들에 비해 (1) ∼ (4) 모두 비슷한 수치가 나왔다. 이는 앞서 Fig. 5에서 보인 것처럼 프로그램 흐름이 모델과 뷰모델을 순차적으로 거쳐 가는데 모델 1에서 데이터 처리하는 데 걸리는 시간이 모델 2에서 데이터 처리하는 데 걸리는 시간과 비슷해서 Tms와 Tme가 크게 차이 나지 않고, 마찬가지로 뷰모델 1에서 데이터 처리하는 데 걸리는 시간이 뷰모델 2 혹은 뷰모델 3에서 데이터 처리하는 데 걸리는 시간과 비슷해서 Tvms와 Tvme가 크게 차이 나지 않는다.
추가로 뷰모델에 동기화 기능을 구현하지 않은 Cnone, Cms, Cvms를 보면 모두 Tvme가 Tvms보다 낮은 것을 볼 수가 있다. 이는 뷰모델 1에서 데이터 처리하는 데 걸리는 시간이 뷰모델 3에서 데이터 처리하는 시간보다 더 길다고 볼 수 있는데 실제로 뷰모델 내부 처리 과정을 살펴보면 일관성이 있다고 볼 수 있다. 뷰모델 1에서는 데이터 갱신 과정에서 11개의 속성을 갱신시키지만, 뷰모델 3에서는 데이터 갱신 과정에서 하나의 속성만 갱신시켜서 데이터를 처리하는 데 시간이 더 걸리는 걸로 파악된다.
다음으로 Cms를 보면 Cnone과 비교해서 Tms가 78.5 % 낮아진 것을 볼 수가 있다. 이는 모든 모델이 정보 처리 요청을 받을 때까지 모델의 데이터 갱신을 못 하게 동기화 기능을 넣은 것이 의도대로 작동한 것으로 보인다. 동기화 기능이 없던 Cnone에서는 모델 1에서 데이터 갱신 알림을 받는 뷰모델 1과 뷰모델 2가 모델 2가 정보 처리 요청을 받기 전에 데이터 갱신 과정을 거치게 되는데 Cms에서는 모델 1이 정보 처리 요청을 받으면 코드 내 await 키워드에서 프로그램 흐름을 멈추고 모델 2에 정보 처리 요청을 보내게 된다. 모델 2도 정보처리 요청을 받은 위치에 도달하면 모델 1에 Task가 완료됐다는 알림을 보내서 모델 1에서 프로그램 흐름이 재개되게 되므로 뷰모델 쪽으로 순서가 넘어가기 전에 모델의 처리가 모두 시작되고 그로 인해 Tms 수치가 낮게 나온 것이다.
하지만 모델 쪽 처리의 시작 시각을 동기화했으니 Tme 수치도 낮게 나올 거로 추측 했지만 예상과는 다르게 Tme 수치는 Cnone과 비교해서 19.8 % 낮은 값으로 Cms의 감소보다는 훨씬 적게 효과를 봤고, Tvms와 Tvme도 각각 21.7 %, 22.6 % 감소했다. 원인은 Fig. 9를 보면 알 수 있는데, 동기화 기능을 설정한 위치까지는 동기화 효과를 봤지만, 그 이후로는 여전히 프로그램 흐름이 순차적으로 진행돼서 Tme 뿐만 아니라 Tvms와 Tvme에서도 큰 효과를 보지 못한 걸로 파악이 된다. 모델 2가 정보처리 요청을 받으면 모델 1의 await이 바로 풀리고 프로그램 흐름이 모델 1쪽으로 넘어가서 그다음 순서인 tm1e, tvm1s ∼ tvm2e, t2me 그리고 마지막으로 tvm3s와 tvm3e를 통과한 것으로 보인다. 이에 따라 Tme, Tvms, Tvme는 여전히 높은 수치를 보인 것이고, 일관적으로 비슷한 감소율을 보인 것은 Cnone 과 비교했을 때 프로그램이 tvm2e와 tvm3s 사이에 tm2s, tm2e 두 위치를 거치는 것이 아닌 tm2e 만 거치기 때문에 그만큼 일관적으로 시간 차이가 감소한 것으로 보인다.
다음으로 Cme를 보면 Cnone과 비교해서 Tms가 61.7 % 낮아졌고, Tme가 61.9 % 낮아진 것을 볼 수가 있다. Cms때와 비슷하게 프로그램 흐름이 모델에서 뷰모델로 넘어가기 전에 동기화 기능이 작동해서 Cnone과 비교했을 때 Tms와 Tme는 많이 감소하고 Tvms와 Tvme는 비교적 적게 감소했다. Tvme와 Tvme는 각각 36.4 %, 37.8 % 감소했는데 이는 프로그램이 tvm2e와 tvm3s 사이에 tm2s, tm2e 두 위치를 거치지 않고 바로 순차적으로 진행되기 때문에 그만큼 일관적으로 시간 차이가 감소한 것으로 보인다.
마지막으로 Cvms를 보면 Cnone과 비교해서 Tms, Tme, Tvms가 각각 35.8 %, 34.6 %, 34.7 % 낮아졌고, Tvme가 많이 감소해서 78.4 % 낮아진 것을 볼 수가 있다. Cms, Cme와 비교해서 Tms, Tme가 오히려 더 적게 감소한 것을 볼 수가 있는데 Fig. 11을 보면 원인을 알 수 있다.
Cms, Cme와 비슷하게 프로그램의 흐름이 tm1s, tm1e부터 순차적으로 통과하지만, 다음에 tm2s로 가는 것이 아니라 tvm1s, 그리고 tvm2s를 통과하는 것을 볼 수 있다. 이는 동기화 기능이 모델에서 정보 처리 요청을 받는 시간이나 갱신 완료 시간을 서로 동기화하는 것이 아니라 뷰모델 쪽에서 데이터 갱신 알림을 받을 때를 동기화해서 그런 것이다. 그래서 모델 1에서는 await 키워드를 만날 일 없이 바로 뷰모델 1, 그리고 뷰모델 2에 데이터 갱신 알림을 보내는 것이고, 각 뷰모델에서는 데이터 갱신 알림을 받자마자 await 키워드에서 멈추고 다음 뷰모델로 프로그램 흐름을 보내는 것이다. 뷰모델 2가 await 키워드에 도달하면 그다음 순서는 모델 2로 가서 데이터를 갱신하고 뷰모델 3으로 알림을 보내고, 뷰모델 3도 await 키워드에 도달하면 다시 뷰모델 1부터 순차적으로 await 단계를 넘어가 데이터 갱신 과정을 거치게 되는 것이다. 따라서 Tms, Tme, Tvms는 모델 쪽의 동기화가 없었기 때문에 Cms, Cme 보다 감소량이 적었던 것이고 반대로 Tvme는 크게 효과를 본 것이다. 다르게 표현하면 모델 쪽 처리 과정을 모두 마쳤기 때문에 뷰모델 데이터 갱신을 하는 동안 다른 작업을 할 필요가 없어서 Tvme 값이 많이 감소할 수 있던 것이다.
만약 동기화 기능을 모델과 뷰모델 두 군데에 넣으면 (Cme와 Cvms를 동시에 적용하면) Tms, Tme, Tvms, Tvme 모두 감소시킬 수 있겠지만 본 논문의 목적상 그럴 필요는 없어 보인다. 최종적으로 각 화면 영역이 갱신되는 시간 차이를 줄이는 게 목표이기 때문에 중간에 어떤 순서로 프로그램이 실행되어도 현재 관점에서는 문제가 없다. 오히려 너무 많은 위치에 동기화 기능을 구현 해놓으면 프로그램 흐름이 자주 옮겨 다녀서 특정 정보처리 요청에 대해 최종적으로 모든 화면 영역이 갱신되는 시간까지 더 오래 걸릴 수 있다. 그러므로 본 논문에서 측정한 Tvme 값이 화면 영역 간 갱신 시간 차이를 측정하는 가장 중요한 값이라고 볼 수 있고, 이 값을 78.4 % 감소시켜서 모든 소프트웨어 구조 중 가장 크게 낮춘 Cvms가 제일 적합하다는 것을 확인하였다.
하지만 본 논문의 한계점은 앞서 언급한 것처럼 타깃 소프트웨어의 구조상 뷰 쪽에서 동기화 기능을 위한 코드를 작성하기 어려워서 Cvme는 측정하지 않은 것이다. 만약 뷰 쪽에도 시간을 측정할 수 있다면 화면 영역 간 갱신 시간 차이를 줄이는 데는 Cvme가 더 효과적일 수 있고, 나아가서 비동기 함수와 await 키워드 자체를 뷰 쪽에서 구현이 가능하면 더욱 큰 효과를 볼 수도 있을 것으로 생각된다.
6. 결 론
본 논문에서는 많고 다양한 정보를 처리해야 되는 무기체계 UI 소프트웨어의 시각적 동기화 문제를 해결하기 위해 비동기 함수를 사용한 동기화 기능을 구현해서 화면 영역 간 갱신되는 시간 차이를 최대 78.4 %까지 줄였다. 이 방법은 모듈화된 MVVM 소프트웨어의 시각적 동기화 문제를 해결하는 새로운 기법으로서, 흐름 동기화 기법처럼 정보 처리 별 인터페이스 갱신을 통해 갱신 시각 차이를 최소화하면서, 동시에 관찰자 동기화 기법의 알림 구독 시스템을 사용해서 코드 유지보수성도 좋게 한다. 본 논문에서는 MVVM 형태로 된 타깃 소프트웨어의 구조상 뷰 쪽에서의 동기화까지 구현하진 못했지만 추후 연구에서는 뷰의 프로그램 흐름도 제어해서 더 효과적인 동기화 효과를 구현하고자 한다.