Alert

์ด ๊ธ€์€ Claude Code์˜ ๋„์›€์„ ๋ฐ›์•„ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค

TL;DR

  • Go ํ•จ์ˆ˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž…๊ณผ ๋ฐ˜ํ™˜ ํƒ€์ž…์„ ๋ฐ˜๋“œ์‹œ ๋ช…์‹œํ•ด์•ผ ํ•˜๋ฉฐ, ์„ ํƒ์  ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์—†์Œ
  • ... ๋ฌธ๋ฒ•์œผ๋กœ ๊ฐ€๋ณ€ ์ธ์ž๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ณ , Python์˜ *args์— ๋Œ€์‘
  • ๋‹ค์ค‘ ๋ฐ˜ํ™˜๊ฐ’์ด ๊ธฐ๋ณธ์ด๋ฉฐ, result, err ํŒจํ„ด์ด Go ์—๋Ÿฌ ์ฒ˜๋ฆฌ์˜ ํ•ต์‹ฌ ๊ด€์šฉ๊ตฌ
  • ํ•จ์ˆ˜๋Š” first-class citizen์ด๋ผ ๋ณ€์ˆ˜์— ๋‹ด๊ฑฐ๋‚˜ ์ธ์ž๋กœ ์ „๋‹ฌ ๊ฐ€๋Šฅํ•˜๊ณ , ํด๋กœ์ €๋„ ์ง€์›
  • defer๋Š” ์ž์› ์ •๋ฆฌ๋ฅผ ํ•จ์ˆ˜ ๋๊นŒ์ง€ ๋ฏธ๋ฃจ๋ฉฐ, ํ›„์ž…์„ ์ถœ(LIFO)๋กœ ์‹คํ–‰๋˜๊ณ  ์ธ์ž๋Š” ๋“ฑ๋ก ์‹œ์ ์— ํ‰๊ฐ€๋จ
  • Go๋Š” ๊ฐ’์— ์˜ํ•œ ํ˜ธ์ถœ(call by value)์ด๋ผ ๊ตฌ์กฐ์ฒด๋Š” ๋ณต์‚ฌ๋˜์ง€๋งŒ, ๋งตยท์Šฌ๋ผ์ด์Šค๋Š” ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•ด ์ˆ˜์ •์ด ๋ฐ˜์˜๋จ

1. ๊ธฐ๋ณธ ํ•จ์ˆ˜ ์„ ์–ธ

Go์˜ ํ•จ์ˆ˜ ์„ ์–ธ์€ func ํ‚ค์›Œ๋“œ๋กœ ์‹œ์ž‘ํ•œ๋‹ค. Python๊ณผ ๋‹ฌ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž…๊ณผ ๋ฐ˜ํ™˜ ํƒ€์ž…์„ ๋ฐ˜๋“œ์‹œ ๋ช…์‹œํ•ด์•ผ ํ•œ๋‹ค.

func add(a int, b int) int {
    return a + b
}

Python์ด๋ผ๋ฉด ์ด๋ ‡๊ฒŒ ์“ด๋‹ค.

def add(a, b):
    return a + b

