[Go] goroutine ๊ณผ channel ๋กœ API ์‹คํ–‰ ์‹œ๊ฐ„ ๊ฐœ์„ ํ•˜๊ธฐ

2024. 9. 13. 17:28ใ†Backend/๐Ÿฉต Go

 

๋ชฉ์ฐจ

- ์„œ๋ก 

- ๋™๊ธฐ์‹ ํ˜ธ์ถœ

- ๋น„๋™๊ธฐ ํ˜ธ์ถœ : Goroutine ํ™œ์šฉ

- ๋น„๋™๊ธฐ ํ˜ธ์ถœ ๊ฐœ์„  : Channel ํ™œ์šฉ

- ๊ฒฐ๋ก 

 

 

์„œ๋ก 

์—ฌ๋Ÿฌ ํ…Œํฌ ๊ธฐ์—…์˜ ๊ธฐ์ˆ  ๋ธ”๋กœ๊ทธ๋ฅผ ์ฝ๊ธฐ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ ๋งค๋ฒˆ ์—ฌ๋Ÿฌ ๋ธ”๋กœ๊ทธ ํ™ˆํŽ˜์ด์ง€๋ฅผ ๋ฐฉ๋ฌธํ•˜๋‹ค ๋ณด๋‹ˆ ์ž์ฃผ ๊ฐ€๋Š” ๋ธ”๋กœ๊ทธ๋Š” ๋”ฐ๋กœ ๋ชจ์•„์„œ ์ฝ๊ณ  ์‹ถ์€ ์ƒ๊ฐ์ด ๋“ค๋”๋ผ๊ณ ์š”. ์ด๋ฅผ ์œ„ํ•ด Go๋ฅผ ํ™œ์šฉํ•œ ํ…Œํฌ ๋ธ”๋กœ๊ทธ ์Šคํฌ๋ž˜ํผ๋ฅผ ๊ฐœ๋ฐœํ•˜๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ ๊ทธ๋Ÿฐ ์„œ๋น„์Šค๋Š” ๋งŽ์ง€ ์•Š๋ƒ๊ณ ์š”? ๋งž์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋„ ํ•œ๋ฒˆ ์ง์ ‘ ํ•ด๋ณด๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค๐Ÿ™ƒ.

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

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

 

์ด ๊ธ€์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ๋ฆ„์œผ๋กœ ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค:

์šฐ์„  ๊ฐ๊ฐ์˜ API๋ฅผ ๋ธ”๋กœํ‚น ๋ฐฉ์‹์œผ๋กœ ๊ฐ€์ ธ์˜ค๋Š” ๊ธฐ์กด ๋ฐฉ์‹์—์„œ, Go ์–ธ์–ด์˜ ํŠน์ง•์ธ goroutine ์„ ํ™œ์šฉํ•œ ๋น„๋™๊ธฐ์‹ API ํ˜ธ์ถœ, ๊ทธ๋ฆฌ๊ณ  channel์„ ํ™œ์šฉํ•œ ์ตœ์ข… ๊ฐœ์„ ๊นŒ์ง€ ๋‹จ๊ณ„๋ณ„๋กœ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐ ๋‹จ๊ณ„์—์„œ ์ง๋ฉดํ•œ ๋ฌธ์ œ์ ๊ณผ ๊ทธ ํ•ด๊ฒฐ ๊ณผ์ •, ๊ทธ๋ฆฌ๊ณ  ์„ฑ๋Šฅ ๊ฐœ์„ ์˜ ๊ฒฐ๊ณผ๋ฅผ ๊ตฌ์ฒด์ ์ธ ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๋™๊ธฐ์‹ ํ˜ธ์ถœ

๊ฐ ๋ธ”๋กœ๊ทธ์˜ ๋‚ด๋ถ€ ํ˜ธ์ถœ ๊ตฌํ˜„์„ ์—ฌ๊ธฐ์„œ ๋ณด์—ฌ๋“œ๋ฆฌ๊ธฐ์—” ๊ธ€์˜ ์ฃผ์ œ์™€ ๊ฑฐ๋ฆฌ๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐ๋˜์–ด ๊นƒํ—™ ๋ ˆํฌ๋กœ ๋Œ€์ฒดํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

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

