1์ฃผ์ฐจ (1 ~ 5 Chapter)

Chapter 01 ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ์–ธ์–ด

์Šค์นผ๋ผ(Scala) ๋ผ๋Š” ์ด๋ฆ„์€ ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ์–ธ์–ด(Scalable) ๋ผ๋Š” ๋œป์ด๋‹ค. ์ด๋ ‡๊ฒŒ ์ด๋ฆ„์„ ์ง€์€ ์ด์œ ๋Š” ์Šค์นผ๋ผ๋ฅผ ์‚ฌ์šฉ์ž์˜ ์š”๊ตฌ์— ๋”ฐ๋ผ ์ž๋ž„ ์ˆ˜ ์žˆ๋Š” ์–ธ์–ด๋กœ ์„ค๊ณ„ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

scalable ์€ ๊ทœ๋ชจ๋ฅผ ๋Š˜์ด๊ณ  ์ค„์ด๋Š”๊ฒŒ ์ž์œ ๋กญ๋‹ค๋Š” ๋œป์ด๋ฉฐ,
๋ณดํ†ต ๊ทœ๋ชจ๊ฐ€ ๋Š˜์–ด๋‚˜๊ฑฐ๋‚˜ ์ค„์–ด๋“ค์–ด๋„ ์„ฑ๋Šฅ์ด๋‚˜ ๋น„์šฉ์ด ์„ ํ˜•์ ์œผ๋กœ ์ฆ๊ฐ€ํ•œ๋‹ค๋Š” ๋œป์ด๋‹ค.

์Šค์นผ๋ผ๋Š” ๊ฐ์ฒด์ง€ํ–ฅ (Object Oriented) ๊ณผ ํ•จ์ˆ˜ํ˜• (Functional) ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐœ๋…์„ ์ •์  ํƒ€์ž… ์–ธ์–ด (Statically Typed Language) ์— ํ•ฉ์ณ๋†“์€ ์–ธ์–ด์ด๋‹ค.

1.1 ์—ฌ๋Ÿฌ๋ถ„์˜ ๋งˆ์Œ์—์„œ ์ ์  ์ž๋ผ๋‚˜๋Š” ์–ธ์–ด (a language that grows on you)

var captial = Map("US" -> "Washington", "France" -> "Paris")
capital += ("Japan" -> "Tokyo")
println(capital("France"))

์œ„์™€ ๊ฐ™์ด ๋†’์€ ์ˆ˜์ค€์˜ ๊ฐ„๊ฒฐํ•˜๊ณ , ๋ถˆํ•„์š”ํ•œ ์„ธ๋ฏธ์ฝœ๋ก ์ด๋‚˜ ํƒ€์ž… ์ง€์ •์œผ๋กœ ์ธํ•ด ์ง€์ €๋ถ„ํ•˜์ง€ ์•Š๊ฒŒ ์ฝ”๋“œ ์ž‘์„ฑ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

์ด๋“ค์˜ ๊ณตํ†ต์ ์ธ ํŠน์ง•์€ ์—ฐ๊ด€๋งต์„ ์–ธ์–ด์ˆ˜์ค€์—์„œ ์ง€์›ํ•œ๋‹ค๋Š” ์ ์ด๋‹ค.

์ƒˆ๋กœ์šด ํƒ€์ž…์„ ํ‚ค์›Œ๊ฐ€๊ธฐ

์Šค์นผ๋ผ๋Š” ์Šค์นผ๋ผ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์ด ํ™•์žฅํ•˜๊ณ  ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„ํ–ˆ๋‹ค. (Growing a language)

def factorial(x: BigInt): BigInt = 
  if (x == 0)
    1
  else 
    x * factorial(x - 1)

factorial(30) ์„ ํ˜ธ์ถœํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

265252859812191058636308480000000

๋ฐ˜ํ™˜ ํƒ€์ž…์ธ BigInt ๋Š” ๋งˆ์น˜ ๋‚ด์žฅ ํƒ€์ž…์ธ๊ฒƒ ์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ ์Šค์นผ๋ผ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋“ค์–ด์žˆ๋Š” ํ‰๋ฒ”ํ•œ ํด๋ž˜์Šค์ผ ๋ฟ์ด๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด Java ์—์„œ ์ง€์›ํ•˜๋Š” BigInteger ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œํ˜„๋  ๊ฒƒ ์ด๋‹ค.

import java.math.BigInteger

def factorial(x: BigInteger): BigInteger = 
  if (x == BigInteger.ZERO)
    BigInteger.ONE
  else
    x.multiply(factorial(x.subtract(BigInteger.ONE)))

์œ„์™€ ๊ฐ™์€ ์ฝ”๋“œ๋Š” ๋‚ด์žฅํƒ€์ž…์ด ๊ทธ์— ๋งž๋Š” ๋ฉ”์„œ๋“œ๋‚˜ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด์ค˜์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ์—์„œ ์œ ์—ฐํ•˜๊ฒŒ ์ ์šฉํ•˜๊ธฐ ์–ด๋ ค์šธ ๊ฒƒ์ด๋‹ค.

๊ฐ€๋ น ์‹ญ์ง„์ˆ˜, ๋ณต์†Œ์ˆ˜, ์œ ๋ฆฌ์ˆ˜, ์‹ ๋ขฐ๊ตฌ๊ฐ„, ๋‹คํ•ญ์‹ ๋“ฑ์˜ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ํ•˜๋‚˜์˜ ์–ธ์–ด์—์„œ ๋ชจ๋“ ๊ฒƒ์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์€ ํ™•์žฅ์„ฑ์ด ์ข‹์ง€ ์•Š๋‹ค.
์Šค์นผ๋ผ๋Š” ์–ธ์–ด๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ง€์›ํ•˜๋Š”๊ฒƒ ์ฒ˜๋Ÿผ ์‚ฌ์šฉ์ž๊ฐ€ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ํ•„์š”ํ•œ ๋ฐฉํ–ฅ์œผ๋กœ ํ™•์žฅํ•˜๊ณ  ๊ณ ์น  ์ˆ˜ ์žˆ๊ฒŒ ํ—ˆ์šฉํ•œ๋‹ค.

์ƒˆ๋กœ์šด ์ œ์–ด ๊ตฌ์กฐ ํ‚ค์›Œ๊ฐ€๊ธฐ

์Šค์นผ๋ผ์˜ ํ™•์žฅ์„ฑ ์›์น™์„ ์ œ์–ด ๊ตฌ์กฐ์—๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ ์šฉ๋œ๋‹ค.

์ด๋Ÿฌํ•œ ํ™•์ •์„ฑ์„ ์•กํ„ฐ ๊ธฐ๋ฐ˜ ๋™์‹œ์„  ํ”„๋กœ๊ทธ๋ž˜๋ฐ (Actor-based concurrent programming) ์Šค์นผ๋ผ API ์ธ ์•„์นด(Akka) ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์ž‘์„ฑํ•˜๋Š” ์ผ์€ ๊ฝค ์–ด๋ ค์šฐ๋ฉฐ ์ž๋ฐ”์˜ ์Šค๋ ˆ๋“œ ๋ชจ๋ธ์€ ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ (Shared Memory) ์™€ ๋ฝ (Lock) ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฉฐ ์ฝ”๋“œ๋ฅผ ๋ณด๊ณ  ๋…ผ๋ฆฌ์ ์œผ๋กœ ์ถ”๋ก ํ•˜๊ธฐ๊ฐ€ ์–ด๋ ต๋‹ค.
์ฝ”๋“œ์— ์ˆจ์–ด์žˆ๋Š” ๊ฒฝํ•ฉ ์กฐ๊ฑด (race condition) ์ด๋‚˜ ๊ต์ฐฉ ์ƒํƒœ (deadlock) ์ด ์—†๋‹ค๊ณ  ํ™•์‹ ํ•˜๊ธฐ๋Š” ์–ด๋ ต๋‹ค.

์•ˆ์ „ํ•œ ๋Œ€์•ˆ์€ ์–ผ๋žญ (Erlang) ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์•กํ„ฐ ๊ฐ™์€ ๋ฉ”์„ธ์ง€ ์ „๋‹ฌ ์•„ํ‚คํ…์ณ์ด๋‹ค.

๋‹ค์Œ ์ฝ”๋“œ๋Š” recipient ๋ผ๋Š” ์•กํ„ฐ์— ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด๋‚ด๋Š” ๋ฌธ์žฅ์ด๋‹ค.

recipient ! msg

์†ก์‹ ์€ ๋น„๋™๊ธฐ์  (asynchronous) ์ด๋ฉฐ ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด๋‚ธ ์•กํ„ฐ๋Š” ์ˆ˜์‹ ๊ฐ€๊ฐ€ ๋ฉ”์„ธ์ง€๋ฅผ ์ˆ˜์‹ ํ•  ๋•Œ ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆด ํ•„์š” ์—†์ด ์ฆ‰์‹œ ๋‹ค์Œ ์ž‘์—…์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ชจ๋“  ์•กํ„ฐ๋Š” ์šฐํŽธํ•จ (mailbox) ๊ฐ€ ์žˆ์œผ๋ฉฐ ์šฐํŽธํ•จ์— ๋„์ฐฉํ•œ ๋ฉ”์„ธ์ง€๋Š” receive ๋ธ”๋Ÿญ์„ ์ด์šฉํ•˜์—ฌ ์ฒ˜๋ฆฌํ•œ๋‹ค.

def receive = {
  case Msg1 => ... // Msg1์„ ์ฒ˜๋ฆฌํ•จ
  case Msg2 => ... // Msg2๋ฅผ ์ฒ˜๋ฆฌํ•จ
}

์ฃผ์–ด์ง„ ์—ฌ๋Ÿฌ case ๋ฅผ ๋งŒ์กฑํ•˜๋Š” ๋ฉ”์„ธ์ง€๊ฐ€ ์šฐํŽธํ•จ์— ์—†์„ ๊ฒฝ์šฐ ์•กํ„ฐ๋Š” ๋™์ž‘์„ ๋ฉˆ์ถ”๊ฐ€ ๋‹ค์Œ ๋ฉ”์„ธ์ง€๊ฐ€ ๋„์ฐฉํ•  ๋•Œ ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.

