콘텐츠로 이동

모델링 DSL과 추적성

모델링 schema는 실행 코드를 대신하는 프로그램이 아니라 요구사항·데이터 설계·검사 계획을 .uni 소스로 표현합니다. schema 종류는 database, requirements, qa, test, dictionary, layout, sequence, infra, contract, wireframe, project 열한 가지이며 파서와 단위 검사, 프로젝트 참조 분석으로 관계를 다룹니다. schema를 작성했다고 DB가 생성되거나 QA가 실행되지는 않습니다.

한 파일에 한 schema unit을 두고 Needs.uni에는 schema requirements Needs처럼 이름을 맞춥니다. package는 필수이며 화면에 보이는 이름은 문자열, 참조 ID는 ASCII 식별자입니다. 블록의 구성 요소는 줄 단위이고 일반 클래스 문장과 달리 세미콜론을 붙이지 않습니다.

식별자는 영구 참조입니다. 이름 변경 시 모든 참조도 함께 바꿉니다. 다른 package의 항목은 import 또는 완전한 이름으로 참조합니다. 다이어그램 배치는 schema layout unit에만 쓰고 모델 블록 안에는 넣지 않습니다. 편집기 화면 상태·실행 결과·분석 캐시는 소스가 아닙니다.

문자열을 받는 구성 요소에는 여러 줄 text block을 쓸 수 있습니다. 일반 코드의 식에는 쓸 수 없고, 코드 선언에서는 @Description·@Notes·@Title의 인수로만 사용합니다.

text block
statement """
상품은 한 번만 등록한다.
같은 "name"은 거절한다.
"""
  • 여는 """는 줄 끝에 두고, 닫는 """는 마지막 줄에 단독으로 둡니다.
  • 닫는 구분자의 들여쓰기만큼 각 줄 앞 공백을 제거합니다. 그보다 덜 들여쓴 내용 줄은 오류입니다. 빈 줄은 유지합니다.
  • 각 줄 끝 공백은 제거하며 마지막 줄바꿈은 붙지 않습니다. 이스케이프는 문자열 리터럴과 같고, 값 안의 따옴표 세 개 이상은 각각 이스케이프합니다.

requirement에 ID와 제목을 정하고 statement에 요구 내용을, accept에 확인 조건을 씁니다. 우선순위 기본 척도는 P0–P3이며 kind는 functional, business, constraint, nonFunctional(선택적으로 performance·security·accessibility·reliability·operations·compliance) 중에서 고릅니다. 비기능 요구의 말단 항목에는 측정 기준 measure도 필요합니다.

Needs.uni
package docs.sample;
schema requirements Needs "목록 요구사항" {
requirement REQ_LIST "목록 저장" {
kind functional
priority P1
statement "항목을 저장하고 다시 조회할 수 있어야 한다."
accept "저장한 항목의 이름이 조회 결과와 같다."
}
}

인수 조건에 이름을 붙이면(accept AC1 "…") <package>.<요구사항>.AC1 심볼이 되어 QA case가 그 조건 하나를 가리킬 수 있습니다. 이름 있는 조건에는 { given "…" when "…" then "…" } 단계를 순서대로 둘 수 있습니다. 이름 없는 accept는 심볼이 없는 설명입니다.

이름 있는 인수 조건과 추적 단계
requirement REQ_CANCEL "주문 취소" {
kind functional
statement "배송 전 주문은 구매자가 취소할 수 있다."
accept AC1 "배송 전 취소는 성공한다." {
given "배송 전 주문"
when "구매자가 취소를 요청한다"
then "주문 상태가 취소로 바뀐다"
}
stages screen, api, database, qaTest
dependsOn REQ_ORDER "주문이 있어야 취소할 수 있다"
}

notes는 메모를, 관계 뒤의 문자열은 관계 설명을 기록합니다. stages는 요구사항이 도달해야 할 추적 단계(screen, api, controller, service, query, class, database, infra, environment, theme, asset, i18n, sequence, smartContract, qaTest, evidence)를 나열합니다. review "자원" designReview|regenerate|retest|evidenceReview open|inProgress|done|waived는 구현·검증 자원 하나의 검토 상태를 기록하며 선택적으로 assignee·note·updated를 붙입니다.

큰 요구사항 집합은 chapter로 다른 unit을 연결합니다. 요구사항 관계는 dependsOn, preconditionFor, references, derivedFrom, conflictsWith, replaces, precedes, triggers, supports이며 요구사항을 가리켜야 합니다. dependsOn/preconditionFor/precedes는 순환과 자기 참조를 허용하지 않습니다. conflictsWith는 대칭 관계입니다. priority의 척도는 schema project의 priorities로 바꿀 수 있습니다. 내용이 덜 채워진 소스도 구문을 읽을 수 있지만 준비도 진단은 별도로 남을 수 있습니다.

