장비 업계에서 Winform 을 벗어나 WPF 로 개발을 한다는건..

안녕하세요 :slight_smile:
.Net Dev 에 올리는 첫 글이라 매우 두근두근 하네요…!
저는 장비 회사에서 c# 으로 윈도우 어플리케이션을 개발 하고 있는 5년차 으린이 엔지니어 입니다.
최근에 팀 내부에서 Winform 으로 개발했던 프로그램을 WPF 로 전환해서 개발중인데
그 과정을 공유하고 기록하고 싶어서 글을 쓰게 됐습니다 :slight_smile:

바야흐로… 저는 입사하고 첫 프로그램 개발을 Winform 으로 시작했습니다
그런데 Winform 로 개발하는 것에 익숙해지기 전,
새로운 기술에 대한 거부감이 없고 오히려 사랑하시는(?) 진보적인 팀장님께서 추후 Maui 로 넘어가기 위해 Xaml 를 경험할 겸 WPF 로 개발을 해보자고 선언 하셨고, 당시 꼬마 개발자였던 저는 C# 언어도 제대로 다룰지 모르지만 그저 팀장님의 열정을 존경하며 WPF 로 넘어가 어설프게나마 MVVM 이라는 디자인 패턴을 사용해서 프로그램을 개발했었습니다. GUI 보다 제어 로직이 중요한 장비 업계에서 프론트 영역에도 깊은 관심을 갖는다는 것이 당시 저에게 ‘배울게 많겠다’ 라는 생각이 들게 해주었고 열정있게 임했던것 같아요 ㅎㅅㅎ

하지만… 당시 꼬마 개발자인 저는 MVVM 이라는 패턴을 ‘왜 쓰는지’, ‘어떻게 쓰는건지’ 에 대해 심도있게 생각하지 못했고 WPF 로 개발을 한다면 MVVM 은 무적권 써야해!! 라는 생각만으로
View - ViewModel - Model 이라는 틀에 갖혀 개발을 했었습니다.
MVVM 에 대한 이런 얉은 이해력으로는 기존 프로그램에 있는 제어 로직을 패턴을 지키며 사용하기 어려웠고 어찌저찌 프로그램을 개발하긴 했지만 아무래도 개발 일정 안에 WPF 로는 완성도 있게 만들 수 없겠다 싶어 다시 Winform 으로 넘어가 작업 했었어요ㅜ

그러다 4년차 쯤 되니 프로그램을 개발할때 유지보수와 같은 프로그램 안정화에 관심을 쏟을 수 있게 되었고Winform 으로는 어느정도 편하게 개발 할 수 있게 됐을때
팀장님께서 내부 프로그램 모듈화 및 리팩토링을 공표하셨고, 해결해야 될 고민 중 하나인
’ 과금 하지 않고 어떻게 하면 프로그램을 이쁘고 보기 좋게 만들 수 있을까’ 를 팀원들과 토론 하던 와중
’ 어차피 Maui 로 넘어가는 것이 최종 목표라면 초반에 고생하더라도 이번기회에 WPF 로 내부 프로그램을 개편하죠!! ’ 라고 겨우 찍먹만 해본 제가 Winform 개발자만 있는 팀원들을 향해 외쳐버렸었죠…

그렇게 온 팀원이 WPF 프로그램 개발에 착수하게 되었고
골치아픈 일거리를 던져버린것 같아 (실제로 맞기도하고…)
도움이 되고자 이전에 WPF 로 개발했었던 경험을 토대로 ‘MVVM 이라는게 무엇인지’ ,
그리고 MVVM 만으로는 역설적이지만 MVVM 패턴을 고수하기 힘들다는걸 느껴봤기에
MVVM + DI 아키텍처 구상, DTO 개념 등을 공부 및 공유해가며 개발한지도 언 반년이 지났네요…!

장비업계 프로그램을 개발하는거니까 아무래도 나중에 양산에서 GUI 로직 수정이 어려우면
WPF 장점 따위는 알고싶지도 않게 될 수도 있으니, WPF 에서도 쉽게 GUI 로직을 수정할 수 있도록 MVVM 을 지키며 구현하는걸 염두해 두며 개발하다 보니까 예전에는 안보이던 바인딩의 장점, MergedDictionaries 의 활용, attached property 의 확장성 그리고 무엇보다도 커스텀 컨트롤의 높은 자유도가 보였고 어느 방면에선 Winform 보다 WPF 가 더 편하다고 느껴지기도 하더라구요 :face_holding_back_tears:

큼큼… 주저리 주저리 얘기가 길어졌는데
결론은 장비 업계에서 Winform 을 벗어나 WPF 로 개발 한다는 건 정말 어려운 일이었지만 공부할수록 단점보다 장점이 더 많이 보이고 있어서 힘들지만 즐겁게 일하고 있네요
언능 개발중인 내부 프로그램이 빛을 내길 바라면서 ,
읽어주셔서 감사해요 :slight_smile:

