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 3 | UIEditor 조정 + MakeCode | 사용자 (UIEditor) |
| Step 4 | C# 코드 구현 | 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 |
|---|---|---|---|---|
0x0000 | RunState | 운전 상태 (0=정지, 1=운전) | R | FC3 |
0x0001 | CurrentRPM | 현재 RPM | R | FC3 |
0x0002 | ErrorCode | 에러 코드 | R | FC3 |
0x0010 | TargetSpeed | 목표 속도 (rpm) | R/W | FC3/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
사용자가 직접 수행하는 단계입니다.
- 바탕화면의 UIEditor 바로가기로 실행
MotorControl.gud파일 열기- 컨트롤 위치/크기 미세 조정 (드래그 앤 드롭)
- 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, PageSetting
↓
dotnet build → dotnet run
라즈베리파이에 배포하려면 → ui-mcp.md (gtcli 배포 가이드) 참조