Getting Started

모터 제어 패널 예제로 배우는 Going Library HMI 개발 전체 과정

시작하기 전에 — 개발 환경이 아직 구성되지 않았다면 먼저 개발 환경 구성을 완료하세요.

시나리오 개요

이 튜토리얼에서는 모터 제어 HMI를 만듭니다. 2개 페이지로 구성된 간단한 프로젝트이지만, Going Library의 핵심 기능(UI 컨트롤, Modbus 통신, 설정 관리)을 모두 다룹니다.

페이지 역할 주요 컨트롤
PageMain 모터 모니터링 + 제어 GoLamp × 2, GoButton × 2, GoValue, GoSlider, GoLabel
PageSetting 통신 파라미터 설정 GoInputString, GoInputNumber × 2, GoButton × 2
단계 작업 환경
Step 1프로젝트 브리프 작성Claude 채팅 / Claude Code
Step 2.gud 파일 생성Claude 채팅 / Claude Code
Step 3UIEditor 조정 + MakeCode사용자 (UIEditor)
Step 4C# 코드 구현Claude Code
Step 5빌드 및 실행사용자 / Claude Code

Step 1 — 프로젝트 브리프 작성

Claude에게 "새 HMI 프로젝트 시작할게요"라고 말하면 인터뷰가 시작됩니다. Claude가 프로젝트 이름, 화면 구성, 통신 방식 등을 순서대로 질문하며 project_brief.md를 작성합니다.

기존 자료(화면 이미지, 레지스터 맵 엑셀 등)가 있으면 함께 전달하면 더 빠릅니다.

이 시나리오의 브리프 요약:

프로젝트명 MotorControl
해상도 1024 × 600
테마 Dark
통신 Modbus TCP (192.168.0.10:502)
페이지 PageMain (모니터링+제어), PageSetting (통신 설정)

레지스터 맵:

주소 명칭 설명 R/W FC
0x0000RunState운전 상태 (0=정지, 1=운전)RFC3
0x0001CurrentRPM현재 RPMRFC3
0x0002ErrorCode에러 코드RFC3
0x0010TargetSpeed목표 속도 (rpm)R/WFC3/FC6

Step 2 — .gud 파일 생성

브리프가 완성되면 Claude가 .gud 파일(JSON)을 자동 생성합니다. .gud는 GoDesign 직렬화 포맷으로 UIEditor에서 열 수 있습니다.

MotorControl.gud
├── GoDesign (1024×600, Dark)
├── Pages
│   ├── PageMain
│   │   └── GoTableLayoutPanel (2행)
│   │       ├── 상단: GoLamp×2, GoValue(RPM), GoLabel(상태)
│   │       └── 하단: GoButton×2(운전/정지), GoSlider(속도)
│   └── PageSetting
│       └── GoTableLayoutPanel
│           ├── GoInputString(IP), GoInputNumber(Port, Timeout)
│           └── GoButton×2(저장, 돌아가기)
└── Windows: {} (없음)

Step 3 — UIEditor에서 조정 + MakeCode

사용자가 직접 수행하는 단계입니다.

  1. 바탕화면의 UIEditor 바로가기로 실행
  2. MotorControl.gud 파일 열기
  3. 컨트롤 위치/크기 미세 조정 (드래그 앤 드롭)
  4. MakeCode 실행 → C# 프로젝트 자동 생성

생성되는 파일:

MotorControl/
├── MotorControl.csproj       ← NuGet 참조 포함
├── design.json               ← 런타임 로드용 (수정 금지)
├── Program.cs                ← 진입점
├── MainWindow.cs             ← 사용자 파일
├── MainWindow.Designer.cs    ← 자동생성 (수정 금지)
├── Pages/
│   ├── PageMain.cs           ← 사용자 파일
│   ├── PageMain.Designer.cs  ← 자동생성 (수정 금지)
│   ├── PageSetting.cs        ← 사용자 파일
│   └── PageSetting.Designer.cs ← 자동생성 (수정 금지)

*.Designer.cs와 design.json은 UIEditor가 관리합니다. 직접 수정하지 마세요.

Step 4 — C# 코드 구현

MakeCode 완료 후, 생성된 프로젝트 폴더를 Claude Code 작업 디렉터리로 지정하고 코드 구현을 요청합니다. Claude Code가 *.cs (사용자 파일)만 수정합니다.

Program.cs + Main

using MotorControl;

Main.Init();

using var view = new MainWindow();
view.Run();

Main.Stop();

