Alert

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

TL;DR

  • Python์€ ๋ชจ๋“  ๋ณ€์ˆ˜๊ฐ€ ์ฐธ์กฐ์ง€๋งŒ Go๋Š” ๊ธฐ๋ณธ์ด ๊ฐ’ ๋ณต์‚ฌ(call by value)
  • &๋กœ ์ฃผ์†Œ๋ฅผ ์–ป๊ณ  *๋กœ ์—ญ์ฐธ์กฐํ•˜๋ฉฐ, ํฌ์ธํ„ฐ ์‚ฐ์ˆ ์€ ๋ถˆ๊ฐ€
  • ํฌ์ธํ„ฐ๋ฅผ ํ•จ์ˆ˜์— ๋„˜๊ฒจ๋„ ํฌ์ธํ„ฐ ๋ณ€์ˆ˜ ์ž์ฒด๋Š” ๋ณต์‚ฌ๋˜๋ฏ€๋กœ, ํฌ์ธํ„ฐ๋ฅผ ์žฌํ• ๋‹นํ•˜๋ฉด ์›๋ณธ์— ์˜ํ–ฅ ์—†์Œ
  • ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ’์„ *px = ...๋กœ ์ˆ˜์ •ํ•ด์•ผ ์›๋ณธ์ด ๋ฐ”๋€œ
  • ์Šฌ๋ผ์ด์Šค๋Š” (ํฌ์ธํ„ฐยท๊ธธ์ดยท์šฉ๋Ÿ‰) ํ—ค๋”๊ฐ€ ๋ณต์‚ฌ๋˜๋ฉฐ, ๊ณต์šฉ API ์ž…์ถœ๋ ฅ์—” ๋งต๋ณด๋‹ค ๊ตฌ์กฐ์ฒด๊ฐ€ ์•ˆ์ „
  • ํฌ์ธํ„ฐ๋Š” ํž™ ํ• ๋‹น(escape)์„ ๋Š˜๋ ค GC ๋ถ€ํ•˜๋ฅผ ํ‚ค์šฐ๋ฏ€๋กœ, ๊ฐ’ ํƒ€์ž…ยท๋ฒ„ํผ ์žฌ์‚ฌ์šฉ์œผ๋กœ GC ์ผ๊ฐ์„ ์ค„์ž„
  • Go์—์„œ๋Š” ํฌ์ธํ„ฐ ์‚ฌ์šฉ์„ ์ตœ์†Œํ™”ํ•˜๋Š” ๊ฒƒ์ด ๊ถŒ์žฅ๋จ

Python์—์„œ๋Š” ๋ณ€์ˆ˜๊ฐ€ ๊ฐ์ฒด์˜ ์ฐธ์กฐ๋ผ๋Š” ๊ฑธ ์˜์‹ํ•˜์ง€ ์•Š์•„๋„ ๋Œ€๋ถ€๋ถ„ ์ž˜ ๋™์ž‘ํ•œ๋‹ค. Go๋Š” ๋‹ค๋ฅด๋‹ค. ๊ฐ’์ด ๋ณต์‚ฌ๋˜๋Š”์ง€ ์ฐธ์กฐ๊ฐ€ ์ „๋‹ฌ๋˜๋Š”์ง€๋ฅผ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๊ฒฐ์ •ํ•ด์•ผ ํ•œ๋‹ค. ์ด ๊ธ€์€ Python ๊ฐœ๋ฐœ์ž๊ฐ€ Go์˜ ํฌ์ธํ„ฐ๋ฅผ ์ฒ˜์Œ ์ ‘ํ•  ๋•Œ ํ—ท๊ฐˆ๋ฆฌ๋Š” ๋ถ€๋ถ„์„ ์ •๋ฆฌํ•œ๋‹ค.


1. Python์€ ๋ชจ๋“  ๊ฒƒ์ด ์ฐธ์กฐ, Go๋Š” ๊ธฐ๋ณธ์ด ๊ฐ’ ๋ณต์‚ฌ

Python์—์„œ๋Š” ๋ณ€์ˆ˜์— ๊ฐ’์„ ํ• ๋‹นํ•˜๋ฉด ์‹ค์ œ๋กœ๋Š” ๊ฐ์ฒด์˜ ์ฐธ์กฐ๊ฐ€ ์ €์žฅ๋œ๋‹ค. ํ•จ์ˆ˜์— ์ธ์ž๋ฅผ ๋„˜๊ธฐ๋ฉด ๊ทธ ์ฐธ์กฐ๊ฐ€ ๋ณต์‚ฌ๋˜๋ฏ€๋กœ, ์›๋ณธ ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

# Python
def modify(lst):
    lst.append(4)
 
a = [1, 2, 3]
modify(a)
print(a)  # [1, 2, 3, 4] โ€” ์›๋ณธ์ด ๋ฐ”๋€œ

Go๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ’ ์ „์ฒด๋ฅผ ๋ณต์‚ฌํ•œ๋‹ค. ํ•จ์ˆ˜์— ๊ตฌ์กฐ์ฒด๋ฅผ ๋„˜๊ธฐ๋ฉด ํ†ต์งธ๋กœ ๋ณต์‚ฌ๋ณธ์ด ๋งŒ๋“ค์–ด์ง„๋‹ค.

// Go
func modify(nums [3]int) {
    nums[0] = 999
}
 
func main() {
    a := [3]int{1, 2, 3}
    modify(a)
    fmt.Println(a) // [1 2 3] โ€” ์›๋ณธ ์•ˆ ๋ฐ”๋€œ. ๋ณต์‚ฌ๋ณธ์ด ์ˆ˜์ •๋จ
}

์ •๋ฆฌํ•˜๋ฉด ์ด๋ ‡๋‹ค.

PythonGo
๋ณ€์ˆ˜ ํ• ๋‹น๊ฐ์ฒด์˜ ์ฐธ์กฐ ์ €์žฅ๊ฐ’ ์ž์ฒด๋ฅผ ์ €์žฅ
ํ•จ์ˆ˜ ์ธ์ž ์ „๋‹ฌ์ฐธ์กฐ์˜ ๋ณต์‚ฌ๊ฐ’์˜ ๋ณต์‚ฌ
์›๋ณธ ์ˆ˜์ •๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ€๋Šฅํฌ์ธํ„ฐ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•จ

์Šฌ๋ผ์ด์Šค, ๋งต, ์ฑ„๋„์€ ์˜ˆ์™ธ

Go์˜ ์Šฌ๋ผ์ด์Šค([]int), ๋งต(map), ์ฑ„๋„(chan)์€ ๋‚ด๋ถ€์— ์ฐธ์กฐ๋ฅผ ํฌํ•จํ•˜๋Š” ํƒ€์ž…์ด๋‹ค. ์ด๋“ค์€ ๊ฐ’ ๋ณต์‚ฌ๊ฐ€ ์ผ์–ด๋‚˜๋„ ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•˜๋ฏ€๋กœ Python์˜ ๋ฆฌ์ŠคํŠธ/๋”•์…”๋„ˆ๋ฆฌ์™€ ๋น„์Šทํ•˜๊ฒŒ ๋™์ž‘ํ•œ๋‹ค. ์œ„ ์˜ˆ์‹œ์—์„œ ๋ฐฐ์—ด([3]int)์„ ์“ด ์ด์œ ๋„ ์ด ์ฐจ์ด๋ฅผ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด์„œ๋‹ค.


2. &์™€ * โ€” ์ฃผ์†Œ์™€ ์—ญ์ฐธ์กฐ

ํฌ์ธํ„ฐ๋Š” ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ณ€์ˆ˜๋‹ค. Go์—์„œ๋Š” ๋‘ ๊ฐ€์ง€ ์—ฐ์‚ฐ์ž๋กœ ํฌ์ธํ„ฐ๋ฅผ ๋‹ค๋ฃฌ๋‹ค.

  • &x โ€” ๋ณ€์ˆ˜ x์˜ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ๊ฐ€์ ธ์˜ด
  • *p โ€” ํฌ์ธํ„ฐ p๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ’์„ ๊ฐ€์ ธ์˜ด (์—ญ์ฐธ์กฐ)