๋‹ค์Œ์€ ์ฒดํฌ์„ฌ (checksum) ๊ณ„์‚ฐ ์„œ๋น„์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ์•„์นด ์•กํ„ฐ๋‹ค.

class CheckSumActor extends Actor {
  var sum = 0
  
  def receive = {
    case Data(byte) => sum += byte
    case GetChecksum(requester) => 
      val checksum = ~(sum & 0xFF) + 1
      requester ! checksum
  }
}

์œ„ ์ฝ”๋“œ๋Š” receive ๋ธ”๋Ÿญ์„ ์ •์˜ํ•œ ํ›„
Data ๋ฉ”์„ธ์ง€๋ฅผ ๋ฐ›์œผ๋ฉด ๊ทธ ์•ˆ์— ๋“ค์–ด์žˆ๋Š” ๋ฐ์ดํ„ฐ (byte) ์— sum ๋ณ€์ˆ˜๋ฅผ ๋”ํ•œ๋‹ค. GetChecksum ๋ฉ”์„ธ์ง€๋ฅผ ๋ฐ›์œผ๋ฉด sum ์˜ ํ˜„์žฌ๊ฐ’์„ ์ด์šฉํ•˜์—ฌ ์ฒดํฌ์„ฌ์„ ๊ณ„์‚ฐํ•œ ๋‹ค์Œ ์š”์ฒญํ•œ requester ์—๊ฒŒ requester ! checksum ์ด๋ผ๋Š” ์†ก์‹  ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒฐ๊ด๊ฐ’์„ ์ „์†กํ•œ๋‹ค.

์ด ์ฝ”๋“œ์—์„œ receive ๋‚˜ ๋ฉ”์„ธ์ง€ ์†ก์‹  (!) ์€ ์Šค์นผ๋ผ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋‚ด์žฅ ๊ธฐ๋Šฅ์ด ์•„๋‹ˆ๋ผ ์•กํ„ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ฉ”์„œ๋“œ์— ๋ถˆ๊ณผํ•˜๋ฉฐ, ์Šค์นผ๋ผ ํ”„๋กœ๊ทธ๋ž˜๋ฐ๊ณผ๋Š” ๋ณ„๊ฐœ์˜ ์ •์˜๋œ ๋ฉ”์„œ๋“œ๋ฅผ ๋™์ž‘์‹œํ‚ค๋Š” ๊ฒƒ์ด๋‹ค.

์•กํ„ฐ ๋ชจ๋ธ์ด ๋ถ„์‚ฐ ์ปดํ“จํŒ…์„ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ ๋งค์šฐ ์ ์ ˆํ•œ ๋„๊ตฌ์ด์ง€๋งŒ ์ด๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž„์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์Šค์นผ๋ผ ์–ธ์–ด์™€ ํ•˜๋‚˜์ธ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋ฉฐ, ์ด๋Š” ๋งˆ์น˜ ์• ์ดˆ์— ๊ทธ ๊ธฐ๋Šฅ์„ ์›๋ž˜ ์–ธ์–ด๊ฐ€ ์ง€์›ํ•˜๋Š”๊ฒƒ ์ฒ˜๋Ÿผ ๋Š๋ผ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.

1.2 ์Šค์นผ๋ผ์˜ ํ™•์žฅ์„ฑ์ด ๊ฐ€๋Šฅํ•œ ์ด์œ 

์Šค์นผ๋ผ์˜ ํ™•์žฅ์„ฑ์— ๊ฐ€์žฅ ํฐ ์˜ํ–ฅ์„ ๋ผ์น˜๋Š” ์š”์ธ์€ ๊ฐ์ฒด ์ง€ํ–ฅ๊ณผ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์กฐํ•ฉ์ด๋‹ค.

์Šค์นผ๋ผ์—์„œ๋Š” ํ•จ์ˆซ๊ฐ’๋„ ๊ฐ์ฒด์ด๋‹ค.
์•ž์—์„œ ๋ณด์—ฌ์ค€ ์•กํ„ฐ์˜ ๊ฐœ๋…์€ ํ•จ์ˆ˜์™€ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ฉํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด ๊ตฌํ˜„ํ•  ์ˆ˜ ์—†์—ˆ์„ ๊ฒƒ์ด๋‹ค.

์Šค์นผ๋ผ๋Š” ๊ฐ์ฒด์ง€ํ–ฅ์ ์ด๋‹ค

์Šค์นผ๋ผ๋Š” ์ˆœ์ˆ˜ํ•œ ํ˜•ํƒœ์˜ ๊ฐ์ฒด์ง€ํ–ฅ ์–ธ์–ด์ด๋‹ค.

๋ชจ๋“  ๊ฐ’์ด ๊ฐ์ฒด์ด๋ฉฐ, ๋ชจ๋“  ์—ฐ์‚ฐ์€ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์ด๋‹ค.
๊ฐ€๋ น 1 + 2 ๋ผ๊ณ  ์“ฐ๋ฉด, ์‹ค์ œ๋กœ๋Š” Int ํด๋ž˜์Šค๊ฐ€ ์ •์˜ํ•œ + ๋ผ๋Š” ์ด๋ฆ„์˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์Šค์นผ๋ผ์˜ ํŠธ๋ ˆ์ดํŠธ (trait) ๋ฅผ ์ด์šฉํ•˜๋ฉด ๋ฏน์Šค์ธ (mixin) ์กฐํ•ฉ์„ ํ†ตํ•˜์—ฌ ํด๋ž˜์Šค์˜ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ธก๋ฉด์„ ๊ฐ๊ฐ ๋ณ„๋„์˜ ํŠธ๋ ˆ์ดํŠธ์— ์บก์Šํ™” (encapsulate) ํ•  ์ˆ˜ ์žˆ๋‹ค.

ํŠธ๋ ˆ์ดํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์ค‘ ์ƒ์†์˜ ๊ณ ์ „์  ๋ฌธ์ œ์ธ '๋‹ค์ด์•„๋ชฌ๋“œ ์ƒ์†' ์„ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‹ค์ด์•„๋ชฌ๋“œ ์ƒ์†

๋™์ผํ•œ ํด๋ž˜์Šค๋ฅผ ์—ฌ๋Ÿฌ ๊ฒฝ๋กœ๋ฅผ ํ†ตํ•ด ์—ฌ๋Ÿฌ๋ฒˆ ์ƒ์†ํ•˜๋Š” ๊ฒฝ์šฐ
Java ์—์„œ๋Š” ๋‹ค์ค‘ ์ƒ์†์„ ์ง€์›ํ•˜์ง€ ์•Š์œผ๋ฉฐ C++ ๊ฐ™์€ ๊ฒฝ์šฐ์—๋„ ์•ˆํ‹ฐํŒจํ„ด์œผ๋กœ ์‚ฌ์šฉ์„ ์ง€์–‘ํ•œ๋‹ค.

์Šค์นผ๋ผ๋Š” ํ•จ์ˆ˜ํ˜•์ด๋‹ค

ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ๋‘๊ฐ€์ง€ ์ฃผ์š” ์•„์ด๋””์–ด์—์„œ ๋ฐฉํ–ฅ์ด ๊ฒฐ์ •๋œ๋‹ค.

1๊ธ‰ ๊ณ„์ธต (First Class) ์ด๋‹ค

ํ•จ์ˆ˜ํ˜• ์–ธ์–ด์—์„œ์˜ ํ•จ์ˆ˜๋Š” ์ •์ˆ˜๋‚˜ ๋ฌธ์ž์—ด๊ณผ ๋™์ผํ•œ ์ž๊ฒฉ์„ ๊ฐ–๋Š” ๊ฐ’์ด๋‹ค.
์ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์„ฑ์„ ๊ฐ–๋Š”๋‹ค.

  • ํ•จ์ˆ˜๋ฅผ ๋‹ค๋ฅธ ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๋„˜๊ธธ์ˆ˜ ์žˆ๋‹ค.
  • ํ•จ์ˆ˜ ์•ˆ์—์„œ ๊ฒฐ๊ณผ๋กœ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํ•จ์ˆ˜๋ฅผ ๋ณ€์ˆ˜์— ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํ•จ์ˆ˜์•ˆ์—์„œ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์ž‡๋‹ค.

ํ”„๋กœ๊ทธ๋žจ์€ ์ž…๋ ฅ๊ฐ’์„ ์ถœ๋ ฅ๊ฐ’์œผ๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ•˜๋ฉฐ, ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ ์ž๋ฆฌ์—์„œ ๋ณ€๊ฒฝํ•˜์ง€ ๋ง์•„์•ผ ํ•œ๋‹ค๋Š” ์ ์ด๋‹ค

์˜ˆ๋ฅผ ๋“ค๋ฉด s.replace(",", ":") ์€ ์ƒˆ๋กœ์šด ๋ฌธ์ž์—ด ๊ฐ์ฒด๊ฐ€ ์ƒ๊ธฐ๋ฉฐ ๊ธฐ์กด s ์™€๋Š” ๋‹ค๋ฅด๋‹ค.
์ด๋Š” ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅ (immutable) ๊ณผ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ (mutable) ์˜ ํŠน์„ฑ๊ณผ๋„ ์œ ์‚ฌํ•œ๋ฐ ๊ฐ ์–ธ์–ด์˜ ์„ฑ๊ฒฉ๋งˆ๋‹ค ๋‹ค๋ฅด๋‹ค.
๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•œ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋Š” ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋žจ์˜ ์ดˆ์„ ์ค‘ ํ•˜๋‚˜์ด๋‹ค.
์Šค์นผ๋ผ์˜ ๊ฒฝ์šฐ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•œ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋กœ์จ ๋ฆฌ์ŠคํŠธ, ํŠœํ”Œ, ๋งต, ์ง‘ํ•ฉ์„ ์ œ๊ณตํ•œ๋‹ค.

๋˜ํ•œ replace ์™€ ๊ฐ™์ด ์‹œ์Šคํ…œ์— ๋‹ค๋ฅธ ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ฐธ์กฐ ํˆฌ๋ช… (referentially transparent) ํ•˜๋‹ค ํ•œ๋‹ค.

