Go for Rubyists

Ruby ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ Go ์–ธ์–ด ๊ฐ€์ด๋“œ โ€” ๋ชจ๋“  ๊ฐœ๋…์„ Ruby์™€ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค

๐Ÿ“– ๊ธฐ๋ณธ ๋ฌธ๋ฒ•

๐Ÿ“ฆ

๋ณ€์ˆ˜์™€ ํƒ€์ž… โ€” Ruby์˜ ๋™์  ํƒ€์ดํ•‘์ด ๊ทธ๋ฆฌ์›Œ์ง€๋Š” ์ˆœ๊ฐ„

duck typing์ด ์‚ฌ๋ผ์ง„ ์„ธ๊ณ„์—์„œ ์‚ด์•„๋‚จ๊ธฐ

Ruby์—์„œ๋Š” x = 1 ํ•˜๋ฉด ๋์ด๋‹ค. Go์—์„œ๋Š” var x int = 1์ด๋‹ค. ์ด ์ฐจ์ด๊ฐ€ ์ฒ˜์Œ์—” ๊ท€์ฐฎ์ง€๋งŒ, ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์žก์•„์ฃผ๋Š” ๋ฒ„๊ทธ๋ฅผ ๊ฒฝํ—˜ํ•˜๋ฉด ์ƒ๊ฐ์ด ๋ฐ”๋€๋‹ค.

๐Ÿ”€

์ œ์–ด๋ฌธ โ€” if/for๋Š” ๋น„์Šทํ•œ๋ฐ while์ด ์—†๋‹ค

Ruby์˜ each/map/select๊ฐ€ ๊ทธ๋ฆฌ์›Œ์ง€๋Š” for ๋ฃจํ”„์˜ ์„ธ๊ณ„

Go์—๋Š” while์ด ์—†๋‹ค. for ํ•˜๋‚˜๋กœ ์ „๋ถ€ ์ฒ˜๋ฆฌํ•œ๋‹ค. Ruby์˜ .each, .map, .select ๊ฐ™์€ ์ปฌ๋ ‰์…˜ ๋ฉ”์„œ๋“œ๋„ ์—†๋‹ค. ์ „๋ถ€ for range๋กœ ์ง์ ‘ ๋Œ๋ฆฐ๋‹ค.

โš™๏ธ

ํ•จ์ˆ˜์™€ ๋ฉ”์„œ๋“œ โ€” ํด๋ž˜์Šค๊ฐ€ ์—†๋Š” ์„ธ๊ณ„์˜ ๋ฉ”์„œ๋“œ

Ruby์˜ def๋Š” ํด๋ž˜์Šค ์•ˆ์— ์‚ฐ๋‹ค. Go์˜ func๋Š” struct์— ๋ถ™๋Š”๋‹ค.

Go์—๋Š” ํด๋ž˜์Šค๊ฐ€ ์—†๋‹ค. ํ•จ์ˆ˜๊ฐ€ ๊ธฐ๋ณธ์ด๊ณ , struct์— ๋ฉ”์„œ๋“œ๋ฅผ ๋ถ™์ด๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ฐ์ฒด์ง€ํ–ฅ์„ ํ‰๋‚ด ๋‚ธ๋‹ค. Ruby์˜ class ... def ํŒจํ„ด๊ณผ๋Š” ๊ทผ๋ณธ์ ์œผ๋กœ ๋‹ค๋ฅด๋‹ค.

๐Ÿ”ฉ ํƒ€์ž… ์‹œ์Šคํ…œ

๐Ÿ—๏ธ

Struct vs Class โ€” ์ƒ์† ์—†์ด ์‚ฌ๋Š” ๋ฒ•

Ruby์˜ class < Base ๋Œ€์‹  Go์˜ struct ์ž„๋ฒ ๋”ฉ

Go์—๋Š” class๊ฐ€ ์—†๋‹ค. struct๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด๊ณ , ๋ฉ”์„œ๋“œ๋Š” struct์— ๋ถ™๋Š”๋‹ค. ์ƒ์† ๋Œ€์‹  ์ž„๋ฒ ๋”ฉ(embedding)์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•œ๋‹ค. Ruby์˜ include/extend์™€ ๋น„์Šทํ•˜๋ฉด์„œ๋„ ๋‹ค๋ฅด๋‹ค.

๐Ÿฆ†

Interface โ€” Ruby์˜ duck typing์ด ํƒ€์ž… ์‹œ์Šคํ…œ์„ ๋งŒ๋‚ฌ์„ ๋•Œ

๋ช…์‹œ์  implements ์—†์ด, ๋ฉ”์„œ๋“œ๋งŒ ๋งž์œผ๋ฉด ์ž๋™์œผ๋กœ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ์กฑํ•œ๋‹ค