result ์— ๋‹ด์„ ํ…Œํฌ ๋ธ”๋กœ๊ทธ๋Š” ์นด์นด์˜คํŽ˜์ด, ์˜ฌ๋ฆฌ๋ธŒ์˜, ๋‹น๊ทผ, ํ† ์Šค, ๋ฑ…ํฌ์ƒ๋Ÿฌ๋“œ๋กœ ์„ ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

type Post struct {
	Title   string
	Url     string
	Summary string
	Date    string
	Corp    compnay.Company
}

func main() {
	start := time.Now() // ์‹œ์ž‘ ์‹œ๊ฐ„

	var result []Post
	result = callSynchronous(result)

	log.Println("Total :", len(result))
	elapsed := time.Since(start) // ๊ฒฝ๊ณผ ์‹œ๊ฐ„
	log.Printf("Execution Time: %s\n", elapsed)
}


// ๋™๊ธฐ์‹ ์ฒ˜๋ฆฌ
func callSynchronous(result []Post) []Post {
	result = append(result, kakaopay.CallApi()...)
	result = append(result, oliveyoung.CallApi()...)
	result = append(result, daangn.CallApi()...)
	result = append(result, toss.CallApi()...)
	result = append(result, banksalad.CallApi()...)
	return result
}

 

๋™๊ธฐ์‹ ํ˜ธ์ถœ ๊ฒฐ๊ณผ ํ™•์ธ

๋™๊ธฐ์‹ ํ˜ธ์ถœ์€ 3.3์ดˆ๋ฅผ ๊ฑธ์ณ ์™„๋ฃŒ๋œ ๊ฒƒ์„ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค.

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

์šฐ์„ ์€ 5๊ฐœ์˜ ์™ธ๋ถ€ API ๋ฅผ ๋™๊ธฐ์‹์œผ๋กœ ํ˜ธ์ถœํ•  ๋•Œ 3.3์ดˆ๊ฐ€ ๋„˜๋Š” ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฐ ๊ฒƒ์„ ํ™•์ธํ–ˆ๊ณ , ์ด๋ฅผ ๊ณ ๋ฃจํ‹ด์„ ํ™œ์šฉํ•ด ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ๋ฐฉ์‹์œผ๋กœ ๊ฐœ์„ ํ•˜๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

 

 

๊ทธ๋ฆผ์œผ๋กœ ํ‘œํ˜„ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ฐ๊ฐ์˜ ํ…Œํฌ๋ธ”๋กœ๊ทธ๋ฅผ ๋™๊ธฐ์‹์œผ๋กœ ํ˜ธ์ถœํ•˜๋ฏ€๋กœ ํ•˜๋‚˜์˜ ๋ธ”๋กœ๊ทธ์—์„œ ์Šคํฌ๋ž˜ํ•‘์ด ์™„๋ฃŒ๋˜์–ด์•ผ ๋‹ค์Œ ๋ธ”๋กœ๊ทธ API ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์„ ๋‚˜ํƒ€๋ƒˆ์Šต๋‹ˆ๋‹ค. (๋ธ”๋กœ๊ทธ์˜ ํ˜ธ์ถœ ์ˆœ์„œ๋Š” ์ž„์˜๋กœ ์„ ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค)

 

 

 

๋น„๋™๊ธฐ ํ˜ธ์ถœ : Goroutine ํ™œ์šฉ

 

๊ณ ๋ฃจํ‹ด(Goroutine)์€ Go ์–ธ์–ด์˜ ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์œ„ํ•œ ๊ฒฝ๋Ÿ‰ ์“ฐ๋ ˆ๋“œ์ž…๋‹ˆ๋‹ค. ์ผ๋ฐ˜ ์“ฐ๋ ˆ๋“œ๋ณด๋‹ค ํ›จ์”ฌ ์ ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ ๋™์‹œ์— ์ˆ˜์ฒœ ๊ฐœ์˜ ๊ณ ๋ฃจํ‹ด์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์–ด ํšจ์œจ์ ์ธ ๋™์‹œ์„ฑ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. go ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ณ ๋ฃจํ‹ด์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๊ณ , ์ด๋ฅผ ํ™œ์šฉํ•ด ๊ธฐ์กด์˜ ๋™๊ธฐ์‹ ๋ธ”๋กœํ‚น Api ํ˜ธ์ถœ์„  ๋ณ‘๋ ฌ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋„๋ก ๊ฐœ์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๋ธ”๋กœ๊ทธ๋ฅผ ์ฐจ๋ก€๋กœ ํ˜ธ์ถœํ•˜๋˜ ๊ธฐ์กด ์ฝ”๋“œ์™€ ๋‹ค๋ฅด๊ฒŒ ๊ณ ๋ฃจํ‹ด์„ ํ™œ์šฉํ•œ ์ฝ”๋“œ๋Š” ์ด์ „๋ณด๋‹ค ๋ณต์žกํ•ด์กŒ์Šต๋‹ˆ๋‹ค.