테이블·컬럼·키·인덱스·뷰·루틴을 선언하고 구현하는 요구사항을 realizes로 연결합니다. 여기의 자료형은 DBMS에 중립적인 DB 모델 문법이며, 환경에서 선택한 DBMS profile이 실제 타입으로 바꾸고 표현할 수 없는 매핑은 거절합니다.

자료형 의미
bool, int, bigint 논리값·정수
float, double 근사 실수(단정도·배정도). 정확한 수는 decimal
decimal, decimal(p), decimal(p, s) 정확한 수. 정밀도를 생략하면 DBMS profile을 따름
varchar(n), char(n) 가변·고정 길이 문자. 길이는 필수
clob 긴 문자 본문(Oracle CLOB, MySQL LONGTEXT, PostgreSQL·SQLite TEXT, SQL Server NVARCHAR(MAX))
date, time, datetime, timestamp 날짜·시간
uuid, json, binary UUID·JSON·바이너리

text 자료형은 없습니다. 짧은 문자는 varchar(n), 긴 본문은 clob을 사용합니다. clob 컬럼은 기본 키·외래 키·unique key·인덱스에 쓸 수 없습니다(MODEL_COLUMN).

unique key 이름 (컬럼, …)은 테이블의 unique 제약이고 unique index는 정렬 방향과 where 조건을 가질 수 있는 별도 인덱스입니다. 컬럼 옵션 nonstandard는 사전 표준 검사에서 이름을 그대로 허용할 컬럼에 붙입니다. dictionary는 사전 schema unit을, 컬럼의 domain·term은 그 사전의 도메인·용어를 심볼로 참조합니다(예: domain OmniDictionary.D_CODE_V30). 다른 종류를 가리키거나 찾지 못하면 MODEL_REFERENCE_KIND·MODEL_UNRESOLVED 오류입니다.

Catalog.uni
package docs.sample;
schema database Catalog "목록 데이터" {
table ITEM "항목" {
realizes REQ_LIST
column ID "번호" bigint not null
column NAME "이름" varchar(100) not null
primary key (ID)
}
}

DB unit은 Catalog.uni와 Catalog.items.uni 같은 partial 파일로 나눌 수 있습니다. 후속 파일에는 같은 unit을 선언하며 중복 구성 요소는 오류입니다. 컬럼의 realizes는 해당 컬럼과 같은 줄에 씁니다. 다음 줄에 새 realizes를 쓰면 테이블의 관계가 됩니다.

@Realizes는 문자열 대신 요구사항 심볼을 받습니다. 여러 요구사항이면 어노테이션을 반복합니다. 배열이나 id = "..." 형태는 허용하지 않습니다.

ItemService.uni
package docs.sample;
import unibase.trace.Realizes;
@Service
public class ItemService {
@Realizes(REQ_LIST)
public string label(string name) {
return name;
}
}

타입·메서드·필드 등 모델링 선언을 요구사항에 연결하며 런타임 동작을 바꾸지 않습니다. 요구사항이 아닌 모델 요소나 코드 심볼과의 관계는 @References(심볼)로 씁니다. @Realizes와 같은 위치에 붙고 같은 방식으로 반복하며, layout·diagram을 가리키면 MODEL_REFERENCE_KIND입니다. partial 화면의 타입 관계는 주 선언에, 메서드·필드 관계는 해당 조각의 선언에 둡니다. HTML 내부 태그에 @Realizes를 넣지 않습니다.

모델 요소 사이의 관계도 그 관계를 가진 요소가 소스에 선언합니다. realizes는 구현하는 요구사항, verifies는 검사하는 대상, references는 그 밖의 모델 요소나 코드 심볼(요구사항·테이블·QA case·scenario·화면·자원·메서드·필드)을 가리킵니다. layout·diagram은 references로 가리킬 수 없습니다.

요소 realizes verifies references
database 테이블·컬럼·뷰·루틴 ○
requirement ○(관계로)
qa case ○(요구사항·인수 조건) ○
test unit·scenario ○(QA case·요구사항·인수 조건) ○
test request, sequence message ○
sequence scenario, infra resource, contract, wireframe page ○ ○

verifies는 요구사항 또는 이름 있는 인수 조건(REQ_LIST.AC1)을, covers는 실제 구현 심볼을 가리킵니다. 요구사항 ID를 covers에 넣거나 테이블을 verifies에 넣으면 관계 종류가 맞지 않습니다.

Checks.uni
package docs.sample;
schema qa Checks "목록 검사" {
plan {
objective "저장과 조회의 연결을 확인한다."
exit "저장 후 재조회 결과가 일치한다."
}
suite Basic "기본 흐름" {
scenario Save "저장 후 조회" {
case TC_SAVE "이름 유지" {
kind functional
priority P1
step "항목을 저장하고 다시 조회한다."
expect "저장한 이름이 표시된다."
verifies REQ_LIST
covers Catalog.ITEM, ItemService.label
}
}
}
}