x := 10
pointerToX := &x        // x์˜ ์ฃผ์†Œ
fmt.Println(pointerToX)  // 0xc0000b4008 ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ
fmt.Println(*pointerToX) // 10 (์—ญ์ฐธ์กฐ)
 
*pointerToX = 20
fmt.Println(x)           // 20 โ€” ํฌ์ธํ„ฐ๋ฅผ ํ†ตํ•ด ์›๋ณธ ์ˆ˜์ •

ํฌ์ธํ„ฐ์˜ zero value๋Š” nil

Go์˜ ๋ชจ๋“  ํƒ€์ž…์—๋Š” zero value๊ฐ€ ์žˆ๋‹ค(02ํŽธ์—์„œ ๋‹ค๋ค˜๋‹ค). int์€ 0, string์€ ""์ธ ๊ฒƒ์ฒ˜๋Ÿผ. ํฌ์ธํ„ฐ์˜ zero value๋Š” **nil**์ด๋‹ค. ์•„์ง ์•„๋ฌด ์ฃผ์†Œ๋„ ๊ฐ€๋ฆฌํ‚ค์ง€ ์•Š๋Š”, โ€œ๋นˆ ํฌ์ธํ„ฐโ€ ์ƒํƒœ๋ฅผ ๋œปํ•œ๋‹ค.

var p *int             // ์„ ์–ธ๋งŒ ํ•˜๋ฉด nil
fmt.Println(p)         // <nil>
fmt.Println(p == nil)  // true

์ฃผ์˜ํ•  ์ ์€ nil ํฌ์ธํ„ฐ๋ฅผ ์—ญ์ฐธ์กฐํ•˜๋ฉด(*p) ๋Ÿฐํƒ€์ž„ ํŒจ๋‹‰์ด ๋‚œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๊ฐ€๋ฆฌํ‚ค๋Š” ๋Œ€์ƒ์ด ์—†๋Š”๋ฐ ๊ทธ ๊ฐ’์„ ๊บผ๋‚ด๋ ค ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

var p *int
fmt.Println(*p)   // panic: runtime error: invalid memory address or nil pointer dereference

Python์˜ None๊ณผ ๋น„์Šทํ•œ ์œ„์น˜๋‹ค. ๋‹ค๋งŒ Python์€ None ์ž์ฒด๊ฐ€ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋ผ ๋ณ€์ˆ˜์— ๋‹ด์•„ ๋‘๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋Š” ํ„ฐ์ง€์ง€ ์•Š์ง€๋งŒ, Go์—์„œ nil ํฌ์ธํ„ฐ๋ฅผ ์—ญ์ฐธ์กฐํ•˜๋Š” ๊ฑด ์ฆ‰์‹œ ํŒจ๋‹‰์œผ๋กœ ์ด์–ด์ง„๋‹ค. ๊ทธ๋ž˜์„œ ํฌ์ธํ„ฐ๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋Š” ํ•จ์ˆ˜์—์„œ๋Š” if p == nil์œผ๋กœ ๋จผ์ € ํ™•์ธํ•˜๋Š” ํŒจํ„ด์ด ํ”ํ•˜๋‹ค.

Python๊ณผ ๋น„๊ต

Python์—๋Š” ํฌ์ธํ„ฐ๊ฐ€ ์—†๋‹ค. id() ํ•จ์ˆ˜๋กœ ๊ฐ์ฒด์˜ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ๋ณผ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ๊ทธ ์ฃผ์†Œ๋ฅผ ํ†ตํ•ด ๊ฐ’์„ ์ง์ ‘ ์กฐ์ž‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์—†๋‹ค.

x = 10
print(id(x))  # 4345678912 ๊ฐ™์€ ์ฃผ์†Œ
# ํ•˜์ง€๋งŒ ์ด ์ฃผ์†Œ๋กœ ๊ฐ’์„ ๋ฐ”๊พธ๋Š” ๋ฐฉ๋ฒ•์€ ์—†์Œ

C์™€ ๋น„๊ต

C/C++ ๊ฒฝํ—˜์ด ์žˆ๋‹ค๋ฉด &์™€ *๊ฐ€ ์นœ์ˆ™ํ•  ๊ฒƒ์ด๋‹ค. ๋‹ค๋งŒ Go์—๋Š” ๋‘ ๊ฐ€์ง€ ์ค‘์š”ํ•œ ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค.

  • ํฌ์ธํ„ฐ ์‚ฐ์ˆ  ๋ถˆ๊ฐ€ โ€” p++ ๊ฐ™์€ ์—ฐ์‚ฐ์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ง์ ‘ ์ด๋™ํ•  ์ˆ˜ ์—†๋‹ค. ์•ˆ์ „์„ฑ์„ ์œ„ํ•œ ์„ค๊ณ„๋‹ค.
  • GC๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌ โ€” free()๋‚˜ delete๋ฅผ ํ˜ธ์ถœํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. Go์˜ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๊ฐ€ ์•Œ์•„์„œ ์ •๋ฆฌํ•œ๋‹ค.

3. ํ•จ์ˆ˜์—์„œ ํฌ์ธํ„ฐ ์‚ฌ์šฉ

์›๋ณธ ๊ฐ’์„ ํ•จ์ˆ˜ ์•ˆ์—์„œ ์ˆ˜์ •ํ•˜๊ณ  ์‹ถ์œผ๋ฉด ํฌ์ธํ„ฐ๋ฅผ ๋„˜๊ธด๋‹ค.

func update(px *int) {
    *px = 20  // ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ’์„ ์ˆ˜์ •
}
 
func main() {
    x := 10
    update(&x)
    fmt.Println(x)  // 20
}

*int์€ โ€˜์ฃผ์†Œ๋ฅผ ๋‹ด๋Š” ํƒ€์ž…โ€™์ด๋‹ค

์—ฌ๊ธฐ์„œ px *int๋ผ๋Š” ํ‘œ๊ธฐ๊ฐ€ ์ฒ˜์Œ ๋ณด๋ฉด ํ—ท๊ฐˆ๋ฆฐ๋‹ค. *int์ด๋ผ๋Š” ํƒ€์ž…์ด ๊ฐ’์„ ๋œปํ•˜๋Š”์ง€ ์ฃผ์†Œ๋ฅผ ๋œปํ•˜๋Š”์ง€ ๋ชจํ˜ธํ•˜๊ฒŒ ๋А๊ปด์ง€๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ฒฐ๋ก ๋ถ€ํ„ฐ ๋งํ•˜๋ฉด *int์€ ์ฃผ์†Œ๋ฅผ ๋‹ด๋Š” ํƒ€์ž…์ด๋‹ค.

  • int ํƒ€์ž… ๋ณ€์ˆ˜ โ†’ ์ •์ˆ˜ ๊ฐ’์„ ๋‹ด๋Š”๋‹ค (x := 10 โ†’ x ์•ˆ์—๋Š” 10)
  • *int ํƒ€์ž… ๋ณ€์ˆ˜ โ†’ int์˜ ์ฃผ์†Œ๋ฅผ ๋‹ด๋Š”๋‹ค (px := &x โ†’ px ์•ˆ์—๋Š” x๊ฐ€ ์‚ฌ๋Š” ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ)

๊ทธ๋ž˜์„œ func update(px *int)์€ โ€œpx๋Š” int์˜ ์ฃผ์†Œ๋ฅผ ๋ฐ›๋Š”๋‹คโ€๋Š” ๋œป์ด๊ณ , px์— ๋“ค์–ด์˜ค๋Š” ๊ฐ’์€ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋๊นŒ์ง€ ์ฃผ์†Œ๋‹ค.