func callGoroutine(result []Post) []Post {
	// (1)
	var mu sync.Mutex
	var wg sync.WaitGroup

	// (2)
	scrapers := []func() []Post{
		kakaopay.CallApi,
		oliveyoung.CallApi,
		daangn.CallApi,
		toss.CallApi,
		banksalad.CallApi,
	}

	for _, scraper := range scrapers {
		wg.Add(1)
		// (3)
		go func(scrapeFunc func() []Post) {
			defer wg.Done()

			// (4)
			posts := scrapeFunc()
            
			mu.Lock()
			result = append(result, posts...)
			mu.Unlock()
		}(scraper)
	}
	// (5)
	wg.Wait()
	return result
}

 

์œ„ ํ•จ์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค:

 

(1) sync.Mutex์™€ sync.WaitGroup์„ ์‚ฌ์šฉํ•˜์—ฌ ๋™์‹œ์„ฑ ์ œ์–ด

(2) ๋ธ”๋กœ๊ทธ์˜ ์Šคํฌ๋ž˜ํ•‘ ํ•จ์ˆ˜๋ฅผ scrapers ์Šฌ๋ผ์ด์Šค์— ์ €์žฅ

(3) ๊ฐ ์Šคํฌ๋ž˜ํ•‘ ํ•จ์ˆ˜์— ๋Œ€ํ•ด ๊ณ ๋ฃจํ‹ด์„ ์ƒ์„ฑํ•˜์—ฌ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰

(4) ๊ณ ๋ฃจํ‹ด ๋‚ด์—์„œ: ์Šคํฌ๋ž˜ํ•‘ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ๊ฒฐ๊ณผ ๋ฆฌํ„ด

(5) WaitGroup์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  ๊ณ ๋ฃจํ‹ด์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ

 

 

 

 

 

๊ณ ๋ฃจํ‹ด์„ ํ™œ์šฉํ•œ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋Š” ๋ชจ๋“  API ํ˜ธ์ถœ์ด ๋™์‹œ์— ์‹คํ–‰๋˜๋ฏ€๋กœ ์ „์ฒด ์‹คํ–‰ ์‹œ๊ฐ„์ด ํฌ๊ฒŒ ๋‹จ์ถ•๋ฉ๋‹ˆ๋‹ค. ๊ณ ๋ฃจํ‹ด์„ ํ™œ์šฉํ•˜์—ฌ 0.6์ดˆ ๋งŒ์— ๋ชจ๋“  ๋ธ”๋กœ๊ทธ์˜ ์Šคํฌ๋ž˜ํ•‘์„ ์™„๋ฃŒํ•˜๋ฉฐ ์ด์ „์˜ ๋™๊ธฐ์‹ ์ฒ˜๋ฆฌ(3.3์ดˆ)์— ๋น„ํ•ด ์‹คํ–‰์‹œ๊ฐ„์„ ํฌ๊ฒŒ ๋‹จ์ถ•ํ•œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์œ„ ์ฝ”๋“œ๋กœ๋„ ์ถฉ๋ถ„ํžˆ ๋‚˜์€ ์„ฑ๋Šฅ์„ ๋‚ผ ์ˆ˜ ์žˆ์ง€๋งŒ ์‚ด์ง ์•„์‰ฌ์šด ๋ถ€๋ถ„๋„ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ๋ฐ”๋กœ mutex๋ฅผ ์‚ฌ์šฉํ•ด ๊ณต์œ  ์ž์›(result)์— ๋ฝ์„ ๊ฑฐ๋Š” ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ๊ณ ๋ฃจํ‹ด์œผ๋กœ API ํ˜ธ์ถœ์€ ๋ณ‘๋ ฌ์ ์œผ๋กœ ์‹คํ–‰๋˜์ง€๋งŒ ๊ฒฐ๊ณผ๋ฅผ ๊ณต์œ  ์ž์›์— ๋‹ด๊ธฐ ์œ„ํ•ด์„  mutex ๋ฝ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. mutex ๋Š” ๊ณต์œ ์ž์›์˜ ๊ฒฝ์Ÿ ์กฐ๊ฑด์„ ๋ฐฉ์ง€ํ•˜๋ฉฐ ๋™์‹œ์„ฑ ์ด์Šˆ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•˜์ง€๋งŒ, ๊ฒฐ๊ตญ ๊ฐœ๋ณ„ ๊ณ ๋ฃจํ‹ด์ด ๋ธ”๋กœํ‚น ๋˜๋Š” ํšจ๊ณผ๋ฅผ ์ดˆ๋ž˜ํ•ฉ๋‹ˆ๋‹ค.

 

 

