Kosmos API Reference

Kosmos DSL Core API는 HTML을 타입 안정성과 성능을 모두 만족하는 방식으로 생성하기 위한 최소 단위의 클래스 집합입니다.
이 문서에서는 DSL 내부의 클래스 구조, 주요 메서드, 상속 관계를 도식과 코드로 설명합니다.

핵심 원리: 모든 DSL 요소는 HtmlComponent 인터페이스를 구현합니다.

1. API 구조 개요

Kosmos DSL의 클래스 구조는 다음과 같습니다:

HtmlComponent
 ├── AbstractHtmlTag
 │    ├── HtmlTag (자식 있음)
 │    └── VoidTag (자식 없음)
 ├── TextNode
 └── CompositeComponent (다중 구성요소)

HtmlComponent는 모든 DSL 요소의 공통 인터페이스이며, render(RenderContext) 메서드를 통해 HTML 문자열을 생성합니다.

2. HtmlComponent

public interface HtmlComponent {
    String render(RenderContext ctx);
}

모든 DSL 컴포넌트는 이 인터페이스를 구현하며, render()가 반환하는 값은 HTML 문자열입니다.

Atomic Design 계층(Page → Template → Organism → Molecule → Atom) 모두 이 인터페이스를 구현합니다.

3. AbstractHtmlTag

HtmlTag와 VoidTag의 공통 부모 클래스입니다. 공통 속성(tagName, attributes, classes)을 관리합니다.

public abstract class AbstractHtmlTag implements HtmlComponent {
    protected final String tagName;
    protected final Map<String, String> attributes = new LinkedHashMap<>();
    protected final List<String> classes = new ArrayList<>();

    public AbstractHtmlTag(String tagName) { this.tagName = tagName; }

    public AbstractHtmlTag addClass(String cls) { classes.add(cls); return this; }
    public AbstractHtmlTag addAttribute(String key, String value) { attributes.put(key, value); return this; }
}

이 추상 클래스는 El.*() 빌더가 호출될 때 기본적인 태그 구성의 뼈대를 제공합니다.

4. HtmlTag

children을 가질 수 있는 일반 태그입니다.

public class HtmlTag extends AbstractHtmlTag {
    private final List<HtmlComponent> children = new ArrayList<>();

    public HtmlTag(String tagName) { super(tagName); }

    public HtmlTag addChild(HtmlComponent child) {
        children.add(child);
        return this;
    }

    public HtmlTag addChildren(HtmlComponent... comps) {
        children.addAll(Arrays.asList(comps));
        return this;
    }

    @Override
    public String render(RenderContext ctx) {
        StringBuilder sb = new StringBuilder();
        sb.append("<").append(tagName);
        if (!classes.isEmpty()) sb.append(" class=\"").append(String.join(" ", classes)).append("\"");
        attributes.forEach((k, v) -> sb.append(" ").append(k).append("=\"").append(v).append("\""));
        sb.append(">");
        for (HtmlComponent child : children) sb.append(child.render(ctx));
        sb.append("</").append(tagName).append(">");
        return sb.toString();
    }
}
Note: 모든 DSL 렌더링의 핵심 클래스입니다. El.div(), El.h1(), El.table() 등은 모두 HtmlTag 인스턴스를 반환합니다.

5. VoidTag

img, input, br 등 자식을 가질 수 없는 태그를 표현합니다.

public class VoidTag extends AbstractHtmlTag {
    public VoidTag(String tagName) { super(tagName); }

    @Override
    public String render(RenderContext ctx) {
        StringBuilder sb = new StringBuilder();
        sb.append("<").append(tagName);
        if (!classes.isEmpty()) sb.append(" class=\"").append(String.join(" ", classes)).append("\"");
        attributes.forEach((k, v) -> sb.append(" ").append(k).append("=\"").append(v).append("\""));
        sb.append(" />");
        return sb.toString();
    }
}
주의: VoidTag에 addChild()를 호출하면 DslValidationLogger가 경고를 출력합니다.

6. TextNode

텍스트 전용 컴포넌트입니다.

public class TextNode implements HtmlComponent {
    private final String text;
    public TextNode(String text) { this.text = text; }
    @Override
    public String render(RenderContext ctx) {
        return HtmlEscape.escapeHtml(text);
    }
}

모든 El.*().text("내용") 호출은 내부적으로 TextNode를 추가합니다.

7. RenderContext

DSL 렌더링 과정의 컨텍스트를 관리합니다 (i18n, 사용자 정보, trace 로그, locale 등).

public class RenderContext {
    private final Locale locale;
    private final boolean debug;
    private final Map<String, Object> vars = new HashMap<>();

    public RenderContext(Locale locale, boolean debug) {
        this.locale = locale;
        this.debug = debug;
    }

    public String getMessage(String key, String def) {
        return MessageSourceHolder.getMessage(key, locale, def);
    }

    public void set(String key, Object val) { vars.put(key, val); }
    public Object get(String key) { return vars.get(key); }
}
특징: Spring의 MessageSource와 결합해 i18n 다국어 렌더링을 지원합니다.

8. 클래스 다이어그램

+---------------------+
|  HtmlComponent      |
|---------------------|
| +render(ctx):String |
+----------^----------+
           |
+----------------------+     +------------------+
|  AbstractHtmlTag     |---->| RenderContext    |
|----------------------|     +------------------+
| +tagName:String      |
| +attributes:Map      |
| +classes:List        |
+----^-----------^-----+
     |           |
+-----------+  +-----------+
| HtmlTag   |  | VoidTag   |
|-----------|  |-----------|
| +children |  | (no child)|
+-----------+  +-----------+

9. 사용 예시

RenderContext ctx = new RenderContext(Locale.KOREAN, false);

String html = El.div().css("alert alert-info").children(
    El.h4().text("Kosmos API Demo"),
    El.p().text("HtmlComponent와 RenderContext 구조를 보여주는 예시입니다.")
).render(ctx);

System.out.println(html);
결과:
<div class="alert alert-info">
  <h4>Kosmos API Demo</h4>
  <p>HtmlComponent와 RenderContext 구조를 보여주는 예시입니다.</p>
</div>

다음으로