case는 scenario 안, suite 바로 아래, 또는 아직 배정하지 않은 상태로 unit 바로 아래에 둘 수 있습니다. mode manual|automated|hybrid는 수동·자동·둘 다 중 확인 방식을, evidence observation|attachment는 수동 통과에 필요한 증거(관찰, 또는 관찰과 첨부)를, environment "…"는 실행 환경을 기록합니다.

이 계획은 저장·조회 검사 방법을 정의합니다. 위의 ItemService.label은 추적성 예시용 코드이며 DB 저장을 구현하지 않습니다. QA의 실제 실행·통과 여부는 별도 실행 증거로 관리합니다.

schema test는 HTTP API·부하 테스트의 plan, scenario를 실행하는 group, 요청으로 이루어진 scenario를 선언합니다.

Test.uni
package tst1;
schema test Test "주문 부하" {
plan "주문 계획" {
baseUrl "http://127.0.0.1:8080"
header "Accept" "application/json"
variable "sku" "S-100"
}
group TG_1 "사용자 10명" {
users 10
rampUp 5
iterations 2
runs SC_1
}
scenario SC_1 "주문" {
stopOnFailure
verifies qam1.Qa.QA_1
request RQ_1 "주문 생성" {
method post
url "/api/orders"
header "Content-Type" "application/json"
body """
{"sku": "{{sku}}"}
"""
timeout 3000
extract "orderId" jsonPath "$.id" default ""
assert status "" equals "201"
assert responseTime "" lessThan "500" optional
}
}
}
  • 요청은 scenario 순서대로, group은 runs에 나열한 순서대로 scenario를 실행합니다. rampUp·duration은 초, timeout·think는 밀리초입니다.
  • scenario의 verifies는 QA case(qam1.Qa.QA_1), 요구사항 또는 이름 있는 인수 조건을 가리키며, 그 scenario가 해당 요소의 자동 검사임을 뜻합니다. unit에도 같은 대상을 가리키는 verifies를 둘 수 있습니다.
  • assert 종류 "식" 비교 "값"은 식이 없는 종류에도 ""를 씁니다. optional은 실패해도 요청을 실패로 보지 않는 검사입니다. disabled는 항목을 보존하되 보내지 않습니다.
  • 실행 표본과 요약은 소스가 아닙니다.

schema dictionary는 단어(word), 단어로 만든 도메인(domain), 컬럼 이름이 되는 용어(term)를 선언하는 명명 표준입니다.

Dictionary.uni
package dicm1;
schema dictionary Dictionary "공통 표준" {
word W_3290 "아이디" {
physical "ID"
english "Identifier"
}
domain D_127 "명V20" {
type "varchar"
length "20"
words W_3290
}
term T_13163 "아이디" {
physical "ID"
words W_3290
domain D_127
}
}

단어·도메인·용어는 unit 안에서 한 이름 공간을 공유하며, ERWeb은 W_·D_·T_에 편집기 ID를 붙여 이름을 짓습니다. words와 용어의 domain은 같은 unit의 항목을 한정 없이 가리킵니다. 제목 외 필드는 모두 선택이며 없는 필드와 빈 값(scale "")은 다릅니다. delete denied는 표준이 소유한 항목을 보호하고, meta "키" "값"은 원본 표준의 열을 보존합니다. origin과 diagnostic은 가져온 표준 집합과 가져오기 진단을 기록합니다.

schema layout은 모델 심볼을 이름 있는 다이어그램에 배치합니다. 상자를 옮겨도 layout 파일만 바뀌고 모델 unit은 그대로입니다.

CatalogLayout.uni
package docs.sample;
schema layout CatalogLayout "목록 다이어그램" {
diagram Main "개요" {
description "항목 테이블"
locked
place Catalog.ITEM at (96, 192) size (288, 320)
}
}
  • layout unit 이름은 보여 주는 모델 unit과 달라야 합니다(Catalog의 배치는 CatalogLayout). partial 파일은 없습니다.
  • place는 테이블·뷰·루틴, 요구사항, QA 요소, 타입을 가리킬 수 있고 다이어그램이나 다른 layout은 가리킬 수 없습니다. 한 다이어그램에 같은 심볼은 한 번만 배치하며 크기는 음수일 수 없습니다.
  • place 줄의 순서가 그리는 순서입니다.
  • place 뒤에 within 심볼을 쓰면 같은 다이어그램의 다른 상자 안에 둡니다(예: 네트워크 안의 infra 자원). 자기 자신이나 배치하지 않은 심볼 안에 두면 MODEL_RELATION입니다.
  • label "…"은 심볼 제목 대신 쓸 상자 제목입니다. place의 locked·collapsed는 그 상자의 편집기 상태이며 다이어그램의 locked와 다릅니다.
  • show 심볼은 infra 관계나 contract 관계를 다이어그램에 그립니다. 한 관계는 다이어그램마다 한 번만 그립니다.