๊ณ ๋ฃจํ‹ด์œผ๋กœ ๊ฐœ์„ ํ•œ ํ๋ฆ„์€ ์œ„์˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. 5๊ฐœ์˜ ํ…Œํฌ๋ธ”๋กœ๊ทธ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•œ API ๋ฅผ ๋ชจ๋‘ ๋ณ‘๋ ฌ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

 

 

Go ์˜ Mutex ๋” ์•Œ์•„๋ณด๊ธฐ

๋”๋ณด๊ธฐ

Go ์˜ ๋ฎคํ…์Šค(mutex)๋Š” ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ์ค‘์š”ํ•œ ๋™๊ธฐํ™” ๋„๊ตฌ๋กœ, ์œ„ ์ฝ”๋“œ์—์„œ๋Š” ์—ฌ๋Ÿฌ ๊ณ ๋ฃจํ‹ด์ด ๊ณต์œ  ์ž์›(result)์— ๋™์‹œ ์ ‘๊ทผ ํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค. mutex ๋Š” Lock()์„ ํ˜ธ์ถœํ•˜๋ฉด ๋ฝ์„ ํš๋“ํ•˜๊ณ , Unlock()์„ ํ˜ธ์ถœํ•˜๋ฉด ๋ฝ์„ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค. ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ๊ณ ๋ฃจํ‹ด๋งŒ ๋ฎคํ…์Šค์˜ ๋ฝ์„ ์†Œ์œ ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋‹ค๋ฅธ ๊ณ ๋ฃจํ‹ด๋“ค์€ ๋ฝ์ด ํ•ด์ œ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค.

 

mu.Lock()๊ณผ mu.Unlock()๋Š” ๊ฐœ๋ณ„ ๊ณ ๋ฃจํ‹ด์„ ๋ธ”๋กœํ‚นํ•˜๋Š” ๋™์ž‘์ž…๋‹ˆ๋‹ค. ์ด ์ฝ”๋“œ๋Š” ๋ฉ”์ธ ๊ณ ๋ฃจํ‹ด์ด ์•„๋‹Œ ๊ฐ ๊ณ ๋ฃจํ‹ด์ด result์— ๋ฐ์ดํ„ฐ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด **Mutex(๋ฎคํ…์Šค)**๋ฅผ ์‚ฌ์šฉํ•ด ์ž ๊ธˆ์„ ๊ฑธ๊ณ  ํ•ด์ œํ•˜๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค.

 

mu.Lock():

 

๊ฐ ๊ณ ๋ฃจํ‹ด์€ result์— ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ ์ „์— mu.Lock()์„ ํ˜ธ์ถœํ•˜์—ฌ ๋ฎคํ…์Šค๋ฅผ ์ž ๊ธˆ๋‹ˆ๋‹ค.

์ž ๊ธˆ์ด ๊ฑธ๋ฆฐ ๊ณ ๋ฃจํ‹ด์ด result๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋™์•ˆ ๋‹ค๋ฅธ ๊ณ ๋ฃจํ‹ด์€ mu.Lock()์—์„œ ๋Œ€๊ธฐ(๋ธ”๋กœํ‚น)ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, mu.Lock()์„ ํ˜ธ์ถœํ•œ ๊ณ ๋ฃจํ‹ด๋งŒ์ด result์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ณ , ๋‹ค๋ฅธ ๊ณ ๋ฃจํ‹ด์€ ๋ฎคํ…์Šค๊ฐ€ ํ•ด์ œ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

mu.Unlock():

 

๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด mu.Unlock()์„ ํ˜ธ์ถœํ•˜์—ฌ ์ž ๊ธˆ์„ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ๊ณ ๋ฃจํ‹ด ์ค‘ ํ•˜๋‚˜๊ฐ€ mu.Lock() ๋Œ€๊ธฐ ์ƒํƒœ์—์„œ ๊นจ์–ด๋‚˜ result์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