ํ•จ์ˆ˜ํ˜• ์–ธ์–ด๋Š” ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•œ ๋ฐ์ดํ„ฐ์™€ ์ฐธ์กฐ ํˆฌ๋ช…ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์žฅ๋ คํ•œ๋‹ค.

1.3 ์™œ ์Šค์นผ๋ผ์ธ๊ฐ€?

์Šค์นผ๋ผ๋Š” ํ™•์žฅ์„ฑ ๋ง๊ณ ๋„ ๋‹ค์Œ ๋„ค๊ฐ€์ง€ ์ธก๋ฉด์ด ํŠน์ง•์ ์ด๋‹ค.

  • ํ˜ธํ™˜์„ฑ
  • ๊ฐ„๊ฒฐ์„ฑ
  • ๊ณ ์ˆ˜์ค€ ์ถ”์ƒํ™”
  • ๊ณ ๊ธ‰ ์ •์  ํƒ€์ž…

์Šค์นผ๋ผ๋Š” ํ˜ธํ™˜์„ฑ์ด ์ข‹๋‹ค

์Šค์นผ๋ผ ํ”„๋กœ๊ทธ๋žจ์€ JVM์˜ ๋ฐ”์ดํŠธ ์ฝ”๋“œ๋กœ ์ปดํŒŒ์ผ ๋œ๋‹ค.

์™„์ „ํ•œ ์ƒํ˜ธ์šด์šฉ์„ฑ (interoperability) ์˜ ๋˜ ๋‹ค๋ฅธ ์ธก๋ฉด์œผ๋กœ๋Š” ์Šค์นผ๋ผ๊ฐ€ ์ž๋ฐ” ํƒ€์ž…์„ ์•„์ฃผ ๋งŽ์ด ์žฌ์‚ฌ์šฉํ•œ๋‹ค๋Š” ์ ์ด๋‹ค.

์ž๋ฐ”์˜ ํƒ€์ž…์„ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๋ฟ๋งŒ์ด ์•„๋‹ˆ๋ผ ์žฌ์ •์˜ (redefinition) ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.

์˜ˆ๋ฅผ ๋“ค๋ฉด ์Šค์นผ๋ผ ๋ฌธ์ž์—ด์€ ์ž์‹ ์„ ์ •์ˆ˜๋‚˜ ๋ถ€๋™์†Œ์ˆ˜์ ์œผ๋กœ ๋ฐ”๊พธ๋Š” toInt ๋‚˜ toFloat ๋ฅผ ์ง€์›ํ•œ๋‹ค.

์Šค์นผ๋ผ์—์„œ๋Š” ์•”์‹œ์  ํ˜•๋ณ€ํ™˜ (implicit conversion) ์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

์Šค์นผ๋ผ๋Š” ๊ฐ„๊ฒฐํ•˜๋‹ค

ํ”„๋กœ๊ทธ๋žจ์„ ์ดํ•ดํ•˜๊ณ  ์ฝ๊ธฐ ์œ„ํ•œ ๋…ธ๋ ฅ์ด ๋œ ๋“ค๊ณ , ๊ทธ์— ๋”ฐ๋ฅธ ์˜ค๋ฅ˜๊ฐ€๋Šฅ์„ฑ์ด ์ค„์–ด๋“ ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

class MyClass {
  private int index;
  private String name;

  public MyClass(int index, String name) {
    this.index = index;
    this.name = name;
  }
}

์œ„ ์ž๋ฐ” ์ฝ”๋“œ๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์€ ์Šค์นผ๋ผ ์ฝ”๋“œ๋กœ ๋ฐ”๊ฟ€์ˆ˜ ์žˆ๋‹ค.

class MyClass(index: Int, name: String)

์Šค์นผ๋ผ์˜ ํƒ€์ž… ์ถ”๋ก  (type inference) ์€ ์ด๋Ÿฐ ๊ฐ„๊ฒฐ์„ฑ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ์š”์†Œ์ด๋‹ค.
๋ฐ˜๋ณต์ ์œผ๋กœ ํƒ€์ž… ์ •๋ณด๋ฅผ ์“ธ ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์—, ํ”„๋กœ๊ทธ๋žจ์ด ๋œ ์–ด์ˆ˜์„ ํ•˜๊ณ  ๋” ์ฝ๊ธฐ ์ข‹์•„์ง„๋‹ค.

์Šค์นผ๋ผ๋Š” ์ผ๋ฐ˜์ ์ธ ๋™์ž‘๋“ค์„ ๋ฌถ์–ด์„œ ๊ฐ•๋ ฅํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์ž‡๋Š” ๋„๊ตฌ๋ฅผ ๋งŽ์ด ์ œ๊ณตํ•œ๋‹ค.
๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํด๋ž˜์Šค์˜ ์—ฌ๋Ÿฌ ์ธก๋ฉด์„ ๊ฐ๊ฐ ๋ณ„๋„์˜ ํŠธ๋ ˆ์ดํŠธ์— ๋ถ„๋ฆฌํ•ด ๋„ฃ์„์ˆ˜ ์žˆ์–ด ์œ ์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

์Šค์นผ๋ผ๋Š” ๊ณ ์ˆ˜์ค€์ด๋‹ค

์•„๋ž˜ ์ฝ”๋“œ๋Š” ์ž๋ฐ”์—์„œ ๋™์ž‘๋˜๋Š” ๋ฌธ์ž์—ด์— ๋Œ€๋ฌธ์ž๊ฐ€ ๋“ค์–ด์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ์ฝ”๋“œ์ด๋‹ค.

boolean nameHasUpperCase = false;

for (int i = 0; i < name.length(); ++i) {
  if (Character.isUpperCase(name.charAt(i))) {
    nameHasUpperCase = true;
    break;
  }
}

์œ„ ์ฝ”๋“œ๋Š” ์Šค์นผ๋ผ๋กœ ์•„๋ž˜์™€ ๊ฐ™์ด ์“ธ ์ˆ˜ ์ž‡๋‹ค.

val nameHashUpperCase = name.exists(_.isUpper)

๋ฌผ๋ก  Java 8 ์ดํ›„๋ถ€ํ„ฐ๋Š” ๋žŒ๋‹ค (lambda) ์™€ ์ŠคํŠธ๋ฆผ (stream) ์— ๋Œ€ํ•œ ์ง€์›์ด ๋“ค์–ด๊ฐ”๊ธฐ ๋•Œ๋ฌธ์— ์Šค์นผ๋ผ์—์„œ๋„ ๋น„์Šทํ•œ ์—ฐ์‚ฐ์ด ๊ฐ€๋Šฅํ•ด์กŒ๋‹ค.

boolean nameHasUpperCase = 
  name.chars().anyMatch(
    (int ch) -> Character.isUpperCase((char) ch)
  )

์ด์ „ ๋ฒ„์ „์— ๋น„ํ•˜๋ฉด ์—„์ฒญ๋‚œ ๊ฐœ์„ ์ด์ง€๋งŒ Java 8 ์ฝ”๋“œ๋Š” ์—ฌ์ „ํžˆ ์Šค์นผ๋ผ ์ฝ”๋“œ๋ณด๋‹ค๋Š” ๋ฒˆ์žก์Šค๋Ÿฌ์›Œ ๋ณด์ธ๋‹ค.

์Šค์นผ๋ผ๋Š” ์ •์  ํƒ€์ž… ์–ธ์–ด๋‹ค

์Šค์นผ๋ผ๋Š” ์•„์ฃผ ์ง„๋ณด์ ์ธ ์ •์  ํƒ€์ž… ์‹œ์Šคํ…œ (static type system) ์„ ๊ฐ€์ง„ ์–ธ์–ด๋กœ์จ ๋‹ค์Œ์„ ์ œ๊ณตํ•œ๋‹ค.

  • ์ž๋ฐ”์™€ ๋น„์Šทํ•œ ์ˆ˜์ค€์˜ ์ค‘์ฒฉ ํด๋ž˜์Šค ํƒ€์ž…
  • ์ œ๋„ค๋ฆญ (Generic) ๊ณผ ํŒŒ๋ผ๋ฏธํ„ฐํ™”ํ•œ ํƒ€์ž…์„ ํ—ˆ์šฉ
  • ๊ต์ง‘ํ•ฉ (intersection) ์„ ์‚ฌ์šฉํ•˜์—ฌ ํƒ€์ž…์„ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ๋‹ค
  • ์ถ”์ƒ ํƒ€์ž… (abstract type) ์„ ์‚ฌ์šฉํ•˜์—ฌ ์–ด๋–ค ํƒ€์ž…์—์„œ ์ƒ์„ธ ๋‚ด์šฉ์„ ๊ฐ์ถœ ์ˆ˜ ์žˆ๋‹ค

์žฌ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•œ ์ปดํฌ๋„ŒํŠธ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ด๋ฃจ๋Š” ๋ฉค๋ฒ„์˜ ํƒ€์ž… ์‹œ๊ทธ๋‹ˆ์ณ (signature) ๋Š” ๋ช…์‹œํ•ด์•ผํ•œ๋‹ค.

1.4 ์Šค์นผ๋ผ์˜ ๋ฟŒ๋ฆฌ

์Šค์นผ๋ผ๋Š” ๋งŽ์€ ์–ธ์–ด๋“ค๋กœ๋ถ€ํ„ฐ ์•„์ด๋””์–ด์™€ ์˜ํ–ฅ์„ ๋ฐ›์•„ ์™”๋‹ค.

์Šค์นผ๋ผ์˜ ์ถ”์ƒํ™” ํƒ€์ž…์€ ์ œ๋„ค๋ฆญํƒ€์ž…๋ณด๋‹ค ๋” ๊ฐ์ฒด์ง€ํ–ฅ์ ์ธ ๋Œ€์•ˆ์ด ๋  ์ˆ˜ ์žˆ๋‹ค.

