/bumblebee

๐ŸŒŸ ๊ฒฝํฌ๋Œ€ํ•™๊ต ์ปค๋ฎค๋‹ˆํ‹ฐ ์ฟ ๋ฎค์˜ ์ด๋ฏธ์ง€๋ฅผ ์ž์œ ์ž์žฌ๋กœ ๋ณ€ํ˜•ํ•˜๋Š” ์ด๋ฏธ์ง€ ํ”„๋กœ์„ธ์‹ฑ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค

Primary LanguageGo

bumblebee - ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์„œ๋ฒ„

bumblebee๋Š” ์ฟ ๋ฎค์˜ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์ž‘์—…์„ ๋‹ด๋‹นํ•˜๋Š” ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค์ด๋‹ค. Go์˜ Worker pool pattern์ด๋‚˜ pipeline pattern, Fan-in Fan-out pattern๊ณผ ๊ฐ™์€ ์—ฌ๋Ÿฌ Concurrency pattern(๋™์‹œ์„ฑ ํŒจํ„ด)๋“ค์„ ์ ์šฉ์‹œ์ผœ๋ณด๊ณ ์žํ–ˆ์œผ๋ฉฐ ๊ธฐ์กด์˜ ๋‹จ์ˆœํ•œ ํ•จ์ˆ˜ ํ˜ธ์ถœ ํ˜•ํƒœ์™€๋Š” ๋‹ค๋ฅธ ๊ตฌ์กฐ๋ฅผ ๊ฐ–๊ณ ์žˆ๋‹ค.

Concurrency pattern in Go

Go ์–ธ์–ด์˜ ํฐ ํŠน์ง• ์ค‘ ํ•˜๋‚˜๋Š” ๋‹ค์–‘ํ•œ Concurrency pattern์„ ์ด์šฉํ•˜๊ธฐ ์‰ฝ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๋ช‡ ๊ฐ€์ง€ Concurrency pattern์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • Worker pool pattern - ์š”์ฒญ์ด ์žˆ์„ ๋•Œ๋งˆ๋‹ค Worker(Goroutine)์ด ์ƒ๊ฒจ๋‚˜๋ฉฐ ๊ทธ ๊ฐœ์ˆ˜์— ์ œํ•œ์ด ์—†๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ผ์ •ํ•œ pool size๋งŒํผ๋งŒ goroutine์„ ์ƒ์„ฑํ•˜๊ณ , ์š”์ฒญ๋งŒ channel์„ ํ†ตํ•ด ๋ถ€๋ถ„ ๋ถ€๋ถ„ ์ „๋‹ฌํ•ด์ฃผ๋Š” ํŒจํ„ด
  • Pipeline pattern - A ๋‹จ๊ณ„์—์„œ ์ž‘์—… ์ฒ˜๋ฆฌ๋ฅผ ๋ชจ๋‘ ์™„๋ฃŒํ•œ ๋’ค์— ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ํ†ต์งธ๋กœ ๋ฆฌํ„ดํ•˜๊ณ , ๊ทธ๊ฒƒ์„ ๋‹ค์Œ ๋‹จ๊ณ„์ธ B ๋‹จ๊ณ„๊ฐ€ ์ž…๋ ฅ์œผ๋กœ์„œ ์ด์šฉํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ A ๋‹จ๊ณ„์—์„œ๋Š” ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ž‘์—… ์ฒ˜๋ฆฌ๋ฅผ ์ „๋‹ฌํ•  channel์„ ๋ฆฌํ„ดํ•˜๊ณ  B ๋‹จ๊ณ„๋„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” channel์„ ์ž…๋ ฅ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ํŒจํ„ด. channel์„ ์ด์šฉํ•ด A์™€ B ๋‹จ๊ณ„ ์‚ฌ์ด์˜ pipline์ด ์ƒ์„ฑ๋œ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
  • Fan-in Fan-out pattern - Fan-in์ด๋ž€ ์—ฌ๋Ÿฌ Worker(goroutine)๋กœ๋ถ€ํ„ฐ 1๊ฐœ์˜ channel์— ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์˜ค๋Š” ๊ฒƒ์„ ๋งํ•˜๊ณ , Fan-out์€ ์—ฌ๋Ÿฌ Worker(goroutine)์œผ๋กœ๋ถ€ํ„ฐ 1๊ฐœ์˜ channel์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ๋น ์ ธ๋‚˜๊ฐ€๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค. ์ฃผ๋กœ ์–ด๋–ค worker๊ฐ€ 1๊ฐœ์˜ channel ์† ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ๊ฐ€๊ฒŒ ๋  ์ง€๋Š” idleํ•œ worker ์ค‘ randomํ•˜๊ฒŒ ์ •ํ•ด์ง„๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