์ฆ‰ ๊ฐœ๋ณ„ ๊ณ ๋ฃจํ‹ด์ด ๋ธ”๋กœํ‚น๋˜๋ฉด์„œ ํ•œ ๊ณ ๋ฃจํ‹ด์ด mu.Lock()์„ ๊ฑธ๊ณ  result๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋™์•ˆ, ๋‹ค๋ฅธ ๊ณ ๋ฃจํ‹ด๋“ค์€ mu.Lock()์—์„œ ๋ธ”๋กœํ‚น๋˜์–ด, result์— ์ ‘๊ทผํ•˜์ง€ ๋ชปํ•˜๊ณ  ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค. ์ด ๋•Œ ๋ฉ”์ธ ๊ณ ๋ฃจํ‹ด์€ ๋ธ”๋กœํ‚น๋˜์ง€ ์•Š์Œ: ๋ฉ”์ธ ๊ณ ๋ฃจํ‹ด์€ wg.Wait()์—์„œ ๋ชจ๋“  ๊ณ ๋ฃจํ‹ด์ด ์™„๋ฃŒ๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์—, mu.Lock()๊ณผ ๊ด€๋ จ๋œ ๋™์ž‘์—๋Š” ๊ด€์—ฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. mu.Lock()๊ณผ mu.Unlock()์€ ๊ณ ๋ฃจํ‹ด ๊ฐ„์˜ ๊ฒฝ์Ÿ ์ƒํƒœ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋ฒ•์ด๋ฉฐ, ๋ฉ”์ธ ๊ณ ๋ฃจํ‹ด์ด ์ง์ ‘์ ์œผ๋กœ ๋ธ”๋กœํ‚น๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

๋น„๋™๊ธฐ ํ˜ธ์ถœ ๊ฐœ์„ : channel ํ™œ์šฉ

๊ณ ๋ฃจํ‹ด์„ ํ™œ์šฉํ•˜๋ฉฐ API ๋ฅผ ๋น„๋™๊ธฐ ํ˜ธ์ถœํ–ˆ์ง€๋งŒ ์œ„์˜ ๋ฐฉ์‹์€ mutex ๋ฝ์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์ผ๋ถ€ ๊ตฌ๊ฐ„์—์„œ ๋ธ”๋กœํ‚น์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฎคํ…์Šค(mutex)๋กœ ๊ณต์œ  ์ž์›์˜ ์ ‘๊ทผ์„ ์ œ์–ดํ•˜๋Š” ๊ฒƒ์€ ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์ด์ง€๋งŒ, ์—ฌ๋Ÿฌ ๊ณ ๋ฃจํ‹ด์ด ๋นˆ๋ฒˆํ•˜๊ฒŒ ๊ณต์œ  ์ž์›์— ์ ‘๊ทผํ•˜๋Š” ๊ฒฝ์šฐ์—” ๋ฎคํ…์Šค๋กœ ์ธํ•œ ๋ธ”๋กœํ‚น์ด ์ „์ฒด ํ”„๋กœ๊ทธ๋žจ์˜ ์„ฑ๋Šฅ์„ ์ €ํ•˜์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

 

์ด๋Ÿฌํ•œ ์ƒํ™ฉ์—์„œ Go๋Š” ์ฑ„๋„(channel)์ด๋ผ๋Š” ๋Œ€์•ˆ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

Go ์˜ ์ฑ„๋„์€ ๊ณ ๋ฃจํ‹ด์„ ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” ํ†ต๋กœ์ž…๋‹ˆ๋‹ค. ์ฑ„๋„์€ ์–‘๋ฐฉํ–ฅ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์•„๋ž˜ ์ด๋ฏธ์ง€์ฒ˜๋Ÿผ ๊ณ ๋ฃจํ‹ด์€ ๋™์ผํ•œ ์ฑ„๋„์„ ์ด์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ตํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

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