22개의 좋아요

3D 가속기가 대중화되기 전이었던 Windows XP 시절에는 일상적인 WPF 애플리케이션조차 GPU가 없으면 성능이 크게 떨어지는 것이 현실적인 허들이었습니다. 하지만 지금은 3D 가속은 모든 PC 환경에서 기본 제공되는 표준 기능이 되어 더 이상 문제가 되지 않습니다.

장비 업계에서는 이 시기부터 제품화가 진행되었기 때문에 기존 기술 스택과 레거시 코드(COM, ActiveX 등)로 인해 여전히 Windows Forms 같은 GDI 기반 애플리케이션을 유지하는 경우가 많을 것입니다.

이런 상호 운용성 이슈가 없다면, 말씀하신 것처럼 Windows Forms에서 WPF로, 더 나아가 Avalonia 같은 최신 크로스 플랫폼 UI 기술로 학습을 확장하는 것은 충분히 타당하고 바람직한 방향이라고 생각합니다. :smiley:

7개의 좋아요

장비업계라니 제가 진행하고 있는 오픈소스 툴킷 라이브러리와 연관있겠다 싶어 댓글 답니다. 제가 개발중인 툴킷은 산업용 터치스크린 전용 앱 개발을 위한 라이브러리 입니다. (SCADA, HMI)

특징은, UI라이브러리(WPF, AvaloniaUI, WinUI3) 와 독립적으로 Xaml 코드 작성 없이 MVVM 의 ViewModel 계층 까지만 구현하면 이를 개발자의 필요에 따라 각각의 UI Framework용 앱으로 View를 내부적으로 처리해서 앱으로 빌드할 수 있는 라이브러리입니다.

아래 샘플코드를 보여드릴께요. GeneratorAvm 클래스가 있습니다. 툴킷을 사용하는 개발자가 작성하게 될 발전기 클래스이며 Avm은 Asset View Model 의 약어입니다.

CurrentPower, CurrentTemperature 두 속성이 있는데 NumericPvm 제너릭 타입입니다.

NumericPvm은 수치형 속성 ViewModel 이며 Pvm은 PropertyViewModel 의 약어입니다.

NumericPvm은 View 생성에 필요한 여러 데코레이터를 개발자가 추가할 수 있습니다.

  • 유닛단위:, Voltage, Temperature, Length, …. 수치와 단위 변환 헬퍼메서드가 있습니다. 예를들어 길이 단위는 천문학에 쓰이는 거대 수치부터 반도체분야에 쓰이는 수치까지 툴킷에서 제공될 예정입니다.
  • NumericThreshold: 최소, 최대값, 경고 단계별 임계값들을 데코레이터로 추가할 수 있습니다. 경고메세지, 경고음 재생여부등을 설정할 수 있습니다.
  • 이 외 숫자형태로 표시할지, 그래프로 표시할지, 게이지로 표시할지 등 개발자 혹은 앱을 사용하는 사용자가 설정할 수 있는 데코레이터

이러한 구조로 ViewModel에 로직과 데코레이션 코드를 작성후 빌드하면 작성된 어셋들과 그 어셋들의 속성들의 목적에 맞도록 View레이어가 바인딩되어 하나의 앱으로 실행되게 됩니다.

아직은 개발 초기단계라 GitHub에 public으로 오픈된 상태는 아니지만, 나중에 어느정도 라이브러리가 구색이 갖춰지면 그 때 이곳(dotnetdev.kr)에 소개해 보도록 하겠습니다.

이 툴킷라이브러리의 목적은 다음과 같습니다.

  • C#과 Xaml에 익숙하지 않은 산업용 장비 소프트웨어 개발자들이 쉽게 사용할 수 있도록 Code snippet 중심으로 그리고 샘플코드를 카피페이스트 해서 빠르게 앱을 개발 할 수 있도록 할 것.
  • 툴킷 라이브러리 내부 구조를 복잡하지 않게 설계해 소스코드 분석과 확장을 어렵지 않도록. 다시말해 블랙박스처럼 내부구조를 만들지 않겠다는 얘기입니다.
  • 모든 UI는 키보드&마우스보다 터치인터페이스를 우선으로 설계
  • Xaml 코드(View Layer) 작성 없이 앱을 빌드할 수 있도록 광범위한 View Control과 앱 레이아웃을 갤러리 형태로 제공.

등등 이러한 방향으로 개발중 입니다.