Fan-in Fan-out pattern ์†์— pipeline pattern์ด ์†ํ•  ์ˆ˜๋„ ์žˆ๋Š” ๋“ฑ ๊ฐ๊ฐ์˜ pattern์€ ์„œ๋กœ ์™„์ „ํžˆ ๋…๋ฆฝ๋œ ๋ณ„๊ฐœ์˜ ํŒจํ„ด์ด ์•„๋‹Œ ๋“ฏ ํ•˜๋‹ค.

bumblebee๋Š” ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์‹œ์— Fan-in Fan-out pattern์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ณ , ์‚ฌ์‹ค์ƒ Fan-in Fan-out์„ ์œ„ํ•ด์„  ๊ฐ step๊ฐ„์˜ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ์„ ์œ„ํ•œ pipeline pattern, N๊ฐœ์˜ worker๋“ค์ด ํ•œ channel์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ๊ฐ€๊ธฐ ์œ„ํ•œ worker pool pattern ๋“ฑ์ด ์ ์šฉ๋˜์–ด์•ผํ–ˆ๋‹ค.

์‚ฌ์šฉ๋œ Concurrency pattern์— ๋Œ€ํ•˜์—ฌ

  1. ๊ฐ„๋‹จํžˆ ๋งํ•˜์ž๋ฉด Fan-in Fan-out pattern์„ ์‚ฌ์šฉ ์ค‘.
  2. ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์— ์‘๋‹ตํ•˜๋Š” HttpHandling gorutine๋“ค(๊ฐœ์ˆ˜๊ฐ€ ์ •ํ•ด์ง€์ง€ ์•Š์Œ)์ด 1๊ฐœ์˜ ์ด๋ฏธ์ง€ ๋ฆฌ์‚ฌ์ด์ง• ์ž‘์—… channel์— ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌ
  3. ์ด๋ฏธ์ง€ ๋ฆฌ์‚ฌ์ด์ง• ์›Œ์ปค๋“ค์ธ M๊ฐœ์˜ goroutine๋“ค์ด ํ•ด๋‹น channel์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ๊บผ๋‚ด์–ด ๋ฆฌ์‚ฌ์ด์ง• ์ž‘์—…
  4. ๋ฆฌ์‚ฌ์ด์ง• ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด ์—…๋กœ๋“œ ์ž‘์—… channel์— ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.
  5. ์—…๋กœ๋“œ ์›Œ์ปค์ธ L๊ฐœ์˜ goroutine๋“ค์ด ํ•ด๋‹น channel์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ๊บผ๋‚ด์–ด ์‹ค์ œ ์—…๋กœ๋“œ ์ž‘์—…์„ ํ•˜๋Š” goroutine์„ ์‹คํ–‰์‹œํ‚จ๋‹ค.

์ด๋ ‡๊ฒŒ concurrency pattern์„ ์ด์šฉํ•  ๋•Œ์˜ ์žฅ์ ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž.