* ๐Ÿ“Œ ๊ทธ๋ ‡๋‹ค๊ณ  ์ฑ„๋„์ด ๋ฎคํ…์Šค๋ฅผ ์™„์ „ํžˆ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ๋‹จ ์˜๋ฏธ๋Š” ์•„๋‹™๋‹ˆ๋‹ค. ์ฑ„๋„์€ ์ฃผ๋กœ ๊ณ ๋ฃจํ‹ด ๊ฐ„์˜ ํ†ต์‹ ๊ณผ ์ž‘์—… ์กฐ์œจ์— ์‚ฌ์šฉ๋˜๋ฉฐ, ๋ฎคํ…์Šค๋Š” ์งง์€ ์‹œ๊ฐ„ ๋™์•ˆ์˜ ๊ณต์œ  ์ž์› ๋ณดํ˜ธ์— ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค. ๋‘˜์€ ๊ฐ๊ฐ ์ ์ ˆํžˆ ์‚ฌ์šฉํ•  ๋•Œ๊ฐ€ ์žˆ์œผ๋ฉฐ ๋•Œ๋กœ๋Š” ๋‘˜์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š”๊ฒƒ์ด ํ•ด๊ฒฐ์ฑ…์ด ๋  ์ˆ˜๋„ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

 

๋‹ค์Œ์€ ์ฑ„๋„์„ ์ด์šฉํ•ด ๊ฐœ์„ ๋œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค:

func callGoroutineChannel(result []Post) []Post {
	scrapers := []func() []Post{
		kakaopay.CallApi,
		oliveyoung.CallApi,
		daangn.CallApi,
		toss.CallApi,
		banksalad.CallApi,
	}
	resultChan := make(chan []Post, len(scrapers))

	var wg sync.WaitGroup
	for _, scraper := range scrapers {
		wg.Add(1)
		go func(scrapeFunc func() []Post) {
			defer wg.Done()
			resultChan <- scrapeFunc()
		}(scraper)
	}

	go func() {
		wg.Wait()
		close(resultChan)
	}()

	for posts := range resultChan {
		result = append(result, posts...)
	}

	return result
}

 

 

1. ๋ฒ„ํผ๋œ ์ฑ„๋„ ์ƒ์„ฑ

resultChan := make(chan []Post, len(scrapers))

๋ฒ„ํผ์˜ ํฌ๊ธฐ๋Š” scarppers ๋ฐฐ์—ด์˜ ๊ธธ์ด๋กœ ์„ค์ •๋œ resultChan ์ฑ„๋„์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ์ฑ„๋„์€ ๊ฐ ๊ณ ๋ฃจํ‹ด์ด ์Šคํฌ๋ž˜ํ•‘ํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ํ†ต๋กœ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋ฒ„ํผ๋œ ์ฑ„๋„์„ ์ด์šฉํ•จ์œผ๋กœ, ๊ณ ๋ฃจํ‹ด์ด ๊ฒฐ๊ณผ๋ฅผ ์ฑ„๋„์— ์ „์†กํ•˜๋Š” ๊ณผ์ •์—์„œ ๋ธ”๋กœํ‚น๋˜์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ๋ฒ„ํผ์˜ ํฌ๊ธฐ๊ฐ€ ์ถฉ๋ถ„ํ•˜๋‹ค๋ฉด, ๊ณ ๋ฃจํ‹ด์ด ๊ฒฐ๊ณผ๋ฅผ ์ฆ‰์‹œ ์ „์†กํ•˜๊ณ  ์ข…๋ฃŒ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

2. ๊ณ ๋ฃจํ‹ด์œผ๋กœ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ

๊ฐ ์Šคํฌ๋ž˜ํ•‘ ํ•จ์ˆ˜๋ฅผ ๊ณ ๋ฃจํ‹ด์œผ๋กœ ๋ณ‘๋ ฌ ์‹คํ–‰ํ•˜๋ฉฐ, ๊ฐ ๊ณ ๋ฃจํ‹ด์€ ์Šคํฌ๋ž˜ํ•‘ ๊ฒฐ๊ณผ๋ฅผ resultChan์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ณ ๋ฃจํ‹ด์ด ์™„๋ฃŒ๋˜๋ฉด WaitGroup์„ ์‚ฌ์šฉํ•ด ๊ฐœ๋ณ„ ๊ณ ๋ฃจํ‹ด์˜ ์ž‘์—…์ด ๋๋‚ฌ๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

3. ์ฑ„๋„ ์ˆ˜์‹  ๋ฐ ๊ฒฐ๊ณผ ์ˆ˜์ง‘

