π‘ λλ©μΈ νΉν μΈμ΄μΈ DSLμ κ°λ μ λνμ¬ μκ³ , κ°λ¨ν μ€μ΅μ μ§ννμμ΅λλ€.
DSL?
- νΉμ μ 무λ λ¬Έμ ν΄κ²°μ μν΄ μ΅μ νλ μΈμ΄λ‘, ν΄λΉ λλ©μΈμμ μΌλ°μ μΌλ‘ μ¬μ©λλ κ°λ κ³Ό μ°μ°μ κ°κ²°νκ³ μ§κ΄μ μΌλ‘ ννν μ μκ² ν΄μ€λλ€.
- Domain Specific Languageμ μ½μλ‘, νΉμ λλ©μΈμ κ΅νν΄ μ¬μ©νλ μΈμ΄μ λλ€.
- λ°λ κ°λ μΌλ‘λ General Purpose Languageκ° μμΌλ©°, C, C++, Kotlin, Swift λ±μ νλ‘κ·Έλλ° μΈμ΄λ€μ΄ μ΄μ ν΄λΉν©λλ€.
DSL vs GPL
- DSL
- μΉ νμ΄μ§ λ μ΄μμ, λ°μ΄ν°λ² μ΄μ€ 쿼리, λΉλ μλν λ± μμ μ μ½κ² νκΈ° μν΄ μ€κ³λμμ΅λλ€.
- μμ°μ±κ³Ό κ°λ μ±μ΄ μ’κ³ , 볡μ‘ν μμ μ κ°λ¨νκ² ννν μ μμ΅λλ€.
- νμ§λ§ λ²μ©μ μ΄μ§ μμμ λ€λ₯Έ λλ©μΈμ μ μ©νκΈ° μ΄λ ΅κ³ , λλ©μΈ μΈμ μμ μλ μ ν©νμ§ μμ΅λλ€.
- νμ΅ κ³‘μ μ΄ μμ΅λλ€.
- νμ€μΈκ³μ λΉκ΅νμλ©΄ λͺ©μμ ν±κ³Ό λ§μΉ, μλμ°¨ μ λΉμ¬μ λ μΉ μΈνΈ λ± νΉμ μμ μ ν¨μ¨μ κ·Ήλνν μ₯λΉλ€μ΄ μμ΅λλ€.
- GPL
- λ€μν λλ©μΈκ³Ό λ¬Έμ μμμμ μ¬μ©ν μ μλλ‘ μ€κ³λ λ²μ© νλ‘κ·Έλλ° μΈμ΄μ λλ€.
- λ€μν λ¬Έμ μμμμ μ¬μ© κ°λ₯νλ©°, μμμ΄ νλΆνκ³ λΌμ΄λΈλ¬λ¦¬μ νλ μμν¬κ° λ§μ΅λλ€.
- νμ§λ§ νΉμ λλ©μΈμ μ΅μ νλμ§ μμμ 볡μ‘ν λλ©μΈ μμ μ μ²λ¦¬νλ λ° λΉν¨μ¨μ μΌ μ μμ΅λλ€.
- νμ€μΈκ³μ λΉκ΅νμλ©΄, λ€μ©λ 곡ꡬ μΈνΈ λ± λ€μν μ§κ΅°μμ νΈλ¦¬νκ² μ¬μ©ν μ μλ μ₯λΉλ€μ΄ μμ΅λλ€.
Kotlinκ³Ό DSL
- KotlinμΌλ‘ μλλ‘μ΄λ κ°λ°νλ©΄μ μμ£Ό DSLμ μ ν μ μμ΅λλ€.
- λνμ μΌλ‘ λΉλ μ€ν¬λ¦½νΈ μμμ μλλ‘μ΄λ κ΄λ ¨ν μ΅μ μ λͺ μν λ μ¬μ©ν©λλ€.
buildFeatures {
viewBinding = true
}
- λΉλλ ν©ν 리λ₯Ό μ΄μ©νμ¬ νμν μ΅μ μ λͺ μνκ³ κ°μ²΄λ₯Ό μμ±νλ ꡬν ν¨ν΄κ³Ό λΉκ΅νμ¬ λ κ°λ΅νκ³ μ½κΈ° μ½κ² μμ±ν μ μμ΅λλ€.
- λΌμ΄λΈλ¬λ¦¬λ₯Ό κ°λ°ν λ DSLμ μ μ ν νμ©νμ¬ μ 곡νλ©΄, λΌμ΄λΈλ¬λ¦¬ μ¬μ©μλ λ³΄λ€ μ½κ³ κ°κ²°νκ² νΈμΆ μ½λλ₯Ό μμ±ν μ μμ΅λλ€.
- μ μ 리λ DSLμ μλμ μΌλ‘ μμ°μ΄μ κ°κΉμ κ°λ μ±λ λμ΅λλ€ !
Kotlinμ κΈ°λ₯
- Kotlinμ΄ DSLκ³Ό μ μ΄μΈλ¦¬λ μ΄μ λ Kotlinμμ μ 곡νλ μλμ κ°μ κΈ°λ₯λ€κ³Ό κ΄λ ¨μ΄ μμ΅λλ€.
- λλ€ ννμ (Lambda Expression)
- μ΄λ€ ν¨μλ₯Ό νλΌλ―Έν°μ λ°νκ°μΌλ‘λ§ λνλΈ ννμμ λλ€.
(Int, Int) -> Unit
- κ³ κ³ν¨μ (Higher-order Function)
- μ΄λ€ ν¨μκ° νλ μ΄μμ ν¨μλ₯Ό νλΌλ―Έν°λ‘ κ°κ±°λ, ν¨μλ₯Ό λ°ννλ κ²½μ°λ₯Ό κ³ κ³ν¨μλΌκ³ ν©λλ€.
fun calculate(a: Int, b: Int, operation: (Int,Int) -> Int): Int {
return operation(a,b)
}
- νμ₯ν¨μ (Extension Function)
- μ΄λ―Έ μ μλ ν΄λμ€λ μΈν°νμ΄μ€μ μμ μμ΄ ν¨μλ₯Ό μΆκ° μ μν μ μλ κΈ°λ₯μ λλ€.
fun Calcualtor.newFunction() { .. }
HTML DSL μ μ©
- HTMLμ TAGλ₯Ό DSLλ‘ κ΅¬νν΄λ΄€μ΅λλ€.
class Tag(val name: String) {
private val children = mutableListOf<Tag>()
private val attributes = mutableMapOf<String, String>()
fun setAttribute(name: String, value: String) {
attributes[name] = value
}
override fun toString(): String {
val attrs = if (attributes.isEmpty()) "" else attributes.map { "${it.key}=\\"${it.value}\\"" }.joinToString(" ", " ")
val childrenStr = children.joinToString("")
return "<$name$attrs>$childrenStr</$name>"
}
fun tag(name: String, init: Tag.() -> Unit) {
val tag = Tag(name)
tag.init()
children.add(tag)
}
}
fun html(init: Tag.() -> Unit): Tag {
val html = Tag("html")
html.init()
return html
}
- HTML νκ·Έλ₯Ό λ΄λΉνλ Tagμ μ€μ DSLμ νμ₯ ν¨μκ° λ htmlμ μ μΈνμμ΅λλ€.
- κ·Έ ν htmlμ μ‘΄μ¬νλ headμ bodyλ₯Ό νμ₯ν¨μλ₯Ό ν΅ν΄ μ μΈνμ¬μ΅λλ€.
- title, p, a λ±μ νμ₯ ν¨μλ‘ μ μΈνμ¬ κ°κ²°νκ² μΆκ°ν μ μλλ‘ νμμ΅λλ€.
fun Tag.head(init: Tag.() -> Unit) = tag("head", init)
fun Tag.body(init: Tag.() -> Unit) = tag("body", init)
fun Tag.title(text: String) = tag("title") { tag("text") { setAttribute("text", text) } }
fun Tag.p(text: String) = tag("p") { tag("text") { setAttribute("text", text) } }
fun Tag.a(href: String, text: String) = tag("a") {
setAttribute("href", href)
tag("text") { setAttribute("text", text) }
}
- νμ₯ ν¨μ, κ³ κ³ ν¨μ, λλ€ ν¨μλ₯Ό μ΄μ©ν DSLλ₯Ό μ¬μ©ν μ μμ΅λλ€.
fun main() {
val htmlDocument = html {
head {
title("My Page")
}
body {
p("Hello, World!")
a(href = "<https://example.com>", text = "Visit Example")
}
}
println(htmlDocument)
}
- html λΈλ‘ μμμ headμ bodyλ₯Ό μ μνκ³ , κ°κ°μ λΈλ‘ μμμ νκ·Έλ₯Ό μΆκ°νμμ΅λλ€.
- νκ·Έλ₯Ό μΆκ°ν λ λλ€ ννμμ μ¬μ©νμ¬ νκ·Έ λ΄λΆλ₯Ό μ μνμμ΅λλ€.
- μ΄λ‘ μΈν΄μ κ°νΈνκ² DSLλ₯Ό μ¬μ©ν μ μκ² λμμΌλ©°, μμ°μ±κ³Ό κ°λ μ±μ΄ λμ μ½λλ‘ λ³΅μ‘ν μμ μ κ°λ¨νκ² ννν μ μκ² λμμ΅λλ€.
μ°Έκ³
https://myungpyo.medium.com/kotlin-dsl-κ°λ¨ν-μμ보기-5f95fddf00f9
https://velog.io/@akimcse/Kotlin-in-Action-11.-DSL-λ§λ€κΈ°