์žฅ์  1. ์ „์ฒด ์ž‘์—…์ด ๋Š˜์–ด์ง€์ง€ ์•Š๊ณ , ์•ž์˜ ์ž‘์—…์€ ์šฐ์„ ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋  ์ˆ˜ ์žˆ๋‹ค.

CPU Boundํ•œ ์ž‘์—…์„ ๋™์‹œ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ CPU์˜ ํ•œ๊ณ„ ์ƒ ์ž‘์—…๋“ค์ด ๊ณจ๊ณ ๋ฃจ ์ˆ˜ํ–‰๋˜์–ด์•ผํ•˜๋ฏ€๋กœ thread๋‚˜ goroutine์ด ๋งŽ์„ ์ˆ˜๋ก ์ „์ฒด ์ž‘์—…๋“ค์ด ๋Š˜์–ด์ง„๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด 30๊ฐœ์˜ ์š”์ฒญ์ด ๋น„์Šทํ•œ ์‹œ๊ธฐ์— ๋“ค์–ด์˜จ๋‹ค๋ฉด 30๊ฐœ์˜ ์ด๋ฏธ์ง€ ๋ฆฌ์‚ฌ์ด์ง• goroutine์ด ์ƒ์„ฑ๋˜๊ณ , 30๊ฐœ๊ฐ€ ๊ณจ๊ณ ๋ฃจ ๋ชจ๋‘ ์ž‘์—…์ด ๋๋‚  ๋•Œ์ฏค ์šฐ๋ฃจ๋ฃจ ์ž‘์—…์ด ์™„๋ฃŒ๋œ๋‹ค.

๋ฐ˜๋ฉด ์ˆ˜ํ–‰์ด๋ฏธ์ง€ ๋ฆฌ์‚ฌ์ด์ง• ์ž‘์—…์„ ์˜ˆ๋ฅผ ๋“ค์–ด 6๊ฐœ์˜ goroutine์ด ๋‹ด๋‹นํ•˜๋„๋ก Worker pool์„ ์ด์šฉํ•œ๋‹ค๋ฉด 30๊ฐœ์˜ ์š”์ฒญ์ด ์™”๋‹ค๊ณ ํ•ด์„œ 30๊ฐœ์˜ ๊ณ ๋ฃจํ‹ด์ด ์ƒ์„ฑ๋œ ๋’ค ์ „์ฒด 30๊ฐœ์˜ ์ž‘์—…์ด ๋Š˜์–ด์ง€๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ 6๊ฐœ ์ž‘์—… ๋‹จ์œ„๋กœ ๋ฐ”๋กœ ๋ฐ”๋กœ ์ฒ˜๋ฆฌ๋œ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค. Throughput๋ฉด์—์„œ๋Š” ๋ณ„ ์ฐจ์ด๊ฐ€ ์—†์ง€๋งŒ ๊ฐœ๋ณ„ ์ž‘์—… ๋ฉด์—์„œ๋Š” latency๊ฐ€ ํฌ๊ฒŒ ๊ฐ์†Œํ•˜๊ณ , Memory ํšจ์œจ๋ฉด์—์„œ๋„ ์ „์ฒด ์ž‘์—…์— ๋Œ€ํ•œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ณ„์† ์ ์œ ํ•  ํ•„์š” ์—†์ด ์™„๋ฃŒ๋œ ์ž‘์—…์— ๋Œ€ํ•œ ๋ฉ”๋ชจ๋ฆฌ๋Š” ๋จผ์ € ํ•ด์ œ๋  ์ˆ˜ ์žˆ์œผ๋‹ˆ ์šฐ์ˆ˜ํ•˜๋‹ค.

