2. 도메인 ID 규칙
PlantPulse의 모든 마스터 데이터는 서버측 정규식 검증을 따릅니다. 서버가 정규식 매칭을 강제하며, 위반하면 E1002 (VALIDATION_FAILED)로 거절됩니다. 정확한 ID 설계는 확장 가능한 IoT 시스템 구축의 출발점입니다.
📖 플랫폼 전반의 컨벤션 요약은 도메인 ID 네이밍 컨벤션 페이지를 참고하세요.
2.1 한눈에 보는 ID 규칙 (서버 정규식 기준)
새 ID 는 «접두 풀네임 + 번호»입니다. 플랫폼이 스스로 발급할 때는 접두 뒤에 여섯 자리 번호를 붙입니다
(SITE_000001, TAG_000001). 도메인마다 시퀀스가 따로이고, 999999 를 넘으면 자릿수가 늡니다(ORDER_1000000).
| 도메인 | 정식 접두 | 옛 접두(계속 유효) | 발급 예 |
|---|---|---|---|
| 기업 (Enterprise) | ENTERPRISE_ | — | ENTERPRISE_000001 |
| 사이트 (Site) | SITE_ | — | SITE_000001 |
| 구역 (Area) | AREA_ | ASSET_ | AREA_000001 |
| 라인 (Line) | LINE_ | ASSET_ | LINE_000001 |
| 설비 (Equipment) | EQUIPMENT_ | ASSET_ | EQUIPMENT_000001 |
| 연결 (OPC) | OPC_ | — | OPC_000001 |
| 태그 (Tag) | TAG_ | — | TAG_000001 |
| 엣지 (Edge) | EDGE_ | — | 발급하지 않음 — EDGE_LINE1_01 처럼 직접 짓습니다 |
| 알람 설정 (AlarmConfig) | ALARM_CONFIG_ | 다섯 자리 번호, ALARM_CONFIG_TAG_… | ALARM_CONFIG_000001 |
| 직원 (Employee) | EMPLOYEE_ | EMP_ | EMPLOYEE_000001 |
| 고객 (Customer) | CUSTOMER_ | — | CUSTOMER_000001 |
| 제품 (Product) | PRODUCT_ | — | PRODUCT_000001 |
| 플로우 (Flow) | FLOW_ | — | FLOW_000001 |
| 워크오더 (Order) | ORDER_ | ORD_ | ORDER_000001 |
| 캘린더 (Calendar) | CALENDAR_ | CAL_ | CALENDAR_000001 |
| 교대 예외 (Shift override) | SHIFT_OVERRIDE_ | OV_ | SHIFT_OVERRIDE_000001 |
| 공정 세그먼트 (Process segment) | PROCESS_SEGMENT_ | SEG_ | PROCESS_SEGMENT_000001 |
| 설비 관계 (Asset relation) | ASSET_RELATION_ | REL_ | ASSET_RELATION_000001 |
| 설비 명령 (Asset command) | ASSET_COMMAND_ | — | ASSET_COMMAND_000001 |
| PLC 명령 영역 (Command area) | COMMAND_AREA_ | CMDAREA_ | COMMAND_AREA_000001 |
| 이미지 (Image) | IMAGE_ | IMG_ | IMAGE_000001 |
| 정비 오더 (Maintenance order) | MAINTENANCE_ORDER_ | 숫자만 | MAINTENANCE_ORDER_000001 |
| 로그인 계정 (User) | 없음 | — | 발급하지 않음 — ^[A-Z][A-Z0-9_]*$ |
접두 뒤에는 대문자·숫자·_ 만 옵니다([A-Z0-9_]+). 정비 오더·알람 설정의 새 ID 는 여섯 자리 이상의 번호만 받습니다.
asset_type 으로 판단합니다옛 ID 는 다시 키를 매기지 않으므로 앞으로도 계속 나옵니다. ASSET_ 하나가 구역·라인·설비에 두루 쓰였기 때문에,
접두를 보고 층을 추측하면 틀립니다. 층은 언제나 asset_type(E · S · A · L · M)을 읽으십시오.
접두로 도메인을 가를 때는 가장 긴 접두가 주인입니다 — ASSET_RELATION_… 과 ASSET_COMMAND_… 은
ASSET_ 이 아니고, SHIFT_PATTERN_… 은 SHIFT_ 가 아닙니다.
ID 를 주고 만들면 형식 검사만 통과하면 준 값이 그대로 저장됩니다. 번호를 발급하는 것은 ID 를 비워 둔 경우입니다.
V5 에서 비워 둘 수 있는 것은 구역·라인·설비(asset_id)와 캘린더(calendar_id)이고, POST /api/v5/site 는
site_id 를 반드시 받습니다. 옛 접두로 새로 만드는 것도 구역·라인·설비는 받습니다.
번호는 연속이 아닙니다 — 거절된 생성이 번호를 쓰고 지나가므로 빈 번호가 생기는 것이 정상입니다.
⚠️ 검증 강제: 서버는 위 규칙을 검사합니다. 위반하면 HTTP 422, 코드
E1002로 거절됩니다. 같은 ID 가 이미 있으면 HTTP 409 입니다.⚠️ 풀네임이 정답입니다:
CUST_,PROD_는 어느 시절에도 유효한 접두가 아니므로 거부됩니다.EMP_,ORD_,CAL_은 이미 있는 ID 를 위한 옛 접두이고, 새로 지을 때는 풀네임을 쓰십시오.⚠️
opc_id는OPC_하나뿐입니다: 엣지 출처든 외부 API 채널이든OPC_로 시작해야 합니다.EDGE_·TEST_·API_는 거부됩니다 — 엣지 출처는OPC_EDGE_00303처럼OPC_뒤에 붙입니다.edge_id는 별개 도메인이고EDGE_만 받습니다.
2.2 Site ID
정규식: ^SITE_[A-Z0-9_]+$
허용: SITE_… 만
가상·집계용 사이트도 접두는 같습니다 — SITE_V_… 처럼 접두 안에서 이름을 짓습니다. 별도 패턴이 아니라 이름 관례입니다.
예시
import plantpulse.api.v5.dto.request.SiteRequestV5;
import plantpulse.api.v5.dto.response.SiteResponseV5;
SiteRequestV5 req = new SiteRequestV5();
req.setSite_id("SITE_DJ"); // 대전공장
req.setSite_name("대전 1공장");
req.setLat("36.3504");
req.setLng("127.3845");
SiteResponseV5 created = client.site().create(req);
if (created == null) {
System.err.println("등록 실패 — site_id 정규식 확인 필요");
}
// 가상 사이트 (테스트·집계용) — 접두는 SITE_ 그대로
SiteRequestV5 vsite = new SiteRequestV5();
vsite.setSite_id("SITE_V_AGG_01");
vsite.setSite_name("집계 가상 사이트");
client.site().create(vsite);
❌ 잘못된 예 (모두 V5에서 null 반환)
req.setSite_id("DJ_FACTORY"); // ❌ SITE_ 누락 → E1002
req.setSite_id("site_00001"); // ❌ 소문자 → E1002
req.setSite_id("00001"); // ❌ 접두사 없음 → E1002
req.setSite_id("VSITE_01"); // ❌ V 변형 접두는 없다 → E1002
2.3 OPC ID
정규식: ^OPC_[A-Z0-9_]+$
허용: OPC_… 만
OPC ID는 데이터 수집의 물리·논리적 출처를 나타냅니다. 같은 OPC 타입 안에서도 의미 분리가 필요할 때는 _ 로 계층을 표현합니다.
OPC Type 별 권장 패턴
| OPC Type | 용도 | 권장 ID 접두 |
|---|---|---|
OPC | OPC UA / OPC DA 서버 | OPC_<UA서버이름>_<번호> |
PLC | Siemens, Mitsubishi, Allen-Bradley 등 | OPC_PLC_<라인>_<번호> |
MODBUS | Modbus TCP/RTU 디바이스 | OPC_MB_<장비>_<번호> |
DATABASE | 외부 RDBMS 폴링 | OPC_DB_<시스템> |
FILE | REST API/파일 임포트 | OPC_FILE_<시스템>_<번호> |
VIRTUAL | 테스트·시뮬레이션 | OPC_TEST_VIRTUAL_<번호> |
| Edge Gateway | 엣지 게이트웨이 (별도 edge_id 도메인 — ^EDGE_[A-Z0-9_]+$) | EDGE_<위치>_<번호> |
⚠️ 외부 API/파일 채널이든 테스트용이든 OPC 도메인에서는
OPC_FILE_…·OPC_TEST_…형태를 사용하세요.
예시
import plantpulse.api.v5.dto.request.OPCRequestV5;
OPCRequestV5 req = new OPCRequestV5();
req.setOpc_id("OPC_PLC_L1_001");
req.setOpc_name("Line1 메인 PLC");
req.setOpc_protocol("S7"); // 프로토콜 코드 — 소스 유형(PLC)은 여기서 파생
req.setSite_id("SITE_DJ");
req.setOpc_source_ip("192.168.10.50");
req.setOpc_source_port(102);
client.opc().create(req);
// ERP 연동 — REST API 로 들어오는 연결
OPCRequestV5 erp = new OPCRequestV5();
erp.setOpc_id("OPC_API_ERP_001");
erp.setOpc_protocol("API");
erp.setSite_id("SITE_DJ");
client.opc().create(erp);
// 테스트·시뮬레이션
OPCRequestV5 testOpc = new OPCRequestV5();
testOpc.setOpc_id("OPC_TEST_001"); // TEST_ 로 시작하면 E1002
testOpc.setOpc_protocol("API");
testOpc.setSite_id("SITE_DJ");
client.opc().create(testOpc);
// 엣지 자기감시 연결 OPC_SYSTEM_<edge_id> 는 엣지가 sync 로 선언한다 — 직접 만들지 않는다.
2.4 Edge ID
정규식: ^EDGE_[A-Z0-9_]+$
edge_id는 엣지 게이트웨이 디바이스 식별자로 opc_id 와 다른 도메인입니다.
req.setEdge_id("EDGE_LINE1_01");
// req.setEdge_id("OPC_EDGE_00303"); // ❌ OPC_ 는 edge_id 의 접두사가 아니다
// req.setEdge_id("TEST_EDGE_01"); // ❌ TEST_ 는 어느 도메인에서도 접두사가 아니다
2.5 Asset ID — 계층 구조의 핵심
설비 계층은 기업 → 사이트 → 구역 → 라인 → 설비 의 다섯 층입니다(ISA-95). 다섯 층이 모두 자산 트리의 노드이고,
노드의 층은 asset_type 이 말합니다.
| asset_type | 층 | 정규식 |
|---|---|---|
E | 기업 (Enterprise) | ^ENTERPRISE_[A-Z0-9_]+$ |
S | 사이트 (Site) | ^SITE_[A-Z0-9_]+$ |
A | 구역 (Area) | ^(AREA_[A-Z0-9_]+|ASSET_[A-Z0-9_]+)$ |
L | 라인 (Line) | ^(LINE_[A-Z0-9_]+|ASSET_[A-Z0-9_]+)$ |
M | 설비 (Equipment, Machine) | ^(EQUIPMENT_[A-Z0-9_]+|ASSET_[A-Z0-9_]+)$ |
💡 EQUIPMENT 코드가
M인 이유: Equipment = Machine. 검색·필터링에서 짧고 명확한 한 글자 코드를 사용합니다.
기업은 설치마다 하나뿐입니다. 둘째를 만들거나 하나뿐인 기업을 지우면 409(enterprise.only_one)로 거절됩니다 —
Site 서비스 를 보십시오.
노드의 층은 바꿀 수 없습니다. 구역을 라인으로 바꾸려는 수정은 거절되므로, 층이 틀렸다면 옮기는 것이 아니라 새로 만드십시오.
표준 ID 패턴 예시
대전공장(SITE_DJ)의 구역 하나, 그 안의 라인 하나, 그 위의 설비 하나 — ID 를 비워 두고 만들면 이렇게 됩니다.
AREA_000001 ← 구역
└ LINE_000001 ← 라인
└ EQUIPMENT_000001 ← 설비
예시 — 자산 트리 생성
import plantpulse.api.v5.dto.request.AssetRequestV5;
import plantpulse.api.v5.dto.response.AssetResponseV5;
// 1) 사이트 직속 Area
AssetRequestV5 area = new AssetRequestV5();
area.setSite_id("SITE_DJ");
area.setParent_asset_id("SITE_DJ"); // 부모는 사이트 ID
area.setAsset_name("조립구역");
area.setAsset_type("A");
client.asset().create(area);
// asset_id 를 비워 두면 플랫폼이 발급합니다 — 응답에서 AREA_000001 을 받습니다
// 2) Area 산하 Line
AssetRequestV5 line = new AssetRequestV5();
line.setSite_id("SITE_DJ");
line.setParent_asset_id("AREA_000001"); // 부모는 Area
line.setAsset_name("1라인");
line.setAsset_type("L");
client.asset().create(line);
// 3) Line 산하 Equipment
AssetRequestV5 equip = new AssetRequestV5();
equip.setSite_id("SITE_DJ");
equip.setParent_asset_id("LINE_000001"); // 부모는 Line
equip.setAsset_name("CNC #1");
equip.setAsset_type("M");
equip.setAsset_class_code("CNC"); // 설비 분류 — 기준정보에 있는 코드
client.asset().create(equip);
parent_asset_id 규칙
| 자식 타입 | parent_asset_id 값 |
|---|---|
구역 (A) | 사이트 ID (예: SITE_DJ) |
라인 (L) | 구역의 asset_id (예: AREA_000001) |
설비 (M) | 라인의 asset_id (예: LINE_000001) |
부모는 바로 위 층이어야 합니다. 층을 건너뛰거나 다른 사이트의 노드를 부모로 주면 거절됩니다.
2.6 Tag ID
정규식: ^TAG_[A-Z0-9_]+$
허용: TAG_… 만 (가상 태그도 TAG_ 로 시작한다)
Tag는 데이터 포인트(센서 값, 카운터, 상태 등)의 정의입니다. OPC와 1:1, Asset과는 0:N (선택적 연결) 관계입니다.
권장 패턴
| 시나리오 | 패턴 | 예시 |
|---|---|---|
| OPC 연결 태그 | TAG_<OPC ID 일부>_<채널번호> | TAG_EDGE_00303_90007 |
| 자체 정의 태그 | TAG_<도메인>_<번호> | TAG_PROD_COUNT_001 |
| Virtual Tag | TAG_V_<용도>_<번호> | TAG_V_OEE_LINE1 |
💡 Virtual Tag: 계산식·집계 태그도 접두사는
TAG_하나입니다. 구분이 필요하면 관례로TAG_V_를 씁니다(별도 패턴이 아니라 이름 관례). 태그가 «계산된 값인가» 는 태그의 계산 설정(use_calculation)이 답합니다. 만드는 법은 가상 태그에 있습니다.
예시
import plantpulse.api.v5.dto.request.TagRequestV5;
TagRequestV5 req = new TagRequestV5();
req.setTag_id("TAG_EDGE_00303_90007");
req.setTag_name("Spindle RPM");
req.setOpc_id("OPC_EDGE_00303");
req.setSite_id("SITE_DJ");
req.setLinked_asset_id("EQUIPMENT_000001");
req.setJava_type("Double");
req.setUnit("RPM");
req.setDescription("Spindle 회전수 (RPM)");
client.tag().create(req);
// Virtual Tag — 라인별 OEE 집계
TagRequestV5 vtag = new TagRequestV5();
vtag.setTag_id("TAG_V_OEE_LINE1");
vtag.setTag_name("Line1 OEE");
vtag.setSite_id("SITE_DJ");
client.tag().create(vtag);
tag_id vs tag_name vs alias_name
| 필드 | V5에서 변경 가능한가 | 용도 |
|---|---|---|
tag_id | 변경 불가 (재생성 권장) | 시스템 내부 고유 키. 불변 |
tag_name | update() 또는 patchBasic() | 사용자에게 보이는 이름 |
alias_name | patchMetadata() | 외부 시스템과 매핑하는 별칭 (예: HMI 태그명) |
가능하면
tag_id는 불변으로 두고, 표시 이름은tag_name/alias_name을 사용하시는 것을 권장합니다. tag_id 변경은 외부 시계열 데이터와의 정합성 이슈가 발생할 수 있습니다.
2.7 AlarmConfig / Employee / Customer / Product / Flow
이 도메인들도 모두 서버 검증이 강제됩니다. 정확한 전체 접두사를 사용하세요. 알람 설정 ID 는 번호 꼴만 받습니다(ALARM_CONFIG_000001).
// Alarm Config
AlarmConfigRequestV5 alarm = new AlarmConfigRequestV5();
alarm.setAlarm_config_id("ALARM_CONFIG_000001");
alarm.setSite_id("SITE_DJ");
// Employee
EmployeeRequestV5 emp = new EmployeeRequestV5();
emp.setEmployee_id("EMPLOYEE_E12345");
emp.setRole_code("OPERATOR"); // OPERATOR, SUPERVISOR 등
// Customer — CUSTOMER_ (전체 단어, CUST_ 아님!)
CustomerRequestV5 cust = new CustomerRequestV5();
cust.setCustomer_id("CUSTOMER_001");
cust.setExternal_customer_id("ERP_C001");
// Product — PRODUCT_ (전체 단어, PROD_ 아님!)
ProductRequestV5 prod = new ProductRequestV5();
prod.setProduct_id("PRODUCT_A001");
prod.setProduct_code("SKU-A001");
// Flow
FlowRequestV5 flow = new FlowRequestV5();
flow.setFlow_id("FLOW_OEE_DAILY");
flow.setSite_id("SITE_DJ");
❌ 자주 발생하는 거부 사례
cust.setCustomer_id("CUST_001"); // ❌ CUST_ 아님 → E1002
prod.setProduct_id("PROD_A001"); // ❌ PROD_ 아님 → E1002
emp.setEmployee_id("E12345"); // ❌ EMPLOYEE_ 누락 → E1002
flow.setFlow_id("flow_oee_daily"); // ❌ 소문자 → E1002
외부 시스템 이름 (external_system)
고객 · 제품 · 직원의 external_system 은 1~50자의 대문자 · 숫자 · _ · : 만 받습니다(^[A-Z0-9_:]{1,50}$).
: 는 그 시스템 안에서 번호를 유일하게 만드는 범위를 붙일 때 씁니다 — 예: SAP PM 의 클라이언트별 SAP_PM:100.
플랫폼은 범위를 해석하지 않고 external_system + external_id 쌍을 그대로 키로 씁니다.
SAP-PM 처럼 하이픈이 들어가면 거절되고, 거절 문구가 이 허용 문자를 알려 줍니다.
2.8 User ID (로그인 계정)
정규식: ^[A-Z][A-Z0-9_]*$
규칙: 대문자로 시작, 이후 [A-Z0-9_]만 허용
다른 도메인과 달리 고정 접두사가 없고, 첫 글자가 대문자여야 합니다.
✅ ADMIN
✅ OPERATOR_01
✅ KOPENS_USER
❌ admin → 소문자 시작
❌ 1USER → 숫자 시작
❌ _ADMIN → _ 시작
2.9 Calendar / Order
두 도메인도 서버가 접두를 검사합니다. 캘린더는 ^(CALENDAR_[A-Z0-9_]+|CAL_[A-Z0-9_]+)$, 워크오더는
^(ORDER_[A-Z0-9_]+|ORD_[A-Z0-9_]+)$ 입니다.
Calendar
import plantpulse.api.v5.dto.request.CalendarRequestV5;
CalendarRequestV5 cal = new CalendarRequestV5();
// calendar_id 를 비워 두면 플랫폼이 CALENDAR_000001 꼴로 발급합니다
cal.setSite_id("SITE_DJ");
cal.setAsset_id("EQUIPMENT_000001");
cal.setTarget_type("MTN"); // 점검 일정
| target_type | 의미 |
|---|---|
MTN | 정기 점검 (Maintenance) |
HOLIDAY | 휴일/비조업 |
INSPECTION | 검사 |
MEETING | 회의 |
Order
import plantpulse.api.v5.dto.Quantity;
import plantpulse.api.v5.dto.request.OrderRequestV5;
OrderRequestV5 order = new OrderRequestV5();
order.setOrder_id("ORDER_000001");
order.setSite_id("SITE_DJ");
order.setAsset_id("EQUIPMENT_000001");
order.setCustomer_id("CUSTOMER_001"); // CUSTOMER_ 주의!
order.setProduct_id("PRODUCT_A001"); // PRODUCT_ 주의!
order.setEmployee_id("EMPLOYEE_E12345");
order.setPlanned_quantity(Quantity.of("500", "EA")); // ISA-95 Quantity — 값 + UN/ECE Rec 20 단위
작업지시 상태(ISA-88): WAIT → START → END / ABORTED (자세한 내용은 Order 서비스)
2.10 ID 설계 모범 사례
권장 사항
- 불변성 유지 — 한번 부여한 ID는 변경하지 마세요. 변경이 필요하면 새 ID로 마이그레이션하시는 것을 권장합니다.
- ID 에 뜻을 싣지 마세요 — 층은
asset_type, 위치는 부모·경로가 말합니다. 꼭 직접 짓는다면 접두 풀네임을 지키세요. - 자동 ID 를 쓰세요 — ID 를 비워 두면 플랫폼이 접두 + 여섯 자리로 발급합니다.
- 대문자·언더스코어 고정 — 시스템 전반에서 대소문자 혼용은 피하고
[A-Z0-9_]패턴을 유지합니다. - 외부 시스템 ID는 별도 필드 — ERP/MES 원본 ID는
external_*_id필드에 보관하고, PlantPulse ID는 자체 체계를 유지하세요.
피해야 할 패턴
- ❌ 한글, 공백, 특수문자 사용 —
LINE_라인1,OPC 001 - ❌ 너무 짧거나 무의미한 ID —
S1,A,T01 - ❌ 접두사 누락 또는 잘못된 약어 —
CUST_001(정답:CUSTOMER_001),PROD_A001(정답:PRODUCT_A001) - ❌ 의미가 ID에 박혀있어 변경 불가 —
LINE_DJ_OLD_BROKEN_LINE
2.11 검증 실패 응답 확인
V5는 검증 실패 시 메서드가 null (또는 false)을 반환합니다. 자세한 에러는 envelope에서 확인할 수 있습니다.
import plantpulse.api.v5.service.BaseServiceV5;
import plantpulse.json.JSONObject;
// V5 서비스 내부는 envelope를 외부에 노출하지 않으나,
// 디버그 모드를 켜면 로그에 출력됩니다.
client = new APIClient_V5(proto, host, port, user, token, true); // debug=true
응답 envelope 예시:
{
"_status": "ERROR",
"_code": "E1002",
"_message": "validation failed: site_id must match ^SITE_[A-Z0-9_]+$",
"_http_status": 422
}
자세한 에러 코드는 응답 형식 및 에러 처리 참고.
2.12 ID 를 미리 받기 — POST /api/v5/domain-ids
객체를 만들기 전에 ID 를 알아야 하는 시뮬레이터 · 외부 시스템이 씁니다.
요청 {"domain": "EQUIPMENT", "count": 3} → 응답 {"domain": "EQUIPMENT", "ids": ["EQUIPMENT_000123", ...]}
| 칸 | 값 |
|---|---|
domain | 도메인 이름(대소문자 무관). 시퀀스가 있는 것만 — ASSET · EDGE · SHIFT · SHIFT_PATTERN · HOLIDAY · BLOB 은 안 됩니다 |
count | 1~1000, 기본 1 |
ADMIN 또는 API 토큰이 필요합니다. 행을 만들지 않고 번호만 가져가므로 안 쓴 번호는 비는 것이 정상입니다. 다시 부르면 새 번호가 나옵니다(같은 Idempotency-Key 를 보내면 그렇지 않습니다).
| 응답 | 뜻 |
|---|---|
400 domain_id.domain_required | domain 없음 |
404 domain_id.unknown | 없는 도메인이거나 시퀀스가 없음 |
422 domain_id.count_invalid | count 가 1~1000 밖 |
콘솔 등록 화면의 ID 칸
등록 화면의 ID 칸 오른쪽에 생성 아이콘(마우스를 올리면 «생성»)이 있습니다. 누르면 새 번호가 채워집니다. 직접 입력하면 대문자로 바뀌고, 칸을 벗어날 때 형식과 중복을 검사해 문제를 칸 아래에 표시합니다. 수정 화면에서는 ID 칸이 잠기고 아이콘이 없습니다. 발급 시퀀스가 없는 도메인(엣지 · 근무조 · 근무 패턴 · 휴일 · 오브젝트)에도 아이콘이 없습니다.
콘솔에서는 ID 칸이 필수입니다. 생성 을 누르거나 직접 입력합니다. 비워 두면 발급되는 칸은 공정 구간뿐입니다. 생성과 중복 검사는 ADMIN · API 역할만 쓸 수 있습니다.
다음 단계
- 응답 형식 및 에러 처리 — 에러 코드 매핑
- Site 서비스 — 사이트 생성으로 시작
- Asset 서비스 — 자산 트리 구축
- Tag 서비스 — 데이터 포인트 정의