ํ—ท๊ฐˆ๋ฆฌ๋Š” ์ง„์งœ ์ด์œ ๋Š” * ๊ธฐํ˜ธ๊ฐ€ ๋ถ™๋Š” ์œ„์น˜์— ๋”ฐ๋ผ ์ •๋ฐ˜๋Œ€๋กœ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์œ„์น˜์˜ˆ์‹œ์˜๋ฏธ
ํƒ€์ž… ์˜†px *intโ€int์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ ํƒ€์ž…โ€ โ€” ์ฃผ์†Œ๋ฅผ ๋‹ด๋Š”๋‹ค (์„ ์–ธ)
๋ณ€์ˆ˜ยท๊ฐ’ ์˜†*px = 20โ€๊ทธ ์ฃผ์†Œ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ’โ€ โ€” ์—ญ์ฐธ์กฐ (์—ฐ์‚ฐ)
  • px *int์—์„œ *๋Š” ํƒ€์ž… int์— ๋ถ™์–ด โ€œint ์ฃผ์†Œ ํƒ€์ž…โ€์„ ๋งŒ๋“ ๋‹ค. ์ฃผ์†Œ ํ•œ ๊ฒน์„ ์”Œ์šฐ๋Š” ์ชฝ์ด๋‹ค.
  • *px์—์„œ *๋Š” ๋ณ€์ˆ˜ px์— ๋ถ™์–ด โ€œpx๊ฐ€ ๋“  ์ฃผ์†Œ๋กœ ์ฐพ์•„๊ฐ„ ๊ฐ’โ€์„ ๊บผ๋‚ธ๋‹ค. ์ฃผ์†Œ ํ•œ ๊ฒน์„ ๋ฒ—๊ธฐ๋Š” ์ชฝ์ด๋‹ค.

๋ฐฉํ–ฅ์ด ๋ฐ˜๋Œ€๋‹ค. ํƒ€์ž… ์ž๋ฆฌ์—์„œ๋Š” ์ฃผ์†Œ๋ฅผ ์”Œ์šฐ๊ณ , ์‹ ์ž๋ฆฌ์—์„œ๋Š” ์ฃผ์†Œ๋ฅผ ๋ฒ—๊ธด๋‹ค.

์ฝ๋Š” ์š”๋ น

  • var px *int โ†’ โ€œpx is a pointer to intโ€ (px๋Š” int๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ = ์ฃผ์†Œ๋ฅผ ๋‹ด๋Š”๋‹ค)
  • *px โ†’ โ€œvalue at pxโ€ (px๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ณณ์˜ ๊ฐ’)

์ง‘ ์ฃผ์†Œ์— ๋น„์œ ํ•˜๋ฉด px๋Š” ์ข…์ด์— ์ ํžŒ ์ฃผ์†Œ์ด๊ณ , *px๋Š” ๊ทธ ์ฃผ์†Œ๋กœ ์ฐพ์•„๊ฐ€ ์ง‘ ์•ˆ์—์„œ ๊บผ๋‚ธ ๋ฌผ๊ฑด์ด๋‹ค. &x๋Š” x๋ผ๋Š” ์ง‘์˜ ์ฃผ์†Œ๋ฅผ ์•Œ์•„๋‚ด๋Š” ์ผ์ด๋‹ค.

์ด ๊ตฌ๋ถ„์„ ์—ผ๋‘์— ๋‘๊ณ  ์œ„ ์˜ˆ์‹œ์˜ ํ๋ฆ„์„ ๋‹จ๊ณ„๋ณ„๋กœ ๋ณด๋ฉด ์ด๋ ‡๋‹ค.

  1. x๋Š” ๊ฐ’ 10์„ ๊ฐ€์ง„ ๋ณ€์ˆ˜๋‹ค (int)
  2. &x๋กœ x์˜ ์ฃผ์†Œ๋ฅผ ๊ตฌํ•ด์„œ update์— ๋„˜๊ธด๋‹ค (*int ๊ฐ’, ์ฆ‰ ์ฃผ์†Œ)
  3. update ์•ˆ์˜ px๋Š” x์˜ ์ฃผ์†Œ๋ฅผ ๋‹ด๊ณ  ์žˆ๋‹ค
  4. *px = 20์œผ๋กœ ๊ทธ ์ฃผ์†Œ์— ์žˆ๋Š” ๊ฐ’์„ 20์œผ๋กœ ๋ฐ”๊พผ๋‹ค (์—ญ์ฐธ์กฐ)
  5. main์˜ x๊ฐ€ 20์ด ๋œ๋‹ค

4. ํฌ์ธํ„ฐ ๋ณ€์ˆ˜ ์ž์ฒด๋„ ๋ณต์‚ฌ๋œ๋‹ค โ€” ๊ฐ€์žฅ ํ”ํ•œ ์‹ค์ˆ˜

์ด ๋ถ€๋ถ„์ด ํฌ์ธํ„ฐ๋ฅผ ์ฒ˜์Œ ๋ฐฐ์šธ ๋•Œ ๊ฐ€์žฅ ํ—ท๊ฐˆ๋ฆฌ๋Š” ์ง€์ ์ด๋‹ค. Go๋Š” ํฌ์ธํ„ฐ๋ฅผ ๋„˜๊ธธ ๋•Œ๋„ ํฌ์ธํ„ฐ ๋ณ€์ˆ˜ ์ž์ฒด๋Š” ๋ณต์‚ฌํ•œ๋‹ค. ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋Œ€์ƒ์„ ๊ณต์œ ํ•  ๋ฟ, ํฌ์ธํ„ฐ ๋ณ€์ˆ˜ ์ž์ฒด๋Š” ๋ณ„๊ฐœ๋‹ค.

์™œ ๋ณ„๊ฐœ์ธ๊ฐ€ โ€” ํฌ์ธํ„ฐ๋„ ์ž๊ธฐ ์ฃผ์†Œ์— ์‚ฌ๋Š” ๋ณ€์ˆ˜๋‹ค

ํ•ต์‹ฌ์€ ํฌ์ธํ„ฐ ๋ณ€์ˆ˜๋„ ๊ฒฐ๊ตญ ์ž๊ธฐ๋งŒ์˜ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ์— ์ €์žฅ๋œ ํ‰๋ฒ”ํ•œ ๋ณ€์ˆ˜๋ผ๋Š” ์ ์ด๋‹ค. ๋‹ด๊ณ  ์žˆ๋Š” ๊ฐ’์ด โ€œ์ฃผ์†Œโ€์ผ ๋ฟ์ด๋‹ค. ๊ทธ๋ž˜์„œ ํ•จ์ˆ˜์— ๋„˜๊ธฐ๋ฉด ๊ทธ ๊ฐ’(์ฃผ์†Œ)์ด ๋˜ ๋‹ค๋ฅธ ์œ„์น˜์— ๋ณต์‚ฌ๋œ๋‹ค.

x := 10
px := &x       // px๋Š” x์˜ ์ฃผ์†Œ๋ฅผ ๋‹ด๋Š”๋‹ค
update(px)     // px์˜ '๊ฐ’'(์ฃผ์†Œ)์ด ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ณต์‚ฌ๋จ

์„ธ ๋ณ€์ˆ˜๊ฐ€ ๊ฐ์ž ๋‹ค๋ฅธ ์ฃผ์†Œ์— ์‚ฐ๋‹ค๊ณ  ๋ณด๋ฉด ๋ช…ํ™•ํ•ด์ง„๋‹ค.

๋ณ€์ˆ˜์‚ฌ๋Š” ์ฃผ์†Œ(์˜ˆ์‹œ)๋‹ด์€ ๊ฐ’
x0x10010
px (= &x)0x2000x100 โ† x์˜ ์ฃผ์†Œ
update์˜ ํŒŒ๋ผ๋ฏธํ„ฐ (px ๋ณต์‚ฌ๋ณธ)0x3000x100 โ† px์—์„œ ๋ณต์‚ฌ๋œ ๊ฐ™์€ ์ฃผ์†Œ