public GeneratorAvm(string name, SandboxAppSettingsVm appSettings) : base(name)
{
    _appSettings = appSettings;

    var currentPower = new NumericPvm<uint>("CurrentPower");
    currentPower.Decorators.Add(new VoltageUnitViewDecorator<uint>(VoltageUnitType.Kilovolt));
    currentPower.Decorators.Add(new NumericThresholdViewDecorator<uint>(400, true, WarningSeverity.Warning, "The power is above 400 kV."));
    currentPower.MinValue = 0;
    currentPower.MaxValue = 500;
    currentPower.Value = 0;
    CurrentPower = currentPower;

    var currentTemperature = new NumericPvm<int>("CurrentTemperature");
    currentTemperature.Decorators.Add(new TemperatureUnitViewDecorator<int>(TemperatureUnitType.Celsius));
    currentTemperature.Decorators.Add(new NumericThresholdViewDecorator<int>(70, true, WarningSeverity.Info, "The temperature is above 70 degrees."));
    currentTemperature.Decorators.Add(new NumericThresholdViewDecorator<int>(80, true, WarningSeverity.Warning, "The temperature is above 80 degrees."));
    currentTemperature.Decorators.Add(new NumericThresholdViewDecorator<int>(90, true, WarningSeverity.Critical, "Temperature is too high!"));
    currentTemperature.MinValue = -10;
    currentTemperature.MaxValue = 100;
    currentTemperature.Value = 10;
    CurrentTemperature = currentTemperature;

    this.Initialize();
}

public NumericPvm<uint> CurrentPower { get; }

public NumericPvm<int> CurrentTemperature { get; }


첨부 이미지는 CheckBox와 RadioButton 샘플 이미지 입니다.

9개의 좋아요

정보 공유 감사드립니다. 혹시 실제로 살펴볼 수 있는 리포지터리가 있을까요?

2개의 좋아요

퍼블릭으로 공개 전환은 올해 말 쯤 목표로 하고 있습니다. 아직은 프로토타입 단계라서 재설계 작업이 수시로 이루어 지고 있습니다. 요즘 더위 때문에 집중하기가 쉽지 않네요. :sweat_smile:

5개의 좋아요

안녕하세요 :slight_smile: !!

안그래도 wpf 로 넘어오면서 제일 골치아팠던게 많은 레시피항목을 ListView 같은 컨트롤을 사용하지 않고 어떻게 하면 View 에 효율적으로 표현할까 였는데 ㅜㅜ

추후 public 으로 공개해주시면 관심있게 보겠습니다!

감사합니다 !

6개의 좋아요

그래서 WPF를 커스텀마이징 할수 있는 프로그램을 만들고 있습니다… 사용자 + 커스텀(개발) 프로그램 개발해서 노코딩으로 할수 있게 최대한 만들고 있어요…

4개의 좋아요

정말.. 공감이 되는 글이여서 댓글을 남깁니다.
저는 입사하고 3년동안 C++, MFC와 장비셋업을하며 3년동안 공장 출장을 다녔고 신입말 쯤에 Winform으로 개발하면서 다른 개발 커뮤니티 눈동냥하며 공부를 했습니다.

대학생때 WPF를 할줄은 알았지만 본격적으로 업무에 적용한건 6년정도 되었군요.
WPF MVVM을 사내 개발팀에 전파하고 운영하면서 정말 고생이란 고생은 다 해본 것 같군요 ㅠ
(그 누구도… -_- 총대를 메지 않기 때문에 기존의 레거시 플랫폼을 혼자서 컨버전 했습니다.)
저는 개발 파트팀 운영하면서 Prism과 Community Toolkit의 장점을 섞은 MVVM라이브러리를 만들어서 팀내에서 사용하고 있습니다.

Slog에 즐겁게 개발 과정을 적으면서 개발하던 중에 너무 일이 많아서.. Slog에는 글을 안올리고 있습니다.
(장비업계에 계시니 잘아실겁니다.ㅠ)
혹시나 기회가 된다면 닷넷 데브에 발표할 자리가 있으면 장비 업계에서는 어떻게 MVVM을 적용하고 레거시 기술을 비벼가면서 쓰고있는지 발표하면 재미있을것 같군요..ㅠ

7개의 좋아요

감사합니다 ㅎㅎ 이번 행사에 바로 해보시죠!

3개의 좋아요

개발 방법론의 하나이죠. 껍데기는 거들뿐.. 결국 제어를 어떻게 하는지 잘 표현해주고 사용자가 눌러서 원하는 제어로 바꾸게 해주고 그러는거죠. 그거 말고 mvvm 을 쓴다면 그건 ui 화면 없이도 내부 로직을 unit test 한다면 의미가 있겠지요. cli 상에서 테스트 코드를 만들수 있을테니까요. maui 를 타겟으로 한다는건 모바일이나 macos 등 다른 플랫폼을 염두에 둔다는 것인데 장비업계만 계속한다면 불필요한 선택이지요. 제가 보기엔 언제든 회사를 떠나 다른 일(앱, 서버, 웹 서비스등)을 할지 모르니 쉬엄쉬엄 준비하자 라고 해석이 되네요….