Go์˜ ์ธํ„ฐํŽ˜์ด์Šค๋Š” Ruby์˜ duck typing๊ณผ Java์˜ interface ์‚ฌ์ด์— ์žˆ๋‹ค. "์ด ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉด ์ด ํƒ€์ž…์ด๋‹ค" โ€” ์ปดํŒŒ์ผ ํƒ€์ž„์— ๊ฒ€์ฆ๋˜๋Š” duck typing์ด๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.

๐Ÿšจ

if err != nil โ€” Ruby์˜ begin/rescue๊ฐ€ ๊ทธ๋ฆฌ์›Œ์ง€๋Š” ์ด์œ 

Go๋Š” ์˜ˆ์™ธ๋ฅผ ์•ˆ ์“ด๋‹ค. ์—๋Ÿฌ๋ฅผ ๊ฐ’์œผ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ฝ”๋“œ์˜ ์ ˆ๋ฐ˜์ด ์—๋Ÿฌ ์ฒ˜๋ฆฌ๊ฐ€ ๋œ๋‹ค.

Ruby์—์„œ begin/rescue/end๋กœ ์˜ˆ์™ธ๋ฅผ ์žก๋Š”๋‹ค. Go์—์„œ๋Š” ์˜ˆ์™ธ๊ฐ€ ์—†๋‹ค. ํ•จ์ˆ˜๊ฐ€ (๊ฒฐ๊ณผ, ์—๋Ÿฌ)๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ํ˜ธ์ถœํ•˜๋Š” ์ชฝ์—์„œ ๋งค๋ฒˆ if err != nil๋กœ ์ฒดํฌํ•œ๋‹ค. ์ด๊ฒŒ Go ์ฝ”๋“œ์˜ 50%๋ฅผ ์ฐจ์ง€ํ•œ๋‹ค.

๐Ÿ”ฌ ์˜คํ”ˆ์†Œ์Šค ๋ถ„์„

๐Ÿ›

Keploy โ€” eBPF๋กœ ํŠธ๋ž˜ํ”ฝ์„ ๊ฐ€๋กœ์ฑ„์„œ API ํ…Œ์ŠคํŠธ๋ฅผ ์ž๋™ ์ƒ์„ฑํ•˜๋Š” ๊ตฌ์กฐ

Go + eBPF + ํˆฌ๋ช… ํ”„๋ก์‹œ๋กœ ์ฝ”๋“œ ์ˆ˜์ • ์—†์ด ํ…Œ์ŠคํŠธ๋ฅผ ๋งŒ๋“œ๋Š” CNCF ํ”„๋กœ์ ํŠธ

Keploy๋Š” eBPF๋กœ ์ปค๋„ ๋ ˆ๋ฒจ์—์„œ ๋„คํŠธ์›Œํฌ syscall์„ ๊ฐ€๋กœ์ฑ„๊ณ , ํˆฌ๋ช… ํ”„๋ก์‹œ๋กœ ํŠธ๋ž˜ํ”ฝ์„ ๋…นํ™”ํ•œ ๋’ค, ๊ทธ๊ฑธ ๊ทธ๋Œ€๋กœ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค+Mock์œผ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค. ์ฝ”๋“œ๋ฅผ ํ•œ ์ค„๋„ ์•ˆ ๊ณ ์น˜๊ณ .

๐Ÿ”€

eBPF ๋ชฉ์ ์ง€ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ โ€” connect() syscall์„ ์ปค๋„์—์„œ ๋ฐ”๊ฟ”์น˜๊ธฐํ•˜๋Š” ์›๋ฆฌ

Keploy, Cilium, Istio๊ฐ€ ์“ฐ๋Š” ํˆฌ๋ช… ํ”„๋ก์‹œ์˜ ํ•ต์‹ฌ ๋ฉ”์ปค๋‹ˆ์ฆ˜

์•ฑ์ด postgres:5432๋กœ connect()๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด, eBPF๊ฐ€ ์ปค๋„ ์•ˆ์—์„œ ๋ชฉ์ ์ง€๋ฅผ 127.0.0.1:proxyPort๋กœ ๋ฐ”๊ฟ”์น˜๊ธฐํ•œ๋‹ค. ์•ฑ์€ ์ „ํ˜€ ๋ชจ๋ฅธ๋‹ค. ์ด ํŠธ๋ฆญ์ด ์–ด๋–ป๊ฒŒ ๊ฐ€๋Šฅํ•œ์ง€, Go ์ฝ”๋“œ ๋ ˆ๋ฒจ์—์„œ ๋œฏ์–ด๋ณธ๋‹ค.