px์™€ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ๊ฐ™์€ ๊ฐ’(0x100)์„ ๋‹ด์ง€๋งŒ, ์ž๊ธฐ ์ž์‹ ์€ ์„œ๋กœ ๋‹ค๋ฅธ ๊ณณ(0x200 vs 0x300)์— ์‚ฌ๋Š” ๋ณ„๊ฐœ์˜ ๋ณ€์ˆ˜๋‹ค. ์—ฌ๊ธฐ์„œ ๋‘ ๋™์ž‘์ด ๊ฐˆ๋ฆฐ๋‹ค.

  • *ํŒŒ๋ผ๋ฏธํ„ฐ = 20 โ†’ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ๋“  ์ฃผ์†Œ 0x100์œผ๋กœ ์ฐพ์•„๊ฐ€ ๊ฐ’์„ ๊ณ ์นจ โ†’ x๊ฐ€ ๋ฐ”๋€๋‹ค (px๋„ ๊ฐ™์€ 0x100์„ ๊ฐ€๋ฆฌํ‚ค๋‹ˆ ๊ณต์œ ๋จ)
  • ํŒŒ๋ผ๋ฏธํ„ฐ = &๋‹ค๋ฅธ๋ณ€์ˆ˜ โ†’ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์‚ฌ๋Š” 0x300์— ์ƒˆ ์ฃผ์†Œ๋ฅผ ๋ฎ์–ด์”€ โ†’ px(0x200)๋Š” ๊ทธ๋Œ€๋กœ โ†’ ๋ฐ”๊นฅ์—” ์˜ํ–ฅ ์—†์Œ

์ฆ‰ โ€œ๊ฐ€๋ฆฌํ‚ค๋Š” ๋Œ€์ƒโ€์€ ๊ณต์œ ํ•˜์ง€๋งŒ โ€œํฌ์ธํ„ฐ ๋ณ€์ˆ˜ ๊ทธ ์ž์ฒดโ€๋Š” ๋ณต์‚ฌ๋ณธ์ด๋ผ ๋”ฐ๋กœ ๋…ผ๋‹ค. ๋งŒ์•ฝ ํ•จ์ˆ˜๊ฐ€ px๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋Œ€์ƒ ์ž์ฒด๋ฅผ ๋ฐ”๊พธ๊ฒŒ ํ•˜๋ ค๋ฉด, px๊ฐ€ ์•„๋‹ˆ๋ผ px์˜ ์ฃผ์†Œ(&px, ํƒ€์ž…์€ **int)๋ฅผ ๋„˜๊ฒจ์•ผ ํ•œ๋‹ค. ๊ฐ’ ๋ณต์‚ฌ ๊ทœ์น™์€ ํฌ์ธํ„ฐ๋ผ๊ณ  ์˜ˆ์™ธ๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

Case 1: nil ํฌ์ธํ„ฐ ์ „๋‹ฌ

func failedUpdate(g *int) {
    x := 10
    g = &x   // g๋Š” ๋ณต์‚ฌ๋ณธ. ๋ฐ”๊นฅ์˜ f๋Š” ์•ˆ ๋ฐ”๋€œ
}
 
func main() {
    var f *int       // nil
    failedUpdate(f)
    fmt.Println(f)   // <nil> โ€” ์—ฌ์ „ํžˆ nil
}

failedUpdate ์•ˆ์—์„œ g์— ์ƒˆ ์ฃผ์†Œ๋ฅผ ํ• ๋‹นํ•ด๋„, g๋Š” f์˜ ๋ณต์‚ฌ๋ณธ์ด๋‹ค. f๋Š” ์—ฌ์ „ํžˆ nil์ด๋‹ค.

Case 2: ํฌ์ธํ„ฐ ์žฌํ• ๋‹น vs ์—ญ์ฐธ์กฐ ์ˆ˜์ •

// ์‹คํŒจํ•˜๋Š” ๋ฒ„์ „
func failedUpdate(px *int) {
    x2 := 20
    px = &x2   // px ๋ณต์‚ฌ๋ณธ๋งŒ ๋ฐ”๋€œ โ€” main์˜ x๋Š” ๊ทธ๋Œ€๋กœ
}
 
// ์„ฑ๊ณตํ•˜๋Š” ๋ฒ„์ „
func update(px *int) {
    *px = 20   // px๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ณณ์˜ ๊ฐ’์„ ์ˆ˜์ • โ€” main์˜ x๊ฐ€ ๋ฐ”๋€œ
}
 
func main() {
    x := 10
 
    failedUpdate(&x)
    fmt.Println(x)   // 10 โ€” ์•ˆ ๋ฐ”๋€œ
 
    update(&x)
    fmt.Println(x)   // 20 โ€” ๋ฐ”๋€œ
}

ํ•ต์‹ฌ ๊ทœ์น™

  • ํฌ์ธํ„ฐ๋ฅผ ๋„˜๊ฒจ๋„ ํฌ์ธํ„ฐ ๋ณ€์ˆ˜ ์ž์ฒด๋Š” ๋ณต์‚ฌ๋œ๋‹ค
  • ํฌ์ธํ„ฐ ๋ณ€์ˆ˜๋ฅผ ๋‹ค๋ฅธ ์ฃผ์†Œ๋กœ ์žฌํ• ๋‹น(px = &x2)ํ•˜๋ฉด ์›๋ณธ์— ์˜ํ–ฅ ์—†์Œ
  • ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ’์„ ์ˆ˜์ •(*px = 20)ํ•ด์•ผ ์›๋ณธ์ด ๋ฐ”๋€œ

Python ์šฉ์–ด๋กœ ๋น„์œ ํ•˜๋ฉด ์ด๋ ‡๋‹ค. Python์—์„œ ํ•จ์ˆ˜ ์•ˆ์—์„œ lst = [4, 5, 6]์ฒ˜๋Ÿผ ์ƒˆ ๋ฆฌ์ŠคํŠธ๋ฅผ ํ• ๋‹นํ•˜๋ฉด ์›๋ณธ์ด ์•ˆ ๋ฐ”๋€Œ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ์›๋ฆฌ๋‹ค. ์ฐธ์กฐ ์ž์ฒด๋ฅผ ๊ต์ฒดํ•œ ๊ฒƒ์ด์ง€, ์ฐธ์กฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋Œ€์ƒ์„ ์ˆ˜์ •ํ•œ ๊ฒŒ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

# Python์—์„œ๋„ ๊ฐ™์€ ์›๋ฆฌ
def failed_update(lst):
    lst = [4, 5, 6]   # ์ƒˆ ๋ฆฌ์ŠคํŠธ๋กœ ๊ต์ฒด โ€” ์›๋ณธ ์•ˆ ๋ฐ”๋€œ
 
def update(lst):
    lst.append(4)      # ๊ธฐ์กด ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆ˜์ • โ€” ์›๋ณธ ๋ฐ”๋€œ
 
a = [1, 2, 3]
failed_update(a)
print(a)  # [1, 2, 3]
 
update(a)
print(a)  # [1, 2, 3, 4]

5. ๋งต๊ณผ ์Šฌ๋ผ์ด์Šค๋ฅผ ํ•จ์ˆ˜์— ๋„˜๊ธธ ๋•Œ

1๋ฒˆ์—์„œ ์งš์—ˆ๋“ฏ ์Šฌ๋ผ์ด์Šคยท๋งตยท์ฑ„๋„์€ ๊ฐ’ ๋ณต์‚ฌ๊ฐ€ ์ผ์–ด๋‚˜๋„ ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•œ๋‹ค. ํ•จ์ˆ˜์— ๋„˜๊ฒจ ๋‚ด์šฉ์„ ๋ฐ”๊พธ๋ฉด ์›๋ณธ์— ๋ฐ˜์˜๋˜๋Š” ์ด์œ ๋‹ค. ์ด ๋™์ž‘์€ 05ํŽธ์˜ call by value์—์„œ๋„ ๋‹ค๋ค˜๋Š”๋ฐ, ์—ฌ๊ธฐ์„œ๋Š” ๊ทธ ๊ตฌ์กฐ์™€ ์‹ค๋ฌด์—์„œ์˜ ์ฃผ์˜์ ์„ ์ •๋ฆฌํ•œ๋‹ค.

์Šฌ๋ผ์ด์Šค๋Š” (ํฌ์ธํ„ฐ, ๊ธธ์ด, ์šฉ๋Ÿ‰) ํ—ค๋”๊ฐ€ ๋ณต์‚ฌ๋œ๋‹ค