์Šค์นผ๋ผ ํŠธ๋ ˆ์ดํŠธ๋Š” ๋” ์œ ์—ฐํ•œ ์ปดํฌ๋„ŒํŠธ ์กฐ๋ฆฝ์„ ํ—ˆ์šฉํ•˜๋ฉฐ, ์ต์ŠคํŠธ๋ž™ํ„ฐ (extractor) ๋Š” ํŒจํ„ด ๋งค์น˜๋ฅผ ๋‚ด๋ถ€ ํ‘œํ˜„๊ณผ ๋ถ„๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•œ๋‹ค.

1.5 ๊ฒฐ๋ก 

์Šค์นผ๋ผ์˜ ํƒ€์ž… ์‹œ์Šคํ…œ๊ณผ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ํ”„๋กœ๊ทธ๋žจ์˜ ์‚ฌ๊ณ ๋ฐฉ์‹์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋Š” ์ง€์ ์ธ ๊ฒฝํ—˜์„ ์ œ๊ณตํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์ฒด๊ฐํ•œ๋‹ค.

Chapter 02 ์Šค์นผ๋ผ ์ฒซ๊ฑธ์Œ

2.1 1๋‹จ๊ณ„: ์Šค์นผ๋ผ ์ธํ„ฐํ”„๋ฆฌํ„ฐ ์‚ฌ์šฉ๋ฒ•์„ ์ตํžˆ์ž

์Šค์นผ๋ผ๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•์€ ์Šค์นผ๋ผ ์ธํ„ฐํ”„๋ฆฌํ„ฐ (๋Œ€ํ™”ํ˜• Shell) ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

ํ‘œํ˜„์‹ (expression) ์„ ์ž…๋ ฅํ•˜๋ฉด ์ธํ„ฐํ”„๋ฆฌํ„ฐ๊ฐ€ ๊ทธ ํ‘œํ˜„์‹์„ ๊ณ„์‚ฐํ•ด์„œ ๊ฒฐ๊ด๊ฐ’์„ ์ถœ๋ ฅํ•  ๊ฒƒ์ด๋‹ค.

$ scala
Welcome to Scala version 2.11.7
Type in expressions to have them evaluated.
Type :help for more information.

scala>

1 + 2 ์™€ ๊ฐ™์€ ํ‘œํ˜„์‹์„ ์ž…๋ ฅํ•˜๊ณ  ์—”ํ„ฐ๋ฅผ ๋ˆ„๋ฅด์ž

scala> 1 + 2

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‘๋‹ตํ•œ๋‹ค.

res0: Int = 3

res{๋ฒˆํ˜ธ} ์˜ ์‹๋ณ„์ž (identifier) ๋Š” ๋‚˜์ค‘์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๋งŒ์•ฝ res0 ๊ฐ€ 3 ์œผ๋กœ ์ •ํ•ด์กŒ์œผ๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ํ•ด๋‹น ์‹๋ณ„์ž์— 3์„ ๊ณฑํ•˜๋ฉด 9๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

scala> res0 * 3
res1: Int = 9

Hello World ์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

scala> println("Hello, world!")
Hello, world!

2.2 2๋‹จ๊ณ„: ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•ด๋ณด์ž

์Šค์นผ๋ผ์—๋Š” ๋‘๊ฐ€์ง€ ์ข…๋ฅ˜์˜ ๋ณ€์ˆ˜๊ฐ€ ์žˆ๋Š”๋ฐ val ๊ณผ var ์ด๋ฉฐ ํŠน์ง•์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • val : ๋ถˆ๋ณ€ (immutable)
  • var : ๊ฐ€๋ณ€ (mutable)

๋˜ํ•œ ์Šค์นผ๋ผ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ํƒ€์ž… ์ถ”๋ก ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

scala> val msg = "Hello, world!"
msg: String = Hello, world!

2.3 3๋‹จ๊ณ„: ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•ด๋ณด์ž

์Šค์นผ๋ผ์—์„œ๋Š” ํ•จ์ˆ˜์˜ ์ •์˜๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•œ๋‹ค.

def max(x: Int, y: Int): Int = {
  if (x > y)
    x
  else 
    y
}

์œ„ ์ฝ”๋“œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ค‘๊ด„ํ˜ธ๋ฅผ ์ƒ๋žตํ•˜์—ฌ ํ‘œํ˜„์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

def max(x: Int, y: Int) = if (x > y) x else y

์Šค์นผ๋ผ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์„ ๋ฐ˜๋“œ์‹œ ์ง€์ •ํ•˜๋„๋ก ์š”๊ตฌํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋Š”๋ฐ ์ด๋Š” ํ•จ์ˆ˜๊ฐ€ ์žฌ๊ท€์  (recursive) ์ด๋ผ๋ฉด ๋ฐ˜๋“œ์‹œ ๋ฐ˜ํ™˜ ํƒ€์ž…์„ ๋ช…์‹œํ•ด์•ผ ํ•œ๋‹ค.

๋งŒ์•ฝ ํ•จ์ˆ˜๊ฐ€ ์–ด๋–ค ๊ด€์‹ฌ์ด ์žˆ์„๋งŒํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋Œ๋ ค์ฃผ์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋ฐ”๋กœ ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฒฝ์šฐ๋‹ค.

def greet() = println("Hello, world!")

greet() ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๋ฉด ์ธํ„ฐํ”„๋ฆฌํ„ฐ๊ฐ€ greet: ()Unit ์ด๋ผ๊ณ  ์‘๋‹ตํ•  ๊ฒƒ์ด๋‹ค.

Unit ์€ greet ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์ธ๋ฐ ์ด๋Š” ์šฐ๋ฆฌ๊ฐ€ ๊ด€์‹ฌ์„ ๊ฐ€์งˆ ๋งŒํ•œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๋œป์ด๋‹ค.
์ด๋Š” ์ž๋ฐ”์˜ void ์™€ ๋น„์Šทํ•œ ์—ญํ™œ์„ ํ•˜๋ฉฐ ์Šค์นผ๋ผ์—์„œ๋Š” ๋ชจ๋‘ Unit ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ๋œ๋‹ค.

์ฆ‰, ๋ฐ˜ํ™˜ ํƒ€์ž…์ด Unit ์ธ ๋ฉ”์„œ๋“œ๋Š” ๋ถ€์ˆ˜ํšจ๊ณผ๋ฅผ ์œ„ํ•ด์„œ๋งŒ ์‹คํ–‰ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.

2.4 4๋‹จ๊ณ„: ์Šค์นผ๋ผ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž‘์„ฑํ•ด๋ณด์ž

println("Hello, " + args(0) + "!" )
$ scala helloarg.scala planet

Hello, planet!

์Šค์นผ๋ผ ๋ฐฐ์—ด์˜ ์ฒซ๋ฒˆ์งธ ์›์†Œ๋Š” args[0] ์ด ์•„๋‹ˆ๊ณ  args(0) ์ด๋‹ค.

2.5 5๋‹จ๊ณ„: while๋กœ ๋ฃจํ”„๋ฅผ ๋Œ๊ณ , if๋กœ ๊ฒฐ์ •ํ•ด๋ณด์ž

var i = 0

while (i < args.length) {
  if (i != 0)
    println(" ")
  println(args(i))
  i += 1
}

์ด ์ฝ”๋“œ๋Š” ๋ช…๋ นํ˜• ์Šคํƒ€์ผ์ด๋ฉฐ ์ž‘๋™์„ ์ง€์‹œํ•˜๋Š” ๋ช…๋ น์„ ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์”ฉ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

์œ„ ์ฝ”๋“œ๋Š” ์˜ˆ์‹œ์ผ ๋ฟ ๋‹ค์Œ์— ๋ฐฐ์šธ ๋ฐฐ์—ด์˜ ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•ด ์ดํ„ฐ๋ ˆ์ด์…˜ ํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์€ ์ ‘๊ทผ๋ฐฉ๋ฒ•์ด๋‹ค.

2.6 6๋‹จ๊ณ„: foreach์™€ for๋ฅผ ์‚ฌ์šฉํ•ด ์ดํ„ฐ๋ ˆ์ด์…˜ํ•ด๋ณด์ž

์Šค์นผ๋ผ๋ฅผ ๋” ์ž˜ ์•Œ๊ฒŒ ๋ ์ˆ˜๋ก ํ•จ์ˆ˜ํ˜• (functional) ์Šคํƒ€์ผ๋กœ ์ฝ”๋“œ ์ž‘์„ฑ์„ ํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.

args.foreach(arg => println(arg))

์œ„ ์ฝ”๋“œ๋Š” ํ•จ์ˆ˜ ๋ฆฌํ„ฐ๋Ÿด (function literal) ์„ ์‚ฌ์šฉํ•˜์˜€์ง€๋งŒ ๋” ์ •ํ™•ํ•œ ํ˜•ํƒœ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

args.foreach(println)

ํ•จ์ˆ˜ ๋ฆฌํ„ฐ๋Ÿด ๋ฌธ๋ฒ•์€ ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„์˜ ๋ชฉ๋ก์ด ๊ด„ํ˜ธ ์•ˆ์— ์˜ค๊ณ , ๊ทธ ์œ„์— ์˜ค๋ฅธ์ชฝ ํ™”์‚ดํ‘œ, ๋งˆ์ง€๋ง‰์œผ๋กœ ํ•จ์ˆ˜์˜ ๋ณธ๋ฌธ์ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.

(x: Int, y: Int) => x + y

2.7 ๊ฒฐ๋ก 

์Šค์นผ๋ผ์˜ ๊ธฐ๋ณธ์ ์€ ๋ฌธ๋ฒ•์„ ์•Œ์•„๋ดค์œผ๋‹ˆ ๋‹ค์Œ์žฅ์—์„œ๋Š” ์ข€ ๋” ์—ฌ๋Ÿฌ์šด ์ฃผ์ œ๋กœ ๋„˜์–ด๊ฐ„๋‹ค.

Chapter 03 ์Šค์นผ๋ผ ๋‘ ๋ฒˆ์งธ ๊ฑธ์Œ

