๐ Scala์ ํ์ ๋๋ค: ๊ณ ์ฐจ ํ์ ํ๋ก๊ทธ๋๋ฐ์ ์ธ๊ณ๋ก ํ๋ฉ! ๐

์๋ ํ์ธ์, ์ฌ๋ฌ๋ถ! ์ค๋์ ์ ๋ง ํฅ๋ฏธ์ง์งํ ์ฃผ์ ๋ก ์ฌ๋ฌ๋ถ๊ณผ ํจ๊ป ํ ๊ฑฐ์์. ๋ฐ๋ก Scala์ ํ์ ๋๋ค์ ๊ณ ์ฐจ ํ์ ํ๋ก๊ทธ๋๋ฐ์ ๋ํด ๊น์ด ํ๊ณ ๋ค์ด๋ณผ ๊ฑฐ๋๋๋ค. ์ด๋จธ, ๋ฒ์จ๋ถํฐ ๋จธ๋ฆฌ๊ฐ ์ง๋๊ฑฐ๋ฆฌ๋์? ใ ใ ใ ๊ฑฑ์ ๋ง์ธ์! ์ฐ๋ฆฌ ํจ๊ป ์ฐจ๊ทผ์ฐจ๊ทผ ์์๊ฐ ๋ณด์ฃ !
์ด ์ฃผ์ ๋ 'ํ๋ก๊ทธ๋จ๊ฐ๋ฐ' ์นดํ ๊ณ ๋ฆฌ์ '๊ธฐํํ๋ก๊ทธ๋จ๊ฐ๋ฐ'์ ์ํ๋ ๋ด์ฉ์ด์์. ํ๋ก๊ทธ๋๋ฐ ์ธ๊ณ์์ ์์ฃผ ์ค์ํ ๊ฐ๋ ์ด์ฃ . ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ์ฌ๋ฅ์ ๊ฑฐ๋ํ๋ฏ์ด, ์ฐ๋ฆฌ๋ ์ค๋ ๋ค์ํ ํ์ ๊ณผ ๋๋ค์ ์ธ๊ณ๋ฅผ ํํํด๋ณผ ๊ฑฐ์์!
๐ ์ ๊น! ์๊ณ ๊ฐ์ธ์: Scala๋ Java Virtual Machine(JVM) ์์์ ๋์ํ๋ ๋ค์ค ํจ๋ฌ๋ค์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์์. ๊ฐ์ฒด ์งํฅ์ ํน์ฑ๊ณผ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ํน์ฑ์ ๋ชจ๋ ๊ฐ์ง๊ณ ์์ฃ . ๊ทธ๋์ Scala๋ก ์ฝ๋ฉํ๋ฉด ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ๋ฌ ์ฌ๋ฅ์ ํ ๋ฒ์ ํ์ฉํ๋ ๊ฒ์ฒ๋ผ ๋ค์ํ ํ๋ก๊ทธ๋๋ฐ ์คํ์ผ์ ๊ตฌ์ฌํ ์ ์๋ต๋๋ค!
์, ์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก ์์ํด๋ณผ๊น์? ์ฐ๋ฆฌ์ ์ฌ์ ์ ๊ธธ๊ณ ๋ ํ๋ํ ์ ์์ด์. ํ์ง๋ง ๊ฑฑ์ ๋ง์ธ์! ์ ๊ฐ ์ฌ๋ฌ๋ถ์ ๋ ๋ ํ ๊ฐ์ด๋๊ฐ ๋์ด ๋๋ฆด๊ฒ์. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ ๋ฌธ๊ฐ์ ๋์์ ๋ฐ๋ฏ์ด ๋ง์ด์ฃ ! ๐
์ฐ๋ฆฌ์ ์ฌ์ ์ ๋ค์๊ณผ ๊ฐ์ ์์๋ก ์งํ๋ ๊ฑฐ์์:
- ํ์ ์์คํ ์ ๊ธฐ์ด
- ๋๋ค์ ๊ฐ๋ ๊ณผ ํ์ฉ
- ๊ณ ์ฐจ ํ์ ์ ์ธ๊ณ
- ํ์ ๋๋ค์ ๋ง๋ฒ
- ์ค์ ์์ ์ ํ์ฉ
์ค๋น๋์ จ๋์? ๊ทธ๋ผ ์ถ๋ฐ~! ๐๐จ
๐งฑ ํ์ ์์คํ ์ ๊ธฐ์ด: ์ฐ๋ฆฌ์ ์ฌ์ ์ ์์์
์, ์ฌ๋ฌ๋ถ! ํ์ ์์คํ ์ด๋ผ๊ณ ํ๋ฉด ๋ญ๊ฐ ์ ์ผ ๋จผ์ ๋ ์ค๋ฅด์๋์? ํน์ "์, ๊ทธ๊ฑฐ Int๋ String ๊ฐ์ ๊ฑฐ ์๋?"๋ผ๊ณ ์๊ฐํ์ จ๋ค๋ฉด... ์, ๋ง์์! ํ์ง๋ง ๊ทธ๊ฒ ์ ๋ถ๋ ์๋๋๋๋ค. ใ ใ ใ
ํ์ ์์คํ ์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ ํต์ฌ ์์์์. ๋ง์น ์ฌ๋ฅ๋ท์์ ๊ฐ ์ฌ๋ฅ๋ค์ด ๋ถ๋ฅ๋์ด ์๋ ๊ฒ์ฒ๋ผ, ํ๋ก๊ทธ๋๋ฐ์์๋ ๋ฐ์ดํฐ์ ์ฐ์ฐ์ ๋ถ๋ฅํ๊ณ ์กฐ์งํํ๋ ์ญํ ์ ํ์ฃ . ๊ทธ๋ผ Scala์ ํ์ ์์คํ ์ ๋ํด ์์ธํ ์์๋ณผ๊น์?
๐ Scala์ ํ์ ์์คํ ํน์ง:
- ์ ์ ํ์ ์์คํ (์ปดํ์ผ ์์ ์ ํ์ ์ฒดํฌ)
- ํ์ ์ถ๋ก (๋ณ์์ ํ์ ์ ๋ช ์์ ์ผ๋ก ์ ์ธํ์ง ์์๋ ๋จ)
- ์ ๋ค๋ฆญ ํ๋ก๊ทธ๋๋ฐ ์ง์
- ๋์์ ๋ฐ์ดํฐ ํ์ (ADT) ์ง์
- ๊ณ ์ฐจ ํ์ (Higher-kinded types) ์ง์
์์ฐ! ๋ฒ์จ๋ถํฐ ๋๋จํด ๋ณด์ด์ฃ ? ใ ใ ใ ํ๋์ฉ ์ดํด๋ณผ๊ฒ์!
1. ์ ์ ํ์ ์์คํ ๐ช
Scala๋ ์ ์ ํ์ ์์คํ ์ ์ฌ์ฉํด์. ์ด๊ฒ ๋ฌด์จ ๋ง์ด๋๊ณ ์? ๊ฐ๋จํ ๋งํด์, ์ปดํ์ผ ์์ ์ ๋ชจ๋ ํํ์์ ํ์ ์ ๊ฒ์ฌํ๋ค๋ ๊ฑฐ์์. ์ด๋ ๊ฒ ํ๋ฉด ๋ฐํ์ ์๋ฌ๋ฅผ ๋ง์ด ์ค์ผ ์ ์์ฃ !
์๋ฅผ ๋ค์ด๋ณผ๊น์?
val x: Int = 5
val y: String = "Hello"
val z: Int = x + y // ์ปดํ์ผ ์๋ฌ!
์ ์ฝ๋์์ z
๋ฅผ ์ ์ํ ๋ ์ปดํ์ผ๋ฌ๊ฐ "์ ๊น๋ง์! Int์ String์ ๋ํ ์ ์์ด์!"๋ผ๊ณ ๋งํด์ค ๊ฑฐ์์. ์ด๋ ๊ฒ ๋ฏธ๋ฆฌ ์ค๋ฅ๋ฅผ ์ก์์ฃผ๋ ์ผ๋ง๋ ํธ๋ฆฌํ๊ฐ์? ๐
2. ํ์ ์ถ๋ก ๐ต๏ธโโ๏ธ
Scala์ ๋ ๋ค๋ฅธ ๋ฉ์ง ๊ธฐ๋ฅ์ ํ์ ์ถ๋ก ์ด์์. ์ด๊ฒ ๋ญ๋๊ณ ์? ์... ์ฌ๋ฌ๋ถ์ด ์ฌ๋ฅ๋ท์์ ์ฌ๋ฅ์ ๋ฑ๋กํ ๋, ์์คํ ์ด ์๋์ผ๋ก ์นดํ ๊ณ ๋ฆฌ๋ฅผ ์ถ์ฒํด์ฃผ๋ ๊ฒ๊ณผ ๋น์ทํ๋ค๊ณ ์๊ฐํ๋ฉด ๋ผ์!
์ฝ๋๋ก ๋ณด๋ฉด ์ด๋ ๋ต๋๋ค:
val x = 5 // Int๋ก ์ถ๋ก ๋จ
val y = "Hello" // String์ผ๋ก ์ถ๋ก ๋จ
val z = x * 2 // Int๋ก ์ถ๋ก ๋จ
๋ณด์ธ์! ํ์ ์ ๋ช ์์ ์ผ๋ก ์ ์ง ์์๋ Scala๊ฐ ์์์ ์ถ๋ก ํด์ฃผ๋ค์. ์ ๋ง ๋๋ํ์ฃ ? ใ ใ ใ
3. ์ ๋ค๋ฆญ ํ๋ก๊ทธ๋๋ฐ ๐งฌ
์ ๋ค๋ฆญ์ด๋ผ๋ ๋ง, ๋ค์ด๋ณด์ จ๋์? ์๋๋ผ๊ณ ์? ๊ด์ฐฎ์์! ์ฝ๊ฒ ์ค๋ช ํด๋๋ฆด๊ฒ์.
์ ๋ค๋ฆญ ํ๋ก๊ทธ๋๋ฐ์ ํ์ ์ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ๋ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ด์์. ์... ๋ญ๊ฐ ์ด๋ ค์ ๋ณด์ด์ฃ ? ํ์ง๋ง ์ค์ ๋ก๋ ์์ฃผ ์ ์ฉํ๋ต๋๋ค!
์๋ฅผ ๋ค์ด๋ณผ๊ฒ์:
def printBox[T](content: T): Unit = {
println(s"๋ฐ์ค ์์๋ $content ๊ฐ ๋ค์ด์์ด์!")
}
printBox(5) // "๋ฐ์ค ์์๋ 5 ๊ฐ ๋ค์ด์์ด์!" ์ถ๋ ฅ
printBox("Hello") // "๋ฐ์ค ์์๋ Hello ๊ฐ ๋ค์ด์์ด์!" ์ถ๋ ฅ
์ฌ๊ธฐ์ [T]
๋ ํ์
ํ๋ผ๋ฏธํฐ์์. ์ด ํจ์๋ ์ด๋ค ํ์
์ ๊ฐ์ด๋ ๋ฐ์์ ์ถ๋ ฅํ ์ ์์ฃ . ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ์ฌ๋ฅ์ ํ ๊ณณ์์ ๋ค๋ฃฐ ์ ์๋ ๊ฒ์ฒ๋ผ์! ๐
4. ๋์์ ๋ฐ์ดํฐ ํ์ (ADT) ๐งฎ
๋์์ ๋ฐ์ดํฐ ํ์ ... ์ผ์ ! ์ํ ๊ฐ์ ๋ณด์ด๋ ์ด๋ฆ์ด์ฃ ? ใ ใ ใ ํ์ง๋ง ๊ฑฑ์ ๋ง์ธ์. ์๊ฐ๋ณด๋ค ์ด๋ ต์ง ์์์!
ADT๋ ์ฌ๋ฌ ๊ฐ์ง ํ์
์ ์กฐํฉํด์ ์๋ก์ด ํ์
์ ๋ง๋๋ ๋ฐฉ์์ด์์. Scala์์๋ ์ฃผ๋ก case class
์ sealed trait
๋ฅผ ์ฌ์ฉํด์ ๊ตฌํํ์ฃ .
์๋ฅผ ๋ค์ด๋ณผ๊น์?
sealed trait Shape
case class Circle(radius: Double) extends Shape
case class Rectangle(width: Double, height: Double) extends Shape
def area(shape: Shape): Double = shape match {
case Circle(r) => Math.PI * r * r
case Rectangle(w, h) => w * h
}
val myCircle = Circle(5)
val myRectangle = Rectangle(3, 4)
println(area(myCircle)) // 78.53981633974483
println(area(myRectangle)) // 12.0
์์ฐ! ์ด๋ ๊ฒ ํ๋ฉด ๋ค์ํ ๋ํ์ ๋ฉด์ ์ ์ฝ๊ฒ ๊ณ์ฐํ ์ ์์ด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ์ฌ๋ฅ์ ํ ๊ณณ์์ ๊ด๋ฆฌํ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ !
5. ๊ณ ์ฐจ ํ์ (Higher-kinded types) ๐
์, ์ด์ ๋๋ง์ ๊ณ ์ฐจ ํ์ ์ด์์! ์ด๊ฑด ๋ญ๋๊ณ ์? ์... ์ผ๋จ "์, ์ด๊ฑฐ ์ง์ง ๊ณ ๊ธ ๊ธฐ๋ฅ์ด๊ตฌ๋!"๋ผ๊ณ ์๊ฐํ์๋ฉด ๋ฉ๋๋ค. ใ ใ ใ
๊ณ ์ฐจ ํ์ ์ ํ์ ์ ์ธ์๋ก ๋ฐ๋ ํ์ ์ด์์. ๋ญ๊ฐ ๋ณต์กํด ๋ณด์ด์ฃ ? ๊ฑฑ์ ๋ง์ธ์. ์ฒ์ฒํ ์ค๋ช ํด๋๋ฆด๊ฒ์!
์๋ฅผ ๋ค์ด, List
๋ Option
๊ฐ์ ํ์
๋ค์ ๋ค๋ฅธ ํ์
์ ์ธ์๋ก ๋ฐ์์. List[Int]
, Option[String]
์ด๋ฐ ์์ผ๋ก์. ์ด๋ฐ ํ์
๋ค์ ๊ณ ์ฐจ ํ์
์ด๋ผ๊ณ ํด์.
Scala์์๋ ์ด๋ฐ ๊ณ ์ฐจ ํ์ ์ ์ง์ ์ ์ํ๊ณ ์ฌ์ฉํ ์ ์์ด์. ์๋ฅผ ๋ค๋ฉด:
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
implicit val listFunctor: Functor[List] = new Functor[List] {
def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f)
}
implicit val optionFunctor: Functor[Option] = new Functor[Option] {
def map[A, B](fa: Option[A])(f: A => B): Option[B] = fa.map(f)
}
์ฐ์! ์ด๊ฒ ๋ฐ๋ก ๊ณ ์ฐจ ํ์
์ ํ์ด์์. Functor
๋ผ๋ ํ๋์ ํธ๋ ์ดํธ๋ก List
์ Option
๋ชจ๋๋ฅผ ๋ค๋ฃฐ ์ ์์ฃ . ๋ง์น ์ฌ๋ฅ๋ท์์ ํ๋์ ํ๋ซํผ์ผ๋ก ๋ค์ํ ์ฌ๋ฅ์ ๊ด๋ฆฌํ๋ ๊ฒ์ฒ๋ผ์! ๐
์, ์ฌ๊ธฐ๊น์ง๊ฐ Scala ํ์ ์์คํ ์ ๊ธฐ์ด์์ด์. ์ด๋ ์ ๊ฐ์? ์กฐ๊ธ์ ๊ฐ์ด ์ค์๋์? ใ ใ ใ ์์ง ์์ ํ ์ดํด๊ฐ ์ ๊ฐ๋ ๊ด์ฐฎ์์. ์ฐ๋ฆฌ๋ ์ด์ ์์์ผ ๋ฟ์ด๋๊น์!
๋ค์ ์น์ ์์๋ ๋๋ค์ ๋ํด ์์๋ณผ ๊ฑฐ์์. ๋๋ค๋ผ... ๋ญ๊ฐ ๋ฉ์ง ์ด๋ฆ ๊ฐ์ฃ ? ๊ธฐ๋๋์ง ์๋์? ์ ๋ ์ ๋ง ์ ๋์! ๐
๐จ ์ฃผ์์ฌํญ: Scala์ ํ์ ์์คํ ์ ์ ๋ง ๊ฐ๋ ฅํ์ง๋ง, ๊ทธ๋งํผ ๋ณต์กํ ์ ์์ด์. ์ฒ์์๋ ์ด๋ ค์ ๋ณด์ผ ์ ์์ง๋ง, ์ฐจ๊ทผ์ฐจ๊ทผ ๋ฐฐ์๋๊ฐ๋ฉด ๋ฐ๋์ ๋ง์คํฐํ ์ ์์ ๊ฑฐ์์! ๋ง์น ์ฌ๋ฅ๋ท์์ ์๋ก์ด ์ฌ๋ฅ์ ๋ฐฐ์ฐ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ . ํ๋ด์ธ์! ๐ช
๐ญ ๋๋ค์ ๊ฐ๋ ๊ณผ ํ์ฉ: ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ํต์ฌ
์, ์ด์ ๋๋ค์ ์ธ๊ณ๋ก ๋ค์ด๊ฐ๋ณผ ์๊ฐ์ด์์! ๋๋ค๋ผ... ๋ญ๊ฐ ๊ทธ๋ฆฌ์ค ๋ฌธ์ ๊ฐ์ ๋๋์ด ๋์ง ์๋์? ใ ใ ใ ์ฌ์ค ํ๋ก๊ทธ๋๋ฐ์์์ ๋๋ค๋ ๊ทธ๋ฆฌ์ค ๋ฌธ์์๋ ์๋ฌด ์๊ด์ด ์์ด์. ๊ทธ๋ผ ๋์ฒด ๋ญ๊น์?
๐ฏ ๊ฟํ: ๋๋ค๋ ๊ฐ๋จํ ๋งํด์ ์ด๋ฆ ์๋ ํจ์์์. "์ต๋ช ํจ์"๋ผ๊ณ ๋ ๋ถ๋ฌ์. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ต๋ช ์ผ๋ก ์ฌ๋ฅ์ ๊ณต์ ํ๋ ๊ฒ์ฒ๋ผ, ํ๋ก๊ทธ๋๋ฐ์์๋ ์ด๋ฆ ์์ด ํจ์๋ฅผ ๋ง๋ค์ด ์ฌ์ฉํ ์ ์๋ต๋๋ค!
1. ๋๋ค์ ๊ธฐ๋ณธ ๋ฌธ๋ฒ ๐
Scala์์ ๋๋ค์ ๊ธฐ๋ณธ ๋ฌธ๋ฒ์ ์์ฃผ ๊ฐ๋จํด์. ํ๋ผ๋ฏธํฐ, ํ์ดํ, ๊ทธ๋ฆฌ๊ณ ํจ์ ๋ณธ๋ฌธ์ผ๋ก ์ด๋ฃจ์ด์ ธ ์์ฃ . ์๋ฅผ ๋ค์ด๋ณผ๊น์?
val add = (x: Int, y: Int) => x + y
์ด๋ ๊ฒ ํ๋ฉด add
๋ผ๋ ์ด๋ฆ์ ํจ์๊ฐ ๋ง๋ค์ด์ ธ์. ์ด ํจ์๋ ๋ ๊ฐ์ Int๋ฅผ ๋ฐ์์ ๋ํด์ฃผ๋ ์ญํ ์ ํด์. ์ฌ์ฉ๋ฒ์ ์ด๋ ๋ต๋๋ค:
println(add(3, 4)) // 7 ์ถ๋ ฅ
์! ์ ๋ง ๊ฐ๋จํ์ฃ ? ใ ใ ใ
2. ๋๋ค์ ํ์ฉ ๐ ๏ธ
๋๋ค๋ ์ ๋ง ๋ค์ํ ๊ณณ์์ ํ์ฉ๋ ์ ์์ด์. ํนํ ์ปฌ๋ ์ ์ ๋ค๋ฃฐ ๋ ์์ฃผ ์ ์ฉํ๋ต๋๋ค. ์๋ฅผ ๋ค์ด๋ณผ๊น์?
val numbers = List(1, 2, 3, 4, 5)
// ๋ชจ๋ ์ซ์๋ฅผ ๋ ๋ฐฐ๋ก ๋ง๋ค๊ธฐ
val doubled = numbers.map(x => x * 2)
println(doubled) // List(2, 4, 6, 8, 10)
// ์ง์๋ง ๊ณจ๋ผ๋ด๊ธฐ
val evens = numbers.filter(x => x % 2 == 0)
println(evens) // List(2, 4)
// ๋ชจ๋ ์ซ์์ ํฉ ๊ตฌํ๊ธฐ
val sum = numbers.reduce((x, y) => x + y)
println(sum) // 15
์ฐ์! ์ด๋ ๊ฒ ๋๋ค๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๋๊ฐ ์ ๋ง ๊ฐ๊ฒฐํด์ง๊ณ ์ฝ๊ธฐ ์ฌ์์ ธ์. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ํ๋ ์ฌ๋ฅ์ ์ฝ๊ฒ ์ฐพ์ ์ ์๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ ! ๐
3. ํด๋ก์ (Closure) ๐ช
๋๋ค๋ฅผ ์ด์ผ๊ธฐํ ๋ ๋นผ๋์ ์ ์๋ ๊ฒ ๋ฐ๋ก ํด๋ก์ ์์. ํด๋ก์ ๋ ๋ญ๊น์? ์... ์ฝ๊ฒ ๋งํด์ ์์ ์ ํ๊ฒฝ์ ๊ธฐ์ตํ๋ ํจ์๋ผ๊ณ ํ ์ ์์ด์.
์๋ฅผ ๋ค์ด๋ณผ๊ฒ์:
def makeAdder(x: Int) = (y: Int) => x + y
val add5 = makeAdder(5)
println(add5(3)) // 8 ์ถ๋ ฅ
println(add5(7)) // 12 ์ถ๋ ฅ
์ฌ๊ธฐ์ makeAdder
ํจ์๋ ํด๋ก์ ๋ฅผ ๋ฐํํด์. ์ด ํด๋ก์ ๋ x
์ ๊ฐ์ "๊ธฐ์ต"ํ๊ณ ์์ฃ . ๊ทธ๋์ add5
๋ ํญ์ 5๋ฅผ ๋ํ๋ ํจ์๊ฐ ๋๋ ๊ฑฐ์์. ์ ๊ธฐํ์ฃ ? ใ
ใ
ใ
4. ๋ถ๋ถ ์ ์ฉ ํจ์ (Partially Applied Functions) ๐งฉ
Scala์์๋ ํจ์์ ์ผ๋ถ ์ธ์๋ง ์ ์ฉํ ์๋ก์ด ํจ์๋ฅผ ๋ง๋ค ์ ์์ด์. ์ด๊ฑธ ๋ถ๋ถ ์ ์ฉ ํจ์๋ผ๊ณ ํด์. ์ด๋ ต๊ฒ ๋ค๋ฆฌ๋์? ๊ฑฑ์ ๋ง์ธ์, ์์ ๋ฅผ ๋ณด๋ฉด ์ฝ๊ฒ ์ดํดํ ์ ์์ ๊ฑฐ์์!
def multiply(x: Int, y: Int) = x * y
val double = multiply(2, _: Int)
println(double(4)) // 8 ์ถ๋ ฅ
println(double(7)) // 14 ์ถ๋ ฅ
์ฌ๊ธฐ์ double
์ multiply
ํจ์์ ์ฒซ ๋ฒ์งธ ์ธ์๋ฅผ 2๋ก ๊ณ ์ ํ ์๋ก์ด ํจ์์์. _
๋ "๋์ค์ ์ฑ์ ๋ฃ์ ๊ฐ"์ ์๋ฏธํด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ผ๋ถ ์กฐ๊ฑด๋ง ์ ํด๋๊ณ ๋๋จธ์ง๋ ๋์ค์ ๊ฒฐ์ ํ๋ ๊ฒ์ฒ๋ผ์! ๐
5. ํจ์ ํฉ์ฑ (Function Composition) ๐ผ
ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ๋ ๋ค๋ฅธ ๋ฉ์ง ํน์ง์ ํจ์๋ฅผ ํฉ์ฑํ ์ ์๋ค๋ ๊ฑฐ์์. ๋ง์น ๋ ๊ณ ๋ธ๋ก์ ์กฐ๋ฆฝํ๋ฏ์ด, ์ฌ๋ฌ ํจ์๋ฅผ ์กฐํฉํด์ ์๋ก์ด ํจ์๋ฅผ ๋ง๋ค ์ ์๋ต๋๋ค!
val double = (x: Int) => x * 2
val addOne = (x: Int) => x + 1
val doubleThenAddOne = double andThen addOne
val addOneThenDouble = double compose addOne
println(doubleThenAddOne(3)) // 7 ์ถ๋ ฅ (3 * 2 + 1)
println(addOneThenDouble(3)) // 8 ์ถ๋ ฅ ((3 + 1) * 2)
andThen
๊ณผ compose
๋ ํจ์๋ฅผ ํฉ์ฑํ๋ ๋ฉ์๋์์. andThen
์ "์ด ํจ์๋ฅผ ์คํํ ๋ค์์ ์ ํจ์๋ฅผ ์คํํด", compose
๋ "์ ํจ์๋ฅผ ์คํํ ๋ค์์ ์ด ํจ์๋ฅผ ์คํํด"๋ผ๋ ์๋ฏธ๋ฅผ ๊ฐ์ ธ์. ์ ๋ง ์ง๊ด์ ์ด์ฃ ? ใ
ใ
ใ
6. ์ปค๋ง (Currying) ๐
์ปค๋ง์ด๋ผ๋ ๋ง, ๋ค์ด๋ณด์ จ๋์? ์, ์ปค๋ฆฌ ์๋ฆฌ ์๊ธฐ๊ฐ ์๋์์! ใ ใ ใ ํ๋ก๊ทธ๋๋ฐ์์ ์ปค๋ง์ ์ฌ๋ฌ ๊ฐ์ ์ธ์๋ฅผ ๋ฐ๋ ํจ์๋ฅผ ๋จ์ผ ์ธ์๋ฅผ ๋ฐ๋ ํจ์๋ค์ ์ฒด์ธ์ผ๋ก ๋ฐ๊พธ๋ ๊ธฐ๋ฒ์ด์์.
์... ๋ญ๊ฐ ๋ณต์กํด ๋ณด์ด์ฃ ? ์์ ๋ฅผ ๋ณด๋ฉด ๋ ์ฝ๊ฒ ์ดํดํ ์ ์์ ๊ฑฐ์์:
def add(x: Int)(y: Int) = x + y
val add5 = add(5)_
println(add5(3)) // 8 ์ถ๋ ฅ
// ์ด๋ ๊ฒ๋ ์ฌ์ฉํ ์ ์์ด์
println(add(2)(3)) // 5 ์ถ๋ ฅ
์ฌ๊ธฐ์ add
ํจ์๋ ์ปค๋ง๋ ํํ์์. ๋ ๊ฐ์ ์ธ์๋ฅผ ๋ฐ๋ก๋ฐ๋ก ๋ฐ์ ์ ์์ฃ . ์ด๋ ๊ฒ ํ๋ฉด ํจ์์ ์ผ๋ถ๋ถ๋ง ์ ์ฉํด์ ์๋ก์ด ํจ์๋ฅผ ๋ง๋ค ์ ์์ด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ํ๋์ ์ฌ๋ฅ์ ์ฌ๋ฌ ๋จ๊ณ๋ก ๋๋์ด ์ ๊ณตํ๋ ๊ฒ์ฒ๋ผ์! ๐
7. ๊ณ ์ฐจ ํจ์ (Higher-Order Functions) ๐
๊ณ ์ฐจ ํจ์๋ ํจ์๋ฅผ ์ธ์๋ก ๋ฐ๊ฑฐ๋ ํจ์๋ฅผ ๋ฐํํ๋ ํจ์๋ฅผ ๋งํด์. Scala์์๋ ํจ์๋ ์ผ๊ธ ์๋ฏผ(first-class citizen)์ด๊ธฐ ๋๋ฌธ์, ์ด๋ฐ ๊ณ ์ฐจ ํจ์๋ฅผ ์ฝ๊ฒ ๋ง๋ค๊ณ ์ฌ์ฉํ ์ ์๋ต๋๋ค.
์๋ฅผ ๋ค์ด๋ณผ๊น์?
def applyTwice(f: Int => Int, x: Int) = f(f(x))
val addOne = (x: Int) => x + 1
println(applyTwice(addOne, 3)) // 5 ์ถ๋ ฅ (3 + 1 + 1)
val double = (x: Int) => x * 2
println(applyTwice(double, 3)) // 12 ์ถ๋ ฅ ((3 * 2) * 2)
์ฌ๊ธฐ์ applyTwice
๋ ๊ณ ์ฐจ ํจ์์์. ํจ์ f
์ ์ ์ x
๋ฅผ ์ธ์๋ก ๋ฐ์์, f
๋ฅผ x
์ ๋ ๋ฒ ์ ์ฉํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ์ฃ . ์ ๋ง ๊ฐ๋ ฅํ๊ณ ์ ์ฐํ ๊ธฐ๋ฅ์ด์ฃ ? ใ
ใ
ใ
๐ก ์์๋์ธ์: ๋๋ค์ ๊ณ ์ฐจ ํจ์๋ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ํต์ฌ์ด์์. ์ด๋ฅผ ์ ํ์ฉํ๋ฉด ์ฝ๋๋ฅผ ๋ ๊ฐ๊ฒฐํ๊ณ , ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ๋ฉฐ, ํ ์คํธํ๊ธฐ ์ฝ๊ฒ ๋ง๋ค ์ ์์ด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ์ฌ๋ฅ์ ์กฐํฉํด์ ์๋ก์ด ๊ฐ์น๋ฅผ ๋ง๋ค์ด๋ด๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ !
์, ์ฌ๊ธฐ๊น์ง๊ฐ ๋๋ค์ ๊ด๋ จ๋ ๊ฐ๋ ๋ค์ด์์ด์. ์ด๋ ์ ๊ฐ์? ์กฐ๊ธ์ ๊ฐ์ด ์ค์๋์? ใ ใ ใ ์ฒ์์๋ ์ด๋ ค์ ๋ณด์ผ ์ ์์ง๋ง, ์ค์ ๋ก ์ฌ์ฉํด๋ณด๋ฉด ์ ๋ง ํธ๋ฆฌํ๊ณ ๊ฐ๋ ฅํ ๋๊ตฌ๋ผ๋ ๊ฑธ ๋๋ผ์ค ๊ฑฐ์์!
๋ค์ ์น์ ์์๋ ๊ณ ์ฐจ ํ์ ์ ์ธ๊ณ๋ก ๋ ๊น์ด ๋ค์ด๊ฐ๋ณผ ๊ฑฐ์์. ๊ณ ์ฐจ ํ์ ์ด๋ผ... ๋ญ๊ฐ ์ ๋ง ๊ณ ๊ธ์ง ๋๋์ด ๋์ง ์๋์? ๊ธฐ๋๋์ง ์๋์? ์ ๋ ์ ๋ง ์ ๋์! ๐
๐จ ์ฃผ์์ฌํญ: ๋๋ค์ ๊ณ ์ฐจ ํจ์๋ ์ ๋ง ๊ฐ๋ ฅํ ๋๊ตฌ์ง๋ง, ๋จ์ฉํ๋ฉด ์ฝ๋๊ฐ ์คํ๋ ค ๋ณต์กํด์ง ์ ์์ด์. ํญ์ ๊ฐ๋ ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ๊ณ ๋ คํด์ ์ ์ ํ ์ฌ์ฉํด์ผ ํด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ๋๋ฌด ๋ง์ ์ฌ๋ฅ์ ํ๊บผ๋ฒ์ ์ ๊ณตํ๋ ค๋ค ์คํ๋ ค ํผ๋์ ์ค ์ ์๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ . ๊ท ํ์ด ์ค์ํด์! โ๏ธ
๐ ๊ณ ์ฐจ ํ์ ์ ์ธ๊ณ: ํ์ ์ ์ฐจ์์ ๋์ด์
์, ์ด์ ์ ๋ง ํฅ๋ฏธ์ง์งํ ๋ถ๋ถ์ด ์์ด์! ๊ณ ์ฐจ ํ์ ์ ์ธ๊ณ๋ก ๋ค์ด๊ฐ๋ณผ ์๊ฐ์ด์์. ๊ณ ์ฐจ ํ์ ์ด๋ผ... ๋ญ๊ฐ ์ ๋ง ๊ณ ์ฐจ์์ ์ธ ๋๋์ด ๋ค์ง ์๋์? ใ ใ ใ ๊ฑฑ์ ๋ง์ธ์, ์ฒ์ฒํ ์ค๋ช ํด๋๋ฆด๊ฒ์!
๐ ์์๋์ธ์: ๊ณ ์ฐจ ํ์ (Higher-kinded types)์ ํ์ ์์ฑ์๋ฅผ ์ธ์๋ก ๋ฐ๋ ํ์ ์ ๋งํด์. ์... ๋ญ๊ฐ ๋ณต์กํด ๋ณด์ด์ฃ ? ํ์ง๋ง ์ค์ ๋ก๋ ์ฐ๋ฆฌ๊ฐ ์ด๋ฏธ ์๊ณ ์๋ ๊ฐ๋ ์ ํ์ฅ์ผ ๋ฟ์ด์์!
1. ํ์ ์์ฑ์ (Type Constructors) ๐๏ธ
๊ณ ์ฐจ ํ์ ์ ์ดํดํ๊ธฐ ์ํด์๋ ๋จผ์ ํ์ ์์ฑ์์ ๋ํด ์์์ผ ํด์. ํ์ ์์ฑ์๋ ๋ค๋ฅธ ํ์ ์ ์ธ์๋ก ๋ฐ์ ์๋ก์ด ํ์ ์ ๋ง๋๋ 'ํจ์'๋ผ๊ณ ์๊ฐํ๋ฉด ๋ผ์.
์๋ฅผ ๋ค์ด๋ณผ๊น์?
List[A]
Option[A]
Map[K, V]
์ฌ๊ธฐ์ List
, Option
, Map
์ ๋ชจ๋ ํ์
์์ฑ์์์. ์ด๋ค์ ๋ค๋ฅธ ํ์
(A, K, V ๋ฑ)์ ๋ฐ์์ ๊ตฌ์ฒด์ ์ธ ํ์
์ ๋ง๋ค์ด๋ด์ฃ .
2. ๊ณ ์ฐจ ํ์ ์ ๊ธฐ๋ณธ ๊ฐ๋ ๐
์, ์ด์ ๊ณ ์ฐจ ํ์ ์ผ๋ก ๋์ด๊ฐ๋ณผ๊น์? ๊ณ ์ฐจ ํ์ ์ ์ด๋ฐ ํ์ ์์ฑ์๋ฅผ ์ธ์๋ก ๋ฐ๋ ํ์ ์ด์์. Scala์์๋ ์ด๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ํํํด์:
trait HigherKinded[F[_]]
์ฌ๊ธฐ์ F[_]
๋ ์์์ ํ์
์์ฑ์๋ฅผ ๋ํ๋ด์. ๋ฐ์ค(_)์ "์์ง ์ ํด์ง์ง ์์ ํ์
"์ ์๋ฏธํ์ฃ .
์ค์ ์์ ๋ฅผ ๋ณผ๊น์?
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
// List์ ๋ํ Functor ๊ตฌํ
implicit val listFunctor: Functor[List] = new Functor[List] {
def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f)
}
// Option์ ๋ํ Functor ๊ตฌํ
implicit val optionFunctor: Functor[Option] = new Functor[Option] {
def map[A, B](fa: Option[A])(f: A => B): Option[B] = fa.map(f)
}
์์ฐ! ์ด๊ฒ ๋ฐ๋ก ๊ณ ์ฐจ ํ์
์ ํ์ด์์. Functor
๋ผ๋ ํ๋์ ํธ๋ ์ดํธ๋ก List
์ Option
๋ชจ๋๋ฅผ ๋ค๋ฃฐ ์ ์์ฃ . ๋ง์น ์ฌ๋ฅ๋ท์์ ํ๋์ ์ธํฐํ์ด์ค๋ก ๋ค์ํ ์ฌ๋ฅ์ ๊ด๋ฆฌํ๋ ๊ฒ์ฒ๋ผ์! ๐
3. ๊ณ ์ฐจ ํ์ ์ ํ์ฉ ๐ ๏ธ
๊ณ ์ฐจ ํ์ ์ ํ์ฉํ๋ฉด ์ ๋ง ๊ฐ๋ ฅํ ์ถ์ํ๋ฅผ ํ ์ ์์ด์. ์๋ฅผ ๋ค์ด, ๋ชจ๋๋(Monad)๋ผ๋ ๊ฐ๋ ์ ๊ตฌํํ ๋ ๊ณ ์ฐจ ํ์ ์ด ์ฌ์ฉ๋ผ์.
trait Monad[F[_]] extends Functor[F] {
def pure[A](a: A): F[A]
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
}
// List์ ๋ํ Monad ๊ตฌํ
implicit val listMonad: Monad[List] = new Monad[List] {
def pure[A](a: A): List[A] = List(a)
def flatMap[A, B](fa: List[A])(f: A => List[B]): List[B] = fa.flatMap(f)
def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f)
}
// Option์ ๋ํ Monad ๊ตฌํ
implicit val optionMonad: Monad[Option] = new Monad[Option] {
def pure[A](a: A): Option[A] = Some(a)
def flatMap[A, B](fa: Option[A])(f: A => Option[B]): Option[B] = fa.flatMap(f)
def map[A, B](fa: Option[A])(f: A => B): Option[B] = fa.map(f)
}
์ด๋ ๊ฒ ํ๋ฉด List
์ Option
์ ๋ํด ๋์ผํ ์ธํฐํ์ด์ค๋ก ์์
ํ ์ ์์ด์. ์ ๋ง ๋ฉ์ง์ง ์๋์? ใ
ใ
ใ
4. ํ์ ๋๋ค (Type Lambdas) ๐ญ
Scala์์๋ ํ์ ์์ค์์๋ ๋๋ค๋ฅผ ์ฌ์ฉํ ์ ์์ด์. ์ด๋ฅผ ํ์ ๋๋ค๋ผ๊ณ ํด์. ํ์ ๋๋ค๋ฅผ ์ฌ์ฉํ๋ฉด ๋ ๋ณต์กํ ํ์ ๊ตฌ์กฐ๋ฅผ ๊ฐ๋จํ๊ฒ ํํํ ์ ์์ฃ .
์๋ฅผ ๋ค์ด๋ณผ๊น์?
type Compose[F[_], G[_]] = ({type ฮป[ฮฑ] = F[G[ฮฑ]]})#ฮป
// ์ฌ์ฉ ์
val listOption: Compose[List, Option] = List(Some(1), None, Some(2))
์ฌ๊ธฐ์ Compose
๋ ๋ ๊ฐ์ ํ์
์์ฑ์๋ฅผ ๋ฐ์์ ์๋ก์ด ํ์
์์ฑ์๋ฅผ ๋ง๋ค์ด๋ด์. ๋ง์น ํจ์๋ฅผ ํฉ์ฑํ๋ ๊ฒ์ฒ๋ผ ํ์
์ ํฉ์ฑํ๋ ๊ฑฐ์ฃ !
5. ์ข ์ ํ์ (Dependent Types) ๐
Scala์์๋ ํ์ ์ด ๊ฐ์ ์์กดํ ์ ์์ด์. ์ด๋ฅผ ์ข ์ ํ์ ์ด๋ผ๊ณ ํด์. ์ด ๊ฐ๋ ์ ์ ๋ง ๊ฐ๋ ฅํ ํ์ ์์คํ ์ ๊ตฌํํ ์ ์๊ฒ ํด์ฃผ์ฃ .
๊ฐ๋จํ ์์ ๋ฅผ ๋ณผ๊น์?
trait Vec {
type T
def length: Int
def apply(i: Int): T
}
object Vec {
def apply[A](xs: A*): Vec = new Vec {
type T = A
def length: Int = xs.length
def apply(i: Int): A = xs(i)
}
}
val v = Vec(1, 2, 3)
println(v.length) // 3
println(v(1)) // 2
์ฌ๊ธฐ์ Vec
์ T
ํ์
์ ์์ฑ ์์ ์ ๊ฒฐ์ ๋ผ์. ์ด๋ ๊ฒ ํ๋ฉด ํ์
์์ ์ฑ์ ๋์ผ ์ ์์ฃ !
6. ํ์ ํด๋์ค (Type Classes) ๐
ํ์ ํด๋์ค๋ Scala์์ ๊ณ ์ฐจ ํ์ ์ ํ์ฉํ๋ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ด์์. ํ์ ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด ๊ธฐ์กด ํ์ ์ ์๋ก์ด ๊ธฐ๋ฅ์ ์ถ๊ฐํ ์ ์์ฃ .
์๋ฅผ ๋ค์ด๋ณผ๊น์?
trait Show[A] {
def show(a: A): String
}
implicit val intShow: Show[Int] = new Show[Int] {
def show(a: Int): String = a.toString
}
implicit val stringShow: Show[String] = new Show[String] {
def show(a: String): String = a
}
def showOff[A](a: A)(implicit s: Show[A]): String = s.show(a)
println(showOff(123)) // "123"
println(showOff("Hello")) // "Hello"
์ด๋ ๊ฒ ํ๋ฉด Int
์ String
์ ๋ํด show
๋ฉ์๋๋ฅผ ์ถ๊ฐํ ๊ฒ๊ณผ ๊ฐ์ ํจ๊ณผ๋ฅผ ๋ผ ์ ์์ด์. ์ ๋ง ์ ์ฐํ์ฃ ? ใ
ใ
ใ
๐ก Pro Tip: ๊ณ ์ฐจ ํ์ ๊ณผ ํ์ ํด๋์ค๋ฅผ ์ ํ์ฉํ๋ฉด ์ฝ๋์ ์ฌ์ฌ์ฉ์ฑ๊ณผ ํ์ฅ์ฑ์ ํฌ๊ฒ ๋์ผ ์ ์์ด์. ํ์ง๋ง ๋๋ฌด ๋ณต์กํ ํ์ ๊ตฌ์กฐ๋ ์คํ๋ ค ์ฝ๋์ ๊ฐ๋ ์ฑ์ ํด์น ์ ์์ผ๋ ์ฃผ์ํด์ผ ํด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ๋๋ฌด ๋ณต์กํ ์๋น์ค ๊ตฌ์กฐ๋ฅผ ๋ง๋ค๋ฉด ์ฌ์ฉ์๊ฐ ํผ๋์ค๋ฌ์ํ ์ ์๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ !
์, ์ฌ๊ธฐ๊น์ง๊ฐ ๊ณ ์ฐจ ํ์ ์ ์ธ๊ณ์์ด์. ์ด๋ ์ ๊ฐ์? ์กฐ๊ธ์ ๋จธ๋ฆฌ๊ฐ ์ํ์ ๊ฐ์? ใ ใ ใ ๊ฑฑ์ ๋ง์ธ์. ์ด๋ฐ ๊ฐ๋ ๋ค์ ์๊ฐ์ ๋๊ณ ์ฒ์ฒํ ์ดํดํด ๋๊ฐ๋ฉด ๋ผ์. ์ฒ์๋ถํฐ ์๋ฒฝํ๊ฒ ์ดํดํ๋ ค๊ณ ํ์ง ๋ง์ธ์!
๋ค์ ์น์ ์์๋ ์ด ๋ชจ๋ ๊ฐ๋ ๋ค์ ์ข ํฉํด์ ์ค์ ์์ ๋ฅผ ์ดํด๋ณผ ๊ฑฐ์์. ๊ธฐ๋๋์ง ์๋์? ์ ๋ ์ ๋ง ์ ๋์! ๐
๐จ ์ฃผ์์ฌํญ: ๊ณ ์ฐจ ํ์ ๊ณผ ๊ด๋ จ๋ ๊ฐ๋ ๋ค์ ์ ๋ง ๊ฐ๋ ฅํ์ง๋ง, ๊ทธ๋งํผ ๋ณต์กํ ์ ์์ด์. ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํ ๋๋ ํ์๋ค๊ณผ ์ถฉ๋ถํ ์์ํ๊ณ , ์ฝ๋์ ๋ณต์ก์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ์ ๊ณ ๋ คํด์ผ ํด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ์๋ก์ด ๊ธฐ๋ฅ์ ๋์ ํ ๋ ์ฌ์ฉ์์ ํธ์์ฑ๊ณผ ์์คํ ์ ๋ณต์ก์ฑ์ ์ ๊ท ํ ์ก์์ผ ํ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ ! ๐ช
๐ฉ ํ์ ๋๋ค์ ๋ง๋ฒ: ๊ณ ๊ธ ํ์ ํ๋ก๊ทธ๋๋ฐ์ ์ ์
์, ์ด์ ์ ๋ง ํฅ๋ฏธ์ง์งํ ๋ถ๋ถ์ด ์์ด์! ํ์ ๋๋ค์ ์ธ๊ณ๋ก ๋ค์ด๊ฐ๋ณผ ์๊ฐ์ด์์. ํ์ ๋๋ค๋ผ... ๋ญ๊ฐ ์ ๋ง ๋ง๋ฒ ๊ฐ์ ๋๋์ด ๋ค์ง ์๋์? ใ ใ ใ ๊ฑฑ์ ๋ง์ธ์, ์ฒ์ฒํ ์ค๋ช ํด๋๋ฆด๊ฒ์!
๐ญ ์์๋์ธ์: ํ์ ๋๋ค๋ ํ์ ์์ค์์์ ์ต๋ช ํจ์์์. ๊ฐ ์์ค์ ๋๋ค์ ๋น์ทํ์ง๋ง, ํ์ ์ ๋ค๋ฃจ๋ ๋ฐ ์ฌ์ฉ๋ผ์. ์ ๋ง ๊ฐ๋ ฅํ ๋๊ตฌ์ฃ !
1. ํ์ ๋๋ค์ ๊ธฐ๋ณธ ๋ฌธ๋ฒ ๐
Scala์์ ํ์ ๋๋ค์ ๊ธฐ๋ณธ ๋ฌธ๋ฒ์ ์กฐ๊ธ ํน์ดํด์. ์๋ฅผ ๋ค์ด๋ณผ๊น์?
type Lambda[A] = ({type L[X] = Either[A, X]})#L
์ด๊ฒ ๋ฐ๋ก ํ์
๋๋ค์์! Either[A, X]
๋ฅผ X
์ ๋ํ ํจ์๋ก ํํํ ๊ฑฐ์ฃ . ์... ์กฐ๊ธ ๋ณต์กํด ๋ณด์ด๋์? ใ
ใ
ใ
๊ฑฑ์ ๋ง์ธ์, ์ฌ์ฉ ์์ ๋ฅผ ๋ณด๋ฉด ๋ ์ดํด๊ฐ ์ ๋ ๊ฑฐ์์!
2. ํ์ ๋๋ค์ ํ์ฉ ๐ ๏ธ
ํ์ ๋๋ค๋ ์ฃผ๋ก ๊ณ ์ฐจ ํ์ ์ ๋ค๋ฃฐ ๋ ์ฌ์ฉ๋ผ์. ์๋ฅผ ๋ค์ด, ๋ค์๊ณผ ๊ฐ์ ์ํฉ์ ์๊ฐํด๋ณผ๊น์?
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
// Either[String, ?]์ ๋ํ Functor ์ธ์คํด์ค๋ฅผ ๋ง๋ค๊ณ ์ถ๋ค๋ฉด?
implicit val eitherStringFunctor: Functor[({type L[X] = Either[String, X]})#L] =
new Functor[({type L[X] = Either[String, X]})#L] {
def map[A, B](fa: Either[String, A])(f: A => B): Either[String, B] = fa.map(f)
}
์์ฐ! ์ด๋ ๊ฒ ํ๋ฉด Either[String, ?]
์ ๋ํ Functor
์ธ์คํด์ค๋ฅผ ๋ง๋ค ์ ์์ด์. ํ์
๋๋ค์ ๋ง๋ฒ์ด์ฃ ! ใ
ใ
ใ
3. ํ์ ํ๋ก์ ์ (Type Projection) ๐ฅ
Scala์์๋ ํ์ ํ๋ก์ ์ ์ด๋ผ๋ ๊ธฐ๋ฅ๋ ์ ๊ณตํด์. ์ด๋ฅผ ์ด์ฉํ๋ฉด ํ์ ๋๋ค๋ฅผ ์กฐ๊ธ ๋ ๊ฐ๋จํ๊ฒ ํํํ ์ ์์ฃ .
trait Foo {
type T
def value: T
}
object Foo {
type Aux[A] = Foo { type T = A }
def apply[A](a: A): Aux[A] = new Foo {
type T = A
def value: A = a
}
}
val foo: Foo.Aux[Int] = Foo(42)
println(foo.value) // 42
์ฌ๊ธฐ์ Foo.Aux[A]
๋ T
๊ฐ A
๋ก ๊ณ ์ ๋ Foo
๋ฅผ ๋ํ๋ด์. ์ด๋ฐ ์์ผ๋ก ํ์
์ ์ ๊ตํ๊ฒ ์ ์ดํ ์ ์๋ต๋๋ค!
4. ํ์ ๋๋ค์ ์์์ ๋ณํ (Implicit Conversion) ๐
ํ์ ๋๋ค๋ ์์์ ๋ณํ๊ณผ ํจ๊ป ์ฌ์ฉํ๋ฉด ๋์ฑ ๊ฐ๋ ฅํด์ ธ์. ์๋ฅผ ๋ค์ด๋ณผ๊น์?
trait Monoid[A] {
def empty: A
def combine(x: A, y: A): A
}
implicit def eitherMonoid[A, B](implicit ma: Monoid[A], mb: Monoid[B]): Monoid[Either[A, B]] =
new Monoid[Either[A, B]] {
def empty: Either[A, B] = Left(ma.empty)
def combine(x: Either[A, B], y: Either[A, B]): Either[A, B] =
(x, y) match {
case (Left(a1), Left(a2)) => Left(ma.combine(a1, a2))
case (Right(b1), Right(b2)) => Right(mb.combine(b1, b2))
case (Left(_), Right(b)) => Right(b)
case (Right(b), Left(_)) => Right(b)
}
}
// ์ฌ์ฉ ์
implicit val intMonoid: Monoid[Int] = new Monoid[Int] {
def empty: Int = 0
def combine(x: Int, y: Int): Int = x + y
}
implicit val stringMonoid: Monoid[String] = new Monoid[String] {
def empty: String = ""
def combine(x: String, y: String): String = x + y
}
val result = implicitly[Monoid[Either[Int, String]]].combine(Left(10), Right("Hello"))
println(result) // Right("Hello")
์! ์ด๋ ๊ฒ ํ๋ฉด Either[Int, String]
์ ๋ํ Monoid
์ธ์คํด์ค๋ฅผ ์๋์ผ๋ก ๋ง๋ค ์ ์์ด์. ์ ๋ง ๊ฐ๋ ฅํ์ฃ ? ใ
ใ
ใ
5. ํ์ ๋๋ค์ ํ์ ํด๋์ค (Type Classes) ๐
ํ์ ๋๋ค๋ ํ์ ํด๋์ค์ ํจ๊ป ์ฌ์ฉํ๋ฉด ๋์ฑ ์ ์ฐํ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ด์. ์๋ฅผ ๋ค์ด๋ณผ๊น์?
trait Applicative[F[_]] extends Functor[F] {
def pure[A](a: A): F[A]
def ap[A, B](ff: F[A => B])(fa: F[A]): F[B]
}
// Either์ ๋ํ Applicative ์ธ์คํด์ค
implicit def eitherApplicative[E]: Applicative[({type L[A] = Either[E, A]})#L] =
new Applicative[({type L[A] = Either[E, A]})#L] {
def pure[A](a: A): Either[E, A] = Right(a)
def ap[A, B](ff: Either[E, A => B])(fa: Either[E, A]): Either[E, B] =
(ff, fa) match {
case (Right(f), Right(a)) => Right(f(a))
case (Left(e), _) => Left(e)
case (_, Left(e)) => Left(e)
}
def map[A, B](fa: Either[E, A])(f: A => B): Either[E, B] = fa.map(f)
}
// ์ฌ์ฉ ์
val result = eitherApplicative[String].pure(5).map(_ * 2)
println(result) // Right(10)
์ด๋ ๊ฒ ํ๋ฉด Either[E, ?]
์ ๋ํ Applicative
์ธ์คํด์ค๋ฅผ ๋ง๋ค ์ ์์ด์. ํ์
๋๋ค์ ํ์
ํด๋์ค์ ํ์์ ์ธ ์กฐํฉ์ด์ฃ ! ใ
ใ
ใ
๐ก Pro Tip: ํ์ ๋๋ค๋ ์ ๋ง ๊ฐ๋ ฅํ ๋๊ตฌ์ง๋ง, ๋จ์ฉํ๋ฉด ์ฝ๋๊ฐ ๋ณต์กํด์ง ์ ์์ด์. ํญ์ ๊ฐ๋ ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ๊ณ ๋ คํด์ ์ฌ์ฉํด์ผ ํด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ๋๋ฌด ๋ณต์กํ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ฉด ์ฌ์ฉ์๊ฐ ํผ๋์ค๋ฌ์ํ ์ ์๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ !
์, ์ฌ๊ธฐ๊น์ง๊ฐ ํ์ ๋๋ค์ ๋ง๋ฒ์ด์์ด์. ์ด๋ ์ ๊ฐ์? ์กฐ๊ธ์ ํ๊ธฐ์ฆ์ด ๋์๋์? ใ ใ ใ ๊ฑฑ์ ๋ง์ธ์. ์ด๋ฐ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ์๊ฐ์ ๋๊ณ ์ฒ์ฒํ ์ตํ๋๊ฐ๋ฉด ๋ผ์. ์ฒ์๋ถํฐ ์๋ฒฝํ๊ฒ ์ดํดํ๋ ค๊ณ ํ์ง ๋ง์ธ์!
๋ค์ ์น์ ์์๋ ์ด ๋ชจ๋ ๊ฐ๋ ๋ค์ ์ข ํฉํด์ ์ค์ ์์ ๋ฅผ ์ดํด๋ณผ ๊ฑฐ์์. ๊ธฐ๋๋์ง ์๋์? ์ ๋ ์ ๋ง ์ ๋์! ๐
๐จ ์ฃผ์์ฌํญ: ํ์ ๋๋ค์ ๊ด๋ จ๋ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ์ ๋ง ๊ฐ๋ ฅํ์ง๋ง, ๊ทธ๋งํผ ์ดํดํ๊ธฐ ์ด๋ ค์ธ ์ ์์ด์. ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํ ๋๋ ํ์๋ค๊ณผ ์ถฉ๋ถํ ์์ํ๊ณ , ์ฝ๋์ ๋ณต์ก์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ์ ๊ณ ๋ คํด์ผ ํด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ์๋ก์ด ๊ณ ๊ธ ๊ธฐ๋ฅ์ ๋์ ํ ๋ ์ฌ์ฉ์์ ํธ์์ฑ๊ณผ ์์คํ ์ ๋ณต์ก์ฑ์ ์ ๊ท ํ ์ก์์ผ ํ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ ! ๐ช
๐ ์ค์ ์์ ์ ํ์ฉ: ์ด๋ก ์ ํ์ค๋ก!
์, ์ด์ ์ฐ๋ฆฌ๊ฐ ๋ฐฐ์ด ๋ชจ๋ ๊ฐ๋ ๋ค์ ์ค์ ๋ก ์ด๋ป๊ฒ ํ์ฉํ ์ ์๋์ง ์ดํด๋ณผ ์๊ฐ์ด์์! ํฅ๋ฏธ์ง์งํ์ง ์๋์? ใ ใ ใ ์ ์ฌ์ฅ์ด ๋ฒ์จ๋ถํฐ ๋๊ทผ๋๊ทผ๊ฑฐ๋ ค์!
๐ฑ ์์๋์ธ์: ์ค์ ์์ ๋ฅผ ํตํด ๋ฐฐ์ฐ๋ ๊ฒ๋งํผ ํจ๊ณผ์ ์ธ ํ์ต ๋ฐฉ๋ฒ์ ์์ด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ค์ ํ๋ก์ ํธ๋ฅผ ์ํํ๋ฉด์ ์ค๋ ฅ์ด ๋์ด๋๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ !
1. ํ์ ์์ ํ HTTP ํด๋ผ์ด์ธํธ ๋ง๋ค๊ธฐ ๐
๋จผ์ , ํ์ ๋๋ค์ ๊ณ ์ฐจ ํ์ ์ ํ์ฉํด์ ํ์ ์์ ํ HTTP ํด๋ผ์ด์ธํธ๋ฅผ ๋ง๋ค์ด๋ณผ๊น์?
import scala.concurrent.Future
// HTTP ๋ฉ์๋๋ฅผ ํํํ๋ sealed trait
sealed trait HttpMethod
case object GET extends HttpMethod
case object POST extends HttpMethod
// HTTP ์๋ต์ ํํํ๋ case class
case class HttpResponse[A](statusCode: Int, body: A)
// HTTP ํด๋ผ์ด์ธํธ ํธ๋ ์ดํธ
trait HttpClient {
def request[A](method: HttpMethod, url: String, body: Option[String] = None): Future[HttpResponse[A]]
}
// ํ์
์์ ํ API ์ ์
trait Api {
type Result[A]
def get[A](url: String): Result[A]
def post[A](url: String, body: String): Result[A]
}
// HttpClient๋ฅผ ์ด์ฉํ Api ๊ตฌํ
class HttpApi(client: HttpClient) extends Api {
type Result[A] = Future[HttpResponse[A]]
def get[A](url: String): Result[A] = client.request[A](GET, url)
def post[A](url: String, body: String): Result[A] = client.request[A](POST, url, Some(body))
}
// ์ฌ์ฉ ์
import scala.concurrent.ExecutionContext.Implicits.global
val api: Api = new HttpApi(new HttpClient {
def request[A](method: HttpMethod, url: String, body: Option[String]): Future[HttpResponse[A]] =
Future.successful(HttpResponse(200, "Response body".asInstanceOf[A]))
})
api.get[String]("https://example.com").foreach(println)
api.post[String]("https://example.com", "Hello, World!").foreach(println)
์์ฐ! ์ด๋ ๊ฒ ํ๋ฉด ํ์
์์ ํ HTTP ํด๋ผ์ด์ธํธ๋ฅผ ๋ง๋ค ์ ์์ด์. Result[A]
๋ฅผ ์ถ์ ํ์
๋ฉค๋ฒ๋ก ์ ์ํจ์ผ๋ก์จ, ๊ตฌ์ฒด์ ์ธ ๊ตฌํ์ ๋์ค์ ๊ฒฐ์ ํ ์ ์์ฃ . ์ ๋ง ์ ์ฐํ๊ณ ๊ฐ๋ ฅํ์ง ์๋์? ใ
ใ
ใ
2. ํ์ ํด๋์ค๋ฅผ ํ์ฉํ JSON ์ธ์ฝ๋ฉ/๋์ฝ๋ฉ ๐
์ด๋ฒ์๋ ํ์ ํด๋์ค๋ฅผ ํ์ฉํด์ JSON ์ธ์ฝ๋ฉ/๋์ฝ๋ฉ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ง๋ค์ด๋ณผ๊น์?
// JSON ๊ฐ์ ํํํ๋ sealed trait
sealed trait Json
case class JString(value: String) extends Json
case class JNumber(value: Double) extends Json
case class JBoolean(value: Boolean) extends Json
case class JObject(value: Map[String, Json]) extends Json
case class JArray(value: List[Json]) extends Json
case object JNull extends Json
// JSON ์ธ์ฝ๋ฉ์ ์ํ ํ์
ํด๋์ค
trait JsonEncoder[A] {
def encode(value: A): Json
}
// JSON ๋์ฝ๋ฉ์ ์ํ ํ์
ํด๋์ค
trait JsonDecoder[A] {
def decode(json: Json): Either[String, A]
}
// ํ์
ํด๋์ค ์ธ์คํด์ค๋ค
object JsonInstances {
implicit val stringEncoder: JsonEncoder[String] = new JsonEncoder[String] {
def encode(value: String): Json = JString(value)
}
implicit val intEncoder: JsonEncoder[Int] = new JsonEncoder[Int] {
def encode(value: Int): Json = JNumber(value.toDouble)
}
implicit val stringDecoder: JsonDecoder[String] = new JsonDecoder[String] {
def decode(json: Json): Either[String, String] = json match {
case JString(value) => Right(value)
case _ => Left("Not a string")
}
}
implicit val intDecoder: JsonDecoder[Int] = new JsonDecoder[Int] {
def decode(json: Json): Either[String, Int] = json match {
case JNumber(value) => Right(value.toInt)
case _ => Left("Not a number")
}
}
}
// ์ฌ์ฉ์ ์ํ Syntax
object JsonSyntax {
implicit class JsonEncoderOps[A](value: A) {
def toJson(implicit encoder: JsonEncoder[A]): Json = encoder.encode(value)
}
implicit class JsonDecoderOps(json: Json) {
def as[A](implicit decoder: JsonDecoder[A]): Either[String, A] = decoder.decode(json)
}
}
// ์ฌ์ฉ ์
import JsonInstances._
import JsonSyntax._
val jsonString = "Hello, World!".toJson
println(jsonString) // JString("Hello, World!")
val decodedString = jsonString.as[ String]
println(decodedString) // Right("Hello, World!")
val jsonInt = 42.toJson
println(jsonInt) // JNumber(42.0)
val decodedInt = jsonInt.as[Int]
println(decodedInt) // Right(42)
์! ์ด๋ ๊ฒ ํ๋ฉด ํ์ ์์ ํ JSON ์ธ์ฝ๋ฉ/๋์ฝ๋ฉ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ง๋ค ์ ์์ด์. ํ์ ํด๋์ค๋ฅผ ์ฌ์ฉํจ์ผ๋ก์จ ๊ธฐ์กด ํ์ ์ ์๋ก์ด ๊ธฐ๋ฅ์ ์ถ๊ฐํ ์ ์์ฃ . ์ ๋ง ๋ฉ์ง์ง ์๋์? ใ ใ ใ
3. ๊ณ ์ฐจ ํ์ ์ ํ์ฉํ ๋ฐ์ดํฐ ๋ณํ ํ์ดํ๋ผ์ธ ๐ฐ
์ด๋ฒ์๋ ๊ณ ์ฐจ ํ์ ์ ํ์ฉํด์ ์ ์ฐํ ๋ฐ์ดํฐ ๋ณํ ํ์ดํ๋ผ์ธ์ ๋ง๋ค์ด๋ณผ๊น์?
// ๋ฐ์ดํฐ ๋ณํ์ ์ํ ํ์
ํด๋์ค
trait Transformer[F[_]] {
def transform[A, B](fa: F[A])(f: A => B): F[B]
}
// Option์ ๋ํ Transformer ์ธ์คํด์ค
implicit val optionTransformer: Transformer[Option] = new Transformer[Option] {
def transform[A, B](fa: Option[A])(f: A => B): Option[B] = fa.map(f)
}
// List์ ๋ํ Transformer ์ธ์คํด์ค
implicit val listTransformer: Transformer[List] = new Transformer[List] {
def transform[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f)
}
// Either์ ๋ํ Transformer ์ธ์คํด์ค
implicit def eitherTransformer[E]: Transformer[({type L[A] = Either[E, A]})#L] =
new Transformer[({type L[A] = Either[E, A]})#L] {
def transform[A, B](fa: Either[E, A])(f: A => B): Either[E, B] = fa.map(f)
}
// ๋ฐ์ดํฐ ๋ณํ ํ์ดํ๋ผ์ธ
class Pipeline[F[_]: Transformer, A] private (val data: F[A]) {
def map[B](f: A => B): Pipeline[F, B] = {
val transformer = implicitly[Transformer[F]]
new Pipeline(transformer.transform(data)(f))
}
}
object Pipeline {
def apply[F[_]: Transformer, A](data: F[A]): Pipeline[F, A] = new Pipeline(data)
}
// ์ฌ์ฉ ์
val optionPipeline = Pipeline(Option("Hello, World!"))
.map(_.toUpperCase)
.map(_.length)
println(optionPipeline.data) // Some(13)
val listPipeline = Pipeline(List(1, 2, 3, 4, 5))
.map(_ * 2)
.map(_.toString)
println(listPipeline.data) // List("2", "4", "6", "8", "10")
val eitherPipeline = Pipeline[({type L[A] = Either[String, A]})#L, Int](Right(10))
.map(_ + 5)
.map(_ * 2)
println(eitherPipeline.data) // Right(30)
์์ฐ! ์ด๋ ๊ฒ ํ๋ฉด ๋ค์ํ ์ปจํ ์ด๋ ํ์ (Option, List, Either ๋ฑ)์ ๋ํด ๋์ผํ ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ ๋ณํ์ ์ํํ ์ ์๋ ํ์ดํ๋ผ์ธ์ ๋ง๋ค ์ ์์ด์. ๊ณ ์ฐจ ํ์ ๊ณผ ํ์ ํด๋์ค์ ํ์ ์ ๋๋ก ๋ณด์ฌ์ฃผ๋ ์์ ์ฃ ! ใ ใ ใ
4. ํ์ ๋๋ค๋ฅผ ํ์ฉํ ์์กด์ฑ ์ฃผ์ ๐
๋ง์ง๋ง์ผ๋ก, ํ์ ๋๋ค๋ฅผ ํ์ฉํด์ ํ์ ์์ ํ ์์กด์ฑ ์ฃผ์ ์์คํ ์ ๋ง๋ค์ด๋ณผ๊น์?
// ์์กด์ฑ์ ํํํ๋ ํ์
trait Dependency[A] {
def get: A
}
// ์์กด์ฑ ์ฃผ์
์ปจํ
์คํธ
trait Context {
type M[A] = Dependency[A]
def provide[A](a: => A): M[A] = new Dependency[A] {
lazy val get: A = a
}
}
// ์๋น์ค ์ ์
trait UserService {
def getUser(id: Int): String
}
trait EmailService {
def sendEmail(to: String, body: String): Unit
}
// ์ ํ๋ฆฌ์ผ์ด์
์ ์
trait Application { self: Context =>
val userService: M[UserService]
val emailService: M[EmailService]
def run(): Unit = {
val user = userService.get.getUser(1)
emailService.get.sendEmail(user, "Hello!")
}
}
// ์ค์ ๊ตฌํ
object RealContext extends Context {
val userService: M[UserService] = provide(new UserService {
def getUser(id: Int): String = s"User$id"
})
val emailService: M[EmailService] = provide(new EmailService {
def sendEmail(to: String, body: String): Unit =
println(s"Sending email to $to: $body")
})
}
// ์ ํ๋ฆฌ์ผ์ด์
์คํ
object MyApp extends Application with RealContext
MyApp.run()
์! ์ด๋ ๊ฒ ํ๋ฉด ํ์
์์ ํ ์์กด์ฑ ์ฃผ์
์์คํ
์ ๋ง๋ค ์ ์์ด์. M[A]
๋ผ๋ ํ์
๋๋ค๋ฅผ ์ฌ์ฉํด์ ์์กด์ฑ์ ํํํ๊ณ , ์ปจํ
์คํธ๋ฅผ ํตํด ์์กด์ฑ์ ์ ๊ณตํ์ฃ . ์ ๋ง ์ฐ์ํ์ง ์๋์? ใ
ใ
ใ
๐ก Pro Tip: ์ด๋ฐ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ์ฌ์ฉํ ๋๋ ํญ์ ํ์ ์ญ๋๊ณผ ํ๋ก์ ํธ์ ๋ณต์ก์ฑ์ ๊ณ ๋ คํด์ผ ํด์. ๋๋ก๋ ๊ฐ๋จํ ํด๊ฒฐ์ฑ ์ด ๋ ๋์ ์ ์์ฃ . ๋ง์น ์ฌ๋ฅ๋ท์์ ๋๋ฌด ๋ณต์กํ ๊ธฐ๋ฅ๋ณด๋ค๋ ์ฌ์ฉ์๊ฐ ์ฝ๊ฒ ์ดํดํ๊ณ ์ฌ์ฉํ ์ ์๋ ๊ธฐ๋ฅ์ด ๋ ์ค์ํ ๊ฒ์ฒ๋ผ ๋ง์ด์์!
์, ์ฌ๊ธฐ๊น์ง๊ฐ ์ค์ ์์ ์์ด์. ์ด๋ ์ จ๋์? ์กฐ๊ธ์ ๋จธ๋ฆฌ๊ฐ ์ํ์ จ๋์? ใ ใ ใ ๊ฑฑ์ ๋ง์ธ์. ์ด๋ฐ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ์๊ฐ์ ๋๊ณ ์ฒ์ฒํ ์ตํ๋๊ฐ๋ฉด ๋ผ์. ์ฒ์๋ถํฐ ์๋ฒฝํ๊ฒ ์ดํดํ๋ ค๊ณ ํ์ง ๋ง์ธ์!
์ด์ ์ฐ๋ฆฌ์ ์ฌ์ ์ด ๊ฑฐ์ ๋๋๊ฐ๊ณ ์์ด์. ๋ง์ง๋ง์ผ๋ก ์ ๋ฆฌ๋ฅผ ํด๋ณผ๊น์?
๐จ ์ฃผ์์ฌํญ: ์ด๋ฐ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ์ ๋ง ๊ฐ๋ ฅํ์ง๋ง, ๊ทธ๋งํผ ์ค์ฉํ๊ธฐ ์ฌ์์. ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํ ๋๋ ํญ์ ํ์๋ค๊ณผ ์ถฉ๋ถํ ์์ํ๊ณ , ์ฝ๋์ ๋ณต์ก์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ์ ๊ณ ๋ คํด์ผ ํด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ์๋ก์ด ๊ณ ๊ธ ๊ธฐ๋ฅ์ ๋์ ํ ๋ ์ฌ์ฉ์์ ํธ์์ฑ๊ณผ ์์คํ ์ ๋ณต์ก์ฑ์ ์ ๊ท ํ ์ก์์ผ ํ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ ! ๐ช
๐ ๋ง๋ฌด๋ฆฌ: ์ฐ๋ฆฌ์ ์ฌ์ ์ ๋๋์๋ณด๋ฉฐ
์์ฐ! ์ ๋ง ๊ธด ์ฌ์ ์ด์์ฃ ? ์ฐ๋ฆฌ๋ Scala์ ํ์ ์์คํ ๋ถํฐ ์์ํด์ ๋๋ค, ๊ณ ์ฐจ ํ์ , ๊ทธ๋ฆฌ๊ณ ํ์ ๋๋ค๊น์ง ์ ๋ง ๊น์ด ์๋ ๋ด์ฉ๋ค์ ๋ค๋ค์ด์. ์ฌ๋ฌ๋ถ์ ๋๋๋ ์์ง ๋ฉ์ฉกํ๊ฐ์? ใ ใ ใ
์ฐ๋ฆฌ๊ฐ ๋ฐฐ์ด ๋ด์ฉ๋ค์ ๊ฐ๋จํ ์ ๋ฆฌํด๋ณผ๊น์?
- Scala์ ๊ฐ๋ ฅํ ํ์ ์์คํ
- ๋๋ค์ ๊ณ ์ฐจ ํจ์์ ๊ฐ๋ ๊ณผ ํ์ฉ
- ๊ณ ์ฐจ ํ์ ๊ณผ ๊ทธ ํ์ฉ
- ํ์ ๋๋ค์ ๋ง๋ฒ ๊ฐ์ ํ
- ์ด ๋ชจ๋ ๊ฐ๋ ๋ค์ ํ์ฉํ ์ค์ ์์ ๋ค
์ด ๋ชจ๋ ๊ฐ๋ ๋ค์ด ์ฒ์์๋ ์ ๋ง ์ด๋ ต๊ณ ๋ณต์กํด ๋ณด์์ ๊ฑฐ์์. ํ์ง๋ง ์ฐจ๊ทผ์ฐจ๊ทผ ์์ ๋ฅผ ํตํด ์ดํด๋ณด๋ ์กฐ๊ธ์ ๊ฐ์ด ์ค์์ง ์๋์? ใ ใ ใ
Scala์ ์ด๋ฐ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ์ ๋ง ๊ฐ๋ ฅํ ๋๊ตฌ์์. ํ์ง๋ง ๊ฐ๋ ฅํ ๋งํผ ์ฃผ์ํด์ ์ฌ์ฉํด์ผ ํด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ๊ณ ๊ธ ๊ธฐ๋ฅ์ ๋์ ํ ๋ ์ ์คํ๊ฒ ๊ณ ๋ คํด์ผ ํ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ !
๐ ๊ธฐ์ตํ์ธ์: ํ๋ก๊ทธ๋๋ฐ์ ๊ฒฐ๊ตญ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋๊ตฌ์ผ ๋ฟ์ด์์. ๊ฐ์ฅ ๋ณต์กํ๊ณ ๊ณ ๊ธ์ง ํด๊ฒฐ์ฑ ์ด ํญ์ ์ต์ ์ ์๋์์. ๋๋ก๋ ๊ฐ๋จํ๊ณ ์ง๊ด์ ์ธ ์ฝ๋๊ฐ ๋ ๋์ ์ ์์ฃ . ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ์ฉ์์ ๋์ฆ๋ฅผ ์ ํํ ํ์ ํ๊ณ ๊ทธ์ ๋ง๋ ์๋น์ค๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ด ์ค์ํ ๊ฒ์ฒ๋ผ ๋ง์ด์์!
์ฌ๋ฌ๋ถ, ์ ๋ง ์๊ณ ๋ง์ผ์ จ์ด์! ์ด๋ ๊ฒ ๊ธด ์ฌ์ ์ ํจ๊ป ํด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ์ด ๊ธ์ ์ฝ์ผ์ ์ฌ๋ฌ๋ถ์ ์ด์ Scala์ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ๋ํด ๊ธฐ๋ณธ์ ์ธ ์ดํด๋ฅผ ๊ฐ์ถ์ จ์ ๊ฑฐ์์. ์์ผ๋ก ์ค์ ํ๋ก์ ํธ์์ ์ด๋ฐ ๊ฐ๋ ๋ค์ ๋ง๋๊ฒ ๋๋ฉด, "์, ์ด๊ฑฐ ์ด๋์ ๋ณธ ๊ฒ ๊ฐ์๋ฐ?" ํ๊ณ ๋ ์ฌ๋ฆฌ์ค ์ ์์ ๊ฑฐ์์. ใ ใ ใ
ํ๋ก๊ทธ๋๋ฐ ์ธ๊ณ๋ ์ ๋ง ๋๊ณ ๊น์ด์. ์ฐ๋ฆฌ๊ฐ ์ค๋ ๋ค๋ฃฌ ๋ด์ฉ์ ๊ทธ ์ค ์์ฃผ ์์ ๋ถ๋ถ์ ๋ถ๊ณผํด์. ํ์ง๋ง ์ด๋ฐ ์์ ์์์ด ์ฌ๋ฌ๋ถ์ ๋ ๋์ ์ธ๊ณ๋ก ์ด๋์ด์ค ๊ฑฐ์์. ๋ง์น ์ฌ๋ฅ๋ท์์ ์์ ์ฌ๋ฅ ํ๋๋ก ์์ํด์ ์ ์ ๋ ๋ค์ํ ๋ถ์ผ๋ก ํ์ฅํด ๋๊ฐ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ !
์, ์ด์ ์ ๋ง ๋์ด์์. ์ฌ๋ฌ๋ถ์ Scala ์ฌ์ ์ ํ์ด์ด ํจ๊ปํ๊ธฐ๋ฅผ ๋ฐ๋๊ฒ์. ํ์ดํ ! ๐โจ
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