์Šฌ๋ผ์ด์Šค ๊ฐ’์€ ๋ฐ์ดํ„ฐ ๋ฐฐ์—ด ์ž์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ, ๊ทธ ๋ฐฐ์—ด์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ž‘์€ ํ—ค๋”๋‹ค. ์ •ํ™•ํžˆ๋Š” ์„ธ ๊ฐ€์ง€ ๊ฐ’์œผ๋กœ ์ด๋ค„์ง„๋‹ค.

  • ํฌ์ธํ„ฐ โ€” ์‹ค์ œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋‹ด๊ธด ๋ฐฐ์—ด์˜ ์‹œ์ž‘ ์ฃผ์†Œ
  • ๊ธธ์ด(len) โ€” ํ˜„์žฌ ์›์†Œ ๊ฐœ์ˆ˜
  • ์šฉ๋Ÿ‰(cap) โ€” ์žฌํ• ๋‹น ์—†์ด ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ๊ฐœ์ˆ˜

ํ•จ์ˆ˜์— ์Šฌ๋ผ์ด์Šค๋ฅผ ๋„˜๊ธฐ๋ฉด ์ด ํ—ค๋” ์„ธ ๊ฐ’์ด ๋ณต์‚ฌ๋œ๋‹ค. ๋ณต์‚ฌ๋ณธ์˜ ํฌ์ธํ„ฐ๋„ ์›๋ณธ๊ณผ ๊ฐ™์€ ๋ฐฐ์—ด์„ ๊ฐ€๋ฆฌํ‚ค๋ฏ€๋กœ, ์›์†Œ๋ฅผ ์ˆ˜์ •ํ•˜๋ฉด ์›๋ณธ์— ๋ฐ˜์˜๋œ๋‹ค.

func zeroFirst(s []int) {
    s[0] = 0   // ๊ฐ™์€ ๋ฐฐ์—ด์„ ๊ฐ€๋ฆฌํ‚ค๋‹ˆ ์›๋ณธ์— ๋ฐ˜์˜
}
nums := []int{1, 2, 3}
zeroFirst(nums)
// nums == [0 2 3]

๋ฐ˜๋ฉด append๋Š” ๋ณต์‚ฌ๋ณธ ํ—ค๋”์˜ ๊ธธ์ด๋งŒ ๋Š˜๋ฆฌ๊ฑฐ๋‚˜, ์šฉ๋Ÿ‰์ด ๋ชจ์ž๋ผ๋ฉด ์•„์˜ˆ ์ƒˆ ๋ฐฐ์—ด์„ ํ• ๋‹นํ•œ๋‹ค. ์–ด๋А ์ชฝ์ด๋“  ์›๋ณธ ํ—ค๋”์˜ ๊ธธ์ด๋Š” ๊ทธ๋Œ€๋กœ๋ผ ์ถ”๊ฐ€๋ถ„์ด ๋ณด์ด์ง€ ์•Š๋Š”๋‹ค. (์ด ๋™์ž‘์€ 03ํŽธ์˜ ์Šฌ๋ผ์ด์‹ฑยท์ €์žฅ ๊ณต๊ฐ„ ๊ณต์œ ์™€ ์ด์–ด์ง„๋‹ค.)

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

๋งต๋„ ๊ฐ™์€ ์›๋ฆฌ๋‹ค. ๋งต ๊ฐ’์€ ๋‚ด๋ถ€ ํ•ด์‹œ ํ…Œ์ด๋ธ”์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ๋ผ์„œ, ๋ณต์‚ฌ๋ผ๋„ ๊ฐ™์€ ํ…Œ์ด๋ธ”์„ ๊ณต์œ ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ํ•จ์ˆ˜ ์•ˆ์—์„œ ์ถ”๊ฐ€ยท์‚ญ์ œํ•œ ํ•ญ๋ชฉ์ด ์›๋ณธ์— ๋ฐ˜์˜๋œ๋‹ค.

๊ณต์šฉ API์—์„œ๋Š” ๋งต์„ ์ž…๋ ฅยท๋ฐ˜ํ™˜์œผ๋กœ ์“ฐ์ง€ ๋งˆ๋ผ

๋งต์ด ๊ณต์œ ๋˜๊ณ  ๊ตฌ์กฐ๋„ ๋А์Šจํ•˜๋‹ค๋Š” ์  ๋•Œ๋ฌธ์—, ์„ค๊ณ„ํ•  ๋•Œ ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค. ํŠนํžˆ ๊ณต์šฉ API์˜ ์ž…๋ ฅ ํŒŒ๋ผ๋ฏธํ„ฐ๋‚˜ ๋ฐ˜ํ™˜๊ฐ’์œผ๋กœ ๋งต์„ ์“ฐ๋Š” ๊ฒƒ์€ ํ”ผํ•˜๋Š” ๊ฒŒ ์ข‹๋‹ค. ๋Œ€์‹  ๊ตฌ์กฐ์ฒด๋ฅผ ์“ด๋‹ค.

// ๊ถŒ์žฅํ•˜์ง€ ์•Š์Œ โ€” ์–ด๋–ค ํ‚ค๊ฐ€ ์œ ํšจํ•œ์ง€ ์‹œ๊ทธ๋‹ˆ์ฒ˜์— ๋“œ๋Ÿฌ๋‚˜์ง€ ์•Š๋Š”๋‹ค
func NewUser(data map[string]string) User { ... }
// ํ˜ธ์ถœํ•˜๋Š” ์ชฝ: "name"? "Name"? "username"? ๋ฌด์—‡์„ ๋„ฃ์–ด์•ผ ํ•˜๋‚˜
// ์˜คํƒ€๊ฐ€ ๋‚˜๋„ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์žก์•„์ฃผ์ง€ ์•Š๋Š”๋‹ค
// ๊ถŒ์žฅ โ€” ํ•„๋“œ๊ฐ€ ์‹œ๊ทธ๋‹ˆ์ฒ˜์— ๋ช…์‹œ๋˜๊ณ  ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๊ฒ€์ฆํ•œ๋‹ค
type UserInput struct {
    Name  string
    Email string
}
func NewUser(in UserInput) User { ... }

์ฐจ์ด๋Š” ๋ถ„๋ช…ํ•˜๋‹ค.

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

๋งต์€ ์ปดํŒŒ์ผ ํƒ€์ž„์— ํ‚ค๋ฅผ ์•Œ ์ˆ˜ ์—†๋Š”, ์ง„์งœ ๋™์ ์ธ ๋ฐ์ดํ„ฐ์—๋งŒ ์“ฐ๋Š” ๊ฒŒ ๋งž๋‹ค. ํ•„๋“œ๊ฐ€ ์ •ํ•ด์ ธ ์žˆ๋‹ค๋ฉด ๊ตฌ์กฐ์ฒด๊ฐ€ ๊ฑฐ์˜ ํ•ญ์ƒ ๋‚ซ๋‹ค.


6. ํฌ์ธํ„ฐ๋Š” ์ตœํ›„์˜ ์ˆ˜๋‹จ

Go ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ๋Š” ํฌ์ธํ„ฐ ์‚ฌ์šฉ์„ ์ตœ์†Œํ™”ํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•œ๋‹ค. ์ด์œ ๋Š” ๋ช…ํ™•ํ•˜๋‹ค.

  • ๋ฐ์ดํ„ฐ ํ๋ฆ„์ด ๋ณต์žกํ•ด์ง„๋‹ค โ€” ํฌ์ธํ„ฐ๋ฅผ ๋”ฐ๋ผ๊ฐ€๋ฉด์„œ ์–ด๋””์„œ ๊ฐ’์ด ๋ฐ”๋€Œ๋Š”์ง€ ์ถ”์ ํ•˜๊ธฐ ์–ด๋ ค์›Œ์ง„๋‹ค
  • GC ๋ถ€ํ•˜๊ฐ€ ์ฆ๊ฐ€ํ•œ๋‹ค โ€” ํž™์— ํ• ๋‹น๋œ ํฌ์ธํ„ฐ๊ฐ€ ๋งŽ์„์ˆ˜๋ก ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๊ฐ€ ํ•  ์ผ์ด ๋Š˜์–ด๋‚œ๋‹ค
  • ๋™์‹œ์„ฑ์—์„œ ์œ„ํ—˜ํ•˜๋‹ค โ€” ํฌ์ธํ„ฐ๋ฅผ ํ†ตํ•ด ๊ณต์œ  ์ƒํƒœ๋ฅผ ๋งŒ๋“ค๋ฉด ๊ฒฝ์Ÿ ์กฐ๊ฑด(race condition)์ด ๋ฐœ์ƒํ•˜๊ธฐ ์‰ฝ๋‹ค