์žฅ์  2. ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค ์„œ๋น„์Šค ์ด์šฉ ์—†์ด ๋ฉ”์‹œ์ง€ ๊ธฐ๋Šฅ์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Image ์„œ๋ฒ„ ํ•˜๋‚˜๋ฅผ ํ•˜๋ฉด์„œ App๋‚ด์˜ ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ์„ ์œ„ํ•ด Kafka๋‚˜ RabbitMQ์™€ ๊ฐ™์€ ์„œ๋น„์Šค๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒƒ์€ ํšจ์œจ์ ์ด์ง€๋„ ์•Š๊ณ  ์„ฑ๊ฐ€์‹ค ๊ฒƒ์ด๋‹ค.

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

ํ•˜์ง€๋งŒ pipeline ํ˜น์€ fan-in fan-out ํŒจํ„ด์„ ์ด์šฉํ•˜๋ฉด ๋ฉ”์‹œ์ง• ์‹œ์Šคํ…œ์„ ์ด์šฉํ•  ๋•Œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ•œ ์ž‘์—…์€ ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ๋งŒ ์‹œ์ผœ๋†“๊ณ  ๊ทธ ๋’ค๋กœ ๊ทธ ๋ฉ”์‹œ์ง€๊ฐ€ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ๋˜๋Š”์ง€๋Š” ์•Œ ํ•„์š” ์—†๋‹ค. ๋”ฐ๋ผ์„œ ์—๋Ÿฌ ์ฒ˜๋ฆฌ๋„ ์ดํ›„์— ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฐ์ž๊ฐ€ ์•Œ์•„์„œํ•˜๋ฉด ๋œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Resize ํ•จ์ˆ˜๋Š” ๋ฆฌ์‚ฌ์ด์ง• ์ž‘์—… ์™„๋ฃŒ ํ›„ Upload task๋ผ๋Š” ๋ฉ”์‹œ์ง€๋งŒ upload task channel์— ์ „์†กํ•˜๋ฉด ๋˜๊ณ  Upload ๊ณผ์ •์—์„œ ์–ด๋–ค ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋“  ๊ทธ๊ฒƒ์€ Resize ํ•จ์ˆ˜์˜ ๊ด€์‹ฌ ๋ฐ–์ด๋‹ค. Upload๋Š” ๋ˆ„๊ฐ€ ์ž๊ธฐ๋ฅผ ํ˜ธ์ถœํ•˜๋Š”์ง€ ์•Œ ํ•„์š” ์—†์ด ๊ทธ๋ƒฅ upload task channel์—์„œ ๋ฉ”์‹œ์ง€(task)๋งŒ ๊บผ๋‚ด์–ด ์ž‘์—…ํ•˜๋ฉด ๋œ๋‹ค.

๋‹จ์  - ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค ์„œ๋น„์Šค์™€ ๋‹ฌ๋ฆฌ ์•ฑ์ด ์ฃฝ์œผ๋ฉด ๋ฉ”๋ชจ๋ฆฌ์— ์ฑ„๋„์„ ํ†ตํ•ด ์ €์žฅ ์ค‘์ด๋˜ ๋ฉ”์‹œ์ง€๊ฐ€ ์†Œ์‹ค๋œ๋‹ค.

๋ฆฌ์‚ฌ์ด์ง• Worker pool Benchmark

๊ณผ์—ฐ ์ •๋ง ๋ฆฌ์‚ฌ์ด์ง• ์ž‘์—…์— Worker pool pattern์„ ์ ์šฉํ•  ๋•Œ๊ฐ€ ์ œํ•œ ์—†์ด goroutine์„ ์ƒ์„ฑํ•ด์„œ ์ด์šฉํ•  ๋•Œ๋ณด๋‹ค ํšจ์œจ์ ์ผ๊นŒ ๋ฒค์น˜๋งˆํฌ๋ฅผ ํ†ตํ•ด ์•Œ์•„๋ณด๊ณ ์žํ•œ๋‹ค.

์‚ฌ์šฉ๋œ Machine: AWS EC2 t2.micro