2์žฅ์—์„œ๋Š” ์Šค์นผ๋ผ์˜ ๊ธฐ์ดˆ๋ฅผ 3์žฅ์—์„œ๋Š” ์Šค์นผ๋ผ์—์„œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์„ ์ •๋„์˜ ์ถฉ๋ถ„ํ•œ ์ง€์‹์„ ์Œ“์„์ˆ˜ ์žˆ๋‹ค.

3.1 7๋‹จ๊ณ„: ๋ฐฐ์—ด์— ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ง€์ •ํ•ด๋ณด์ž

์Šค์นผ๋ผ์—์„œ๋Š” new ๋ฅผ ์‚ฌ์šฉํ•ด ๊ฐ์ฒด๋ฅผ ์ธ์Šคํ„ด์Šคํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‹ค์Œ ์ฝ”๋“œ๋Š” ์Šค์นผ๋ผ์—์„œ java.math.BigInteger ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ๊ฐ’ "12345" ๋ฅผ ์ธ์Šคํ„ด์Šคํ™” ํ•œ๋‹ค.

val big = new java.math.BigInteger("12345")

๋ฐฐ์—ด์„ ํƒ€์ž…์œผ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐํ™” ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

val greetStrings = new Array[String](3)

greetStrings(0) = "Hello"
greetStrings(1) = ", "
greetStrings(2) = "world!\n"

for (i < 0 to 2)
  print(greetStrings(i))

๋ฐฐ์—ด์˜ ์ฒซ๋ฒˆ์งธ ์š”์†Œ๋ฅผ ์ ‘๊ทผํ•˜๋ ค๋ฉด ์ž๋ฐ”์—์„œ๋Š” greetStrings[0] ์ด์ง€๋งŒ ์Šค์นผ๋ผ์—์„œ๋Š” greetStrings(0) ์ด๋‹ค.

for ๋ฐ˜๋ณต๋ฌธ์˜ ์ฝ”๋“œ์ค‘์— ๋‚˜ํƒ€๋‚˜๋Š” ์Šค์นผ๋ผ์˜ ํŠน์ง•์€ ๋ฉ”์„œ๋“œ๊ฐ€ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํ•˜๋‚˜๋งŒ ์š”๊ตฌํ•˜๋Š” ๊ฒฝ์šฐ, ๊ทธ ๋ฉ”์„œ๋“œ๋ฅผ ์ (.)๊ณผ ๊ด„ํ˜ธ ์—†์ด ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค.

์ด ์˜ˆ์—์„œ to ๋Š” ์‹ค์ œ๋กœ Int ์ธ์ž๋ฅผ ํ•˜๋‚˜๋งŒ ๋ฐ›๋Š” ๋ฉ”์„œ๋“œ์ด๋ฉฐ 0 to 2 ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ (0).to(2) ๋ผ๋Š” ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ๋กœ ๋ฐ”๋€๋‹ค.

์Šค์นผ๋ผ๋Š” ๋ชจ๋“  ๊ฐ์ฒด๊ฐ€ ํ•จ์ˆ˜์ด๋‹ค.

์ „ํ†ต์ ์œผ๋กœ 1 + 2 ๋ผ๋Š” ์ฝ”๋“œ๋Š” (1).+(2) ๋ผ๊ณ ๋„ ์“ธ ์ˆ˜ ์žˆ๋‹ค.

๋ณ€์ˆ˜ ํ•˜๋‚˜ ์ด์ƒ์˜ ๊ฐ’์„ ๊ด„ํ˜ธ๋กœ ๋‘˜๋Ÿฌ์‹ธ์„œ ํ˜ธ์ถœํ•˜๋ฉด ์Šค์นผ๋ผ๋Š” ๊ทธ ์ฝ”๋“œ๋ฅผ ๋ณ€์ˆ˜์— ๋Œ€ํ•ด apply ๋ผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ฐ”๊พผ๋‹ค.

์ฆ‰, greetStrings(i) ๋Š” greetStrings.apply(i) ๋กœ ๋ฐ”๋€๋‹ค.

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์–ด๋–ค ๋ณ€์ˆ˜ ๋’ค์— ๊ด„ํ˜ธ๋กœ ๋‘˜๋Ÿฌ์‹ผ ์ธ์ž๋“ค์ด ์žˆ๋Š” ํ‘œํ˜„์‹์— ํ• ๋‹น ํ•˜๋ฉด, ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ธ์ž์™€ ๋“ฑํ˜ธ, ์˜ค๋ฅธ์ชฝ๊ฐ’๋“ฑ์„ ๋ชจ๋‘ ๋„ฃ์–ด update ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

์ฆ‰ greetStrings(0) = "Hello" ๋Š” greetStrings.update(0, "Hello") ๋กœ ๋ฐ”๋€๋‹ค.

ํ•˜์ง€๋งŒ ์œ„ ์ฝ”๋“œ๋Š” ๊ฐœ๋…์„ ๋ณด์—ฌ์ฃผ๋ ค๋Š” ์˜๋„๋กœ ์Šค์นผ๋ผ์—์„œ๋Š” ์ถ”์ฒœํ•˜์ง€ ์•Š๋Š” ์ฝ”๋“œ์ด๋ฉฐ ๋” ์ข‹์€ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

์Šค์นผ๋ผ์—์„œ๋Š” ํƒ€์ž… ์ถ”๋ก ์ด ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์•„๋ž˜์™€ ๊ฐ™์ด ๋ฐฐ์—ด์„ ๋งŒ๋“ค๊ณ  ์ดˆ๊ธฐํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค.

val numNames = Array("zero", "one", "two")

์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๊ฒƒ ์ฒ˜๋Ÿผ ์œ„ ์ฝ”๋“œ๋ฅผ ์ข€ ๋” ์žฅํ™ฉํ•˜๊ฒŒ ๋งŒ๋“ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

val numNames = Array.apply("zero", "one", "two")

3.2 8๋‹จ๊ณ„: ๋ฆฌ์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์ž

ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ๊ฐ€์žฅ ํฐ ์ฐฉ์•ˆ์  ํ•˜๋‚˜๋Š” ๋ฉ”์„œ๋“œ์— ๋ถ€์ˆ˜ํšจ๊ณผ๊ฐ€ ์—†์–ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ด๋‹ค.

๋ฉ”์„œ๋“œ์˜ ์œ ์ผํ•œ ๋™์ž‘์€ ๊ณ„์‚ฐ์„ ํ•ด์„œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ ๋ฟ์ด๋‹ค.

๋ฆฌ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค๊ณ  ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๋ฐฉ์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

val oneTwoThree = List(1, 2, 3)

๋ฆฌ์ŠคํŠธ์— ์›์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ด๋ฃจ์–ด์ง„๋‹ค.

val twoThree = List(2, 3)
val oneTwoThree = 1 :: twoThree

println(oneTwoThree)