public static class Main
{
    public static DataManager DataMgr { get; } = new();
    public static DeviceManager DeviceMgr { get; } = new();

    public static void Init()
    {
        DataMgr.Load();       // 설정 로드
        DeviceMgr.Start();    // 통신 시작
    }

    public static void Stop()
    {
        DeviceMgr.Stop();     // 통신 종료
    }
}

DeviceManager (Modbus TCP)

using Going.Basis.Communications;

public class DeviceManager
{
    public MasterTCP TCP { get; } = new();

    public DeviceManager()
    {
        TCP.WordAreas.Add(0x0000, "D");
        TCP.BitAreas.Add(0x0000, "P");
    }

    // 읽기 — 의미있는 프로퍼티
    public bool IsConnected  => TCP.IsOpen;
    public bool IsRunning    => TCP.GetWord(1, "D0") == 1;
    public int  CurrentRPM   => TCP.GetWord(1, "D1") ?? 0;
    public int  TargetSpeed  => TCP.GetWord(1, "D16") ?? 0;

    // 쓰기
    public void SetTargetSpeed(int rpm) => TCP.SetWord(1, "D16", rpm);
    public void SetRunCmd(bool on)      => TCP.SetBit(1, "P0", on);
    public void SetStopCmd(bool on)     => TCP.SetBit(1, "P1", on);

    public void Start()
    {
        var s = Main.DataMgr.Setting;
        TCP.IP = s.IP;  TCP.Port = s.Port;  TCP.Timeout = s.Timeout;

        TCP.MonitorWord_F3(1, 0x0000, 3);   // D0~D2
        TCP.MonitorWord_F3(1, 0x0010, 1);   // D16 (TargetSpeed)
        TCP.MonitorBit_F1(1, 0x0000, 2);    // P0~P1
        TCP.Start();
    }

    public void Stop() => TCP.Stop();
}

PageMain.cs — UI 이벤트 + 데이터 반영

public partial class PageMain : GoPage
{
    public PageMain()
    {
        InitializeComponent();

        btnStart.ButtonClicked += (s, e) => Main.DeviceMgr.SetRunCmd(true);
        btnStop.ButtonClicked  += (s, e) => Main.DeviceMgr.SetStopCmd(true);

        sldSpeed.ValueChanged += (s, e) =>
            Main.DeviceMgr.SetTargetSpeed((int)sldSpeed.Value);
    }

    // 매 프레임 호출 — 통신 데이터를 UI에 반영
    protected override void OnUpdate()
    {
        var dev = Main.DeviceMgr;
        lampRun.OnOff  = dev.IsRunning;
        lampStop.OnOff = !dev.IsRunning;
        valRPM.Value   = dev.CurrentRPM;
        sldSpeed.Value = dev.TargetSpeed;
        lblStatus.Text = dev.IsConnected
            ? (dev.IsRunning ? "운전 중" : "정지")
            : "통신 끊김";

        base.OnUpdate();
    }
}

PageSetting.cs — 설정 저장/로드

public partial class PageSetting : GoPage
{
    public PageSetting()
    {
        InitializeComponent();

        var s = Main.DataMgr.Setting;
        inpIP.Value      = s.IP;
        inpPort.Value    = s.Port;
        inpTimeout.Value = s.Timeout;

        btnSave.ButtonClicked += (s, e) =>
        {
            Main.DataMgr.Setting.IP      = inpIP.Value;
            Main.DataMgr.Setting.Port    = (int)inpPort.Value;
            Main.DataMgr.Setting.Timeout = (int)inpTimeout.Value;
            Main.DataMgr.Save();
        };

        btnBack.ButtonClicked += (s, e) =>
            MainWindow.Current.Design.SetPage("PageMain");
    }
}

Step 5 — 빌드 및 실행

cd MotorControl
dotnet build
dotnet run

design.json이 실행 디렉터리에 필요합니다. MakeCode가 .csproj에 빌드 복사 설정을 포함하므로 별도 작업 불필요.

전체 흐름 요약

"새 HMI 프로젝트 시작할게요"
  ↓ Claude가 인터뷰 진행
project_brief.md 완성
  ↓ Claude가 JSON 생성
MotorControl.gud 생성
  ↓ 사용자가 UIEditor에서 조정
MakeCode → C# 프로젝트 생성
  ↓ Claude Code가 코드 구현
Program.cs, DeviceManager, PageMain, PageSettingdotnet build → dotnet run

라즈베리파이에 배포하려면 → ui-mcp.md (gtcli 배포 가이드) 참조