ํฌ์ธํ„ฐ ๋Œ€์‹  ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํŒจํ„ด

๊ตฌ์กฐ์ฒด๋ฅผ ํ•จ์ˆ˜์— ๋„˜๊ฒจ์„œ ์ˆ˜์ •ํ•˜๋Š” ๋Œ€์‹ , ํ•จ์ˆ˜ ์•ˆ์—์„œ ์ƒˆ๋กœ ๋งŒ๋“ค์–ด์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด ๊น”๋”ํ•˜๋‹ค.

// ํฌ์ธํ„ฐ๋ฅผ ์“ฐ๋Š” ๋ฐฉ์‹
func initUser(u *User) {
    u.Name = "Alice"
    u.Age = 30
}
 
// ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐฉ์‹ (๊ถŒ์žฅ)
func newUser() User {
    return User{
        Name: "Alice",
        Age:  30,
    }
}

ํฌ์ธํ„ฐ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ

๋ฌผ๋ก  ํฌ์ธํ„ฐ๊ฐ€ ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•œ ์ƒํ™ฉ๋„ ์žˆ๋‹ค.

  • ์ธํ„ฐํŽ˜์ด์Šค ์ถฉ์กฑ โ€” ๋ฉ”์„œ๋“œ์˜ ๋ฆฌ์‹œ๋ฒ„๊ฐ€ ํฌ์ธํ„ฐ ํƒ€์ž…์ด์–ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ
  • JSON ๋งˆ์ƒฌ๋ง โ€” null๊ณผ zero value๋ฅผ ๊ตฌ๋ถ„ํ•ด์•ผ ํ•  ๋•Œ
  • ํฐ ๊ตฌ์กฐ์ฒด โ€” ๋ณต์‚ฌ ๋น„์šฉ์ด ์‹ค์ธก์œผ๋กœ ๋ฌธ์ œ๊ฐ€ ๋  ๋•Œ

์ด๋Ÿฐ ์ผ€์ด์Šค๋Š” ๋ณ„๋„ ๊ธ€์—์„œ ๋‹ค๋ฃฌ๋‹ค.


7. Go์˜ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ์™€ ๋ฉ”๋ชจ๋ฆฌ

ํฌ์ธํ„ฐ๋ฅผ ์ตœ์†Œํ™”ํ•˜๋ผ๋Š” ์กฐ์–ธ(6๋ฒˆ)์˜ ๋ฐฐ๊ฒฝ์—๋Š” Go์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ๋ฐฉ์‹์ด ์žˆ๋‹ค. Go๋Š” ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ(GC)๋ฅผ ๊ฐ€์ง„ ์–ธ์–ด์ด๊ณ , ํฌ์ธํ„ฐ๋ฅผ ์–ด๋–ป๊ฒŒ ์“ฐ๋А๋ƒ๊ฐ€ GC ๋ถ€ํ•˜์— ์ง์ ‘ ์˜ํ–ฅ์„ ์ค€๋‹ค.

garbage์™€ ์Šคํƒยทํž™

garbage๋Š” ํ”„๋กœ๊ทธ๋žจ์—์„œ ๋” ์ด์ƒ ๋„๋‹ฌํ•  ์ˆ˜ ์—†๋Š”(unreachable) ๋ฉ”๋ชจ๋ฆฌ๋‹ค. ์ „์—ญ ๋ณ€์ˆ˜๋‚˜ ์‹คํ–‰ ์ค‘์ธ ํ•จ์ˆ˜์˜ ์ง€์—ญ ๋ณ€์ˆ˜์—์„œ ์ถœ๋ฐœํ•ด ํฌ์ธํ„ฐ๋ฅผ ๋”ฐ๋ผ๊ฐ€๋„ ๋‹ฟ์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋งํ•œ๋‹ค. C์ฒ˜๋Ÿผ ์ง์ ‘ freeํ•˜์ง€ ์•Š์•„๋„, Go ๋Ÿฐํƒ€์ž„์ด ์ด๋Ÿฐ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฐพ์•„ ์ž๋™์œผ๋กœ ํšŒ์ˆ˜ํ•œ๋‹ค.

๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์–ด๋””์— ํ• ๋‹น๋˜๋Š”์ง€๊ฐ€ ์ค‘์š”ํ•˜๋‹ค.

  • ์Šคํƒ(stack) โ€” ํ•จ์ˆ˜์˜ ์ง€์—ญ ๋ณ€์ˆ˜ยทํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์˜ฌ๋ผ๊ฐ€๋Š” ์˜์—ญ. ํ• ๋‹น์ด ์‹ธ๊ณ (์Šคํƒ ํฌ์ธํ„ฐ๋งŒ ์ด๋™), ํ•จ์ˆ˜๊ฐ€ ๋๋‚˜๋ฉด ์ž๋™์œผ๋กœ ํ•ด์ œ๋œ๋‹ค. GC๊ฐ€ ์‹ ๊ฒฝ ์“ธ ํ•„์š”๊ฐ€ ์—†๋‹ค.
  • ํž™(heap) โ€” ํ•จ์ˆ˜๊ฐ€ ๋๋‚˜๋„ ์‚ด์•„๋‚จ์•„์•ผ ํ•˜๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๊ฐ€๋Š” ์˜์—ญ. GC๊ฐ€ ์ถ”์ ํ•˜๊ณ  ํšŒ์ˆ˜ํ•ด์•ผ ํ•œ๋‹ค. ํž™ ํ• ๋‹น์ด ๋งŽ์„์ˆ˜๋ก GC๊ฐ€ ํ•  ์ผ์ด ๋Š˜์–ด๋‚œ๋‹ค.

escape analysis โ€” ๋ฌด์—‡์ด ํž™์œผ๋กœ ๊ฐ€๋Š”๊ฐ€

Go ์ปดํŒŒ์ผ๋Ÿฌ๋Š” escape analysis๋กœ ๊ฐ’์„ ์Šคํƒ์— ๋‘˜์ง€ ํž™์— ๋‘˜์ง€ ๊ฒฐ์ •ํ•œ๋‹ค. ๊ธฐ์ค€์€ ๊ฐ’ ์ž์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ, ๊ทธ ๋ณ€์ˆ˜๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ฐธ์กฐ๊ฐ€ ํ•จ์ˆ˜ ๋ฐ–๊นŒ์ง€ ์‚ด์•„๋‚จ์•„์•ผ ํ•˜๋А๋ƒ๋‹ค. ๊ฐ™์€ ์ง€์—ญ ๋ณ€์ˆ˜๋ผ๋„ ๊ฐ’์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋ฉด ์Šคํƒ์— ๋จธ๋ฌผ๊ณ , ์ฃผ์†Œ๋กœ ๋ฐ˜ํ™˜ํ•˜๋ฉด ํž™์œผ๋กœ ๊ฐ„๋‹ค(โ€œescapeโ€).

func valueReturn() int {
    x := 10
    return x      // ๊ฐ’์˜ ๋ณต์‚ฌ๋ณธ๋งŒ ๋‚˜๊ฐ โ†’ x๋Š” ์Šคํƒ์— ๋จธ๋ฌพ, ํž™ ํ• ๋‹น ์—†์Œ
}
 
func pointerReturn() *int {
    x := 10
    return &x     // x์˜ ์ฃผ์†Œ๊ฐ€ ๋ฐ–์œผ๋กœ ๋‚˜๊ฐ โ†’ x๋Š” ํž™์œผ๋กœ escape
}