์—ฐ์‚ฐ์ž ์ฝ˜์ฆˆ (:๐Ÿ˜ƒ ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฒ˜๋ฆฌํ•˜๋Š”๋ฐ ์ด๋Š” ์—ฐ์‚ฐ์ž ๊ฒฐํ•ฉ๋ฒ•์น™์— ์˜๊ฑฐํ•˜์—ฌ ์ดํ›„ 5.9 ์ ˆ์—์„œ ์„ค๋ช…ํ•œ๋‹ค.

์œ„ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

List(1, 2, 3)

๋นˆ ๋ฆฌ์ŠคํŠธ๋ฅผ Nil ๋กœ ์ค„์—ฌ ์“ธ ์ˆ˜ ์žˆ์–ด ์ด๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ดˆ๊ธฐํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค.

val oneTwoThree = 1 :: 2 :: 3 :: Nil

println(oneTwoThree)

๋ฆฌ์ŠคํŠธ์™€ ๋ฆฌ์ŠคํŠธ ๊ฐ„์„ ๋ถ™์ผ ๋•Œ๋Š” ::: ์„ ์‚ฌ์šฉํ•œ๋‹ค.

List("a", "b") ::: List("c", "d", "e")

3.3 9๋‹จ๊ณ„: ํŠœํ”Œ์„ ์‚ฌ์šฉํ•ด๋ณด์ž

ํŠœํ”Œ์€ ๋ฆฌ์ŠคํŠธ์™€ ๋‹ค๋ฅด๊ฒŒ ๋™์‹œ์— ๋ฌธ์ž์—ด๊ณผ ์ •์ˆ˜๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•˜๋‹ค.

ํŠœํ”Œ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

var pair = (99, "Luftballons")

println(pair._1)
println(pair._2)

ํŠœํ”Œ์„ ์ธ์Šคํ„ด์Šคํ™”ํ•˜๊ณ  ๋‚˜์„œ ๊ฐ ์›์†Œ์— ์ ‘๊ทผํ•˜๋ ค๋ฉด, ์  (.) ๊ณผ ๋ฐ‘์ค„ (_) ๋‹ค์Œ์— 1๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š” ์ธ๋ฑ์Šค๋ฅผ ๋„ฃ๋Š”๋‹ค. (0 ์ด ์•„๋‹Œ 1๋ถ€ํ„ฐ ์‹œ์ž‘)

99
Luftballons

ํŠœํ”Œ์˜ ์‹ค์ œ ํƒ€์ž…์€ ๋‚ด๋ถ€์— ๋“ค์–ด ์žˆ๋Š” ์›์†Œ์˜ ๊ฐฏ์ˆ˜์™€ ๊ฐ๊ฐ์˜ ํƒ€์ž…์— ๋”ฐ๋ผ ๋ฐ”๋€๋‹ค.

์œ„ ํŠœํ”Œ์€ Tuple2[Int, String] ์ด๋‹ค.

('u', 'r', "the", 1, 4, "me")

์œ„ ํŠœํ”Œ์˜ ํƒ€์ž…์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

Tuple6[Char, Char, String, Int, Int, String]

3.4 10๋‹จ๊ณ„: ์ง‘ํ•ฉ๊ณผ ๋งต์„ ์จ๋ณด์ž

์Šค์นผ๋ผ์˜ ๋ชฉ์ ์€ ํ•จ์ˆ˜ํ˜• ์Šคํƒ€์ผ๊ณผ ๋ช…๋ นํ˜• ์Šคํƒ€์ผ์˜ ์žฅ์ ์„ ๋ชจ๋‘ ์ทจํ• ์ˆ˜ ์žˆ๊ฒŒ ๋•๋Š”๊ฒƒ์ด๋‹ค.

์ด๋ฅผ ์œ„ํ•ด ์Šค์นผ๋ผ ์ปฌ๋ ‰์…˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ๋Š” ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ปฌ๋ ‰์…˜๊ณผ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•œ ์ปฌ๋ ‰์…˜์„ ๊ตฌ๋ถ„ํ•ด๋†“๋Š” ๊ณณ์ด ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋ฐฐ์—ด์€ ํ•ญ์ƒ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ๋ฆฌ์ŠคํŠธ๋Š” ํ•ญ์ƒ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.
ํ•˜์ง€๋งŒ ์ง‘ํ•ฉ ํ˜น์€ ๋งต์€ ๋ณ€๊ฒฝํ•œ ๊ฒƒ๊ณผ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅ ๊ฒƒ์„ ๋ชจ๋‘ ์ œ๊ณตํ•œ๋‹ค.

์ด๋Š” ์Šค์นผ๋ผ์—์„œ๋Š” ํด๋ž˜์Šค ๊ณ„์ธต ์•ˆ์—์„œ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ์„ฑ์„ ๋ชจ๋ธ๋ง ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์Šค์นผ๋ผ์—์„œ ์ œ๊ณตํ•˜๋Š” ํŠธ๋ ˆ์ดํŠธ (trait) ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ™•์žฅ (extends) ํ•˜๊ฑฐ๋‚˜ ํ˜ผํ•ฉ (mixed) ํ•˜์—ฌ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

์Šค์นผ๋ผ ์ง‘ํ•ฉ์˜ ํด๋ž˜์Šค ๊ณ„์ธต๋„

์œ„ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•˜๊ฑฐ๋‚˜ ํ˜น์€ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•œ ํด๋ž˜์Šค๋ฅผ ์ž„ํฌํŠธ (import) ํ•˜์—ฌ ์‚ฌ์šฉํ•œ๋‹ค.

๋‹ค์Œ์€ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•œ ์ง‘ํ•ฉ์„ ์ƒ์„ฑ, ์ดˆ๊ธฐํ™”, ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

var jetSet = Set("Boeing", "Airbus")
jetSet += "Lear"
println("jetSet.contains("Cessna")

์œ„ ์ฝ”๋“œ์˜ Set ์€ scala.collection.immutable.Set ์˜ ๋™๋ฐ˜ ๊ฐ์ฒด์— ์žˆ๋Š” apply ๋ฅผ ํ˜ธ์ถœ ํ•˜์˜€๋‹ค.

๋งŒ์•ฝ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ง‘ํ•ฉ์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด scala.collection.mutable ์„ ์ž„ํฌํŠธ (import) ํ•˜๋ฉด ๋œ๋‹ค.

import scala.collection.mutable

val moiveSet = mutable.Set("Hitch", "Poltergeist")
movieSet += "Shrek"
println(movieSet)

movieSet += "Sherk" ๋Œ€์‹ ์— moiveSet.+=("Shrek") ์ด๋ผ๊ณ  ์“ธ ์ˆ˜ ์žˆ๋‹ค.

๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ๋งต์€ ์œ„์™€ ์œ ์‚ฌํ•˜๊ฒŒ ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

import scala.collection.mutable

val treasureMap = mutable.Map[Int, String]()

treasureMap += (1 -> "Go to island.")
treasureMap += (2 -> "Find big X on ground")
treasureMap += (3 -> "Dig.")

println(treasureMap(2))
Find big X on ground.

๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•œ ๋งต์„ ์ƒ์„ฑ, ์ดˆ๊ธฐํ™”, ์‚ฌ์šฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

val romanNumeral = Map(
  1 -> "I", 2 -> "II", 3 -> "III", 4 -> "IV", 5 -> "V"
)
println(romanNumeral)

์Šค์นผ๋ผ๊ฐ€ -> ๋ฅผ ๋ชจ๋“  ๊ฐ์ฒด์— ์ ์šฉ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์ด์œ ๋Š”
์Šค์นผ๋ผ์˜ ๋‹ค์–‘ํ•œ ๋งค์ปค๋‹ˆ์ฆ˜ ์ค‘ ํ•˜๋‚˜์ธ ์•”์‹œ์  ๋ณ€ํ™˜ (implicit conversion) ์ด ์ผ์–ด๋‚˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. (21์žฅ)

๊ธฐ๋ณธ์ ์œผ๋กœ ์ปฌ๋ž™์…˜ ํด๋ž˜์Šค๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•œ ํด๋ž˜์Šค๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ ๊ฐ™์Œ

3.5 11๋‹จ๊ณ„: ํ•จ์ˆ˜ํ˜• ์Šคํƒ€์ผ์„ ์ธ์‹ํ•˜๋Š” ๋ฒ•์„ ๋ฐฐ์šฐ์ž

ํ•จ์ˆ˜ํ˜• ์Šคํƒ€์ผ์˜ ์‚ฌ์šฉ์„ ๊ถŒ์žฅ ํ•˜๋Š”๋ฐ, ์ฝ”๋“œ์ƒ์—์„œ var ๋Œ€์‹ ์— val ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํ•˜๋„๋ก ๋…ธ๋ ฅํ•˜์ž.

์ด๋Š” ๋”๋”์šฑ ์ฝ”๋“œ๋ฅผ ํ•จ์ˆ˜์ ์œผ๋กœ ๋™์ž‘ ์‹œํ‚ค๋„๋ก ๋งŒ๋“ค์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ๋ถ€์ˆ˜ํšจ๊ณผ๋ฅผ ์—†์• ๋„๋ก ์œ ๋„ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋ถ€์ˆ˜ํšจ๊ณผ๊ฐ€ ์ ˆ๋Œ€์ ์œผ๋กœ ๋‚˜์œ๊ฑด ์•„๋‹ˆ์ง€๋งŒ ์ตœ๋Œ€ํ•œ ์ง€์–‘ํ•˜๋„๋ก ํ•˜์ž

3.6 12๋‹จ๊ณ„: ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ ์ค„ ๋‹จ์œ„๋กœ ์ฝ์ž

์–ด๋–ค ํŒŒ์ผ์˜ ๋ชจ๋“  ์ค„์˜ ๋ฌธ์ž ๊ฐœ์ˆ˜๋ฅผ ์ค„์„ ์ž˜ ๋งž์ถฐ ์ถœ๋ ฅํ•˜๊ธฐ

import scala.io.Source

def widthOfLength(s: String) = s.length.toString.length

if (arg.length > 0) {
  val lines = Source.formFile(args(0)).getLines().toList
   
  val longestLine = lines.reduceLeft(
    (a, b) => if (a.length > a.length) a else b
   )

  val maxWidth = widthOfLength(longestLine)

  for (line <- lines) {
    val numSpaces = maxWidth - widthOfLength(line)
    val padding = " " * numSpaces
    println(padding + line.length + " | " + line)
  }
} else
  Console.err.println("Please enter filename")

3.7 ๊ฒฐ๋ก 

์Šค์นผ๋ผ ์Šคํฌ๋ฆฝํŠธ ์‚ฌ์šฉ ์ค€๋น„๋Š” ๋๋‚ฌ๊ณ , ๊ฐ ์ฃผ์ œ์— ๋Œ€ํ•ด ๋” ์ƒ์„ธํ•˜๊ฒŒ ์•Œ์•„๋ณธ๋‹ค.

Chapter 04 ํด๋ž˜์Šค์™€ ๊ฐ์ฒด

2์žฅ๊ณผ 3์žฅ์—์„œ ์Šค์นผ๋ผ์˜ ํด๋ž˜์Šค์™€ ๊ฐ์ฒด์— ๋Œ€ํ•œ ๊ธฐ๋ณธ์ ์ธ ์‚ฌํ•ญ์€ ์‚ดํŽด๋ณด์•˜๋‹ค.

์ด ์žฅ์—์„œ๋Š” ๋‹ค์Œ ๋‚ด์šฉ๋“ค์„ ์‚ดํŽด๋ณธ๋‹ค.

  • ํด๋ž˜์Šค (class)
  • ํ•„๋“œ (field)
  • ๋ฉ”์„œ๋“œ (method)
  • ์„ธ๋ฏธ์ฝœ๋ก  ์ถ”๋ก  (semicolon interface)

๋˜ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•œ ์‹ฑ๊ธ€ํ†ค์„ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ• ์ง€ ์‚ดํŽด๋ณธ๋‹ค.

์ž๋ฐ”์™€ ๋น„์Šทํ•œ ๊ฐœ๋…์ด์ง€๋งŒ ์™„์ „ํžˆ ๊ฐ™์ง€๋Š” ์•Š๋‹ค.

4.1 ํด๋ž˜์Šค, ํ•„๋“œ, ๋ฉ”์„œ๋“œ

ํด๋ž˜์Šค๋Š” ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ฒญ์‚ฌ์ง„์ด๋‹ค.

ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๊ณ  ๋‚˜๋ฉด new ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

class ChecksumAccumulator {
  // ์—ฌ๊ธฐ ํด๋ž˜์Šค์˜ ์ •์˜๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค.
}

ํด๋ž˜์Šค ์•ˆ์—๋Š” ๋ณ€์ˆ˜์™€ ๋ฉ”์„œ๋“œ๋ฅผ ๋„ฃ์„์ˆ˜ ์žˆ์œผ๋ฉฐ ์ด๋ฅผ ๋ฉค๋ฒ„ (member) ๋ผ๊ณ  ํ•œ๋‹ค.

์ดํ›„ ChecksumAccumulator ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•  ์ˆ˜ ์žˆ๋‹ค.

new ChecksumAccumulator

ํด๋ž˜์Šค๋ฅผ ์ธ์Šคํ„ด์Šคํ™” (instanciate) ํ•  ๋•Œ, ์Šค์นผ๋ผ ๋Ÿฐํƒ€์ž„์€ ํ•ด๋‹น ๊ฐ์ฒด์˜ ์ƒํƒœ (๊ฐ ๋ณ€์ˆ˜์˜ ๋‚ด์šฉ) ๋ฅผ ๋‹ด์„ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ™•๋ณดํ•œ๋‹ค.
๊ฐ ํด๋ž˜์Šค๋ฅผ ์—ฌ๋Ÿฌ ๋ณ€์ˆ˜์— ์ธ์Šคํ„ด์Šคํ™” ํ•˜๋ฉด ๊ทธ ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ ์ธ์Šคํ„ด์Šค ๊ฐ์ฒด๋Š” ํ”„๋กœ๊ทธ๋žจ ์ง„ํ–‰์— ๋”ฐ๋ผ ๋ณ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ฐ์ฒด์˜ ๊ฐ•๊ฑด์„ฑ (robustness) ๋ฅผ ์ถ”๊ตฌํ•˜๋Š” ํ•œ ๊ฐ€์ง€ ์ค‘์š”ํ•œ ๋ฐฉ๋ฒ•์€ ๊ฐ์ฒด์˜ ์ƒํƒœ (์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜ ๊ฐ’ ์ „์ฒด) ๋ฅผ ํ•ด๋‹น ์ธ์Šคํ„ด์Šค๊ฐ€ ์‚ด์•„ ์žˆ๋Š” ๋™์•ˆ ํ•ญ์ƒ ๋ฐ”๋ฅด๊ฒŒ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์ด๋Š” ํด๋ž˜์Šค ๋‚ด๋ถ€ ํ•„๋“œ๋ฅผ ๋น„๊ณต๊ฐœ (private) ๋กœ ๋งŒ๋“ค์–ด์„œ ์™ธ๋ถ€์—์„œ ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋„๋ก ํ•˜๋Š” ๊ฒƒ ์ด๋‹ค.
๋น„๊ณต๊ฐœ ํ•„๋“œ๋Š” ๊ฐ™์€ ํด๋ž˜์Šค ์•ˆ์— ์ •์˜ํ•œ ํ•จ์ˆ˜์—์„œ๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ํด๋ž˜์Šค ๋‚ด๋ถ€๋กœ ํ•œ์ •ํ•˜๋Š” ํšจ๊ณผ๊ฐ€ ์žˆ๋‹ค.

์Šค์นผ๋ผ ๋ฉ”์„œ๋“œ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” val (immutable: ๋ถˆ๋ณ€) ์ด๋ผ๋Š” ์  ์ด๋‹ค.

์Šค์นผ๋ผ ํŒŒ๋ฆฌ๋ฏธํ„ฐ๊ฐ€ val ์ธ ์ด์œ ๋Š” val ์ด ๋ถ„์„ํ•˜๊ธฐ ๋” ์‰ฝ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
val ์˜ ๊ฒฝ์šฐ ๋ถ„์„์„ ์œ„ํ•ด ๋‚˜์ค‘์— ์žฌํ• ๋‹นํ•ด์„œ ๊ฐ’์ด ๋ฐ”๋€Œ๋Š”์ง€ ์‚ดํŽด๋ณผ ํ•„์š”๊ฐ€ ์žˆ๋‹ค.

๋ฐ˜๋ฉด์— var ์€ ์ถ”์ ํ•ด์•ผ ํ•œ๋‹ค.

๋ถ€์ˆ˜ํšจ๊ณผ๋งŒ์„ ์œ„ํ•ด ์‹คํ–‰๋˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ”„๋กœ์‹œ์ € (procedure) ๋ผ๊ณ  ํ•œ๋‹ค.

4.2 ์„ธ๋ฏธ์ฝœ๋ก  ์ถ”๋ก 

์•„๋ž˜์™€ ๊ฐ™์ด ํ•œ์ค„์— ์—ฌ๋Ÿฌ๋ฌธ์žฅ์„ ๋„ฃ์œผ๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ผญ ์ค‘๊ฐ„์— ์„ธ๋ฏธ์ฝœ๋ก ์„ ๋„ฃ์–ด์•ผ ํ•œ๋‹ค.

val s = "hello"; println(s)

4.3 ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด

์Šค์นผ๋ผ๋Š” ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด๋ฅผ ์ง€์›ํ•œ๋‹ค.

class ๋ผ๋Š” ํ‚ค์›Œ๋“œ ๋Œ€์‹  object ๋ผ๋Š” ํ‚ค์›Œ๋“œ๋กœ ์‹œ์ž‘ํ•œ๋‹ค.

import scala.collection.mutable

object ChecksumAccumulator {
  private val cache = mutable.Map.empty[String, Int]

  def calculate(s: String): Int = 
    if (cache.contains(s)) 
      cache(s)
    else {
      val acc = new ChecksumAccumulator
      for (c <- s)
        acc.add(c.toByte)
      val cs = acc.checksum()
      cache += (s -> cs)
      cs
    }
}

์–ด๋–ค ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด์˜ ์ด๋ฆ„์ด ์–ด๋–ค ํด๋ž˜์Šค์™€ ๊ฐ™์„ ๋•Œ, ๊ทธ ๊ฐ์ฒด๋ฅผ ํด๋ž˜์Šค์˜ ๋™๋ฐ˜๊ฐ์ฒด (companion object) ๋ผ๊ณ  ํ•œ๋‹ค.

ํด๋ž˜์Šค์™€ ๋™๋ฐ˜ ๊ฐ์ฒด๋Š” ๋ฐ˜๋“œ์‹œ ๊ฐ™์€ ์†Œ์ŠคํŒŒ์ผ ์•ˆ์— ์ •์˜ํ•ด์•ผ ํ•œ๋‹ค.

์ž๋ฐ”์™€ ๊ฐ™์ด ํด๋ž˜์Šค๋‚˜ ๊ฐ์ฒด๋ฅผ ํŒŒ์ผ ์ด๋ฆ„๊ณผ ๋™์ผํ•˜๊ฒŒ ๊ตฌ์„ฑํ•˜์ง€ ์•Š์•„๋„ ๋˜์ง€๋งŒ ๊ฐœ๋ฐœ์˜ ํŽธ์˜์„ฑ์„ ์œ„ํ•ด์„œ ํŒŒ์ผ๋ณ€๊ณผ ํด๋ž˜์Šค๋ช…์„ ๋™์ผํ•˜๊ฒŒ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•œ๋‹ค.

๋™๋ฐ˜ ํด๋ž˜์Šค๊ฐ€ ์—†๋Š” ์‹ฑ๊ธ€ํ†ค ํด๋ž˜์Šค๋ฅผ ๋…๋ฆฝ๊ฐ์ฒด (standalone object) ๋ผ๊ณ  ํ•œ๋‹ค.

4.4 ์Šค์นผ๋ผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜

์Šค์นผ๋ผ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๋ ค๋ฉด Array[String] ์„ ์œ ์ผํ•œ ์ธ์ž๋กœ ๋ฐ›๊ณ  Unit ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” main ์ด๋ผ๋Š” ๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ๊ฐ€์ง„ ๋…๋ฆฝ ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด ์ด๋ฆ„์„ ์•Œ์•„์•ผ ํ•œ๋‹ค.

์œ„ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” main ๋ฉ”์„œ๋“œ๋งŒ ์žˆ์œผ๋ฉด ์–ด๋–ค ๋…๋ฆฝ ๊ฐ์ฒด๋“  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์‹œ์ž‘์ ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

import ChecksumAccumulator.calculate

object Summer {
  def main(args: Array[String]) {
    for (arg <- args)
      println(args + ": " + calculate(arg))
  }
}

์Šค์นผ๋ผ๋Š” ํ•ญ์ƒ java.lang ๊ณผ scala ํŒจํ‚ค์ง€์˜ ์— ๋ฒ„๋ฅผ ์•”์‹œ์ ์œผ๋กœ ์ž„ํฌํŠธ ํ•œ๋‹ค.

4.5 App ํŠธ๋ ˆ์ดํŠธ

์Šค์นผ๋ผ๋Š” ํƒ€์ดํ•‘ ์ˆ˜๊ณ ๋ฅผ ๋œ ์ˆ˜ ์ž‡๋Š” scala.App ์ด๋ผ๋Š” ํŠธ๋ ˆ์ดํŠธ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

ํŠธ๋ ˆ์ดํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์ •์˜ํ•  ์‹ฑ๊ธ€ํ†ค ๋’ค์— extends App ์ด๋ผ๊ณ  ์จ์•ผ ํ•œ๋‹ค.
๊ทธ ํ›„, main ๋ฉ”์„œ๋“œ๋ฅผ ์ ์€ ๋Œ€์‹  main ๋ฉ”์„œ๋“œ์— ๋„ฃ๊ณ  ์‹ถ์€ ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด๋ฅผ ์ค‘๊ด„ํ˜ธ ์‚ฌ์ด (๋ฐ”๋””) ์— ๋„ฃ๋Š”๋‹ค.

import ChecksumAccumulator.calculate

object FallWinterSpringSummer extends App {
  for (season <- List("fall", "winter", "spring"))
    println(season + ": " + calculate(season))
}

์ด๋•Œ args ๋ผ๋Š” ๋ฌธ์ž์—ด์˜ ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ช…๋ นํ–‰ ์ธ์ž์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

4.5 ๊ฒฐ๋ก 

์Šค์นผ๋ผ์˜ ๊ธฐ๋ณธ์ ์ธ ์‚ฌํ•ญ์„ ์•Œ์•„๋ดค๋‹ค.

๋‹ค์Œ์žฅ์—์„œ๋Š” ์Šค์นผ๋ผ์˜ ๊ธฐ๋ณธํƒ€์ž…๊ณผ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์šธ๊ฒƒ์ด๋‹ค.

Chapter 05 ๊ธฐ๋ณธ ํƒ€์ž…๊ณผ ์—ฐ์‚ฐ

์Šค์นผ๋ผ๋Š” ์•”์‹œ์  ๋ณ€ํ™˜ (implicit conversion) ์„ ํ†ตํ•ด ์ž๋ฐ”๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์—ฐ์‚ฐ ์™ธ์˜ ์—ฌ๋Ÿฌ ์—ฐ์‚ฐ์„ ์ถ”๊ฐ€๋กœ ์ œ๊ณตํ•จ์œผ๋กœ์จ ๊ธฐ๋ณธํƒ€์ž…์ด ์–ผ๋งˆ๋‚˜ ํ’๋ถ€ํ•ด์งˆ ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

5.1 ๊ธฐ๋ณธ ํƒ€์ž…

  • ์ •์ˆ˜ํ˜• ํƒ€์ž… (intergral type) : Byte, Short, Int, Long, Char
  • ์ˆ˜ ํƒ€์ž… (numeric type) : Float, Double

5.2 ๋ฆฌํ„ฐ๋Ÿด

์Šค์นผ๋ผ์˜ ๋ชจ๋“  ํƒ€์ž…์€ ๋ฆฌํ„ฐ๋Ÿด (literal) ๋กœ ์ ์„์ˆ˜ ์žˆ๋‹ค.

๋ฆฌํ„ฐ๋Ÿด
์ƒ์ˆซ๊ฐ’์„ ์ฝ”๋“œ์— ์ง์ ‘ ์ ๋Š” ๋ฐฉ๋ฒ•

์ •์ˆ˜ ๋ฆฌํ„ฐ๋Ÿด

val hex = 0x5
// Int = 5

val hex2 = 0x00FF
// Int = 255

val magic = 0xcafebebe
// Int = -889275714

๋ถ€๋™์†Œ์ˆ˜์  ๋ฆฌํ„ฐ๋Ÿด

val big = 1.2345
// Double = 1.2345

val bigger = 1.2345e1
// Double = 12.345

val biggerStill 123E45
// Double = 1.23E47

๋ฌธ์ž ๋ฆฌํ„ฐ๋Ÿด

val a = 'A'
// Char = A

val d = '\u0041'
// Char = A

๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด

val hello = "Hello"
// String = Hello
println("""Welcome to Ultamix 3000
           Type "HELP" for help.""")

์œ„ ์ฝ”๋“œ์˜ ๊ฒฐ๊ณผ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

Welcome to Ultamix 3000
           Type "HELP" for help.

์ด๋Š” ๋‘๋ฒˆ์งธ ์ค„์— ๊ณต๋ฐฑ์ด ๋“ค์–ด๊ฐ”๊ธฐ ๋•Œ๋ฌธ์ธ๋ฐ, ์ด ๋ฌธ์ œํ•ด๊ฒฐ์„ ์œ„ํ•ด์„œ๋Š” stripMargin ๋ฌธ์ž์—ด์— ๋Œ€ํ•ด ํ˜ธ์ถœํ•˜์—ฌ ์ฒ˜๋ฆฌํ•œ๋‹ค.

println("""|Welcome to Ultamix 3000
           |Type "HELP" for help.""".stripMargin)

์ด์ œ ์ฝ”๋“œ๊ฐ€ ์›ํ•˜๋Š” ๋Œ€๋กœ ๋™์ž‘ํ•œ๋‹ค.

Welcome to Ultamix 3000
Type "HELP" for help.

์‹ฌ๋ณผ ๋ฆฌํ„ฐ๋Ÿด

val s = 'aSymbol
// Symbol = 'aSymbol

๋ถˆ๋ฆฌ์–ธ ๋ฆฌํ„ฐ๋Ÿด

val bool = true
// Boolean = true

val full = false
// Boolean = false

5.3 ๋ฌธ์ž์—ด ์ธํ„ฐํด๋ ˆ์ด์…˜

์Šค์นผ๋ผ๋Š” ์ธํ„ฐํด๋ ˆ์ด์…˜ (interpolation) ์„ ์œ„ํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ํฌํ•จํ•œ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” s ์™€ f ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

s"The answer is ${6 * 7}."
// The answer is 42

f ๋ฌด์ž์—ด ์ดํ„ฐํด๋ ˆ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‚ด์žฅ๋œ ํ‘œํ˜„์‹์— ๋Œ€ํ•ด printlnf ์Šคํƒ€์ผ์˜ ํ˜•์‹์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

val pi = "Pi"

f"$pi is approximately ${math.Pi}.8f."
// String = Pi is approximately 3.14159265

5.4 ์—ฐ์‚ฐ์ž๋Š” ๋ฉ”์„œ๋“œ๋‹ค

์Šค์นผ๋ผ๋Š” ๊ธฐ๋ณธํƒ€์ž…์— ๋Œ€ํ•ด ํ’๋ถ€ํ•œ ์—ฐ์‚ฐ์ž๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

๋ชจ๋“  ๋ฉ”์„œ๋“œ๋Š” ์—ฐ์‚ฐ์ž๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค.

1๊ฐœ์˜ ์ธ์ž๋ฅผ ๋ฐ›๋Š” ๋ฉ”์„œ๋“œ์ธ ๊ฒฝ์šฐ ์•„๋ž˜์™€ ๊ฐ™์ด ์ถ•์•ฝํ•œ ํ‘œํ˜„์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
๋‹ค์Œ์€ ๊ฐ™์€ ํ‘œํ˜„์˜ ์ฝ”๋“œ์ด๋‹ค.

val s = "Hello, world!"

s.indexOf('o')

or 

s indexOf 'o'

// Int = 4

-2.0

or

(2.0).unary_-

// Double = -2.0
val s = "Hello, world!"

s.toLowerCase()

or 

s toLowerCase

// String = hello, world!

5.5 ์‚ฐ์ˆ ์—ฐ์‚ฐ

๋ชจ๋“  ์ˆ˜ ํƒ€์ž…์— ๋”ํ•˜๊ธฐ (+), ๋นผ๊ธฐ (-), ๊ณฑํ•˜๊ธฐ (*), ๋‚˜๋ˆ„๊ธฐ (/), ๋‚˜๋จธ์ง€ (%) ๋ฅผ ์ค‘์œ„ ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•ด ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค.

5.6 ๊ด€๊ณ„ ์—ฐ์‚ฐ๊ณผ ๋…ผ๋ฆฌ์—ฐ์‚ฐ

์ˆ˜ ํƒ€์ž…์„ ํฌ๋‹ค (>), ์ž‘๋‹ค (<), ํฌ๊ฑฐ๋‚˜ ๊ฐ™๋‹ค (>=), ์ž‘๊ฑฐ๋‚˜ ๊ฐ™๋‹ค (<=) ๋ผ๋Š” ๊ด€๊ณ„ ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•ด ๋น„๊ต ๊ฐ€๋Šฅํ•˜๋ฉฐ ๊ทธ ๊ฒฐ๊ณผ๋Š” Boolean ๊ฐ’์œผ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๋…ผ๋ฆฌ ์—ฐ์‚ฐ์œผ๋กœ๋Š” ๋…ผ๋ฆฌ๊ณฑ (&&, &), ๋…ผ๋ฆฌํ•ฉ (||, |) ์ด ์žˆ๋‹ค.
๊ฐ๊ฐ์€ ๋‘ Boolean ํ”ผ ์—ฐ์‚ฐ์ž๋ฅผ ์ทจํ•˜๋ฉฐ Boolean ๊ฒฐ๊ด๊ฐ’์„ ๋‚ด๋†“๋Š”๋‹ค.

์Šค์นผ๋ผ์—์„œ && ์™€ || ์—ฐ์‚ฐ์€ ์ž๋ฐ”์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์‡ผํŠธ ์„œํ‚ท (short circuit: ํšŒ๋กœ) ์—ฐ์‚ฐ์ด๋‹ค.

5.7 ๋น„ํŠธ ์—ฐ์‚ฐ

  • ๋น„ํŠธ๊ณฑ (&)
  • ๋น„ํŠธํ•ฉ (|)
  • ๋น„ํŠธ ๋ฐฐํƒ€ํ•ฉ (^)
  • ๋‹จํ•ญ ๋น„ํŠธ ๋ฐ˜์ „ ์—ฐ์‚ฐ์ž (~)

5.8 ๊ฐ์ฒด ๋™์ผ์„ฑ

๋‘ ๊ฐ์ฒด๊ฐ€ ๊ฐ™์€์ง€ ๋น„๊ตํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด == ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ  ๊ฐ™์ง€ ์•Š์€์ง€ ๋น„๊ตํ•˜๋ ค๋ฉด != ์„ ์‚ฌ์šฉํ•œ๋‹ค.

5.9 ์—ฐ์‚ฐ์ž ์šฐ์„ ์ˆœ์œ„์™€ ๊ฒฐํ•ฉ ๋ฒ•์น™

ํ‘œํ˜„์‹์—์„œ ์–ด๋Š ๋ถ€๋ถ„์„ ์šฐ์„ ์ ์œผ๋กœ ์‹คํ–‰ํ• ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ๊ฒฐํ•ฉ๋ฒ•์น™์„ ๋”ฐ๋ฅธ๋‹ค (๊ณฑํ•˜๊ธฐ / ๋‚˜๋ˆ„๊ธฐ > ๋”ํ•˜๊ธฐ / ๋นผ๊ธฐ)

5.10 ํ’๋ถ€ํ•œ ๋ž˜ํผ

์•”์‹œ์  ๋ณ€ํ™˜์— ๋”ฐ๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ ์Šค์นผ๋ผ API ๋ฅผ ํ†ตํ•ด ํ™•์ธ ๊ฐ€๋Šฅํ•˜๋‹ค.

5.11 ๊ฒฐ๋ก 

์ด๋ฒˆ์žฅ์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์‚ฌํ•ญ์€ ์Šค์นผ๋ผ์—์„œ๋Š” ์—ฐ์‚ฐ์ž๊ฐ€ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์ด๋ผ๋Š” ์‚ฌ์‹ค, ์Šค์นผ๋ผ ๊ธฐ๋ณธํƒ€์ž…์— ๋” ์œ ์šฉํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•ด์ฃผ๋Š” ํ’๋ถ€ํ•œ ๋ ˆํผ ํด๋ž˜์Šค๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์•”์‹œ์  ๋ณ€ํ™˜์ด ์กด์žฌํ•œ๋‹ค๋Š” ์ ์ด๋‹ค.