์ž‘์—…: 2MB์˜ Image์— ๋Œ€ํ•œ 128x128๋กœ์˜ ๋ฆฌ์‚ฌ์ด์ง• ์š”์ฒญ 30๊ฐœ๋ฅผ ์ฒ˜๋ฆฌ.

goos: linux
goarch: amd64
pkg: github.com/khu-dev/bumblebee
BenchmarkTransformer_Start/30_task_worker_pool_1         	       5	 426898179 ns/op
BenchmarkTransformer_Start/30_task_worker_pool_10        	       5	 424531051 ns/op
BenchmarkTransformer_Start/30_task_worker_pool_19        	       5	 423642287 ns/op
BenchmarkTransformer_Start/30_task_worker_pool_28        	       5	 424124379 ns/op
BenchmarkTransformer_Start/30_task_unlimited_concurrency 	       5	 425058364 ns/op
PASS
ok  	github.com/khu-dev/bumblebee	21.476s

์˜ˆ์ƒํ–ˆ๋˜ ๋Œ€๋กœ throughput์€ ํฐ ์ฐจ์ด๊ฐ€ ์—†์—ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋จผ์ € ๋“ค์–ด์˜จ ์ž‘์—…์€ ๋จผ์ € ์ฒ˜๋ฆฌ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด ์žฅ์ ์ผ ๊ฒƒ ๊ฐ™๋‹ค.

์›Œ์ปค(goroutine)์˜ ์ˆ˜๋ฅผ N์ด๋ผ๊ณ  ํ–ˆ์„ ๋•Œ

N = 1: ๋จผ์ € ๋“ค์–ด์˜จ ์ž‘์—…์ด ๋ฌด์กฐ๊ฑด ๋จผ์ € ์ฒ˜๋ฆฌ๋œ๋‹ค. ๋งŒ์•ฝ ์•ž์„  ์ž‘์—…์ด ์˜ค๋žœ ์‹œ๊ฐ„์„ ์†Œ๋ชจํ•œ๋‹ค๋ฉด ๋’ค์˜ ์ž‘์—…๋“ค๋„ ๋ชจ๋‘ ์ง€์—ฐ๋œ๋‹ค.

N=๋ฌดํ•œ๋Œ€: ๋จผ์ € ๋“ค์–ด์˜จ ์ž‘์—…๊ณผ ๋‚˜์ค‘์— ๋“ค์–ด์˜จ ์ž‘์—…์ด ๋ชจ๋‘ ๋Š˜์–ด์ง€๋ฉด์„œ ํ•œ๊บผ๋ฒˆ์— ์ฒ˜๋ฆฌ๋œ๋‹ค.

๋”ฐ๋ผ์„œ ๋จผ์ € ๋“ค์–ด์˜จ ์ž‘์—…์ด ๋จผ์ € ์ฒ˜๋ฆฌ๋  ์ˆ˜ ์žˆ์œผ๋ฉด์„œ ์˜ค๋žœ ์ž‘์—… ์‹œ๊ฐ„์„ ์†Œ๋ชจํ•˜๋Š” ์ž‘์—…์ด ์•ž์— ์œ„์น˜ํ•ด๋„ ๋’ค์˜ ์ž‘์—…๋“ค์ด ์™„์ „ํžˆ ์ง€์—ฐ๋˜๊ธฐ๋ณด๋‹ค๋Š” ์–ด๋Š ์ •๋„ ๋จผ์ € ์ฒ˜๋ฆฌ๋  ์ˆ˜๋„ ์žˆ๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด ์ ๋‹นํžˆ 3๊ฐœ~5๊ฐœ ์ •๋„์˜ goroutine์„ ์ด์šฉํ•˜๋Š” ๊ฒƒ์ด ์–ด๋–จ๊นŒ์‹ถ๋‹ค.

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

์•„์‰ฌ์šด ์ 

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

