프로젝트 소개
# plantuml.rs
Java 다이어그램 생성 라이브러리인 [PlantUML](https://plantuml.com/)을 100% Rust로 재구현한 프로젝트로, 동작 동등성을 목표로 하며 FFI를 통한 Java, TypeScript, Python 언어 바인딩을 제공합니다.
## 상태
**진행 중.** 시퀀스 다이어그램 파싱, SVG 렌더링, PREPROC(전처리된 텍스트) 출력이 작동하며 Java 참조 구현에 대해 테스트되었습니다. 다른 다이어그램 유형(클래스, 액티비티, 유스 케이스 등)과 렌더링 백엔드(PNG, PDF, LaTeX)는 점진적으로 포팅 중입니다. 전체 로드맵은 [`.agents/architecture.md`](.agents/architecture.md)를 참조하세요.
## 기능
**현재 작동:**
- 시퀀스 다이어그램 파싱 (`plantuml-sequence`)
- SVG 렌더링 백엔드 (`plantuml-svg`)
- PREPROC 출력 (TIM 엔진을 통한 전처리된 텍스트, `plantuml-preproc`)
- 통합 렌더 API: `render_svg`, `render_preproc`, `render(source, format)` (`plantuml-engine`)
- JNI를 통한 Java 바인딩 — `PlantUml.renderSvg` / `PlantUml.renderPreproc`
- WASM을 통한 TypeScript 바인딩 — `renderSvg` / `renderPreproc` (브라우저 + Node.js)
- 레이아웃 위치 지정을 위한 1D 제약 솔버 (`plantuml-real`)
- 사용자 정의 정규식 엔진 (`plantuml-regex`)
- 전처리기: `!include`, `!define`, 변수, 조건문 (`plantuml-preproc`)
- 명령 파싱 프레임워크 (`plantuml-command`)
- 2D 그래픽 기본 요소 (`plantuml-klimt`)
- 스킨 / 스타일 / 테마 시스템 (`plantuml-skin`)
**계획됨:**
- 클래스, 액티비티, 유스 케이스 및 기타 다이어그램 유형
- PNG, PDF, LaTeX/TikZ 렌더링 백엔드
- 레이아웃 엔진 (Graphviz / ELK)
- CLI 바이너리 (`plantuml-cli`)
- Python 바인딩 (PyO3 + maturin)
- 추가 언어 바인딩을 위한 C FFI 공유 라이브러리
## 아키텍처
### 파이프라인
```
소스 텍스트
│
▼
BlockUmlBuilder 입력을 @start/@end 블록으로 분할
│
▼
BlockUml @start/@end 블록당 하나. 지연: TimLoader가
전처리 (!include, !define, 변수)
▼
PSystemBuilder createPSystem()이 다이어그램 유형
팩토리(Sequence, Class,
Activity, UseCase 등)로 디스패치
▼
Diagram 객체 메모리 내 다이어그램 모델
│
▼
Diagram.exportDiagram() FileFormat별 StringBinder를 통해
SVG / PNG / PDF / LaTeX / EPS 등으로 렌더링
▼
출력 바이트
```
### Java 패키지 → Rust 크레이트
| Java 패키지 | Rust 크레이트 | 책임 |
|------------------|------------|---------------|
| `klimt` | `plantuml-klimt` | 2D 그래픽: 도형, 기하학, 폰트, `StringBounder`, `UGraphic`, `TextBlock` |
| `com.plantuml.ubrex` | `plantuml-regex` | 사용자 정의 정규식 엔진 |
| `preproc` / `tim` | `plantuml-preproc` | 전처리기: `!include`, `!define`, 변수, 조건문 |
| `command` | `plantuml-command` | `Command` / `CommandFactory` 파싱 프레임워크 |
| `abel` / `cucadiagram` | `plantuml-model` | 엔티티/관계 모델: `Entity`, `Link`, `LeafType` |
| `sequencediagram` | `plantuml-sequence` | 시퀀스 다이어그램 |
| `skin` / `style` / `theme` | `plantuml-skin` | 스킨 / 스타일 / 테마 시스템 |
| `real` | `plantuml-real` | 레이아웃 위치 지정을 위한 1D 제약 솔버 |
| `svg` | `plantuml-svg` | SVG 렌더링 백엔드 |
| 루트 (부분) | `plantuml-engine` | `BlockUml`, `BlockUmlBuilder`, `PSystemBuilder`, `SourceStringReader`, 통합 렌더 API |
| 루트 (부분) | `plantuml-core` | `Diagram`, `TextBlock`, `StringBounder`, `FileFormat`, `FileFormatOption` |
| — | `plantuml-ffi` | 언어 바인딩을 위한 C FFI 공유 라이브러리 |
| — | `plantuml-wasm` | TypeScript 바인딩을 위한 WASM 모듈 (wasm-bindgen) |
### 디자인 패턴
Rust 포트는 Java 원본의 핵심 디자인 패턴을 유지합니다:
1. **팩토리 + 레지스트리** — `PSystemBuilder`가 트레이트 기반 레지스트리를 통해 유형별 `*DiagramFactory` 구현으로 디스패치합니다.
2. **명령 패턴** — 각 소스 라인 파서는 `CommandFactory`에 등록된 `Command`이며, 구현이 있는 `Command` 트레이트에 매핑됩니다.
3. **전략** — `FileFormat`이 렌더링 백엔드를 선택하며, 레이아웃 백엔드 선택(Graphviz vs ELK)도 트레이트 객체 또는 열거형을 사용하는 전략입니다.
4. **지연 초기화** — `BlockUml.getDiagram()`이 `OnceCell<T>` 또는 명시적 `build()` 호출을 통해 필요 시 모델을 빌드합니다.
5. **템플릿 메서드** — `TitledDiagram` / `Diagram`이 서브클래스로 확장되는 기본 동작을 정의하며, 기본 메서드와 컴포지션이 있는 트레이트에 매핑됩니다.
## 워크스페이스 구조
```
plantuml.rs/
├── crates/
│ ├── plantuml-core/ # Diagram, TextBlock, StringBounder, FileFormat
│ ├── plantuml-klimt/ # 2D 그래픽: 도형, 기하학, 폰트
│ ├── plantuml-regex/ # 사용자 정의 정규식 엔진
│ ├── plantuml-preproc/ # 전처리기: !include, !define, 변수
│ ├── plantuml-command/ # Command / CommandFactory 파싱 프레임워크
│ ├── plantuml-model/ # 엔티티/관계 모델
│ ├── plantuml-engine/ # 최상위 파이프라인 및 통합 렌더 API
│ ├── plantuml-svg/ # SVG 렌더링 백엔드
│ ├── plantuml-skin/ # 스킨 / 스타일 / 테마 시스템
│ ├── plantuml-real/ # 레이아웃을 위한 1D 제약 솔버
│ ├── plantuml-sequence/ # 시퀀스 다이어그램
│ ├── plantuml-ffi/ # C FFI 공유 라이브러리
│ └── plantuml-wasm/ # WASM 모듈 (wasm-bindgen)
├── bindings/
│ ├── plantuml-java/ # Java 바인딩 (JNI) — com.vgerbot.plantuml:plantuml-java
│ └── plantuml-ts/ # TypeScript 바인딩 (WASM) — @vgerbot/plantuml
├── .agents/ # 에이전트 가이드라인 및 아키텍처 문서
└── Cargo.toml # 워크스페이스 매니페스트
```
## 시작하기
### 사전 요구 사항
- **Rust 툴체인** (edition 2021, `resolver = "2"`)
- **Java 17+** — Java 바인딩에만 필요
- **Node.js** — TypeScript 바인딩에만 필요 (`bindings/plantuml-ts`에서 `npm install`)
### 빌드
```sh
cargo build
```
### 테스트
```sh
cargo test
```
### 린트
```sh
cargo clippy --workspace -- -D warnings
```
## 사용법
### Rust
```rust
use plantuml_engine::render_svg;
let svg = render_svg("@startuml\nAlice -> Bob: hello\n@enduml")?;
```
`render` 함수는 `FileFormat`에 따라 디스패치합니다:
```rust
use plantuml_engine::render;
use plantuml_core::FileFormat;
let svg = render("@startuml\nAlice -> Bob: hello\n@enduml", FileFormat::Svg)?;
```
### Java
Maven 좌표:
```xml
<dependency>
<groupId>com.vgerbot.plantuml</groupId>
<artifactId>plantuml-java</artifactId>
<version>0.1.0</version>
</dependency>
```
사용법:
```java
import com.vgerbot.plantuml.PlantUml;
String svg = PlantUml.renderSvg("@startuml\nAlice -> Bob: hello\n@enduml");
System.out.println(svg);
```
### TypeScript
설치:
```sh
npm install @vgerbot/plantuml
```
사용법 (브라우저 또는 Node.js):
```typescript
import { renderSvg } from '@vgerbot/plantuml';
const svg = await renderSvg('@startuml\nAlice -> Bob: hello\n@enduml');
```
### Python
계획됨 (PyO3 + maturin). 아직 구현되지 않음.
## 바인딩 빌드
| 바인딩 | 빌드 명령 |
|---------|-------------|
| Java | `cd bindings/plantuml-java && ./gradlew build` |
| TypeScript | `cd bindings/plantuml-ts && npm run build` |
## 테스트
```sh
cargo test --workspace
```
테스트는 PlantUML Java 참조 구현에서 직접 포팅됩니다:
- **Vega 데이터 기반 테스트** — 예상 `.svg` / `.preproc` 출력이 있는 `.puml` 파일을 Java 참조 데이터와 비교합니다. `asciiverse/`, `svg/`, `mvp/` 스위트 전반에 걸쳐 38개의 시퀀스 SVG 테스트와 PREPROC 테스트를 포함합니다.
- **Nonreg 테스트** — Java nonreg 스위트에서 포팅된 회귀 테스트.
- **단위 / 기타 테스트** — `#[cfg(test)] mod tests`의 크레이트별 단위 테스트.
테스트 데이터는 `crates/plantuml-engine/tests/resources/vega/` 아래에 커밋됩니다.
## 포팅 가이드라인
포트는 엄격한 1:1 Java → Rust 파일 매핑을 따릅니다:
- **명명**: 파일과 메서드에 대해 PascalCase → snake_case; Java 패키지 → Rust 크레이트 경로.
- **파일 매핑**: 하나의 Java 파일 → 하나의 Rust 파일; 파일 크기 관리 (≤500 / 501–800 / >800 줄).
- **OOP → Rust**: 인터페이스 → 트레이트, 클래스 → 구조체, 오버로드 → 빌더.
- **오류 처리**: 라이브러리에는 `Result` + `thiserror`, CLI에는 `anyhow`. 라이브러리 코드에서 패닉 없음.
- **문서 주석**: 모든 공개 항목은 Java 소스를 인용합니다, 예: `/// Ported from: net/sourceforge/plantuml/SourceStringReader.java`.
전체 세부 사항은 [`.agents/rules/java-to-rust-porting.md`](.agents/rules/java-to-rust-porting.md)를 참조하세요.
## 기여
프로젝트 규칙은 [`.agents/AGENTS.md`](.agents/AGENTS.md)를, 아키텍처 개요, 레이어 매핑, 디자인 패턴은 [`.agents/architecture.md`](.agents/architecture.md)를 참조하세요.
## 라이선스
MIT 라이선스 (워크스페이스 [`LICENSE`](LICENSE) 파일에 따름).
> **참고:** `Cargo.toml`은 워크스페이스 패키지 메타데이터에서 `license = "GPL-3.0-only"`를 선언하지만, 권위 있는 `LICENSE` 파일은 MIT입니다. 이 README는 `LICENSE` 파일을 반영합니다. 프로젝트가 GPL-3.0을 의도한다면 `LICENSE` 파일과 `Cargo.toml` 메타데이터를 조정해야 합니다.
Comments
0 Rating appears after 10 ratings
Sign in to join the discussion.