๐ญ Groovy์ ๋น๋ ํจํด: DSL ์์ฑ ๊ธฐ๋ฒ ๐ ๏ธ

์๋ ํ์ธ์, ์ฌ๋ฌ๋ถ! ์ค๋์ ์ ๋ง ํฅ๋ฏธ์ง์งํ ์ฃผ์ ๋ก ์ฌ๋ฌ๋ถ๊ณผ ํจ๊ปํ ๊ฑฐ์์. ๋ฐ๋ก "Groovy์ ๋น๋ ํจํด: DSL ์์ฑ ๊ธฐ๋ฒ"์ ๋ํด ๊น์ด ํํค์ณ๋ณผ ๊ฑฐ๋๋๋ค. ์ด ์ฃผ์ , ์ฒ์ ๋ค์ผ๋ฉด ์ข ์ด๋ ต๊ฒ ๋๊ปด์ง ์ ์์ฃ ? ํ์ง๋ง ๊ฑฑ์ ๋ง์ธ์! ์ ๊ฐ ์ฌ๋ฌ๋ถ์ ๋๋์ด์ ๋ง์ถฐ ์ฝ๊ณ ์ฌ๋ฏธ์๊ฒ ์ค๋ช ํด๋๋ฆด๊ฒ์. ๋ง์น ์นดํก์ผ๋ก ์น๊ตฌ์ ๋ํํ๋ฏ์ด ๋ง์ด์ฃ . ใ ใ ใ
๊ทธ๋ผ ์ด์ ๋ถํฐ Groovy ์ธ์ด์ ๋งค๋ ฅ์ ์ธ ์ธ๊ณ๋ก ๋น ์ ธ๋ณผ๊น์? ๐
์ ๊น! ํน์ ์ฌ๋ฌ๋ถ ์ค์ ํ๋ก๊ทธ๋๋ฐ์ ๊ด์ฌ ์์ผ์ ๋ถ๋ค ๊ณ์ ๊ฐ์? ๊ทธ๋ ๋ค๋ฉด ์ฌ๋ฅ๋ท(https://www.jaenung.net)์์ ๋ค์ํ ํ๋ก๊ทธ๋๋ฐ ๊ด๋ จ ์ฌ๋ฅ์ ์ฐพ์๋ณด์ธ์. ์ฌ๋ฌ๋ถ์ ์ค๋ ฅ ํฅ์์ ํฐ ๋์์ด ๋ ๊ฑฐ์์!
๐ค Groovy๊ฐ ๋ญ๊ธธ๋?
์, ๋จผ์ Groovy์ ๋ํด ๊ฐ๋จํ ์์๋ณผ๊น์? Groovy๋ Java ํ๋ซํผ์ ์ํ ๋์ ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์์. Java์ ๋น์ทํ๋ฉด์๋ ๋ ๊ฐ๊ฒฐํ๊ณ ์ ์ฐํ ๋ฌธ๋ฒ์ ๊ฐ์ง๊ณ ์์ฃ . ๋ง์น Java์ ์ฟจํ ์ฌ์ด ๊ฐ์ ๋๋์ด๋๊น์? ๐
Groovy์ ํน์ง์ ๋ช ๊ฐ์ง ์ดํด๋ณผ๊น์?
- Java์ 100% ํธํ๋ผ์. Java ์ฝ๋๋ฅผ ๊ทธ๋๋ก Groovy์์ ์ธ ์ ์์ด์!
- ๋์ ํ์ดํ์ ์ง์ํด์. ๋ณ์ ํ์ ์ ์ผ์ผ์ด ์ ์ธํ์ง ์์๋ ๋ผ์.
- ํด๋ก์ (Closure)๋ฅผ ์ง์ํด์. ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ๊ฝ์ด์ฃ !
- ๋ฉํํ๋ก๊ทธ๋๋ฐ์ด ๊ฐ๋ฅํด์. ํ๋ก๊ทธ๋จ์ด ์๊ธฐ ์์ ์ ์์ ํ ์ ์๋ค๋, ์ฉ๋ค ์ฉ๋ค~ ๐
์ด๋ฐ ํน์ง๋ค ๋๋ฌธ์ Groovy๋ ํนํ DSL(Domain-Specific Language) ๋ง๋ค๊ธฐ์ ์์ฃผ ์ ํฉํด์. ๊ทธ๋ผ DSL์ด ๋ญ์ง ๊ถ๊ธํ์์ฃ ?
๐ฃ๏ธ DSL์ด ๋ญ์์? ๋จน๋ ๊ฑด๊ฐ์?
ใ ใ ใ ์๋์, DSL์ ๋จน๋ ๊ฒ ์๋์์! DSL์ "Domain-Specific Language"์ ์ฝ์๋ก, ํน์ ๋๋ฉ์ธ(๋ถ์ผ)์ ํนํ๋ ์ธ์ด๋ฅผ ๋งํด์. ์ฝ๊ฒ ๋งํด, ์ด๋ค ํน์ ํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ง๋ค์ด์ง '๋ง์ถค ์ธ์ด'๋ผ๊ณ ์๊ฐํ๋ฉด ๋ผ์.
์๋ฅผ ๋ค์ด๋ณผ๊น์? HTML์ ์น ํ์ด์ง๋ฅผ ๋ง๋ค๊ธฐ ์ํ DSL์ด์์. SQL์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋ค๋ฃจ๊ธฐ ์ํ DSL์ด๊ณ ์. ์ด๋ ๊ฒ ํน์ ๋ชฉ์ ์ ๋ง์ถฐ ๋ง๋ค์ด์ง ์ธ์ด๋ค์ด ๋ฐ๋ก DSL์ด์์.
์ฃผ์! DSL์ ๋ง๋ค ๋๋ ๊ทธ ์ธ์ด๋ฅผ ์ฌ์ฉํ ์ฌ๋๋ค์ ํญ์ ์๊ฐํด์ผ ํด์. ๋๋ฌด ๋ณต์กํ๋ฉด ์๋ฌด๋ ์ ์ธ ๊ฑฐ์์. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ๋ฅ์ ์ค๋ช ํ ๋์ฒ๋ผ, ๋๊ตฌ๋ ์ฝ๊ฒ ์ดํดํ ์ ์๋๋ก ๋ง๋ค์ด์ผ ํด์!
๊ทธ๋ผ ์ด์ Groovy์์ ์ด๋ป๊ฒ DSL์ ๋ง๋๋์ง ์์๋ณผ๊น์? ์ฌ๊ธฐ์ ๋น๋ ํจํด์ด ๋ฑ์ฅํฉ๋๋ค!
๐๏ธ ๋น๋ ํจํด? ๊ฑด์ถ๊ฐ ๋๋ ๊ฑฐ์์?
ใ ใ ใ ์๋์์, ์ฌ๋ฌ๋ถ์ด ์ง์ ๊ฑด๋ฌผ์ ์ง๋ ๊ฑด ์๋์์! ํ์ง๋ง ๋น์ ํ์๋ฉด ๊ฝค ๋น์ทํด์. ๋น๋ ํจํด์ ๋ณต์กํ ๊ฐ์ฒด๋ฅผ ๋จ๊ณ๋ณ๋ก ๋ง๋ค์ด๊ฐ๋ ๋์์ธ ํจํด์ด์์. ๋ง์น ๊ฑด๋ฌผ์ ์ง์ ๋ ๊ธฐ์ด๋ถํฐ ์ฐจ๊ทผ์ฐจ๊ทผ ์ฌ๋ผ๊ฐ๋ ๊ฒ์ฒ๋ผ์.
Groovy์์๋ ์ด ๋น๋ ํจํด์ ์ฌ์ฉํด์ ์์ฃผ ์ฐ์ํ๊ณ ์ฝ๊ธฐ ์ฌ์ด DSL์ ๋ง๋ค ์ ์์ด์. ์ด๋ป๊ฒ ํ๋์ง ํ๋ฒ ๋ณผ๊น์?
def html = new MarkupBuilder()
html.html {
head {
title 'My Awesome Page'
}
body {
h1 'Welcome to my page!'
p 'This is a paragraph.'
}
}
์ด ์ฝ๋๋ฅผ ๋ณด๋ฉด HTML์ ๋ง๋๋ DSL์ด ์ด๋ป๊ฒ ์๊ฒผ๋์ง ์ ์ ์์ด์. ๋ง์น HTML ๊ตฌ์กฐ๋ฅผ ๊ทธ๋๋ก ์ฝ๋๋ก ์ฎ๊ฒจ๋์ ๊ฒ ๊ฐ์ฃ ? ์ด๊ฒ ๋ฐ๋ก Groovy์ ๋น๋ ํจํด์ ์ด์ฉํ DSL์ ํ์ด์์!
๊ฟํ! DSL์ ๋ง๋ค ๋๋ ํญ์ ์ฌ์ฉ์ ๊ฒฝํ์ ์๊ฐํด์ผ ํด์. ์ฌ๋ฅ๋ท์์ ์ฌ๋ฅ์ ์ค๋ช ํ๋ฏ์ด, ๋๊ตฌ๋ ์ฝ๊ฒ ์ดํดํ๊ณ ์ฌ์ฉํ ์ ์๋๋ก ๋ง๋ค์ด์ผ ํด์. ๊ทธ๋์ผ ๋ง์ ์ฌ๋๋ค์ด ์ฌ์ฉํ๊ฒ ์ฃ ?
๐จ Groovy๋ก DSL ๋ง๋ค๊ธฐ: step by step
์, ์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก Groovy๋ก DSL์ ๋ง๋๋ ๋ฐฉ๋ฒ์ ์์๋ณผ๊น์? ์ฒ์ฒํ, ๋จ๊ณ๋ณ๋ก ์ค๋ช ํด๋๋ฆด๊ฒ์. ์ค๋น๋์ จ๋์? Let's go! ๐
Step 1: ํด๋ก์ (Closure) ์ดํดํ๊ธฐ
Groovy์ DSL์ ์ดํดํ๋ ค๋ฉด ๋จผ์ ํด๋ก์ ์ ๋ํด ์์์ผ ํด์. ํด๋ก์ ๋ ๊ฐ๋จํ ๋งํด '์ฝ๋ ๋ธ๋ก'์ด์์. ํจ์์ฒ๋ผ ์ฌ์ฉํ ์ ์๋ ์ฝ๋ ๋ญ์น๋ผ๊ณ ์๊ฐํ๋ฉด ๋ผ์.
def greet = { name ->
println "์๋
, $name!"
}
greet("์ํฌ") // ์ถ๋ ฅ: ์๋
, ์ํฌ!
์ด๋ ๊ฒ ํด๋ก์ ๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๋๋ฅผ ๋ ์ ์ฐํ๊ฒ ๋ง๋ค ์ ์์ด์. DSL์ ๋ง๋ค ๋ ์ด ํด๋ก์ ๊ฐ ์์ฃผ ์ค์ํ ์ญํ ์ ํด์!
Step 2: ๋ฉ์๋ ํธ์ถ ๋ฌธ๋ฒ ์ดํดํ๊ธฐ
Groovy์์๋ ๋ฉ์๋๋ฅผ ํธ์ถํ ๋ ๊ดํธ๋ฅผ ์๋ตํ ์ ์์ด์. ์ด๊ฒ ์ ์ค์ํ๋๊ณ ์? DSL์ ๋ ์์ฐ์ค๋ฝ๊ฒ ๋ง๋ค ์ ์๊ฑฐ๋ ์!
// ์ผ๋ฐ์ ์ธ ๋ฉ์๋ ํธ์ถ
println("Hello, World!")
// Groovy ์คํ์ผ
println "Hello, World!"
์ด๋์? ๋ ๋ฒ์งธ ๋ฐฉ์์ด ๋ ์์ฐ์ค๋ฝ๊ฒ ์ฝํ์ง ์๋์?
Step 3: ๋น๋ ํจํด ๊ตฌํํ๊ธฐ
์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก ๋น๋ ํจํด์ ๊ตฌํํด๋ณผ๊น์? ๊ฐ๋จํ ์์ ๋ก ์์ํด๋ณผ๊ฒ์. ํผ์๋ฅผ ์ฃผ๋ฌธํ๋ DSL์ ๋ง๋ค์ด๋ณผ๊น์?
class Pizza {
String size
List toppings = []
def size(String s) {
size = s
}
def topping(String t) {
toppings << t
}
}
def pizza(closure) {
Pizza pizzaBuilder = new Pizza()
closure.delegate = pizzaBuilder
closure()
return pizzaBuilder
}
def myPizza = pizza {
size "large"
topping "cheese"
topping "pepperoni"
}
println "๋ด๊ฐ ์ฃผ๋ฌธํ ํผ์: ${myPizza.size} ์ฌ์ด์ฆ, ํ ํ: ${myPizza.toppings.join(', ')}"
์ฐ์~ ์ด๋ ๊ฒ ํ๋ฉด ํผ์ ์ฃผ๋ฌธ์ ๋ง์น ์์ด๋ก ๋งํ๋ฏ์ด ์ฝ๋๋ก ํํํ ์ ์์ด์! ๐๐
์ฌ๋ฏธ์๋ ์ฌ์ค! ์ด๋ฐ ์์ผ๋ก DSL์ ๋ง๋ค๋ฉด, ํ๋ก๊ทธ๋๋ฐ์ ์ ๋ชจ๋ฅด๋ ์ฌ๋๋ค๋ ์ฝ๊ฒ ์ดํดํ๊ณ ์ฌ์ฉํ ์ ์์ด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ์ฌ๋ฅ์ ์ฝ๊ฒ ์ฐพ์๋ณผ ์ ์๋ ๊ฒ์ฒ๋ผ์!
Step 4: ์ค์ฒฉ ๊ตฌ์กฐ ๋ง๋ค๊ธฐ
์ค์ DSL์ ๋ณดํต ๋ ๋ณต์กํ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์์ด์. ์ค์ฒฉ๋ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์ด๋ณผ๊น์? ์ด๋ฒ์๋ ๊ฐ๋จํ HTML DSL์ ๋ง๋ค์ด๋ณผ๊ฒ์.
class HtmlBuilder {
def html = new StringBuilder()
def methodMissing(String name, args) {
html << "<$name>"
if (args) {
if (args[0] instanceof Closure) {
args[0].delegate = this
args[0].call()
} else {
html << args[0]
}
}
html << "</$name>"
}
}
def html(closure) {
def builder = new HtmlBuilder()
closure.delegate = builder
closure()
return builder.html.toString()
}
def result = html {
html {
head {
title "My Awesome Page"
}
body {
h1 "Welcome!"
p "This is a paragraph."
}
}
}
println result
์์ฐ! ์ด์ HTML์ ๋ง์น Groovy ์ฝ๋์ฒ๋ผ ์์ฑํ ์ ์๊ฒ ๋์์ด์. ์ด๊ฒ ๋ฐ๋ก DSL์ ํ์ด์์! ๐
๐ญ DSL์ ์ฅ๋จ์
์, ์ด์ DSL์ ๋ํด ๊ฝค ๋ง์ด ์๊ฒ ๋์์ฃ ? ๊ทธ๋ผ DSL์ ์ฅ๋จ์ ์ ๋ํด ํ๋ฒ ์๊ฐํด๋ณผ๊น์?
์ฅ์ ๐
- ๊ฐ๋ ์ฑ์ด ์ข์์: DSL์ ๋๋ฉ์ธ ์ ๋ฌธ๊ฐ๋ ์ฝ๊ฒ ์ฝ์ ์ ์์ด์.
- ์์ฐ์ฑ์ด ๋์์ ธ์: ๋ณต์กํ ๋ก์ง์ ๊ฐ๋จํ๊ฒ ํํํ ์ ์์ด์.
- ์ ์ง๋ณด์๊ฐ ์ฌ์์: ์ฝ๋๊ฐ ๋ ๋ช ํํด์ง๋๊น ๋ฒ๊ทธ ์ฐพ๊ธฐ๋ ์ฌ์์ ธ์.
- ๋๋ฉ์ธ ์ง์์ ์ฝ๋๋ก ํํํ๊ธฐ ์ฌ์์: ๋น์ฆ๋์ค ๋ก์ง์ ๋ ์ง๊ด์ ์ผ๋ก ํํํ ์ ์์ด์.
๋จ์ ๐
- ํ์ต ๊ณก์ ์ด ์์ด์: ์๋ก์ด DSL์ ๋ฐฐ์ฐ๋ ๋ฐ ์๊ฐ์ด ๊ฑธ๋ฆด ์ ์์ด์.
- ๊ณผ๋ํ ์ฌ์ฉ์ ๊ธ๋ฌผ: ๋ชจ๋ ๊ฒ์ DSL๋ก ๋ง๋ค๋ ค๊ณ ํ๋ฉด ์คํ๋ ค ๋ณต์กํด์ง ์ ์์ด์.
- ์ฑ๋ฅ ์ด์๊ฐ ์์ ์ ์์ด์: ๋๋ก๋ ์ผ๋ฐ ์ฝ๋๋ณด๋ค ๋๋ฆด ์ ์์ด์.
- ๋๋ฒ๊น ์ด ์ด๋ ค์ธ ์ ์์ด์: DSL ์์ฒด์ ๋ฒ๊ทธ๋ฅผ ์ฐพ๊ธฐ๊ฐ ์ฝ์ง ์์ ์ ์์ด์.
์๊ฐํด๋ณด๊ธฐ: DSL์ ๋ง๋ค ๋๋ ํญ์ ๊ทธ DSL์ด ์ ๋ง ํ์ํ์ง ๊ณ ๋ฏผํด๋ด์ผ ํด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ์๋ก์ด ์ฌ๋ฅ์ ๋ฑ๋กํ ๋ ๊ทธ ์ฌ๋ฅ์ด ์ ๋ง ๊ฐ์น ์๋์ง ๊ณ ๋ฏผํ๋ ๊ฒ์ฒ๋ผ์!
๐ ์ค์ : ๋ณต์กํ DSL ๋ง๋ค๊ธฐ
์, ์ด์ ์ฐ๋ฆฌ๊ฐ ๋ฐฐ์ด ๊ฑธ ํ ๋๋ก ์กฐ๊ธ ๋ ๋ณต์กํ DSL์ ๋ง๋ค์ด๋ณผ๊น์? ์ด๋ฒ์๋ ๊ฐ๋จํ ๊ฒ์ ์บ๋ฆญํฐ๋ฅผ ๋ง๋๋ DSL์ ๊ตฌํํด๋ณผ๊ฒ์!
class Character {
String name
int health = 100
int strength = 10
List<String> skills = []
Map<String, String> equipment = [:]
def name(String n) { name = n }
def health(int h) { health = h }
def strength(int s) { strength = s }
def skill(String s) { skills << s }
def equip(String slot, String item) { equipment[slot] = item }
}
def character(Closure closure) {
def characterBuilder = new Character()
closure.delegate = characterBuilder
closure()
return characterBuilder
}
def myHero = character {
name "์ํผ ๊ฐ๋ฐ์"
health 120
strength 15
skill "์ฝ๋ฉ ํญํ"
skill "๋๋ฒ๊น
๋ง์คํฐ"
equip "๋จธ๋ฆฌ", "์ง์์ ์๊ด"
equip "์", "๊ธฐ๊ณ์ ํค๋ณด๋"
}
println "์บ๋ฆญํฐ ์ ๋ณด:"
println "์ด๋ฆ: ${myHero.name}"
println "์ฒด๋ ฅ: ${myHero.health}"
println "ํ: ${myHero.strength}"
println "์คํฌ: ${myHero.skills.join(', ')}"
println "์ฅ๋น: ${myHero.equipment}"
์~ ์ ๋ง ๋ฉ์ง ์บ๋ฆญํฐ๊ฐ ํ์ํ๋ค์! ๐ ์ด๋ ๊ฒ DSL์ ์ฌ์ฉํ๋ฉด ๋ณต์กํ ๊ฐ์ฒด๋ ์์ฃผ ์ง๊ด์ ์ผ๋ก ๋ง๋ค ์ ์์ด์.
๐ก DSL ์ค๊ณ ํ
DSL์ ๋ง๋ค ๋ ์ฃผ์ํด์ผ ํ ์ ๋ค์ด ์์ด์. ํจ๊ป ์ดํด๋ณผ๊น์?
- ๊ฐ๊ฒฐ์ฑ์ ์ ์งํ์ธ์: DSL์ ๊ฐ๊ฒฐํ ์๋ก ์ข์์. ๋ถํ์ํ ๋ฌธ๋ฒ์ ๊ณผ๊ฐํ ์ ๊ฑฐํ์ธ์.
- ์ผ๊ด์ฑ์ ์งํค์ธ์: ๋น์ทํ ๋์์ ๋น์ทํ ๋ฌธ๋ฒ์ผ๋ก ํํ๋์ด์ผ ํด์.
- ์ง๊ด์ ์ผ๋ก ๋ง๋์ธ์: DSL์ ์ฒ์ ๋ณด๋ ์ฌ๋๋ ๋์ถฉ ์ดํดํ ์ ์์ด์ผ ํด์.
- ํ์ฅ์ฑ์ ๊ณ ๋ คํ์ธ์: ๋์ค์ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๊ธฐ ์ฝ๋๋ก ์ค๊ณํ์ธ์.
- ๋ฌธ์ํ๋ฅผ ์ํ์ธ์: ์๋ฌด๋ฆฌ ์ง๊ด์ ์ธ DSL์ด๋ผ๋ ๋ฌธ์ํ๋ ํ์์์!
๊ฟํ! DSL์ ์ค๊ณํ ๋๋ ํญ์ ์ฌ์ฉ์์ ์ ์ฅ์์ ์๊ฐํด๋ณด์ธ์. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ๋ฅ์ ์ค๋ช ํ ๋ ๊ตฌ๋งค์์ ์ ์ฅ์ ๊ณ ๋ คํ๋ ๊ฒ์ฒ๋ผ์!
๐ Groovy DSL์ ์ค์ ์ฌ์ฉ ์ฌ๋ก
Groovy DSL์ ์ค์ ๋ก ๋ง์ ๊ณณ์์ ์ฌ์ฉ๋๊ณ ์์ด์. ๋ช ๊ฐ์ง ์๋ฅผ ์ดํด๋ณผ๊น์?
1. Gradle
์๋๋ก์ด๋ ๊ฐ๋ฐ์๋ค์ ์์ค ๊ฑฐ์์. Gradle์ ๋น๋ ์๋ํ ๋๊ตฌ์ธ๋ฐ, Groovy DSL์ ์ฌ์ฉํด์ ๋น๋ ์คํฌ๋ฆฝํธ๋ฅผ ์์ฑํด์.
apply plugin: 'java'
dependencies {
compile 'org.springframework:spring-core:5.2.6.RELEASE'
testCompile 'junit:junit:4.12'
}
์ด๋ ๊ฒ ๊ฐ๋จํ๊ฒ ํ๋ก์ ํธ ์ค์ ์ ํ ์ ์์ด์. ๋ฉ์ง์ฃ ? ๐
2. Jenkins Pipeline
CI/CD ๋๊ตฌ์ธ Jenkins์์๋ Groovy DSL์ ์ฌ์ฉํด ํ์ดํ๋ผ์ธ์ ์ ์ํ ์ ์์ด์.
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'mvn clean package'
}
}
stage('Test') {
steps {
sh 'mvn test'
}
}
}
}
์ด๋ ๊ฒ ํ๋ฉด ๋น๋ ๊ณผ์ ์ ์์ฃผ ๋ช ํํ๊ฒ ํํํ ์ ์์ด์!
3. Spock Framework
Spock์ Groovy๋ก ์์ฑ๋ ํ ์คํ ํ๋ ์์ํฌ์์. Groovy DSL์ ์ฌ์ฉํด์ ํ ์คํธ ์ฝ๋๋ฅผ ์์ฃผ ์ฝ๊ธฐ ์ฝ๊ฒ ๋ง๋ค ์ ์์ด์.
def "๋ ์์ ํฉ์ ๊ณ์ฐํ๋ค"() {
given:
def calculator = new Calculator()
when:
def result = calculator.add(a, b)
then:
result == expected
where:
a | b || expected
1 | 2 || 3
3 | 4 || 7
}
์ด๋ ๊ฒ ํ๋ฉด ํ ์คํธ ์ฝ๋๊ฐ ๋ง์น ๋ฌธ์์ฒ๋ผ ์ฝํ์ฃ ? ๐
์ฌ๋ฏธ์๋ ์ฌ์ค: ์ด๋ ๊ฒ DSL์ ์ ํ์ฉํ๋ฉด, ์ฝ๋ ์์ฒด๊ฐ ๋ฌธ์๊ฐ ๋ ์ ์์ด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ๋ฅ ์ค๋ช ์ ์ฝ๋ ๊ฒ๋ง์ผ๋ก๋ ๊ทธ ์ฌ๋ฅ์ ์ดํดํ ์ ์๋ ๊ฒ์ฒ๋ผ์!
๐ค Groovy DSL vs ๋ค๋ฅธ ์ธ์ด์ DSL
Groovy DSL์ด ์ข์ ๊ฑด ์๊ฒ ๋๋ฐ, ๋ค๋ฅธ ์ธ์ด์์๋ ์ด๋ป๊ฒ DSL์ ๋ง๋ค๊น์? ๋ช ๊ฐ์ง ๋น๊ตํด๋ณผ๊น์?
Ruby DSL
Ruby๋ DSL์ ๋ง๋ค๊ธฐ ์ข์ ์ธ์ด๋ก ์ ๋ช ํด์. Ruby on Rails ํ๋ ์์ํฌ๊ฐ ๋ํ์ ์ธ ์์ฃ .
class Product < ActiveRecord::Base
belongs_to :category
has_many :orders
validates :name, presence: true
validates :price, numericality: { greater_than: 0 }
end
Ruby์ DSL๋ ๊ฝค ์ฝ๊ธฐ ์ฝ์ฃ ? ํ์ง๋ง Groovy๋งํผ ์์ ๋กญ์ง ์์์.
Kotlin DSL
Kotlin๋ DSL์ ์ง์ํด์. ํนํ ์๋๋ก์ด๋ ๊ฐ๋ฐ์์ ๋ง์ด ์ฌ์ฉ๋์ฃ .
fun html(init: HTML.() -> Unit): HTML {
val html = HTML()
html.init()
return html
}
val result = html {
head {
title { +"HTML encoding with Kotlin" }
}
body {
h1 { +"HTML encoding with Kotlin" }
p { +"this format can be used as an alternative markup to HTML" }
}
}
Kotlin์ DSL์ ํ์ ์์ ์ฑ์ด ์ข์์. ํ์ง๋ง Groovy๋งํผ ๋์ ์ด์ง ์์ฃ .
Python DSL
Python์์๋ DSL์ ๋ง๋ค ์ ์์ด์. ํ์ง๋ง ๋ค๋ฅธ ์ธ์ด๋ค๋งํผ ์ฐ์ํ์ง ์์์.
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run()
Python์ ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ฌ์ฉํ DSL์ด์์. ๊ฐ๋จํ์ง๋ง, Groovy๋งํผ ์ ์ฐํ์ง ์์ฃ .
์๊ฐํด๋ณด๊ธฐ: ๊ฐ ์ธ์ด๋ง๋ค DSL์ ๋ง๋๋ ๋ฐฉ์์ด ๋ค๋ฅด๋ค์. ์ด๋ค ์ธ์ด๊ฐ ๊ฐ์ฅ ๋ง์์ ๋๋์? ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ์ฌ๋ฅ ์ค ์์ ์๊ฒ ๋ง๋ ๊ฑธ ๊ณ ๋ฅด๋ ๊ฒ์ฒ๋ผ, ํ๋ก์ ํธ์ ๋ง๋ ์ธ์ด์ DSL ์คํ์ผ์ ์ ํํ๋ ๊ฒ๋ ์ค์ํด์!
๐จ DSL ๋์์ธ ํจํด
DSL์ ๋ง๋ค ๋ ์ฌ์ฉํ ์ ์๋ ์ฌ๋ฌ ๋์์ธ ํจํด๋ค์ด ์์ด์. ๋ช ๊ฐ์ง ์ดํด๋ณผ๊น์?
1. ์ค์ฒฉ ํจ์ ํจํด
์ด ํจํด์ ํจ์ ์์ ํจ์๋ฅผ ์ค์ฒฉํด์ ๊ตฌ์กฐ๋ฅผ ํํํด์.
menu {
category("์๋ฃ") {
item("์ปคํผ", 3000)
item("์ฃผ์ค", 3500)
}
category("๋์ ํธ") {
item("์ผ์ดํฌ", 5000)
item("์ฟ ํค", 2000)
}
}
์ด๋ ๊ฒ ํ๋ฉด ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ์์ฃผ ๋ช ํํ๊ฒ ํํํ ์ ์์ด์!
2. ๋ฉ์๋ ์ฒด์ด๋ ํจํด
์ด ํจํด์ ๋ฉ์๋๋ฅผ ์ฐ์ํด์ ํธ์ถํ๋ ๋ฐฉ์์ด์์.
new Robot()
.setName("R2D2")
.setColor("Silver")
.setHeight(1.2)
.build()
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