์ฐจ์ด์ ์„ ์ •๋ฆฌํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • ํƒ€์ž… ๋ช…์‹œ ํ•„์ˆ˜ : Go๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž…(int)๊ณผ ๋ฐ˜ํ™˜ ํƒ€์ž…(int)์„ ์ƒ๋žตํ•  ์ˆ˜ ์—†๋‹ค. Python์˜ ํƒ€์ž… ํžŒํŠธ(a: int)๋Š” ์„ ํƒ์ด์ง€๋งŒ Go์—์„œ๋Š” ๊ฐ•์ œ๋‹ค.
  • ๊ฐ™์€ ํƒ€์ž… ์ถ•์•ฝ : ์—ฐ์†๋œ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ๊ฐ™์€ ํƒ€์ž…์ด๋ฉด func add(a, b int) int์ฒ˜๋Ÿผ ๋งˆ์ง€๋ง‰์— ํ•œ ๋ฒˆ๋งŒ ์ ์„ ์ˆ˜ ์žˆ๋‹ค.
  • ์„ ํƒ์  ํŒŒ๋ผ๋ฏธํ„ฐ ์—†์Œ : Python์€ def add(a, b=0):์ฒ˜๋Ÿผ ๊ธฐ๋ณธ๊ฐ’์„ ์ค„ ์ˆ˜ ์žˆ์ง€๋งŒ, Go๋Š” ๋ชจ๋“  ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ํ•„์ˆ˜๋‹ค. ์„ ํƒ์  ์„ค์ •์ด ํ•„์š”ํ•˜๋ฉด ๊ตฌ์กฐ์ฒด๋ฅผ ์“ฐ๋Š” ํŒจํ„ด์ด ์ผ๋ฐ˜์ ์ด๋‹ค.
  • ์ค‘๊ด„ํ˜ธ ์œ„์น˜ : ์—ฌ๋Š” ์ค‘๊ด„ํ˜ธ {๋Š” ๋ฐ˜๋“œ์‹œ func ์„ ์–ธ๊ณผ ๊ฐ™์€ ์ค„์— ์žˆ์–ด์•ผ ํ•œ๋‹ค. ๋‹ค์Œ ์ค„๋กœ ๋‚ด๋ฆฌ๋ฉด ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋‚œ๋‹ค.

2. ๊ฐ€๋ณ€ ์ž…๋ ฅ ํŒŒ๋ผ๋ฏธํ„ฐ

์ธ์ž ๊ฐœ์ˆ˜๊ฐ€ ์œ ๋™์ ์ผ ๋•Œ ... ๋ฌธ๋ฒ•์„ ์“ด๋‹ค. Python์˜ *args์— ๋Œ€์‘ํ•˜๋Š” ๊ฐœ๋…์ด๋‹ค.

func addTo(base int, vals ...int) []int {
    out := make([]int, 0, len(vals))
    for _, v := range vals {
        out = append(out, base+v)
    }
    return out
}

ํ˜ธ์ถœํ•  ๋•Œ๋Š” ์ธ์ž๋ฅผ ๋‚˜์—ดํ•˜๊ฑฐ๋‚˜, ์Šฌ๋ผ์ด์Šค๋ฅผ ํŽผ์ณ์„œ ๋„˜๊ธธ ์ˆ˜ ์žˆ๋‹ค.

addTo(3, 2, 4, 6)       // [5, 7, 9]
 
a := []int{4, 3}
addTo(3, a...)           // ์Šฌ๋ผ์ด์Šค ํŽผ์น˜๊ธฐ โ†’ [7, 6]

Python์œผ๋กœ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋ฉด ์ด๋ ‡๋‹ค.

def add_to(base, *vals):
    return [base + v for v in vals]
 
add_to(3, 2, 4, 6)      # [5, 7, 9]
 
a = [4, 3]
add_to(3, *a)            # ๋ฆฌ์ŠคํŠธ ์–ธํŒจํ‚น โ†’ [7, 6]

**kwargs๋Š” ์—†๋‹ค

Python์˜ **kwargs(ํ‚ค์›Œ๋“œ ๊ฐ€๋ณ€ ์ธ์ž)์— ๋Œ€์‘ํ•˜๋Š” Go ๋ฌธ๋ฒ•์€ ์—†๋‹ค. ์ด๋ฆ„ ๋ถ™์€ ์„ ํƒ์  ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ํ•„์š”ํ•˜๋ฉด ๊ตฌ์กฐ์ฒด๋ฅผ ์ •์˜ํ•ด์„œ ๋„˜๊ธฐ๋Š” ํŒจํ„ด์„ ์“ด๋‹ค. ์ด ๋ถ€๋ถ„์€ ๊ตฌ์กฐ์ฒด ํŽธ์—์„œ ๋‹ค๋ฃฌ๋‹ค.


3. ๋‹ค์ค‘ ๋ฐ˜ํ™˜๊ฐ’

Go ํ•จ์ˆ˜์˜ ๊ฐ€์žฅ ํฐ ํŠน์ง• ์ค‘ ํ•˜๋‚˜๋‹ค. ์—ฌ๋Ÿฌ ๊ฐ’์„ ๋™์‹œ์— ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๊ณ , ์ด๋ฅผ ํ†ตํ•ด ์—๋Ÿฌ ์ฒ˜๋ฆฌ ํŒจํ„ด์ด ๋งŒ๋“ค์–ด์ง„๋‹ค.

func divAndRemainder(num, den int) (int, int, error) {
    if den == 0 {
        return 0, 0, errors.New("cannot divide by zero")
    }
    return num / den, num % den, nil
}
 
result, remainder, err := divAndRemainder(5, 2)
// result=2, remainder=1, err=nil

Python์—์„œ ๋น„์Šทํ•œ ์ฝ”๋“œ๋ฅผ ์“ฐ๋ฉด ์ด๋ ‡๋‹ค.

def div_and_remainder(num, den):
    if den == 0:
        raise ValueError("cannot divide by zero")
    return num // den, num % den
 
result, remainder = div_and_remainder(5, 2)
 
# ๋˜๋Š” ํŠœํ”Œ๋กœ ํ•œ ๋ฒˆ์— ๋ฐ›๊ธฐ
result = divmod(5, 2)   # (2, 1)

ํ•ต์‹ฌ์ ์ธ ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค.

  • ๊ฐœ๋ณ„ ๋ณ€์ˆ˜๋กœ ๋ฐ›์•„์•ผ ํ•จ : Python์€ result = divmod(5, 2)์ฒ˜๋Ÿผ ํŠœํ”Œ ํ•˜๋‚˜๋กœ ๋ฌถ์–ด ๋ฐ›์„ ์ˆ˜ ์žˆ์ง€๋งŒ, Go๋Š” ๋ฐ˜ํ™˜๊ฐ’ ๊ฐœ์ˆ˜๋งŒํผ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•ด์•ผ ํ•œ๋‹ค.
  • ์•ˆ ์“ฐ๋Š” ๊ฐ’์€ _๋กœ ๋ฌด์‹œ : ๋ฐ˜ํ™˜๊ฐ’ ์ค‘ ํ•„์š” ์—†๋Š” ๊ฒƒ์ด ์žˆ์œผ๋ฉด _์— ํ• ๋‹นํ•œ๋‹ค. Python๋„ ๊ฐ™์€ ๊ด€๋ก€๋ฅผ ์“ด๋‹ค.
result, _, err := divAndRemainder(5, 2)   // remainder ๋ฌด์‹œ
  • result, err ํŒจํ„ด : Go๋Š” ์˜ˆ์™ธ(exception) ๋Œ€์‹  ์—๋Ÿฌ๋ฅผ ๋ฐ˜ํ™˜๊ฐ’์œผ๋กœ ๋Œ๋ ค์ฃผ๋Š” ๋ฐฉ์‹์„ ์“ด๋‹ค. ๋งˆ์ง€๋ง‰ ๋ฐ˜ํ™˜๊ฐ’์„ error ํƒ€์ž…์œผ๋กœ ๋‘๊ณ , ํ˜ธ์ถœ ์ธก์—์„œ err != nil์„ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด Go์˜ ๊ธฐ๋ณธ ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๊ด€์šฉ๊ตฌ๋‹ค.
result, remainder, err := divAndRemainder(5, 0)
if err != nil {
    fmt.Println(err)    // "cannot divide by zero"
    return
}

์—๋Ÿฌ ์ฒ˜๋ฆฌ๋Š” ๋ณ„๋„ ํŽธ์—์„œ

Go์˜ ์—๋Ÿฌ ์ฒ˜๋ฆฌ(error ์ธํ„ฐํŽ˜์ด์Šค, errors.New, fmt.Errorf, ๋ž˜ํ•‘ ๋“ฑ)๋Š” ๋‚ด์šฉ์ด ๋งŽ์•„ ๋ณ„๋„ ๊ธ€์—์„œ ๋‹ค๋ฃฌ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” โ€œ๋งˆ์ง€๋ง‰ ๋ฐ˜ํ™˜๊ฐ’์œผ๋กœ ์—๋Ÿฌ๋ฅผ ๋Œ๋ ค์ค€๋‹คโ€๋Š” ํŒจํ„ด๋งŒ ๊ธฐ์–ตํ•˜๋ฉด ๋œ๋‹ค.


4. ํ•จ์ˆ˜๋Š” ๊ฐ’์ด๋‹ค (first-class function)

Go์—์„œ ํ•จ์ˆ˜๋Š” first-class citizen(์ผ๊ธ‰ ๊ฐ์ฒด)์ด๋‹ค. ์–ด๋–ค ๊ฐ’์ด first-class๋ผ๋Š” ๊ฑด ๋‹ค์Œ์„ ๋ชจ๋‘ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋œป์ด๋‹ค.

  • ๋ณ€์ˆ˜์— ๋‹ด์„ ์ˆ˜ ์žˆ๋‹ค
  • ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๋„˜๊ธธ ์ˆ˜ ์žˆ๋‹ค
  • ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜๊ฐ’์œผ๋กœ ์“ธ ์ˆ˜ ์žˆ๋‹ค
  • ์Šฌ๋ผ์ด์Šค๋‚˜ ๋งต ๊ฐ™์€ ์ž๋ฃŒ๊ตฌ์กฐ์— ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค

ํ•จ์ˆ˜๊ฐ€ ์ด ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋ฉด โ€œ๊ทธ ์–ธ์–ด๋Š” ํ•จ์ˆ˜๋ฅผ first-class๋กœ ์ทจ๊ธ‰ํ•œ๋‹คโ€๊ณ  ๋งํ•˜๊ณ , ์ด๋Ÿฐ ํ•จ์ˆ˜๋ฅผ first-class function์ด๋ผ ๋ถ€๋ฅธ๋‹ค. Go์™€ Python ๋ชจ๋‘ ์—ฌ๊ธฐ์— ํ•ด๋‹นํ•œ๋‹ค. ๋ฐ˜๋ฉด C๋Š” ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋กœ ๋น„์Šทํ•˜๊ฒŒ ํ‰๋‚ด ๋‚ผ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ์ต๋ช… ํ•จ์ˆ˜๋‚˜ ํด๋กœ์ €๊ฐ€ ์—†์–ด์„œ ํ•จ์ˆ˜๋ฅผ ์™„์ „ํ•œ first-class๋กœ ๋ณด๊ธฐ๋Š” ์–ด๋ ต๋‹ค.

ํ—ท๊ฐˆ๋ฆฌ๋Š” ์šฉ์–ด ์ •๋ฆฌ

ํ•จ์ˆ˜๋ฅผ ๊ฐ’์œผ๋กœ ๋‹ค๋ฃจ๋Š” ์ด์•ผ๊ธฐ์—๋Š” ๋น„์Šทํ•ด ๋ณด์ด๋Š” ์šฉ์–ด๊ฐ€ ์—ฌ๋Ÿฟ ๋‚˜์˜จ๋‹ค. ๊ด€๊ณ„๋ฅผ ์ •๋ฆฌํ•˜๋ฉด ์ด๋ ‡๋‹ค.

์šฉ์–ด๋ฌด์—‡์„ ๊ฐ€๋ฆฌํ‚ค๋‚˜
first-class functionํ•จ์ˆ˜๋ฅผ ๊ฐ’์ฒ˜๋Ÿผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋‹ค๋Š” ์–ธ์–ด์˜ ์„ฑ์งˆ. ์•„๋ž˜ ๊ฐœ๋…๋“ค์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” ํ† ๋Œ€
function value๋ณ€์ˆ˜์— ๋‹ด๊ฑฐ๋‚˜ ์ „๋‹ฌ๋˜๋Š” ๊ฐ’์œผ๋กœ์„œ์˜ ํ•จ์ˆ˜. Go ๊ณต์‹ ๋ฌธ์„œ์—์„œ ์“ฐ๋Š” ํ‘œํ˜„
higher-order function(๊ณ ์ฐจ ํ•จ์ˆ˜)ํ•จ์ˆ˜๋ฅผ ์ธ์ž๋กœ ๋ฐ›๊ฑฐ๋‚˜ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜
anonymous function(์ต๋ช… ํ•จ์ˆ˜)์ด๋ฆ„ ์—†์ด ์ฆ‰์„์—์„œ ์ •์˜ํ•œ ํ•จ์ˆ˜. Go์˜ func(){...}, Python์˜ lambda
closure(ํด๋กœ์ €)์ต๋ช… ํ•จ์ˆ˜๊ฐ€ ๋ฐ”๊นฅ ์Šค์ฝ”ํ”„ ๋ณ€์ˆ˜๋ฅผ ์บก์ฒ˜ํ•œ ๊ฒƒ

ํ•ต์‹ฌ์€ first-class function์ด โ€œ์„ฑ์งˆโ€์ด๊ณ , ๋‚˜๋จธ์ง€๋Š” ๊ทธ ์„ฑ์งˆ ์œ„์—์„œ ๋งŒ๋“ค์–ด์ง€๋Š” ํ™œ์šฉ ํŒจํ„ด์ด๋ผ๋Š” ์ ์ด๋‹ค. ์ต๋ช… ํ•จ์ˆ˜์™€ ํด๋กœ์ €๋Š” ๊ฐ™์ด ๋“ฑ์žฅํ•  ๋•Œ๊ฐ€ ๋งŽ์ง€๋งŒ ์—„๋ฐ€ํžˆ๋Š” ๋‹ค๋ฅด๋‹ค. ์ต๋ช… ํ•จ์ˆ˜๊ฐ€ ๋ฐ”๊นฅ ๋ณ€์ˆ˜๋ฅผ ๋ถ™์žก์ง€ ์•Š์œผ๋ฉด ํด๋กœ์ €๊ฐ€ ์•„๋‹ˆ๋‹ค.

๋‘˜์€ ์„œ๋กœ ๋‹ค๋ฅธ ์ถ•์œผ๋กœ ๋ณด๋ฉด ๊น”๋”ํ•˜๋‹ค. ์ต๋ช… ํ•จ์ˆ˜๋Š” โ€œ์ด๋ฆ„์ด ์žˆ๋ƒ ์—†๋ƒโ€(ํ˜•ํƒœ)์˜ ๋ฌธ์ œ๊ณ , ํด๋กœ์ €๋Š” โ€œ๋ฐ”๊นฅ ๋ณ€์ˆ˜๋ฅผ ์บก์ฒ˜ํ–ˆ๋ƒโ€(๋™์ž‘)์˜ ๋ฌธ์ œ๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋ก ์ ์œผ๋กœ๋Š” ์ด๋ฆ„ ์žˆ๋Š” ํ•จ์ˆ˜๋„ ๋ฐ”๊นฅ ๋ณ€์ˆ˜๋ฅผ ์บก์ฒ˜ํ•˜๋ฉด ํด๋กœ์ €๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค(Python์˜ nonlocal์ด ๊ทธ ์˜ˆ๋‹ค). ๋‹ค๋งŒ Go๋Š” ํ•จ์ˆ˜ ์•ˆ์—์„œ ์ด๋ฆ„ ์žˆ๋Š” ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์—†์–ด์„œ, Go์˜ ํด๋กœ์ €๋Š” ์‚ฌ์‹ค์ƒ ํ•ญ์ƒ ์ต๋ช… ํ•จ์ˆ˜๋‹ค.

// ๋ณ€์ˆ˜์— ํ•จ์ˆ˜ ํ• ๋‹น
add := func(a, b int) int { return a + b }
fmt.Println(add(3, 4))   // 7

Python์ด๋ผ๋ฉด lambda๋ฅผ ์“ฐ๊ฑฐ๋‚˜, ์ผ๋ฐ˜ ํ•จ์ˆ˜๋ฅผ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•œ๋‹ค.

add = lambda a, b: a + b
print(add(3, 4))   # 7

ํ•จ์ˆ˜๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๋Š” ์˜ˆ์‹œ๋„ ๋ณด์ž.

func apply(a, b int, op func(int, int) int) int {
    return op(a, b)
}
 
result := apply(3, 4, func(a, b int) int {
    return a + b
})
// result=7
def apply(a, b, op):
    return op(a, b)
 
result = apply(3, 4, lambda a, b: a + b)
# result=7

Go์—์„œ ํ•จ์ˆ˜ ํƒ€์ž… ์‹œ๊ทธ๋‹ˆ์ฒ˜(func(int, int) int)๋ฅผ ๋งค๋ฒˆ ์“ฐ๋Š” ๊ฒƒ์ด ๋ฒˆ๊ฑฐ๋กœ์šฐ๋ฉด type์œผ๋กœ ๋ณ„์นญ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

type mathFunc func(int, int) int
 
func apply(a, b int, op mathFunc) int {
    return op(a, b)
}

์œ„ apply๋Š” ์„ค๋ช…์šฉ ์˜ˆ์‹œ์ง€๋งŒ, ํ•จ์ˆ˜๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ธฐ๋Š” ํŒจํ„ด์€ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์ž์ฃผ ๋งŒ๋‚œ๋‹ค. ๋Œ€ํ‘œ์ ์ธ ๊ฒƒ์ด sort.Slice๋‹ค. ์ •๋ ฌ ๊ธฐ์ค€์„ ํ•จ์ˆ˜๋กœ ๋ฐ›์•„์„œ, โ€œ๋‘ ์›์†Œ ์ค‘ ์–ด๋А ์ชฝ์ด ์•ž์— ์™€์•ผ ํ•˜๋Š”๊ฐ€โ€๋ฅผ ํ˜ธ์ถœ ์ธก์ด ๊ฒฐ์ •ํ•˜๊ฒŒ ํ•œ๋‹ค.

type Person struct {
    Name string
    Age  int
}
 
people := []Person{
    {Name: "Alice", Age: 30},
    {Name: "Bob", Age: 25},
    {Name: "Carol", Age: 35},
}
 
// ๋‚˜์ด ์˜ค๋ฆ„์ฐจ์ˆœ ์ •๋ ฌ โ€” ๋น„๊ต ํ•จ์ˆ˜๋ฅผ ์ธ์ž๋กœ ์ „๋‹ฌ
sort.Slice(people, func(i, j int) bool {
    return people[i].Age < people[j].Age
})

Python์—์„œ sort์˜ key ์ธ์ž์— ํ•จ์ˆ˜๋ฅผ ๋„˜๊ธฐ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ฐœ์ƒ์ด๋‹ค.

people.sort(key=lambda p: p.age)

์ด ์˜ˆ์‹œ๋Š” ์‚ฌ์‹ค ํด๋กœ์ €๋‹ค

sort.Slice์— ๋„˜๊ธด ์ต๋ช… ํ•จ์ˆ˜๋Š” ๋ฐ”๊นฅ์˜ people ๋ณ€์ˆ˜๋ฅผ ์บก์ฒ˜ํ•˜๊ณ  ์žˆ๋‹ค. ์ฆ‰ ๋‹จ์ˆœํžˆ ํ•จ์ˆ˜๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ธด ๊ฒƒ์„ ๋„˜์–ด, ๋ฐ”๊นฅ ๋ณ€์ˆ˜๋ฅผ ๋ถ™์žก์€ ํด๋กœ์ €๋ฅผ ๋„˜๊ธด ๊ฒƒ์ด๋‹ค. ์‹ค๋ฌด์—์„œ ํ•จ์ˆ˜๋ฅผ ์ธ์ž๋กœ ๋„˜๊ธธ ๋•Œ๋Š” ์ด๋ ‡๊ฒŒ ํด๋กœ์ €์ธ ๊ฒฝ์šฐ๊ฐ€ ๋Œ€๋ถ€๋ถ„์ด๋‹ค. ํด๋กœ์ € ์ž์ฒด๋Š” ๋ฐ”๋กœ ๋‹ค์Œ ์„น์…˜์—์„œ ๋‹ค๋ฃฌ๋‹ค.


5. ํด๋กœ์ €

ํด๋กœ์ €๋Š” ํ•จ์ˆ˜๊ฐ€ ์ž์‹ ์ด ์„ ์–ธ๋œ ๋ฐ”๊นฅ ์Šค์ฝ”ํ”„์˜ ๋ณ€์ˆ˜๋ฅผ ์บก์ฒ˜ํ•ด์„œ ์œ ์ง€ํ•œ๋‹ค. Go์™€ Python ๋ชจ๋‘ ํด๋กœ์ €๋ฅผ ์ง€์›ํ•œ๋‹ค.

func makeCounter() func() int {
    count := 0
    return func() int {
        count++
        return count
    }
}
 
counter := makeCounter()
fmt.Println(counter())   // 1
fmt.Println(counter())   // 2
fmt.Println(counter())   // 3

Python ๋ฒ„์ „์€ ์ด๋ ‡๋‹ค.

def make_counter():
    count = 0
    def counter():
        nonlocal count
        count += 1
        return count
    return counter
 
counter = make_counter()
print(counter())   # 1
print(counter())   # 2
print(counter())   # 3
  • Go๋Š” ๋ฐ”๊นฅ ๋ณ€์ˆ˜๋ฅผ ์ž๋™์œผ๋กœ ์บก์ฒ˜ํ•œ๋‹ค. Python์ฒ˜๋Ÿผ nonlocal ๊ฐ™์€ ํ‚ค์›Œ๋“œ๊ฐ€ ํ•„์š” ์—†๋‹ค.
  • makeCounter()๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ๋…๋ฆฝ์ ์ธ count๊ฐ€ ์ƒ๊ธฐ๋ฏ€๋กœ, ์นด์šดํ„ฐ ์ธ์Šคํ„ด์Šค๋ผ๋ฆฌ ์ƒํƒœ๊ฐ€ ์„ž์ด์ง€ ์•Š๋Š”๋‹ค.

5-1. ์™œ ํด๋กœ์ €๋ฅผ ์“ฐ๋Š”๊ฐ€ โ€” ๋ฒ”์œ„๋ฅผ ์ขํžŒ๋‹ค

ํด๋กœ์ €์˜ ํšจ์šฉ์ด ์ž˜ ์™€๋‹ฟ์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค. ๊ฐ€์žฅ ์‹ค์šฉ์ ์ธ ์ด์œ  ํ•˜๋‚˜๋Š” ํ•จ์ˆ˜์˜ ๋ฒ”์œ„๋ฅผ ์ขํžˆ๋Š” ๊ฒƒ์ด๋‹ค.

Go ํ•จ์ˆ˜๋Š” ๋ณดํ†ต ํŒจํ‚ค์ง€ ๋ ˆ๋ฒจ(ํŒŒ์ผ ์ตœ์ƒ์œ„)์— ์„ ์–ธํ•œ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์–ด๋–ค ํ—ฌํผ ํ•จ์ˆ˜๊ฐ€ ๋”ฑ ํ•œ ํ•จ์ˆ˜ ์•ˆ์—์„œ๋งŒ ์“ฐ์ธ๋‹ค๋ฉด, ๊ตณ์ด ํŒจํ‚ค์ง€ ๋ ˆ๋ฒจ์— ๋‘˜ ์ด์œ ๊ฐ€ ์—†๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด process ์•ˆ์—์„œ๋งŒ ์“ฐ๋Š” double์ด ์žˆ๋‹ค๊ณ  ํ•˜์ž.

// ๋ฐฉ๋ฒ• 1: ํŒจํ‚ค์ง€ ๋ ˆ๋ฒจ์— ์„ ์–ธ โ€” ํŒจํ‚ค์ง€ ์ „์ฒด์— ๋…ธ์ถœ๋จ
func double(x int) int {
    return x * 2
}
 
func process(nums []int) []int {
    out := make([]int, 0, len(nums))
    for _, n := range nums {
        out = append(out, double(n))
    }
    return out
}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด double์ด ๊ฐ™์€ ํŒจํ‚ค์ง€์˜ ๋‹ค๋ฅธ ํ•จ์ˆ˜, ๋‹ค๋ฅธ ํŒŒ์ผ์—์„œ๋„ ์ „๋ถ€ ๋ณด์ธ๋‹ค. ์‹ค์ œ๋กœ๋Š” process์—์„œ๋งŒ ์“ฐ๋Š”๋ฐ๋„ ํŒจํ‚ค์ง€ ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ฅผ ์ฐจ์ง€ํ•œ๋‹ค. ๋‚ด๋ถ€ ํ•จ์ˆ˜๋กœ ๊ฐ€๋‘๋ฉด ํ˜ธ์ถœ ๋ฒ”์œ„๊ฐ€ process ์•ˆ์œผ๋กœ ์ œํ•œ๋œ๋‹ค.

// ๋ฐฉ๋ฒ• 2: process ์•ˆ์— ๊ฐ€๋‘  โ€” ๋ฐ”๊นฅ์—์„œ๋Š” ์กด์žฌ์กฐ์ฐจ ๋ชจ๋ฆ„
func process(nums []int) []int {
    double := func(x int) int {
        return x * 2
    }
 
    out := make([]int, 0, len(nums))
    for _, n := range nums {
        out = append(out, double(n))
    }
    return out
}

์ด๊ฒŒ ์™œ ์ด๋“์ธ์ง€๋Š” 02ํŽธ์—์„œ ๋‹ค๋ฃฌ ๋‚ด์šฉ๊ณผ ์—ฐ๊ฒฐ๋œ๋‹ค.

  • ํŒจํ‚ค์ง€ ๋ ˆ๋ฒจ ์„ ์–ธ ์ˆ˜๊ฐ€ ์ค„์–ด๋“ ๋‹ค : Go ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ํŒจํ‚ค์ง€ ๋ ˆ๋ฒจ์˜ ๋ฏธ์‚ฌ์šฉ ํ•จ์ˆ˜/๋ณ€์ˆ˜๋ฅผ ์—๋Ÿฌ๋กœ ์žก์•„์ฃผ์ง€ ์•Š๋Š”๋‹ค. ํŒจํ‚ค์ง€ ๋ ˆ๋ฒจ์— ์ด๋ฆ„์ด ๋งŽ์„์ˆ˜๋ก โ€œ์ด๊ฑฐ ์•„์ง ์“ฐ๋‚˜?โ€๋ฅผ ํŒ๋‹จํ•˜๊ธฐ ์–ด๋ ค์›Œ์ง€๋Š”๋ฐ, ํ•œ ๊ณณ์—์„œ๋งŒ ์“ฐ๋Š” ํ—ฌํผ๋ฅผ ํ•จ์ˆ˜ ์•ˆ์œผ๋กœ ๋„ฃ์œผ๋ฉด ๊ทธ๋งŒํผ ํŒจํ‚ค์ง€ ๋ ˆ๋ฒจ์ด ๊น”๋”ํ•ด์ง„๋‹ค.
  • ์•ˆ ์“ฐ๋Š” ์ด๋ฆ„์„ ์ฐพ๊ธฐ ์‰ฌ์›Œ์ง„๋‹ค : ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ์ง€์—ญ ๋ณ€์ˆ˜๋‚˜ ๋‚ด๋ถ€ ํ•จ์ˆ˜๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋‚œ๋‹ค. ์ฆ‰ ๋‚ด๋ถ€๋กœ ๊ฐ€๋‘๋ฉด โ€œ์•ˆ ์“ฐ๋Š” ์ฝ”๋“œโ€๊ฐ€ ์ž๋™์œผ๋กœ ๋“œ๋Ÿฌ๋‚œ๋‹ค.

๋ฐฉ๊ธˆ ์˜ˆ์‹œ๋Š” ์—„๋ฐ€ํžˆ๋Š” ํด๋กœ์ €๊ฐ€ ์•„๋‹ˆ๋‹ค

double์€ ๋ฐ”๊นฅ ๋ณ€์ˆ˜๋ฅผ ์บก์ฒ˜ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ •ํ™•ํžˆ๋Š” ์ต๋ช… ํ•จ์ˆ˜์ผ ๋ฟ์ด๋‹ค(์„น์…˜ 4์˜ ์šฉ์–ด ์ •๋ฆฌ ์ฐธ๊ณ ). ๋‹ค๋งŒ ๋‚ด๋ถ€ ํ•จ์ˆ˜๊ฐ€ ๋ฐ”๊นฅ์˜ ์ง€์—ญ ๋ณ€์ˆ˜๊นŒ์ง€ ์บก์ฒ˜ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„์„œ, ์‹ค๋ฌด์—์„œ๋Š” ์ด ํŒจํ„ด์„ ๋ฌถ์–ด์„œ ํด๋กœ์ €๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. ์บก์ฒ˜๊นŒ์ง€ ํ•˜๋ฉด ํ—ฌํผ์— ๋งค๋ฒˆ ์ธ์ž๋ฅผ ๋„˜๊ธฐ์ง€ ์•Š์•„๋„ ๋˜๋Š” ์ด์ ์ด ์ถ”๊ฐ€๋œ๋‹ค.

func process(nums []int, factor int) []int {
    // factor๋ฅผ ์บก์ฒ˜ โ€” ์ธ์ž๋กœ ์•ˆ ๋„˜๊ฒจ๋„ ๋จ
    multiply := func(x int) int { return x * factor }
    out := make([]int, 0, len(nums))
    for _, n := range nums {
        out = append(out, multiply(n))
    }
    return out
}

ํด๋กœ์ €์˜ ์‹ค์ „ ์šฉ๋„

ํด๋กœ์ €๋Š” ๋ฏธ๋“ค์›จ์–ด, ํŒฉํ† ๋ฆฌ ํ•จ์ˆ˜, ์ง€์—ฐ ์‹คํ–‰ ๋“ฑ์—์„œ ์ž์ฃผ ์“ฐ์ธ๋‹ค. ํŠนํžˆ Go์˜ HTTP ํ•ธ๋“ค๋Ÿฌ์—์„œ ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•  ๋•Œ ํด๋กœ์ € ํŒจํ„ด์ด ์ผ๋ฐ˜์ ์ด๋‹ค.


6. defer

defer๋Š” ํ•จ์ˆ˜ ํ˜ธ์ถœ์„ ๊ทธ ํ•จ์ˆ˜๊ฐ€ ๋๋‚  ๋•Œ๊นŒ์ง€ ๋ฏธ๋ค„๋‘๋Š” ํ‚ค์›Œ๋“œ๋‹ค. ์ฃผ๋กœ ์—ด์–ด๋‘” ์ž์›(ํŒŒ์ผ, ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ, ๋ฝ ๋“ฑ)์„ ์žŠ์ง€ ์•Š๊ณ  ์ •๋ฆฌํ•˜๋Š” ๋ฐ ์“ด๋‹ค. ์ •๋ฆฌ ์ฝ”๋“œ๋ฅผ ์ž์›์„ ์—ฐ ์ฝ”๋“œ ๋ฐ”๋กœ ์˜†์— ์ ์–ด๋‘˜ ์ˆ˜ ์žˆ์–ด์„œ, ํ•จ์ˆ˜๊ฐ€ ์–ด๋–ค ๊ฒฝ๋กœ๋กœ ๋๋‚˜๋“  ์ •๋ฆฌ๊ฐ€ ๋ณด์žฅ๋œ๋‹ค.

func readFile(name string) error {
    f, err := os.Open(name)
    if err != nil {
        return err
    }
    defer f.Close()   // ํ•จ์ˆ˜๊ฐ€ ๋๋‚  ๋•Œ ์‹คํ–‰๋จ โ€” ์—ฌ๊ธฐ์„œ ๋‹ซ๋Š” ๊ฑธ ์žŠ์„ ์ผ์ด ์—†๋‹ค
 
    // f๋ฅผ ๊ฐ€์ง€๊ณ  ์ž‘์—…...
    // ์ค‘๊ฐ„์— returnํ•ด๋„ f.Close()๋Š” ๋ฐ˜๋“œ์‹œ ์‹คํ–‰๋œ๋‹ค
 
    return nil
}

Python์˜ with๋ฌธ์ด๋‚˜ try/finally์™€ ๋ชฉ์ ์ด ๊ฐ™๋‹ค.

# Python โ€” with๋ฌธ์ด ๋ธ”๋ก์„ ๋ฒ—์–ด๋‚  ๋•Œ ์ž๋™์œผ๋กœ close
def read_file(name):
    with open(name) as f:
        # f๋ฅผ ๊ฐ€์ง€๊ณ  ์ž‘์—…...
        ...
    # ๋ธ”๋ก์„ ๋ฒ—์–ด๋‚˜๋ฉด ์ž๋™์œผ๋กœ ๋‹ซํž˜

์ฐจ์ด๊ฐ€ ์žˆ๋‹ค๋ฉด, Python์˜ with๋Š” ๋ธ”๋ก์„ ๋ฒ—์–ด๋‚  ๋•Œ ์ •๋ฆฌ๋˜๊ณ , Go์˜ defer๋Š” ํ•จ์ˆ˜๊ฐ€ ๋๋‚  ๋•Œ ์ •๋ฆฌ๋œ๋‹ค๋Š” ์ ์ด๋‹ค.

defer๋Š” ํด๋กœ์ € ์ „์šฉ ๊ธฐ๋Šฅ์ด ์•„๋‹ˆ๋‹ค

defer ๋’ค์—๋Š” ์•„๋ฌด ํ•จ์ˆ˜ ํ˜ธ์ถœ์ด๋‚˜ ์˜ฌ ์ˆ˜ ์žˆ๋‹ค. ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ(f.Close()), ์ผ๋ฐ˜ ํ•จ์ˆ˜ ํ˜ธ์ถœ(fmt.Println("done")), ์ต๋ช… ํ•จ์ˆ˜(func(){...}())๋ฅผ ๋ชจ๋‘ ๋ฏธ๋ฃฐ ์ˆ˜ ์žˆ๋‹ค. defer์˜ ๋ณธ์งˆ์€ โ€œ์ด ํ˜ธ์ถœ์„ ํ•จ์ˆ˜ ๋์œผ๋กœ ๋ฏธ๋ฃฌ๋‹คโ€๋Š” ์‹คํ–‰ ์‹œ์  ์ œ์–ด์ผ ๋ฟ, ํด๋กœ์ €์™€๋Š” ๋ณ„๊ฐœ์˜ ๊ธฐ๋Šฅ์ด๋‹ค.

defer f.Close()              // ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ โ€” ํด๋กœ์ € ์•„๋‹˜
defer fmt.Println("done")    // ์ผ๋ฐ˜ ํ•จ์ˆ˜ ํ˜ธ์ถœ โ€” ํด๋กœ์ € ์•„๋‹˜
defer func() { ... }()       // ์ต๋ช… ํ•จ์ˆ˜ โ€” ์บก์ฒ˜ํ•˜๋ฉด ํด๋กœ์ €

์ฑ…์—์„œ โ€œdefer๋Š” ์—ฌ๋Ÿฌ ํด๋กœ์ €๋ฅผ ์ง€์—ฐ์‹œํ‚จ๋‹คโ€๊ณ  ํ‘œํ˜„ํ•˜๋Š” ๊ฑด defer์˜ ์ •์˜๊ฐ€ ์•„๋‹ˆ๋ผ ์‹ค์ œ ์“ฐ์ž„์„ ๋ฐ˜์˜ํ•œ ๊ฒƒ์ด๋‹ค. ์ž์› ํ•˜๋‚˜ ๋‹ซ๋Š” ์ •๋„๋ฉด defer f.Close() ํ•œ ์ค„๋กœ ๋๋‚˜์ง€๋งŒ, ์•„๋ž˜ 6-3ยท6-4์—์„œ ๋ณผ โ€œ์‹คํ–‰ ์‹œ์ ์˜ ๋ณ€์ˆ˜ ์ฝ๊ธฐโ€๋‚˜ โ€œ๋ช…๋ช…๋œ ๋ฐ˜ํ™˜๊ฐ’ ์ˆ˜์ •โ€, recover ๊ฐ™์€ ์˜๋ฏธ ์žˆ๋Š” ์ •๋ฆฌ ์ž‘์—…์€ ์—ฌ๋Ÿฌ ์ค„์„ ์ต๋ช… ํ•จ์ˆ˜๋กœ ๋ฌถ๊ณ  ๋ฐ”๊นฅ ๋ณ€์ˆ˜๋ฅผ ์บก์ฒ˜ํ•˜๊ฒŒ ๋œ๋‹ค. ๊ทธ๊ฒŒ ๊ณง ํด๋กœ์ €๋‹ค. ์ฆ‰ defer๊ฐ€ ํด๋กœ์ €๋ฅผ ์š”๊ตฌํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, ์“ธ ๋งŒํ•œ defer๊ฐ€ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํด๋กœ์ € ํ˜•ํƒœ๊ฐ€ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

๋‘ ์ถ•์„ ๋ถ„๋ฆฌํ•ด์„œ ๋ณด๋ฉด ๊น”๋”ํ•˜๋‹ค. defer๋Š” โ€œ์–ธ์ œ ์‹คํ–‰ํ• ์ง€โ€(์‹คํ–‰ ์‹œ์  ์ œ์–ด), ํด๋กœ์ €๋Š” โ€œ๋ฌด์—‡์„ ๋“ค๊ณ  ์žˆ์„์ง€โ€(๋ณ€์ˆ˜ ์บก์ฒ˜) ๋ฅผ ๋‹ด๋‹นํ•œ๋‹ค. ์„œ๋กœ ์ง๊ตํ•˜๋Š” ๊ฐœ๋…์ด๊ณ , defer ์˜ˆ์‹œ์—์„œ ํด๋กœ์ €๊ฐ€ ์ž์ฃผ ๋ณด์ด๋Š” ๊ฑด ๋ณต์žกํ•œ ์ •๋ฆฌ๋ฅผ ์ต๋ช… ํ•จ์ˆ˜๋กœ ๋ฌถ๋‹ค ๋ณด๋‹ˆ ์บก์ฒ˜๊ฐ€ ๋”ฐ๋ผ์˜จ ๊ฒฐ๊ณผ์ผ ๋ฟ์ด๋‹ค.

6-1. ์‹คํ–‰ ์‹œ์  โ€” return ์ดํ›„์— ์‹คํ–‰๋œ๋‹ค

defer๋กœ ๋ฏธ๋ฃฌ ํ•จ์ˆ˜๋Š” ๋ฐ”๊นฅ ํ•จ์ˆ˜์˜ return์ด ๋ฐ˜ํ™˜๊ฐ’์„ ์ •ํ•œ ๋’ค, ํ˜ธ์ถœํ•œ ์ชฝ์œผ๋กœ ๋Œ์•„๊ฐ€๊ธฐ ์ง์ „์— ์‹คํ–‰๋œ๋‹ค. ์ฆ‰ return ๋ฌธ์žฅ ์ž์ฒด๋ณด๋‹ค ๋Šฆ๊ฒŒ ์‹คํ–‰๋œ๋‹ค.

func example() {
    fmt.Println("1. ํ•จ์ˆ˜ ์‹œ์ž‘")
    defer fmt.Println("3. defer ์‹คํ–‰ (๋งˆ์ง€๋ง‰)")
    fmt.Println("2. ํ•จ์ˆ˜ ๋ณธ๋ฌธ ๋")
}
// ์ถœ๋ ฅ:
// 1. ํ•จ์ˆ˜ ์‹œ์ž‘
// 2. ํ•จ์ˆ˜ ๋ณธ๋ฌธ ๋
// 3. defer ์‹คํ–‰ (๋งˆ์ง€๋ง‰)

6-2. ํ›„์ž…์„ ์ถœ(LIFO) โ€” ๋‚˜์ค‘์— ์“ด defer๊ฐ€ ๋จผ์ € ์‹คํ–‰๋œ๋‹ค

defer๋Š” ์—ฌ๋Ÿฌ ๋ฒˆ ์“ธ ์ˆ˜ ์žˆ๊ณ , ์Œ“์•„๋‘” ์ˆœ์„œ์˜ ์—ญ์ˆœ์œผ๋กœ ์‹คํ–‰๋œ๋‹ค. ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์— ๋“ฑ๋กํ•œ ๊ฒƒ์ด ๊ฐ€์žฅ ๋จผ์ € ์‹คํ–‰๋œ๋‹ค.

func main() {
    defer fmt.Println("first")
    defer fmt.Println("second")
    defer fmt.Println("third")
    fmt.Println("body")
}
// ์ถœ๋ ฅ:
// body
// third
// second
// first

์ด ์ˆœ์„œ๊ฐ€ ์ž์—ฐ์Šค๋Ÿฌ์šด ์ด์œ ๊ฐ€ ์žˆ๋‹ค. ๋ณดํ†ต ์ž์›์€ โ€œ๋จผ์ € ์—ฐ ๊ฒƒ์„ ๋‚˜์ค‘์— ๋‹ซ๋Š”โ€ ๊ฒŒ ๋งž๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํŒŒ์ผ์„ ์—ด๊ณ  ๊ทธ ์œ„์— ๋ฒ„ํผ๋ฅผ ์”Œ์› ๋‹ค๋ฉด, ๋ฒ„ํผ๋ฅผ ๋จผ์ € ๋‹ซ๊ณ  ํŒŒ์ผ์„ ๋‚˜์ค‘์— ๋‹ซ์•„์•ผ ํ•œ๋‹ค. LIFO ๋•๋ถ„์— ์—ฐ ์ˆœ์„œ๋Œ€๋กœ defer๋ฅผ ์ ๊ธฐ๋งŒ ํ•˜๋ฉด ๋‹ซ๋Š” ์ˆœ์„œ๊ฐ€ ์•Œ์•„์„œ ๋งž์ถฐ์ง„๋‹ค.

f, _ := os.Open("data.txt")
defer f.Close()          // ๋‚˜์ค‘์— ์‹คํ–‰ (2์ˆœ์œ„)
 
gz, _ := gzip.NewReader(f)
defer gz.Close()         // ๋จผ์ € ์‹คํ–‰ (1์ˆœ์œ„) โ€” ์—ฐ ์ˆœ์„œ์˜ ์—ญ์ˆœ์œผ๋กœ ๋‹ซํž˜

6-3. ์ธ์ž๋Š” defer๋ฅผ ๋งŒ๋‚˜๋Š” ์ˆœ๊ฐ„ ํ‰๊ฐ€๋œ๋‹ค

๊ฐ€์žฅ ํ—ท๊ฐˆ๋ฆฌ๋Š” ๋ถ€๋ถ„์ด๋‹ค. defer์— ๋„˜๊ธด ํ•จ์ˆ˜์˜ ์ธ์ž๋Š” defer ๋ฌธ์žฅ์„ ๋งŒ๋‚˜๋Š” ์‹œ์ ์— ์ฆ‰์‹œ ๊ณ„์‚ฐ๋˜๊ณ , ์‹ค์ œ ํ˜ธ์ถœ๋งŒ ๋ฏธ๋ค„์ง„๋‹ค.

func main() {
    i := 0
    defer fmt.Println("defer๊ฐ€ ๋ณธ i:", i)   // ์ด ์‹œ์ ์˜ i(0)๊ฐ€ ๋ฐ•์ œ๋จ
    i = 100
    fmt.Println("ํ˜„์žฌ i:", i)
}
// ์ถœ๋ ฅ:
// ํ˜„์žฌ i: 100
// defer๊ฐ€ ๋ณธ i: 0      โ† 100์ด ์•„๋‹ˆ๋ผ 0

i๊ฐ€ ๋‚˜์ค‘์— 100์œผ๋กœ ๋ฐ”๋€Œ์–ด๋„, defer๋Š” ๋“ฑ๋ก ์‹œ์ ์˜ ๊ฐ’ 0์„ ์ด๋ฏธ ๋ถ™์žก์•„ ๋‘์—ˆ๋‹ค. ์ธ์ž๊ฐ€ ์•„๋‹ˆ๋ผ ํด๋กœ์ €๋กœ ๊ฐ์‹ธ๋ฉด ๋™์ž‘์ด ๋‹ฌ๋ผ์ง„๋‹ค. ํด๋กœ์ € ์•ˆ์˜ i๋Š” ์‹คํ–‰ ์‹œ์ ์— ์ฝํžˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

func main() {
    i := 0
    defer func() {
        fmt.Println("defer๊ฐ€ ๋ณธ i:", i)   // ์‹คํ–‰ ์‹œ์ ์— i๋ฅผ ์ฝ์Œ
    }()
    i = 100
}
// ์ถœ๋ ฅ:
// defer๊ฐ€ ๋ณธ i: 100     โ† ํด๋กœ์ €๋ผ ์ตœ์‹  ๊ฐ’

์ธ์ž ํ‰๊ฐ€ vs ํด๋กœ์ € ์บก์ฒ˜

  • defer f(x) : x๋Š” ์ง€๊ธˆ ํ‰๊ฐ€๋˜์–ด ๊ณ ์ •๋œ๋‹ค
  • defer func(){ ... x ... }() : x๋Š” ๋‚˜์ค‘์—(์‹คํ–‰ ์‹œ์ ์—) ์ฝํžŒ๋‹ค ์ด ์ฐจ์ด๊ฐ€ defer์™€ ํด๋กœ์ €๊ฐ€ ๋งŒ๋‚˜๋Š” ์ง€์ ์ด๋‹ค. ๋‘˜ ์ค‘ ๋ฌด์—‡์„ ์›ํ•˜๋Š”์ง€ ์˜์‹ํ•˜๊ณ  ์จ์•ผ ํ•œ๋‹ค.

6-4. ๋ช…๋ช…๋œ ๋ฐ˜ํ™˜๊ฐ’ ์ˆ˜์ •

defer์— ๋„˜๊ธด ํด๋กœ์ €๋Š” ํ•จ์ˆ˜์˜ ๋ช…๋ช…๋œ ๋ฐ˜ํ™˜๊ฐ’(named return value) ์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค. ๋ฐ˜ํ™˜๊ฐ’์— ์ด๋ฆ„์„ ๋ถ™์ด๋ฉด, return์ด ๊ทธ ๋ณ€์ˆ˜์— ๊ฐ’์„ ๋„ฃ์€ ๋’ค defer๊ฐ€ ์‹คํ–‰๋˜๋ฏ€๋กœ, defer ์•ˆ์—์„œ ์ตœ์ข… ๋ฐ˜ํ™˜๊ฐ’์„ ์†๋ณผ ์ˆ˜ ์žˆ๋‹ค.

func double(x int) (result int) {   // ๋ฐ˜ํ™˜๊ฐ’์— result๋ผ๋Š” ์ด๋ฆ„์„ ์คŒ
    defer func() {
        result *= 2                 // return์ด ์ •ํ•œ result๋ฅผ ๋‘ ๋ฐฐ๋กœ
    }()
    result = x + 1
    return result                   // result์— x+1์„ ๋„ฃ๊ณ  โ†’ defer๊ฐ€ *2
}
 
fmt.Println(double(3))   // (3+1) * 2 = 8

์ด ํŒจํ„ด์€ ์ฃผ๋กœ ์—๋Ÿฌ๋ฅผ ๊ฐ€๊ณตํ•˜๊ฑฐ๋‚˜, panic์„ ๋ณต๊ตฌํ•ด์„œ ์—๋Ÿฌ๋กœ ๋ฐ”๊พธ๋Š” ๊ณณ(recover)์—์„œ ์“ฐ์ธ๋‹ค. ์—๋Ÿฌ ์ฒ˜๋ฆฌ ํŽธ์—์„œ ๋” ๋‹ค๋ฃฌ๋‹ค.

6-5. ์ฃผ์˜ โ€” ๋ฐ˜๋ณต๋ฌธ ์•ˆ์˜ defer

defer๋Š” ํ•จ์ˆ˜๊ฐ€ ๋๋‚  ๋•Œ ์‹คํ–‰๋˜์ง€, ๋ฐ˜๋ณต๋ฌธ ํ•œ ๋ฐ”ํ€ด๊ฐ€ ๋๋‚  ๋•Œ ์‹คํ–‰๋˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋‹ค. ๋ฃจํ”„ ์•ˆ์—์„œ ์ž์›์„ ์—ด๊ณ  defer๋กœ ๋‹ซ์œผ๋ฉด, ์ž์›์ด ๋ฃจํ”„ ๋‚ด๋‚ด ์Œ“์˜€๋‹ค๊ฐ€ ํ•จ์ˆ˜๊ฐ€ ๋๋‚˜๋Š” ์ˆœ๊ฐ„์—์•ผ ํ•œ๊บผ๋ฒˆ์— ๋‹ซํžŒ๋‹ค.

// ๋‚˜์œ ์˜ˆ โ€” ํŒŒ์ผ ํ•ธ๋“ค์ด ๋ฃจํ”„ ๋‚ด๋‚ด ์•ˆ ๋‹ซํžˆ๊ณ  ์Œ“์ธ๋‹ค
func processAll(names []string) error {
    for _, name := range names {
        f, err := os.Open(name)
        if err != nil {
            return err
        }
        defer f.Close()   // ํ•จ์ˆ˜๊ฐ€ ๋๋‚  ๋•Œ๊นŒ์ง€ ์•ˆ ๋‹ซํž˜ โ†’ ํ•ธ๋“ค ๋ˆ„์ˆ˜
        // ...
    }
    return nil
}

ํŒŒ์ผ ์ˆ˜๊ฐ€ ๋งŽ์œผ๋ฉด ํ•ธ๋“ค์ด ๊ณ ๊ฐˆ๋  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Ÿด ๋•Œ๋Š” ๋ฃจํ”„ ๋ณธ๋ฌธ์„ ๋ณ„๋„ ํ•จ์ˆ˜๋กœ ๋ถ„๋ฆฌํ•ด์„œ, ํ•œ ๋ฐ”ํ€ด๊ฐ€ ๊ณง ํ•œ ํ•จ์ˆ˜ ํ˜ธ์ถœ์ด ๋˜๊ฒŒ ๋งŒ๋“ ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋งค ๋ฐ˜๋ณต๋งˆ๋‹ค defer๊ฐ€ ์ œ๋•Œ ์‹คํ–‰๋œ๋‹ค.

// ์ข‹์€ ์˜ˆ โ€” ํ•œ ํŒŒ์ผ ์ฒ˜๋ฆฌ๋ฅผ ํ•จ์ˆ˜๋กœ ๋ถ„๋ฆฌ
func processAll(names []string) error {
    for _, name := range names {
        if err := processOne(name); err != nil {
            return err
        }
    }
    return nil
}
 
func processOne(name string) error {
    f, err := os.Open(name)
    if err != nil {
        return err
    }
    defer f.Close()   // processOne์ด ๋๋‚  ๋•Œ๋งˆ๋‹ค ๋‹ซํž˜
    // ...
    return nil
}

defer ํ•ต์‹ฌ ์ •๋ฆฌ

  • ์ž์› ์ •๋ฆฌ(ํŒŒ์ผ/์—ฐ๊ฒฐ/๋ฝ)๋ฅผ ์—ฐ ์ฝ”๋“œ ๋ฐ”๋กœ ์˜†์— ์ ์–ด๋‘๋Š” ์šฉ๋„
  • ์‹คํ–‰ ์‹œ์ : ํ•จ์ˆ˜์˜ return ์ดํ›„, ํ˜ธ์ถœ ์ธก์œผ๋กœ ๋Œ์•„๊ฐ€๊ธฐ ์ง์ „
  • ์—ฌ๋Ÿฌ ๊ฐœ๋ฉด ํ›„์ž…์„ ์ถœ(LIFO)๋กœ ์‹คํ–‰ โ€” ์—ฐ ์ˆœ์„œ๋Œ€๋กœ ์ ์œผ๋ฉด ๋‹ซ๋Š” ์ˆœ์„œ๊ฐ€ ์—ญ์ˆœ์œผ๋กœ ๋งž์ถฐ์ง
  • ์ธ์ž๋Š” ๋“ฑ๋ก ์‹œ์ ์— ํ‰๊ฐ€๋˜๊ณ , ํด๋กœ์ €๋กœ ๊ฐ์‹ธ๋ฉด ์‹คํ–‰ ์‹œ์ ์— ์ฝํž˜
  • ๋ช…๋ช…๋œ ๋ฐ˜ํ™˜๊ฐ’์„ defer ํด๋กœ์ €๋กœ ์ˆ˜์ • ๊ฐ€๋Šฅ
  • ๋ฐ˜๋ณต๋ฌธ ์•ˆ์—์„œ๋Š” ํ•จ์ˆ˜๋กœ ๋ถ„๋ฆฌํ•˜์ง€ ์•Š์œผ๋ฉด ์ž์›์ด ๋๊นŒ์ง€ ์Œ“์ž„

7. ๊ฐ’์— ์˜ํ•œ ํ˜ธ์ถœ (call by value)

Go๋Š” ํ•จ์ˆ˜์— ์ธ์ž๋ฅผ ๋„˜๊ธธ ๋•Œ ํ•ญ์ƒ ๊ฐ’์„ ๋ณต์‚ฌํ•œ๋‹ค. ์ด๊ฒƒ์„ ๊ฐ’์— ์˜ํ•œ ํ˜ธ์ถœ(call by value)์ด๋ผ๊ณ  ํ•œ๋‹ค. ํ•จ์ˆ˜๋Š” ์›๋ณธ์ด ์•„๋‹ˆ๋ผ ๋ณต์‚ฌ๋ณธ์„ ๋ฐ›์œผ๋ฏ€๋กœ, ํ•จ์ˆ˜ ์•ˆ์—์„œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์•„๋ฌด๋ฆฌ ์ˆ˜์ •ํ•ด๋„ ํ˜ธ์ถœ ์ธก์˜ ์›๋ณธ์€ ๊ทธ๋Œ€๋กœ๋‹ค.

๊ตฌ์กฐ์ฒด๋ฅผ ๋„˜๊ธฐ๋Š” ๊ฒฝ์šฐ๋ฅผ ๋ณด์ž.

type Point struct {
    X, Y int
}
 
func modify(p Point) {
    p.X = 100   // ๋ณต์‚ฌ๋ณธ์˜ ํ•„๋“œ๋ฅผ ๋ฐ”๊ฟˆ
}
 
func main() {
    pt := Point{1, 2}
    modify(pt)
    fmt.Println(pt)   // {1 2} โ€” ์›๋ณธ์€ ๊ทธ๋Œ€๋กœ
}

modify๋Š” pt์˜ ๋ณต์‚ฌ๋ณธ์„ ๋ฐ›์•˜๊ธฐ ๋•Œ๋ฌธ์—, p.X = 100์€ ๋ณต์‚ฌ๋ณธ๋งŒ ๋ฐ”๊พธ๊ณ  ๋๋‚œ๋‹ค.

7-1. ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐ๋กœ ๋„˜๊ธฐ๋Š” ์–ธ์–ด์™€์˜ ์ฐจ์ด

Python์ด๋‚˜ Java๋Š” ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•œ๋‹ค. ๊ฐ์ฒด๋ฅผ ๋„˜๊ธฐ๋ฉด ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ฐธ์กฐ๊ฐ€ ์ „๋‹ฌ๋˜๋ฏ€๋กœ, ํ•จ์ˆ˜ ์•ˆ์—์„œ ๊ฐ์ฒด์˜ ์†์„ฑ์„ ๋ฐ”๊พธ๋ฉด ํ˜ธ์ถœ ์ธก์—๋„ ๋ฐ˜์˜๋œ๋‹ค.

# Python โ€” ๊ฐ์ฒด๋Š” ์ฐธ์กฐ๋กœ ๊ณต์œ ๋œ๋‹ค
class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y
 
def modify(p):
    p.x = 100   # ์‹ค์ œ ๊ฐ์ฒด์˜ ์†์„ฑ์„ ๋ฐ”๊ฟˆ
 
pt = Point(1, 2)
modify(pt)
print(pt.x)   # 100 โ€” ์›๋ณธ์ด ๋ฐ”๋€๋‹ค!

๊ฐ™์€ ์ฝ”๋“œ๋ฅผ Go์™€ Python์—์„œ ๋Œ๋ฆฌ๋ฉด ๊ฒฐ๊ณผ๊ฐ€ ์ •๋ฐ˜๋Œ€๋‹ค. Python ๊ฐœ๋ฐœ์ž๊ฐ€ Go๋กœ ๋„˜์–ด์˜ฌ ๋•Œ ๊ฐ€์žฅ ์ž์ฃผ ํ—ท๊ฐˆ๋ฆฌ๋Š” ์ง€์ ์ด๋‹ค.

  • Go: ๊ตฌ์กฐ์ฒด๋Š” ํ†ต์งธ๋กœ ๋ณต์‚ฌ๋œ๋‹ค โ†’ ํ•จ์ˆ˜ ์•ˆ ์ˆ˜์ •์ด ์›๋ณธ์— ๋ฐ˜์˜ ์•ˆ ๋จ
  • Python/Java: ๊ฐ์ฒด๋Š” ์ฐธ์กฐ๋กœ ๊ณต์œ ๋œ๋‹ค โ†’ ํ•จ์ˆ˜ ์•ˆ ์ˆ˜์ •์ด ์›๋ณธ์— ๋ฐ˜์˜๋จ

7-2. ๋งต๊ณผ ์Šฌ๋ผ์ด์Šค๋Š” ์˜ˆ์™ธ์ฒ˜๋Ÿผ ๋ณด์ธ๋‹ค

๊ทธ๋Ÿฐ๋ฐ ๋งต๊ณผ ์Šฌ๋ผ์ด์Šค๋Š” ๋™์ž‘์ด ๋‹ค๋ฅด๋‹ค. ํ•จ์ˆ˜์— ๋„˜๊ฒจ์„œ ๋‚ด์šฉ์„ ๋ฐ”๊พธ๋ฉด ํ˜ธ์ถœ ์ธก์—๋„ ๋ฐ˜์˜๋œ๋‹ค.

// ๋งต โ€” ํ•จ์ˆ˜ ์•ˆ์—์„œ ์ถ”๊ฐ€ํ•œ ํ•ญ๋ชฉ์ด ์›๋ณธ์— ๋ฐ˜์˜๋จ
func addEntry(m map[string]int) {
    m["new"] = 1
}
 
func main() {
    m := map[string]int{}
    addEntry(m)
    fmt.Println(m)   // map[new:1] โ€” ๋ฐ”๋€๋‹ค
}
// ์Šฌ๋ผ์ด์Šค โ€” ๊ธฐ์กด ์›์†Œ๋ฅผ ์ˆ˜์ •ํ•˜๋ฉด ์›๋ณธ์— ๋ฐ˜์˜๋จ
func zeroFirst(s []int) {
    s[0] = 0
}
 
func main() {
    nums := []int{1, 2, 3}
    zeroFirst(nums)
    fmt.Println(nums)   // [0 2 3] โ€” ๋ฐ”๋€๋‹ค
}

์ด๊ฒŒ call by value ์›์น™์„ ์–ด๊ธฐ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ, ์‚ฌ์‹ค์€ ์ผ๊ด€๋œ๋‹ค. ๋งต๊ณผ ์Šฌ๋ผ์ด์Šค์˜ ๊ฐ’์€ ๋ฐ์ดํ„ฐ ์ž์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ž‘์€ ํ—ค๋”(ํฌ์ธํ„ฐ๋ฅผ ํ’ˆ์€ ๊ตฌ์กฐ) ๋‹ค. ํ•จ์ˆ˜์— ๋„˜๊ธธ ๋•Œ ์ด ํ—ค๋”๊ฐ€ ๋ณต์‚ฌ๋˜์ง€๋งŒ, ๋ณต์‚ฌ๋ณธ๋„ ๊ฒฐ๊ตญ ๊ฐ™์€ ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค. ๊ทธ๋ž˜์„œ ๊ทธ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•˜๋ฉด ์›๋ณธ์—๋„ ๋ณด์ด๋Š” ๊ฒƒ์ด๋‹ค.

๋ณต์‚ฌ๋˜๋Š” ๊ฑด ํ—ค๋”, ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฐ์ดํ„ฐ๋Š” ๊ณต์œ 

์Šฌ๋ผ์ด์Šค๋ฅผ ๋„˜๊ธฐ๋ฉด (ํฌ์ธํ„ฐ, ๊ธธ์ด, ์šฉ๋Ÿ‰) ์„ธ ๊ฐ’์œผ๋กœ ๋œ ํ—ค๋”๊ฐ€ ๋ณต์‚ฌ๋œ๋‹ค. ๋ณต์‚ฌ๋ณธ์˜ ํฌ์ธํ„ฐ๋Š” ์›๋ณธ๊ณผ ๊ฐ™์€ ๋‚ด๋ถ€ ๋ฐฐ์—ด์„ ๊ฐ€๋ฆฌํ‚ค๋ฏ€๋กœ, s[0] = 0์ฒ˜๋Ÿผ ๊ทธ ๋ฐฐ์—ด์˜ ์›์†Œ๋ฅผ ๊ฑด๋“œ๋ฆฌ๋ฉด ์›๋ณธ์—๋„ ๋ฐ˜์˜๋œ๋‹ค. ๋งต๋„ ๊ฐ™์€ ์›๋ฆฌ๋‹ค.

7-3. ์Šฌ๋ผ์ด์Šค์˜ ํ•จ์ • โ€” append๋Š” ๋ฐ˜์˜ ์•ˆ ๋  ์ˆ˜ ์žˆ๋‹ค

๊ฐ™์€ ์ด์œ ๋กœ, ์Šฌ๋ผ์ด์Šค์— appendํ•œ ๊ฒฐ๊ณผ๋Š” ํ˜ธ์ถœ ์ธก์— ๋ฐ˜์˜๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค.

func addItem(s []int) {
    s = append(s, 99)   // ๋ณต์‚ฌ๋ณธ ํ—ค๋”์˜ ๊ธธ์ด๋งŒ ๋ฐ”๋€œ
}
 
func main() {
    nums := []int{1, 2, 3}
    addItem(nums)
    fmt.Println(nums)   // [1 2 3] โ€” 99๊ฐ€ ์•ˆ ๋ณด์ธ๋‹ค
}

์›์†Œ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ(s[0] = 0)์€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฐฐ์—ด์„ ์ง์ ‘ ๊ฑด๋“œ๋ฆฌ๋‹ˆ ๋ฐ˜์˜๋˜์ง€๋งŒ, append๋Š” ๋ณต์‚ฌ๋ณธ ํ—ค๋”์˜ ๊ธธ์ดยทํฌ์ธํ„ฐ๋งŒ ๋ฐ”๊พผ๋‹ค. ์›๋ณธ ํ—ค๋”์˜ ๊ธธ์ด๋Š” ์—ฌ์ „ํžˆ 3์ด๋ผ์„œ ์ถ”๊ฐ€๋œ ์›์†Œ๊ฐ€ ๋ณด์ด์ง€ ์•Š๋Š”๋‹ค. (์ด ๋™์ž‘์€ 03ํŽธ์˜ ์Šฌ๋ผ์ด์‹ฑยท์ €์žฅ ๊ณต๊ฐ„ ๊ณต์œ  ๋‚ด์šฉ๊ณผ ์ด์–ด์ง„๋‹ค.)

7-4. ๊ทธ๋ž˜์„œ ํฌ์ธํ„ฐ๊ฐ€ ํ•„์š”ํ•˜๋‹ค

์ •๋ฆฌํ•˜๋ฉด Go์—์„œ ํ•จ์ˆ˜๊ฐ€ ์›๋ณธ์„ ๋ฐ”๊พธ๊ฒŒ ํ•˜๋ ค๋ฉด ๋‘ ๊ฐ€์ง€ ๊ธธ์ด ์žˆ๋‹ค.

  • ๋งตยท์Šฌ๋ผ์ด์Šค์ฒ˜๋Ÿผ ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•˜๋Š” ํƒ€์ž…์€ ๊ทธ๋Œ€๋กœ ๋„˜๊ฒจ๋„ ๋‚ด์šฉ ์ˆ˜์ •์ด ๋ฐ˜์˜๋œ๋‹ค
  • ๊ตฌ์กฐ์ฒด๋‚˜ ๊ธฐ๋ณธ ํƒ€์ž…์˜ ์›๋ณธ์„ ๋ฐ”๊พธ๋ ค๋ฉด ๊ทธ ๊ฐ’์˜ ์ฃผ์†Œ(ํฌ์ธํ„ฐ)๋ฅผ ๋„˜๊ฒจ์•ผ ํ•œ๋‹ค