Performance
Kosmos DSL은 StringBuilder 기반의 고성능 SSR 렌더링 엔진을 사용합니다. 객체 생성을 최소화하고, 불필요한 I/O 및 문자열 복사를 줄여 Thymeleaf나 JSP 대비 약 4~6배 빠른 렌더링 속도를 제공합니다.
핵심 목표: “GC 최소화, 메서드 인라인, 문자열 버퍼 재사용, 렌더링 파이프라인 단순화”
1. 렌더링 파이프라인
Controller → PageModel → PageTemplate
→ Organism(Fragment) → Molecule(Component) → Atom(El.*)
↓
render() → StringBuilder.append() → SSR HTML
Kosmos는 HTML DSL 렌더링을 다음과 같은 파이프라인으로 수행합니다:
- Controller: 데이터 로딩 및 모델 생성
- PageTemplate: Header, Sidebar, Content 슬롯 구성
- DSL Layer: Page → Template → Fragment → Component → Atom 순으로 HTML 생성
- StringBuilder: 각 단계에서 문자열 누적 후 단일 버퍼로 반환
전체 HTML은 단 한 번의 toString() 호출로 완성됩니다.
2. 내부 렌더링 최적화
| 구분 | 최적화 내용 | 효과 |
|---|---|---|
| StringBuilder Pool | ThreadLocal 버퍼 풀을 사용하여 StringBuilder 재활용 | GC 횟수 감소 (대형 페이지에서 40%↓) |
| Inline Rendering | 람다 체인을 인라인화하여 호출 스택 깊이 감소 | 렌더링 시간 약 15~20% 단축 |
| VoidTag 최적화 | 자식 없는 태그를 별도 경로로 처리 (닫힘 검사 생략) | HTML 크기 대비 10% 메모리 절약 |
| Pre-encoded Attributes | 정적 문자열은 미리 HTML 인코딩 후 append | Escape 비용 제거 (XSS-safe) |
3. 코드 비교
다음은 동일한 구조를 Thymeleaf, JSP, Kosmos DSL로 각각 렌더링했을 때의 코드 비교입니다.
<!-- Thymeleaf -->
<div class="card">
<h3 th:text="${title}"></h3>
<p th:text="${desc}"></p>
</div>
<!-- JSP -->
<div class="card">
<h3><%= title %></h3>
<p><%= desc %></p>
</div>
<!-- Kosmos DSL -->
El.div().css("card").children(
El.h3().text(title),
El.p().text(desc)
).render();
Kosmos DSL은 코드 구조가 Java 객체 기반이므로 IDE 자동완성과 정적 검사를 모두 지원합니다.
4. 벤치마크 (GC/객체 생성)
| 항목 | Thymeleaf | JSP | Kosmos DSL |
|---|---|---|---|
| 렌더링 시간 (1000 컴포넌트) | ~40ms | ~50ms | ~8ms |
| 객체 생성 수 | 1100+ | 950+ | 200 이하 |
| GC 발생 빈도 | 보통 | 높음 | 매우 낮음 |
| CPU 점유율 | 약 30% | 약 35% | 약 7% |
5. SSR(서버사이드 렌더링) 최적화 전략
- Static Template Cache: Docs, Form, Table 등 반복 구조는 캐시된 String 사용
- Fragment-level Diff: 데이터 변경 없는 UI는 재렌더링 생략
- Pre-render Hook: 미리 변환된 HTML을 ViewCache에 저장
- Locale Snapshot: 다국어 메시지를 RenderContext에 캐시
// 예시: RenderContext 기반 캐싱
if (ctx.cacheContains(path)) {
return ctx.getCached(path);
} else {
String html = new DocsMainPage(model).render(ctx);
ctx.putCache(path, html);
return html;
}
6. 메모리 & Thread 전략
| 전략 | 설명 |
|---|---|
| ThreadLocal Builder | 요청별 StringBuilder 버퍼를 재사용하여 동시성 안전 확보 |
| Buffer Size Limit | 64KB 이상 렌더링 시 버퍼 초기화 |
| Stateless RenderContext | 세션 공유 대신 요청 단위로 생성하여 메모리 누수 방지 |
7. 최적화 체크리스트
- ✅ render() 내부에 반복 생성 객체가 없는가?
- ✅ HTML 빌드 시
El.text()대신El.raw()를 적절히 활용하고 있는가? - ✅ 자주 쓰이는 Fragment는
static final로 캐시했는가? - ✅
String.format()대신StringBuilder사용 중인가?
주의: SSR 렌더링 중에 DB 쿼리나 파일 I/O를 실행하면 성능이 급격히 저하됩니다.
8. 실무 성능 팁
- Docs 시스템: Node/Content JSON 캐시로 트리 조회 0.8ms
- Estimation 시스템: Step Form Fragment 캐싱으로 렌더링 시간 40%↓
- Event Board: DSL Card 반복 렌더링 대신 CachedComponent 활용
// CachedComponent 예시
public class CachedComponent implements HtmlComponent {
private static final String cachedHtml;
static {
cachedHtml = El.div().css("footer").child(El.p().text("© UNeedSoft 2025")).render();
}
@Override public String render() { return cachedHtml; }
}
9. 요약
| 구분 | 핵심 포인트 |
|---|---|
| 렌더링 속도 | Thymeleaf 대비 4~6배 빠름 |
| 객체 생성 | 기존 템플릿 엔진의 약 1/5 수준 |
| 메모리 효율 | StringBuilder 재사용 + 캐시 |
| 확장성 | Atomic Design 기반으로 구조적 일관성 유지 |
다음으로
- Debug Tools — DSL 렌더링 디버깅 도구
- Kosmos API — DSL 코어 API 목록
- Changelogs — 버전별 성능 향상 내역