๋‹น๊ทผ๋งˆ์ผ“์˜ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ๊ด€๋ จ ๊ธ€์„ ๋ณด๋ฉด 2019.01 ๊ธฐ์ค€ ํ•˜๋ฃจ 50๋งŒ์žฅ์˜ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ๊ฐ€ ์ด๋ค„์ง„๋‹ค๊ณ ํ–ˆ๋‹ค. ๋‹น๊ทผ๋งˆ์ผ“ ์ด์šฉ์ž ๋ณ€ํ™”๋ฅผ ๋ณด๋ฉด ์ด๋•Œ ๊ธฐ์ค€์œผ๋กœ ์ด์šฉ์ž๊ฐ€ ์•ฝ 2021๋…„์—” 4๋ฐฐ ์ฆ๊ฐ€ํ–ˆ์„ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋œ๋‹ค. ๊ทธ๋Ÿผ ์•ฝ 200๋งŒ์žฅ์˜ ์ด๋ฏธ์ง€๊ฐ€ ์—…๋กœ๋“œ ๋œ๋‹ค๊ณ  ๊ฐ€์ •, ์ž๊ณ  ์ผํ•˜๋Š” ์‹œ๊ฐ„ ์ œ์™ธ ๊ทธ 200๋งŒ์žฅ์˜ ์ด๋ฏธ์ง€๋Š” ํ•˜๋ฃจ 24์‹œ๊ฐ„์ด ์•„๋‹ˆ๋ผ ์‹ค์งˆ์ ์œผ๋กœ 6์‹œ๊ฐ„์ •๋„ ๋™์•ˆ ์—…๋กœ๋“œ ๋œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด 1๋ถ„๋‹น ์•ฝ 5500์žฅ ์ •๋„์˜ ์ด๋ฏธ์ง€๊ฐ€ ์—…๋กœ๋“œ ๋˜๋Š” ์…ˆ์ด๋ผ๊ณ  ์ถ”์ •ํ•ด๋ณผ ์ˆ˜ ์žˆ๊ฒ ๋‹ค. ์ด๋Ÿฐ ๋Œ€๊ทœ๋ชจ ์„œ๋น„์Šค์—์„œ๋Š” ์ด๋ฏธ์ง€ ํ”„๋กœ์„ธ์‹ฑ ์„œ๋ฒ„์—์„œ ์ž‘์—…์„ Go์˜ ์ฑ„๋„๊ณผ ๊ณ ๋ฃจํ‹ด์„ ์ด์šฉํ•œ ๋™์‹œ์„ฑ ํŒจํ„ด์„ ์ ์šฉํ•ด ์ž‘์—… ํ์ฒ˜๋Ÿผ ์ˆ˜ํ–‰ํ•˜๋ฉด ์–ด๋Š์ •๋„ ์ด์ ์ด ์žˆ์„ ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค. ์ถ”ํ›„์— ์ฟ ๋ฎค์—๋„ ๋ญ”๊ฐ€ ๊ณ ํ™”์งˆ ์ด๋ฏธ์ง€๋ฅผ ๋งŽ์ด ์—…๋กœ๋“œํ•  ๋งŒํ•œ ์„œ๋น„์Šค๊ฐ€ ์ถ”๊ฐ€๋˜๋ฉด ์ข‹๊ฒ ๋‹ค.

(2021.01.28) ์ƒ๊ฐ๋ณด๋‹ค ๊ณ ํ™”์งˆ(์•ฝ 5MB ์ด์ƒ) ์ด๋ฏธ์ง€์˜ ๊ฒฝ์šฐ ๋ฆฌ์‚ฌ์ด์ง• ์ž‘์—…์ด ๋ฉ”๋ชจ๋ฆฌ์™€ CPU๋ฅผ ๋งŽ์ด ์žก์•„๋จน๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ธ๋‹ค. Python์ด๋‚˜ Node.js์—์„œ ์ž‘์—…ํ•  ๋•Œ๋Š” ์ž์› ์†Œ๋ชจ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋  ์ง€ ๊ถ๊ธˆํ•˜๋‹ค. ํ˜„์žฌ๋กœ์„œ๋Š” Go๋กœ ์ˆ˜ํ–‰ ์ค‘์ธ ์ด ์ž‘์—…์ด ์ž์› ์†Œ๋ชจ ์ธก๋ฉด์—์„œ ํšจ์œจ์ ์ธ์ง€ ์•Œ ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ๋น„๊ต๊ตฐ์ด ์—†๋‹ค.