schema 표현하는 것 주요 구성 요소
sequence 상호작용 시나리오 scenario 안의 participant(actor·controller·service·database 등), 시간순 message(sync·async·return·create·destroy)·note·ref·activate/deactivate, 범위를 덮는 fragment(alt·opt·loop·par·break·critical)와 operand. participant의 uses, message의 calls는 구현 심볼을 가리킴
infra 인프라 아키텍처 사용자 정의 component 종류, resource(종류·provider generic/aws/azure/oci·property), 두 자원을 잇는 relation(connects·requests·dataFlow·dependsOn·routesTo 등)과 선 모양
contract Solidity 스마트 계약 계약마다 solidity { } 원문 블록 하나, 종류(contract·abstract·interface·library), 계약 사이 relation(inherits·implements·uses·calls), unit의 compiler·license·target(evm·tron). Solidity 원문은 Unibase 토큰으로 해석하지 않음
wireframe 화면 설계 page(route·memo), 채널·기기별 artboard(web·mobileApp, desktop·tablet·phone·custom), 절대 좌표의 box와 within, property·style 값, unit의 component 정의와 미리보기 theme
project 프로젝트 자체 정보 description·key·theme·prompt, 우선순위 척도 priorities, generation(target·basePackage·application), screen(테마·mode·첫 페이지·디자인 토큰), 패키지 설명 namespace. 프로젝트마다 하나이며 관례상 소스 루트의 Project.uni
  • 각 unit 안의 이름이 중복되면 MODEL_DUPLICATE, 선언하지 않은 참여자·자원·계약·상자를 가리키면 MODEL_UNRESOLVED, 자기 자신을 잇는 관계나 자기 안에 둔 fragment·상자는 MODEL_RELATION, 뒤집힌 범위와 허용 범위 밖의 크기는 MODEL_RANGE입니다.
  • sequence·infra·contract·wireframe의 다이어그램 배치는 다른 모델과 같이 schema layout unit에 둡니다.
  • project의 generation·screen 값은 도구가 읽는 정보이며 compiler가 소스와 대조해 검사하지 않습니다.

unic check <파일>은 그 unit 하나의 문법·단위 규칙을 검사합니다. unic check <폴더>는 폴더 아래 모든 .uni 파일의 참조를 해석하고 오류를 <경로>:<줄>:<열>: MODEL_<CODE>: <메시지> 형태로 보고합니다. 준비도 안내는 검사를 실패시키지 않습니다. 이어서 코드 파일을 하나의 프로그램으로 검사하며 모델링 unit만 있는 폴더에는 프로그램이 필요하지 않습니다. HTML 화면과 서버 역할이 섞여 하나의 native 프로그램이 아닌 프로젝트는 unic check <폴더> --model을 사용합니다. 같은 참조 검사를 하고 코드 파일은 타입 검사 없이 선언만 참조에 사용합니다. --json을 붙이면 결과를 JSON 하나로 출력합니다. 관계 그래프를 출력하는 CLI 명령은 없습니다.

진단 상황 수정할 곳
파일명과 unit명 불일치 파일 또는 unit 이름과 참조를 일관되게 변경
참조를 찾지 못함 package·import·ID와 분석에 포함한 소스 집합
잘못된 참조 종류 realizes는 요구사항, verifies는 요구사항·인수 조건(test는 QA case도 가능), covers는 구현 심볼, domain·term은 사전 항목, references·@References는 layout·diagram 이외
text 자료형 또는 길이 없는 varchar·char varchar(n)·char(n) 또는 clob으로 변경
순환 관계 요구사항의 의존·선행 관계
중복 unit 구성 요소 partial 파일의 중복 정의
준비도 부족 statement·accept·비기능 measure

포맷터는 모델링 선언을 줄 단위로 다시 배치합니다. 중괄호마다 4칸 들여쓰기, 이어지는 줄(expect, on delete)은 한 단계 더 들여쓰기, 빈 줄은 하나로 정리하고, 연속된 column·place 줄은 표시 폭에 맞춰 정렬합니다. sql·루틴 본문, text block과 블록 주석은 그대로 둡니다. 구성 요소를 정규 순서로 재배열하지는 않습니다. ERWeb 요구사항과 추적성은 화면 작업 흐름, 이 장은 소스 문법을 설명합니다. 각각의 저장·재열기·분석·실행 확인은 실행 범위와 구분합니다.