for posts := range resultChan ๊ตฌ๋ฌธ์„ ํ†ตํ•ด ์ฑ„๋„์—์„œ ๊ฒฐ๊ณผ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ์ˆ˜์‹ ํ•ฉ๋‹ˆ๋‹ค. ์ฑ„๋„์ด ๋‹ซํž ๋•Œ๊นŒ์ง€ ์ด ๋™์ž‘์ด ๋ฐ˜๋ณต๋˜๋ฉฐ, ์ฑ„๋„์ด ๋‹ซํžˆ๋ฉด for ๋ฃจํ”„๋„ ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” range ๊ตฌ๋ฌธ์ด <- resultChan ๊ณผ ๋™์ผํ•œ ์ˆ˜์‹  ๋™์ž‘์„ ๋ฐ˜๋ณต์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

4. WatiGroup ๊ณผ ์ฑ„๋„ ์ข…๋ฃŒ

๋ณ„๋„์˜ ๊ณ ๋ฃจํ‹ด์—์„œ wg.Wait()๋ฅผ ํ˜ธ์ถœํ•ด, ๋ชจ๋“  ๊ณ ๋ฃจํ‹ด์ด ์™„๋ฃŒ๋  ๋•Œ ์ฑ„๋„์„ close(resultChan)๋กœ ๋‹ซ์Šต๋‹ˆ๋‹ค. ์ฑ„๋„์ด ๋‹ซํžˆ๋ฉด ๋” ์ด์ƒ ์ƒˆ๋กœ์šด ๊ฐ’์ด ์ „์†ก๋˜์ง€ ์•Š์œผ๋ฉฐ, ์ฑ„๋„์˜ ๋ฐ์ดํ„ฐ๋Š” ์•ˆ์ „ํ•˜๊ฒŒ ๋ชจ๋‘ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

 

 

channel ์„ ์‚ฌ์šฉํ•œ ๊ฒฐ๊ณผ๋Š” 0.5์ดˆ๋กœ mutex ๋ฅผ ์‚ฌ์šฉํ•œ ๋ฐฉ์‹๊ณผ ๋น„๊ตํ–ˆ์„ ๋•Œ ์ƒ๊ฐ๋ณด๋‹ค ์œ ์˜๋ฏธํ•œ ๊ฐœ์„ ์€ ์—†์Šต๋‹ˆ๋‹ค.

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

 

๊ฒฐ๋ก 

 

๋™๊ธฐ์‹ ๋ณด๋‹ค ๋น„๋™๊ธฐ์‹์ด ๋น ๋ฅธ๊ฑด ์‚ฌ์‹ค ๋„ˆ๋ฌด ๋‹น์—ฐํ•œ ์–˜๊ธฐ์ง€๋งŒ ใ…Žใ…Ž,, ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ๋ฅผ ํ†ตํ•ด Go ์–ธ์–ด์˜ ๋™์‹œ์„ฑ ๋ชจ๋ธ์„ ์‹ค์ œ๋กœ ์ ์šฉํ•ด๋ณผ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์Šคํฌ๋ž˜ํผ ํ˜ธ์ถœ ๊ณผ์ •์—์„œ ๋™๊ธฐ์‹ ํ˜ธ์ถœ๋ถ€ํ„ฐ goroutine์„ ํ™œ์šฉํ•œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ, ๊ทธ๋ฆฌ๊ณ  channel์„ ์ด์šฉํ•œ ๊ฐœ์„ ๊นŒ์ง€ ๋‹จ๊ณ„์ ์œผ๋กœ ์ ‘๊ทผํ•˜๋ฉฐ ๊ฐ ๋ฐฉ์‹์˜ ํŠน์ง•์„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

Goroutine ์„ ์‚ฌ์šฉํ•œ ๊ฐ„๋‹จํ•˜๊ณ  ํšจ์œจ์ ์ธ ๋™์‹œ์„ฑ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์—ˆ๊ณ , mutex ๋ฅผ ์‚ฌ์šฉํ•œ ๊ณต์œ  ์ž์› ์ ‘๊ทผ ์ œ์–ด์˜ ์ค‘์š”์„ฑ๊ณผ ํ•œ๊ณ„๋ฅผ ํŒŒ์•…ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜์•„๊ฐ€ channel ์„ ํ™œ์šฉํ•ด lock ์„ ์ œ๊ฑฐํ•˜์—ฌ ๋”์šฑ ์œ ์—ฐํ•˜๊ณ  Go ์Šค๋Ÿฌ์šด(?) ๋™์‹œ์„ฑ ์ฒ˜๋ฆฌ๋ฐฉ์‹์— ๋Œ€ํ•ด์„œ๋„ ์•Œ๊ฒŒ ๋์Šต๋‹ˆ๋‹ค.

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