๋‘ ํ•จ์ˆ˜์˜ ์ฐจ์ด๋Š” ํ•จ์ˆ˜๊ฐ€ ๋๋‚˜๋Š” ์ˆœ๊ฐ„์— ๋“œ๋Ÿฌ๋‚œ๋‹ค.

  • valueReturn โ€” ๋๋‚˜๊ธฐ ์ง์ „์— x์˜ ๊ฐ’(10)์ด ํ˜ธ์ถœ ์ธก์œผ๋กœ ๋ณต์‚ฌ๋˜๊ณ , ํ•จ์ˆ˜ ์Šคํƒ ํ”„๋ ˆ์ž„์€ ํ†ต์งธ๋กœ ์‚ฌ๋ผ์ง„๋‹ค. ํ˜ธ์ถœ์ž๋Š” ์ด๋ฏธ ๋ณต์‚ฌ๋ณธ์„ ๋“ค๊ณ  ์žˆ์œผ๋‹ˆ x๊ฐ€ ์—†์–ด์ ธ๋„ ๋ฌธ์ œ์—†๋‹ค. ๊ทธ๋ž˜์„œ ์Šคํƒ์— ๋‘ฌ๋„ ๋œ๋‹ค.
  • pointerReturn โ€” ํ˜ธ์ถœ์ž๊ฐ€ x์˜ ์ฃผ์†Œ๋ฅผ ๋“ค๊ณ  ์žˆ๋Š”๋ฐ, ํ•จ์ˆ˜๊ฐ€ ๋๋‚˜๋ฉด์„œ ๊ทธ ์ฃผ์†Œ์˜ ์Šคํƒ ์Šฌ๋กฏ์ด ์‚ฌ๋ผ์ง€๋ฉด ๊ฐ€๋ฆฌํ‚ฌ ๊ณณ์ด ์—†์–ด์ง„๋‹ค(C๋ผ๋ฉด dangling pointer ๋ฒ„๊ทธ๋‹ค). ๊ทธ๋ž˜์„œ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” x๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ํž™์— ์˜ฌ๋ ค ํ•จ์ˆ˜๊ฐ€ ๋๋‚˜๋„ ์‚ด์•„์žˆ๊ฒŒ ๋งŒ๋“ ๋‹ค.

์ฆ‰ ๊ฐ’ ๋ณต์‚ฌ๋Š” escape๋ฅผ ์ผ์œผํ‚ค์ง€ ์•Š๊ณ , ์ฃผ์†Œ(ํฌ์ธํ„ฐ)๊ฐ€ ํ”„๋ ˆ์ž„ ๋ฐ–์œผ๋กœ ์ƒˆ์–ด๋‚˜๊ฐˆ ๋•Œ๋งŒ ํž™์œผ๋กœ ๊ฐ„๋‹ค. return &x๋ฟ ์•„๋‹ˆ๋ผ &x๋ฅผ ์ „์—ญ ๋ณ€์ˆ˜์— ์ €์žฅํ•˜๊ฑฐ๋‚˜, ๋ฐ–์œผ๋กœ ํƒˆ์ถœํ•˜๋Š” ํด๋กœ์ €๊ฐ€ x๋ฅผ ์บก์ฒ˜ํ•˜๋Š” ๊ฒฝ์šฐ๋„ ๊ฐ™์€ ์ด์œ ๋กœ escapeํ•œ๋‹ค. ํž™ ํ• ๋‹น์ด ๋Š˜๋ฉด GC ๋น„์šฉ์ด ๋”ฐ๋ผ์˜ค๋ฏ€๋กœ, ํฌ์ธํ„ฐ๋ฅผ ๋‚จ๋ฐœํ•˜๋ฉด ๊ทธ๋งŒํผ GC ๋ถ€ํ•˜๊ฐ€ ์ปค์ง„๋‹ค โ€” 6๋ฒˆ์—์„œ โ€œGC ๋ถ€ํ•˜๊ฐ€ ์ฆ๊ฐ€ํ•œ๋‹คโ€๊ณ  ํ•œ ์ด์œ ๋‹ค.

์–ด๋–ค ๊ฐ’์ด escapeํ•˜๋Š”์ง€๋Š” ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ ๋ฌผ์–ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

go build -gcflags="-m" main.go
# pointerReturn์—์„œ๋งŒ "moved to heap: x" ๊ฐ€ ๋œฌ๋‹ค

GC ๋ถ€ํ•˜๋ฅผ ์ค„์ด๋Š” ํŒจํ„ด

๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ป๊ฒŒ ๋ฐฐ์น˜ํ•˜๋А๋ƒ๋กœ ํž™ ํ• ๋‹น๊ณผ GC ๋ถ€ํ•˜๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

๊ฐ’ ํƒ€์ž…๊ณผ ์—ฐ์† ๋ฉ”๋ชจ๋ฆฌ. ๊ตฌ์กฐ์ฒด ์Šฌ๋ผ์ด์Šค([]Point)๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์— ์—ฐ์†์œผ๋กœ ๋†“์ด๊ณ  ํ• ๋‹น๋„ ํ•œ ๋ฒˆ์ด๋‹ค. ๋ฐ˜๋ฉด ํฌ์ธํ„ฐ ์Šฌ๋ผ์ด์Šค([]*Point)๋Š” ์›์†Œ๊ฐ€ ๋”ฐ๋กœ ํž™์— ํ• ๋‹น๋˜๊ธฐ ์‰ฌ์›Œ, GC๊ฐ€ ์ถ”์ ํ•  ๋Œ€์ƒ์ด ๊ทธ๋งŒํผ ๋Š˜๊ณ  ์บ์‹œ ํšจ์œจ๋„ ๋–จ์–ด์ง„๋‹ค. ํŠน๋ณ„ํ•œ ์ด์œ ๊ฐ€ ์—†์œผ๋ฉด ๊ฐ’ ์Šฌ๋ผ์ด์Šค๊ฐ€ ๋‚ซ๋‹ค.

๋ฒ„ํผ ์Šฌ๋ผ์ด์Šค ์žฌ์‚ฌ์šฉ. ๋ฐ˜๋ณต๋ฌธ์—์„œ ๋งค๋ฒˆ ์ƒˆ ์Šฌ๋ผ์ด์Šค๋ฅผ ํ• ๋‹นํ•˜๋ฉด ๊ทธ๋งŒํผ garbage๊ฐ€ ์Œ“์ธ๋‹ค. ์Šฌ๋ผ์ด์Šค ํ•˜๋‚˜๋ฅผ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด ๋ฒ„ํผ๋กœ ์žฌ์‚ฌ์šฉํ•˜๋ฉด ํ• ๋‹น์ด ํ•œ ๋ฒˆ์œผ๋กœ ์ค€๋‹ค.

// ๋งค ๋ฐ˜๋ณต๋งˆ๋‹ค ์ƒˆ๋กœ ํ• ๋‹น โ€” garbage ๋ˆ„์ 
func process(r io.Reader) {
    for {
        buf := make([]byte, 1024)   // ๋ฐ˜๋ณต๋งˆ๋‹ค ํ• ๋‹น
        n, err := r.Read(buf)
        if n > 0 {
            handle(buf[:n])
        }
        if err != nil {
            break
        }
    }
}
 
// ๋ฒ„ํผ ํ•˜๋‚˜๋ฅผ ์žฌ์‚ฌ์šฉ โ€” ํ• ๋‹น ํ•œ ๋ฒˆ
func process(r io.Reader) {
    buf := make([]byte, 1024)       // ํ•œ ๋ฒˆ๋งŒ ํ• ๋‹น
    for {
        n, err := r.Read(buf)       // ๊ฐ™์€ ๋ฒ„ํผ์— ๋ฎ์–ด์”€
        if n > 0 {
            handle(buf[:n])
        }
        if err != nil {
            break
        }
    }
}

Go GC์˜ ์„ฑํ–ฅ โ€” ์ €์ง€์—ฐ ์šฐ์„ 

