본문 바로가기

C#(WPF)

WPF 로딩시간 대처방법

[출처] http://wpfkorea.tistory.com/43

 

WPF를 사용하여 구현하고 있는 현재 프로젝트에서 한가지 문제가 생겼다.
개발 환경인 Windows Vista에서 테스트 할 때와 Windows XP에서 테스트 할때
로딩 시간이 엄청나게 차이가 난다는 것이다.

물론 간단한 UI를 가지고 있는 Application이라면 로딩시간이 차이가 별로 나지 않아 중요 하냐 싶지만,
현재 작업중인 프로젝트와 같이 규모가 큰 Application이라면 꼭 체크해봐야 할 문제다.

Vista에서 실행했을때는 1초 미만의 로딩 시간이 소요됬지만,  XP에서는 짧게는 8초 길게는 20초까지 걸렸다.
아마 저사양 PC에서도 마찬가지의 성능을 보일것 같다.

프로그램을 실행 시켰을때 뭔가 실행되고 있다는 느낌이 나야 기다리든지 말든지 할텐데,
화면상에 아무런 반응이 없어 프로그램이 실행되고 있는건지 알 방법이 없다.
(나는 처음엔 하드 디스크 돌아가는 소리로 실행됫는가를 판단햇엇다 -_-ㅋ )

한국사람들의 특성상 3초만되도 반응이 없다면 왜 실행이 안되 하고 다시 실행을 하려는 사람이 대부분 일것이다.
나또한 그렇지만, 어쨋든 WindowsXP사용자를 고려 해야 하기 때문에 해결할 수 밖에 없는 상황.

먼저 원인을 찾아야 했다. 어.디.서. 이렇게 오래걸리는것인가???
몇번의 디버깅으로 원인은 쉽게 찾을수 있었는데,

XAML에서 작성한 Code를 C# Code에서 사용가능하도록 해주며
프로그램이 실행될때 XAML에서 생성한 객체들을 초기화 해주는 .g.cs 파일 의 InitializeComponent()가 원인이였다.

보통 UserControl이나 Window를 VS상에서생성하게되면 InitializeComponent()부분을
해당 Class의 생성자에서 호출하도록 자동으로 구현해 놓는다.

객체를 생성하면 화면에 아무것도 보이지 않는 상태에서 열심히 XAML에서 생성한 객체들을 열심히 초기화 하는것이다. 전체적인 안정성면에서 이방법이 좋을지 모르겟지만, 기다릴줄 모르는 사용자들을 위해서라도 로딩시간에는 뭐라도 보여줘야만 한다.

그렇다면 어떻게 해결하면 좋을까?

나는 이러한 문제를 해결하기 위하여 Loaded 이벤트를 추가하고, Loaded이벤트에
InitializeComponent()의 호출부분을 추가했다.

Loaded 이벤트는 객체의 핸들이 모두 생성되었을때 호출되는 건데 이때부터 컨트롤의 크기를 조절하거나,
이름을 바꾼다거나 하는 작업이 가능하다.

Loaded가 되면 아래와 같이 Visibility속성을 Visible로 변경해 화면에 보여지도록 변경하고,
타이틀을 로딩중이다라는 메세지로 변경했다. 그다음 InitializeComponent()가 호출을 했다.

        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            this.Visibility = Visibility.Visible;
            this.Title = "로딩중입니다요!!";
            InitializeComponent();
        }

이렇게하면, 내부적으로 Window를 생성하는데 최소한의 부분한 실행이 되기 로딩시간을 최소화 할 수 있으며,
사용자에게 로딩중이라는 메세지를 전달 할 수 있다.

나는 아래와 같이 MainWindow를 띄우기전 로딩창을 만들어 사용자에게 로드되고 있음을 더 명확하게 알려줄 수 있도록 구현했다.

        void LoadingWindow_Loaded(object sender, RoutedEventArgs e)
        {
            InitializeComponent();
            this.Visibility = Visibility.Visible;
            MainWindow Main = new MainWindow();
            Main.Show();
            this.Close();
        }

내용을 살펴보면 Load가 완료되었을때 이번엔 InitializeComponent();가 먼저 나와있다.
로딩중이라는 메세지를 XAML로 작성했는데. 이부분은 어쩔수 없이 로딩을 해야 하기때문이다.
(최소한의 Code를 사용하여 부하를 줄였다.)

마찬가지로 Visibility  속성을 Visible로 바꾸고, 본격적으로 보여줘야하는 MainWindow를 생성을 했고,
생성이 끝나면 MainWindow를 Show해줌으로서 로딩창을 닫았다.

MainWindow에서의 InitializeComponent()는 어느 위치에 놓여져도 상관은 없다.
로딩화면에서 미리 로딩중이라는 메세지를 미리 전달을 했기때문에!!

하고보면 되게 간단하지만, 개발자나 사용자 입장에서 볼때 로딩창은 꼭 필요한 요소라고 다시한번 느꼇다.
오피스나 포토샵을 실행할때 괜히 로딩창나와서 시간만 잡아먹네 하고 생각했었는데,
이러한 문제를 겪고 나보니 왜 필요한가를 절실히 깨닳을수 있는 기회엿던거 같다.

이렇게 간단하게 해결할 수 있는 부분을 귀찮다고 빼먹지 말자!

------------------------------------------------------------------------------------------
언제나 그랫듯이 생각나는데로 막쓴 글이라 두서가없고 내용이 엉망일수도 있습니다.
혹시나 이글을 보고 질문이 있는 사람은 리플이나 메일 또는 메신저로 물어보길 바랍니다.