타입 안전한 HTML/Config DSL 만들기
빌더 패턴과 확장 람다를 사용해 간단한 설정 DSL을 구현해 보세요.
타입 안전한 HTML/Config DSL 만들기은(는) CoddyKit의 무료 Kotlin Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Kotlin Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Kotlin Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
목표: 실용적인 DSL
Kotlin으로 최소한이지만 실제적인 HTML 빌더 DSL을 만듭니다. 동일한 패턴을 모든 구성, 테스트 픽스처 또는 보고서 빌더에 적용할 수 있습니다. 그 결과 문자열 연결을 대체하는 타입 안전하고 IDE 친화적인 API를 만들 수 있습니다.
Tag 기본 클래스 정의하기
모든 HTML 요소는 이름, 속성 및 자식 요소라는 공통 구조를 공유합니다. 다음과 같이 기본 클래스부터 시작합니다.
open class Tag(val name: String) {
val attrs = mutableMapOf<String, String>()
val children = mutableListOf<Tag>()
fun render(indent: Int = 0): String {
val pad = " ".repeat(indent)
val attrStr = if (attrs.isEmpty()) "" else " " + attrs.entries.joinToString(" ") { "${it.key}=\"${it.value}\"" }
val body = children.joinToString("\n") { it.render(indent + 2) }
return "$pad<$name$attrStr>\n$body\n$pad</$name>"
}
}@DslMarker 적용하기
모든 빌더 클래스에 표시하여 내부 범위에서 바깥 범위의 메서드를 실수로 호출하지 못하게 합니다.
@DslMarker
annotation class HtmlDsl
@HtmlDsl class Html : Tag("html")
@HtmlDsl class Head : Tag("head")
@HtmlDsl class Body : Tag("body")
@HtmlDsl class Div : Tag("div")
@HtmlDsl class P : Tag("p")빌더 함수 추가하기
각 태그 클래스에 자식 태그를 생성하고, 블록을 적용한 다음, 자식 요소에 추가하는 확장 함수를 만듭니다.
fun Html.head(block: Head.() -> Unit) = Head().also { it.block(); children += it }
fun Html.body(block: Body.() -> Unit) = Body().also { it.block(); children += it }
fun Body.div(block: Div.() -> Unit) = Div().also { it.block(); children += it }
fun Div.p(text: String) = P().also { it.attrs["text"] = text; children += it }최상위 html 빌더
루트 요소를 생성하고 사용자 블록을 적용하는 최상위 진입점을 제공합니다.
fun html(block: Html.() -> Unit): Html {
val root = Html()
root.block()
return root
}DSL 사용하기
그 결과 깔끔하고 읽기 쉬운 DSL이 만들어집니다.
val page = html {
head { }
body {
div {
p("Hello, DSL!")
}
}
}
println(page.render())속성 추가하기
임의의 속성을 자연스럽게 설정할 수 있도록 attr 도우미를 추가합니다.
fun Tag.attr(key: String, value: String) { attrs[key] = value }
// Usage
div {
attr("class", "container")
p("Content")
}구성 DSL 패턴
동일한 패턴을 구성 객체에도 적용할 수 있습니다. HTML 태그 대신 도메인 클래스를 사용합니다.
class ServerConfig {
var host = "localhost"
var port = 8080
var db: DbConfig? = null
fun database(block: DbConfig.() -> Unit) { db = DbConfig().apply(block) }
}
fun server(block: ServerConfig.() -> Unit) = ServerConfig().apply(block)중첩 및 조합
각 빌더 함수가 생성한 객체를 반환하므로 빌더를 자유롭게 조합할 수 있습니다. DSL의 중첩 깊이는 데이터 계층 구조의 깊이와 일치합니다.
타입을 통한 오류 방지
타입 시스템이 구조를 적용합니다. Head에는 body 확장 함수가 없으므로 Head 안에서 body { }를 호출할 수 없습니다. 잘못된 구조는 컴파일 시 오류가 됩니다.
렌더링 및 테스트
DSL이 일반 Kotlin 객체 트리를 생성하므로 렌더링과 테스트는 간단합니다. render()를 호출하고 출력 문자열을 확인하거나, 테스트에서 객체 트리를 순회하면 됩니다.
나중에 DSL 확장하기
새 태그나 구성 옵션을 추가하려면 적절한 수신 클래스에 새 확장 함수만 추가하면 됩니다. 기존 호출부는 영향을 받지 않으므로 실제로 개방-폐쇄 원칙이 적용됩니다.
빠른 확인
Kotlin HTML/구성 DSL을 "타입 안전"하게 만드는 요소는 무엇인가요?
요약: 타입 안전한 DSL 구축하기
핵심 단계:
- 계층 구조의 각 수준에 맞는 빌더 클래스를 정의합니다
- 수신 객체가 의도하지 않게 누출되지 않도록
@DslMarker를 적용합니다 - 자식 객체를 생성하고 구성한 후 추가하는 확장 함수를 작성합니다
- 최상위 진입점 함수를 노출합니다
- 렌더링과 검증은 일반 Kotlin 객체를 대상으로 수행합니다
자주 묻는 질문
“타입 안전한 HTML/Config DSL 만들기” 강의는 무료인가요?
네 — “타입 안전한 HTML/Config DSL 만들기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Kotlin Academy 강의 전체를 잠금 해제할 수 있습니다. Kotlin Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“타입 안전한 HTML/Config DSL 만들기”에서 뭘 배우나요?
빌더 패턴과 확장 람다를 사용해 간단한 설정 DSL을 구현해 보세요. 브라우저에서 직접 실행하는 실습 코드로 Kotlin Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Kotlin Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Kotlin Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“타입 안전한 HTML/Config DSL 만들기” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Kotlin Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Kotlin Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 수신 객체가 있는 람다: DSL의 기반
- @DslMarker: 수신 객체 누출 방지
- 타입 안전한 HTML/Config DSL 만들기
- 사용자를 방해하지 않고 DSL 테스트하고 발전시키기