Test code

  • JUnit์—์„œ ์•„์ด๋””์–ด๋ฅผ ์–ป์–ด BeforeEach, AfterEach ๋“ฑ์„ ์ •์˜ํ•จ์œผ๋กœ์จ ๊ฐ test case๋“ค ๊ฐ„์˜ ์˜์กด์„ฑ์„ ์—†์•ฐ.
  • AfterEach์—์„œ test ์ˆ˜ํ–‰ ํ›„ ์—…๋กœ๋“œํ•œ ๋ฆฌ์‚ฌ์ด์ง• ๋œ ์ด๋ฏธ์ง€๋“ฑ์„ ์ง€์›€์œผ๋กœ์จ ๊น”๋”ํ•˜๊ฒŒ ์ด์šฉ.
  • ๊ฐœ๋ฐœ์„ ํ•˜๋ฉด์„œ ๊ฒฐ๊ณผ ํ™•์ธ์„ ์œ„ํ•ด ๋งค๋ฒˆ ํŠน์ • ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ์ปค๋งจ๋“œ๋‚˜ ๋‹จ์ถ•ํ‚ค๋ฅผ ์ด์šฉํ•  ํ•„์š” ์—†์ด file watcher์—์„œ test code๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ์„ค์ •ํ•ด๋†“์œผ๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ„ํŽธ.

์•„ํ‚คํ…์ฒ˜

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

AWS์˜ S3 + CloudFront + Route53์„ ์ด์šฉํ–ˆ๋‹ค. ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ์— ๋Œ€ํ•œ API์˜ ๋„๋ฉ”์ธ ๋„ค์ž„์€ ๋‹ค๋ฅธ API์™€ ๋™์ผํ•˜์ง€๋งŒ ์—…๋กœ๋“œํ•œ ์ด๋ฏธ์ง€๋Š” https://api.xxx.xxx๊ฐ€ ์•„๋‹Œ https://storage.xxx.xxx๋ฅผ ๋ฃจํŠธ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

  • S3 public bucket
  • CloudFront
    • Origin - S3 public bucket
    • Alternative CNAME -
  • Route53
    • GoDaddy์—์„œ ๊ตฌ๋งคํ•œ ๋„๋ฉ”์ธ์€ GCP์˜ CloudDNS์˜ NS์— ์—ฐ๊ฒฐ๋˜์–ด์žˆ์Œ.
    • Route53์—์„œ drive.khumu.me Hosted Zone ์ƒ์„ฑ
    • GCP์˜ CloudDNS์—์„œ Route53์˜ drive.khumu.me Hosted Zone NS๋ฅผ ๋ ˆ์ฝ”๋“œ๋กœ ์ถ”๊ฐ€

๊ฐ„๋‹จํ•œ ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ

$ for ((i=1;i<=100;i++)); 
do curl -F 'image=@test_data_wallpaper.jpg' http://localhost:9001/api/images
done

๋กœ์ปฌ์—์„œ ์„œ๋ฒ„ ์‹คํ–‰ ํ›„ ์œ„์˜ ์ปค๋งจ๋“œ๋ฅผ ํ†ตํ•ด ์ž‘์—…์„ ์š”์ฒญํ•˜๊ณ  CPU, Memory ์‚ฌ์šฉ๋ฅ ์„ ๊ด€์ฐฐํ•ด๋ณธ๋‹ค.

์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์‹œ Exif Metadata์˜ Orientation ์ •๋ณด