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%๋ฅผ ์ฐจ์งํ๋ค.
โก ๋์์ฑ
Goroutine โ Ruby์ Thread์๋ ์ฐจ์์ด ๋ค๋ฅธ ๊ฒฝ๋ ๋์์ฑ
go ํค์๋ ํ๋๋ก ์๋ง ๊ฐ์ ๋์ ์์ ์ ๋๋ฆฐ๋ค. GIL์ ์๋ค.
Ruby์ Thread๋ GIL(Global Interpreter Lock) ๋๋ฌธ์ ์ง์ ํ ๋ณ๋ ฌ ์คํ์ด ์ ๋๋ค. Go์ goroutine์ OS ์ค๋ ๋๋ณด๋ค ๊ฐ๋ณ๊ณ , ์๋ง ๊ฐ๋ฅผ ๋์์ ์คํํ ์ ์๋ค.
Channel โ goroutine ์ฌ์ด์ ํ์ดํ๋ผ์ธ
Ruby์๋ ์๋ ๊ฐ๋ . goroutine ๊ฐ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๊ฒ ์ฃผ๊ณ ๋ฐ๋ ํต๋ก.
Channel์ goroutine ๊ฐ ๊ฐ์ ์ฃผ๊ณ ๋ฐ๋ ํ์ ์์ ํ ํ์ดํ๋ค. Ruby์๋ ์ ํํ ๋์ํ๋ ๊ฐ๋ ์ด ์๋ค. Queue๊ฐ ๊ฐ์ฅ ๊ฐ๊น์ง๋ง, channel์ ์ธ์ด ๋ ๋ฒจ์์ ์ง์๋๋ค.
๐ ํ๋ก์ ํธ ๊ตฌ์กฐ
ํจํค์ง์ ๋ชจ๋ โ Gemfile์ด go.mod๊ฐ ๋์ ๋
Ruby์ require/gem ์์คํ vs Go์ package/module ์์คํ
Ruby์ Gemfile + Bundler๊ฐ Go์์๋ go.mod + go get์ด๋ค. ํจํค์ง ๊ด๋ฆฌ ๊ฐ๋ ์ ๋น์ทํ์ง๋ง, Go๋ GitHub URL์ด ํจํค์ง ์ด๋ฆ์ด๊ณ , ์ค์ ๋ ์ง์คํธ๋ฆฌ(RubyGems)๊ฐ ์๋ค.
ํ ์คํธ โ RSpec ์์ด ์ฌ๋ ๋ฒ
Go์ ํ ์คํธ๋ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ด์ฅ๋์ด ์๋ค. gem install ๋ถํ์.
Ruby์์ RSpec + FactoryBot + shoulda-matchers๋ฅผ ์ค์ ํ๋ ๋ฐ 30๋ถ์ด ๊ฑธ๋ฆฐ๋ค. Go์์๋ _test.go ํ์ผ ํ๋ ๋ง๋ค๋ฉด ๋ฐ๋ก ํ ์คํธ ๊ฐ๋ฅํ๋ค. go test ๋ช ๋ น ํ๋.
๐ฌ ์คํ์์ค ๋ถ์
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 ์ฝ๋ ๋ ๋ฒจ์์ ๋ฏ์ด๋ณธ๋ค.