Go์˜ GC๋Š” ๋™์‹œ(concurrent) ์‚ผ์ƒ‰ mark-and-sweep ๋ฐฉ์‹์ด๋‹ค. ํ”„๋กœ๊ทธ๋žจ์„ ๋ฉˆ์ถ”๊ณ  ํ•œ๊บผ๋ฒˆ์— ์ฒญ์†Œํ•˜๋Š” ๋Œ€์‹ , ํ”„๋กœ๊ทธ๋žจ๊ณผ ๋™์‹œ์— ๋Œ๋ฉด์„œ ์“ฐ๋ ˆ๊ธฐ๋ฅผ ํ‘œ์‹œยทํšŒ์ˆ˜ํ•œ๋‹ค. ์„ค๊ณ„ ์ฒ ํ•™์€ ๋‚ฎ์€ ์ง€์—ฐ์‹œ๊ฐ„(low latency) ์šฐ์„ ์ด๋‹ค. ์ž ๊น ๋ฉˆ์ถ”๋Š” stop-the-world ๊ตฌ๊ฐ„์„ ๊ทน๋„๋กœ ์งง๊ฒŒ ์œ ์ง€ํ•œ๋‹ค(Go 1.8 ์ดํ›„ ์„œ๋ธŒ๋ฐ€๋ฆฌ์ดˆ ์ˆ˜์ค€, ๋ณดํ†ต ์ˆ˜๋ฐฑ ๋งˆ์ดํฌ๋กœ์ดˆ. ํž™ ํฌ๊ธฐ์™€ ๋ถ€ํ•˜์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง„๋‹ค). ๋Œ€์‹  ์ „์ฒด ์ฒ˜๋ฆฌ๋Ÿ‰(throughput)์€ ์•ฝ๊ฐ„ ํฌ์ƒํ•˜๋Š” ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๋ฅผ ํƒํ–ˆ๋‹ค. ์งง๊ณ  ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ๋ฉˆ์ถค์ด ์„œ๋ฒ„ ์‘๋‹ต์„ฑ์— ์ค‘์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋˜ ๊ฐ์ฒด๋ฅผ ์˜ฎ๊ธฐ์ง€ ์•Š๋Š”(non-compacting) ๋ฐฉ์‹์ด๋ผ, GC๊ฐ€ ๋Œ์•„๋„ ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ฃผ์†Œ๊ฐ€ ๋„์ค‘์— ๋ฐ”๋€Œ์ง€ ์•Š๋Š”๋‹ค.

๋™์ž‘์„ ์กฐ์ ˆํ•˜๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ๋‘˜ ์žˆ๋‹ค.

  • GOGC โ€” ๋‹ค์Œ GC๋ฅผ ์–ธ์ œ ๋Œ๋ฆด์ง€ ์ •ํ•œ๋‹ค. ๊ธฐ๋ณธ๊ฐ’ 100์€ ๋Œ€๋žต โ€œ์ง์ „ GC ํ›„ ์‚ด์•„๋‚จ์€ ํž™๋งŒํผ ์ƒˆ๋กœ ํ• ๋‹น๋˜๋ฉด(์ฆ‰ ํž™์ด ์•ฝ ๋‘ ๋ฐฐ๊ฐ€ ๋˜๋ฉด) ๋‹ค์Œ GC๋ฅผ ๋Œ๋ฆฐ๋‹คโ€๋Š” ๋œป์ด๋‹ค. ๊ฐ’์„ ๋†’์ด๋ฉด GC๊ฐ€ ๋œ ์ž์ฃผ ๋Œ๊ณ  ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋” ์“ฐ๋ฉฐ, ๋‚ฎ์ถ”๋ฉด ์ž์ฃผ ๋Œ๊ณ  ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์•„๋‚€๋‹ค.
  • GOMEMLIMIT โ€” ์†Œํ”„ํŠธ ๋ฉ”๋ชจ๋ฆฌ ํ•œ๋„(Go 1.19+). ํž™์ด ์ด ํ•œ๋„์— ๊ฐ€๊นŒ์›Œ์ง€๋ฉด GC๊ฐ€ ๋” ์ ๊ทน์ ์œผ๋กœ ์ผํ•ด์„œ ๋ฉ”๋ชจ๋ฆฌ ์ดˆ๊ณผ๋ฅผ ๋ง‰๋Š”๋‹ค. ์ปจํ…Œ์ด๋„ˆ์ฒ˜๋Ÿผ ๋ฉ”๋ชจ๋ฆฌ ์ƒํ•œ์ด ์žˆ๋Š” ํ™˜๊ฒฝ์—์„œ OOM ๋ฐฉ์ง€์— ์“ด๋‹ค.

GOGC ํŠธ๋ฆฌ๊ฑฐ๋ฅผ ๋” ์ •ํ™•ํžˆ

์œ„์˜ โ€œํž™์ด ์•ฝ ๋‘ ๋ฐฐโ€๋Š” ์ง๊ด€์šฉ ๊ทผ์‚ฌ๋‹ค. Go 1.18๋ถ€ํ„ฐ ์‹ค์ œ ํŠธ๋ฆฌ๊ฑฐ ๊ธฐ์ค€์€ ์‚ด์•„์žˆ๋Š” ํž™๋ฟ ์•„๋‹ˆ๋ผ GC roots(๊ณ ๋ฃจํ‹ด ์Šคํƒยท์ „์—ญ ํฌ์ธํ„ฐ)๊นŒ์ง€ ํฌํ•จํ•œ๋‹ค. ์ •ํ™•ํ•œ ๊ณต์‹์€ ๋ชฉํ‘œ ํž™ = ์‚ด์•„์žˆ๋Š” ํž™ + (์‚ด์•„์žˆ๋Š” ํž™ + GC roots) ร— GOGC / 100์ด๊ณ , GC roots๊ฐ€ ์ž‘์„ ๋•Œ ๊ทผ์‚ฌ์ ์œผ๋กœ โ€œ์‚ด์•„์žˆ๋Š” ํž™์˜ ๋‘ ๋ฐฐโ€๊ฐ€ ๋œ๋‹ค. (์ถœ์ฒ˜: go.dev/doc/gc-guide)

Python์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ์™€ ๋น„๊ต

CPython์€ ์ฐธ์กฐ ์นด์šดํŒ…์ด ๊ธฐ๋ณธ์ด๊ณ , ์ˆœํ™˜ ์ฐธ์กฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ณ„๋„ GC๊ฐ€ ๋ณด์กฐ๋กœ ๋ˆ๋‹ค. ์ฐธ์กฐ ์นด์šดํŠธ๊ฐ€ 0์ด ๋˜๋Š” ์ฆ‰์‹œ ํ•ด์ œ๋˜๋Š” ๊ตฌ์กฐ๋ผ ์˜ˆ์ธก ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ์นด์šดํŠธ๋ฅผ ๊ฐฑ์‹ ํ•˜๋Š” ๋น„์šฉ์ด ์ƒ์‹œ ๋“ ๋‹ค. Go๋Š” ์ฐธ์กฐ ์นด์šดํŒ… ์—†์ด ๋™์‹œ mark-sweep์œผ๋กœ๋งŒ ๋Œ๋ฉฐ, ๊ฐ’ ํƒ€์ž…๊ณผ ์Šคํƒ ํ• ๋‹น์„ ์ ๊ทน ํ™œ์šฉํ•ด ์• ์ดˆ์— GC๊ฐ€ ๊ฑด๋“œ๋ฆด ๋Œ€์ƒ์„ ์ค„์ด๋Š” ์ชฝ์œผ๋กœ ์„ค๊ณ„๋๋‹ค.

Python ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ ํ•œ ์ค„ ์š”์•ฝ

Python์—์„œ๋Š” ์‹ ๊ฒฝ ์•ˆ ์จ๋„ ๋˜๋˜ ๊ฒƒ์„ Go์—์„œ๋Š” ๋ช…์‹œ์ ์œผ๋กœ ๋‹ค๋ค„์•ผ ํ•œ๋‹ค. ๊ฐ’์ด ๋ณต์‚ฌ๋˜๋Š”์ง€, ์ฐธ์กฐ๊ฐ€ ์ „๋‹ฌ๋˜๋Š”์ง€๋ฅผ ์ฝ”๋“œ์—์„œ ์ง์ ‘ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์ด Go ๋ฐฉ์‹์ด๋‹ค.