[Erlang] OTP
OTP๋ Open Telecom Platform์ ์ถ์ฝ์ผ๋ก, Erlang์ ๋ถ์ฐ์์คํ
์ฉ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ชจ์, ํน์ ๊ทธ๋ฌํ ์ํคํ
์ฒ๋ฅผ ๋งํ๋ค.
Erlang์ ์กด์ฌ ๋ชฉ์ ์ด๊ธฐ๋ ํ๋ค.
Telecom์ด ๋ค์ด๊ฐ์๊ธด ํ๋ฐ, ํต์ ์๋ง ์ธ์ ์๋๊ฑด ์๋๊ณ , ๋ง ์์ฒญ๋ ํ๋ ์์ํฌ๋ฅผ ๋งํ๋ ๊ฒ๋ ์๋๋ค.
๊ทธ๋ฅ ์ฑ๋ ๋ฑ์ ํฌํจํ erlang์ ํ์ ๊ธฐ๋ฅ์์๋ค๊ณผ, ๊ทธ๊ฑธ ์ด์ฉํ ๊ตฌํ ํจํด์ ๋งํ๋ ๊ฒ์ด๋ค.
ํ์ฌ์ ๋น๋๊ธฐ-๋ถ์ฐ์์คํ
์ ์ด๋ก ์ ๋ชจํ์ด๊ธฐ๋ ํ๋ค.
ํํ Go, Rust์์ ์ฌ์ฉ๋๋ ์ฑ๋์ ๊ฐ๋
์ด ์ฌ๊ธฐ์์ ๋์๋ค.
supervision tree
erlang OTP๋ supervision tree๋ผ๋ ํํ๋ก ํ๋ก์ธ์ค ๊ฐ์ ์ฐ๊ฒฐ, ํต์ ์ ๊ด๋ฆฌํ๋ค.
์ฌ๊ธฐ์ ๋๊ทธ๋ผ๋ฏธ๊ฐ Worker, ๋ค๋ชจ๊ฐ Supervisor๋ค. OTP์์๋ ์ด ๋์ ์๊ฒฉํ๊ฒ ๊ตฌ๋ถํด์ ์ญํ ์ ๊ตฌ๋ถํ๋ค.
Worker๋ ์์ํ ์๋ฏธ์ ์์
์ ํ๋ก์ธ์ค๋ค. ์ค์ ๋ก ์๋ฏธ๊ฐ ์๋ ์์
๋ค์ ์ฒ๋ฆฌํ๋ค.
ํ์ง๋ง worker๋ ์ธ์ ๋ Supervisor์ ์ํด ์ฌ๋ผ์ง๊ฑฐ๋, ์๊ธฐ๊ฑฐ๋, ๋ณ๋๋ ์ ์๋ค.
Supervisor๋ worker๋ค์ ๊ด๋ฆฌ๋ง ํ๋ ๊ด๋ฆฌ ์ ์ฉ ํ๋ก์ธ์ค๋ค.
erlang OTP๋ ์ด๋ฌํ ๊ตฌ์กฐ๋ฅผ ํตํด ๋ด๊ฒฐํจ์ฑ(fault-tolerant)์ ๋ณด์ฅํ๋ค.
๊ทผ๋ฐ erlang์ด ์ด๋ฌํ ๊ตฌ์กฐ ํ ํ๋ฆฟ์ ์น์ ํ๊ฒ ์ ๊ณตํ๋๊ฑด ์๋๋ผ์, ์ง์ ๊ตฌํํด์ผ ํ๋๊ฒ ๋ง๋ค. ๊ทธ๋์ ์ฌ๊ธฐ์์๋ ๊ฐ๋จํ ์ฌ์ฉ ํํ๋ง ๋์ถฉ ๋ณด์ด๊ณ ์ ๋๋ก ๋ ์์ปค ํธ๋ฆฌ ๊ตฌ์กฐ๋ ๋์ค์ ๋ค๋ค๋ณด๊ฒ ๋ค.
๊ฐ๋จํ ํ๋ก๊ทธ๋จ ๋ง๋ค์ด๋ณด๊ธฐ
์์๋ก ๊ฐ๋จํ ์ค์ ์๋ฒ๊ฐ ์๊ณ , ์ค์ ์๋ฒ์ rpc๋ฅผ ํตํด ๋ก์ง์ ์ ๊ณตํ๋ ํ์ ์๋ฒ๋ฅผ ๊ตฌ์ฑํ๋ ์ฝ๋๋ฅผ ๋ณด์ฌ๋ณด๊ฒ ๋ค.
์ฐ์ ์๋ฒ ์ฝ๋๋ค.
-module(server).
-export([start/2, rpc/2]).
% ํน์ ์ด๋ฆ์ ๊ฐ์ง๋ ์๋ฒ ๋ฃจํ๋ฅผ ์์ํ๋ค.
start(Name, Mod) ->
register(Name, spawn(fun() -> loop(Name, Mod, Mod:init()) end)).
% ํน์ ์ด๋ฆ์ ๊ฐ์ง ํ๋ก์ธ์ค์๊ฒ Request๋ฅผ ๋ณด๋ด๊ณ , Response๋ฅผ ๋ฐ๋๋ค.
rpc(Name, Request) ->
Name ! {self(), Request},
receive
{Name, Response} -> Response
end.
% ๋ฌดํ๋ฃจํ๋ฅผ ๋๋ฉฐ ๊ณ์ํด์ Request๋ฅผ ๋ฐ๊ณ , Mod:handle/2๋ฅผ ํธ์ถํ์ฌ Response๋ฅผ ๋ฐํํ๋ค.
loop(Name, Mod, State) ->
receive
{From, Request} ->
{Response, State1} = Mod:handle(Request, State),
From ! {Name, Response},
loop(Name, Mod, State1)
end.
start ํจ์๋ ํ์ ์๋ฒ์ ์ด๋ฆ๊ณผ, ๋ชจ๋๋ช
์ ์ ๋ฌ๋ฐ๊ณ ๋ชจ๋์ ์๋ฒ์ ๋ฑ๋กํ๋ค.
๊ทธ๋ฆฌ๊ณ rpc ํจ์๋ฅผ ํตํด์ ๋ฑ๋ก๋ ํ์์๋ฒ๋ค์ ์์ฒญ์ ๋ณด๋ด๊ณ ์๋ต์ ๋ฐ์์ฌ ์ ์๋ค.
๊ทธ ๋ค์์๋ ํ์์๋ฒ๋ก ์ฌ์ฉํ name_server ์ฝ๋๋ฅผ ์์ฑํด๋ณด๊ฒ ๋ค.
๊ทธ๋ฅ ๋์
๋๋ฆฌ ํ๋ ๋๊ณ , ํค:๊ฐ ์์ ์ถ๊ฐํ๊ณ ์กฐํํ ์๋ง ์๋ ๋จ์ํ ๊ธฐ๋ฅ์ ๊ฐ์ง๋ค.
-module(name_server).
-export([init/0, add/2, whereis/1, handle/2]).
-import(server, [rpc/2]).
% ์ค์ ์๋ฒ์ rpc ์์ฒญ (์ค์ ์๋ฒ์์ ๋ค์ handler๋ก echo)
add(Name, Place) -> rpc(name_server, {add, Name, Place}).
whereis(Name) -> rpc(name_server, {whereis, Name}).
init() -> dict:new().
% rpc ํธ์ถ์ ์๋ตํ ํธ๋ค๋ฌ๋ค
handle({add, Name, Place}, Dict) -> {ok, dict:store(Name, Place, Dict)};
handle({whereis, Name}, Dict) -> {dict:find(Name, Dict), Dict}.
handle ํจ์๋ฅผ ํตํด ์ค์ง์ ์ธ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ณ , ์ค์ ํธ์ถ์ ์ค์ ์๋ฒ๋ฅผ ํตํ๋๋ก ํ๋ค.
๊ทธ๋ฆฌ๊ณ ์ 2๊ฐ์ ์์คํ์ผ์ ์ปดํ์ผํ๋ค.

๊ทธ๋์ ์ด๋ ๊ฒ 2๊ฐ์ beam ํ์ผ์ด ๋จ์ด์ง๋ฉด ๋ ๊ฒ์ด๋ค.
erl ์ธํฐํ๋ฆฌํฐ์ ์ง์ ํด์

server:start(name_server, name_server).
name_server๋ฅผ ์คํ์์ผ์ค๋ค.
๊ทธ๋ฆฌ๊ณ name_server์ ๊ธฐ๋ฅ์ ํตํด์ add ํจ์๋ฅผ ํธ์ถํ๋ค.
name_server:add(erlang,"foo").

๊ทธ๋ผ whereis ํจ์๋ฅผ ํตํด ์ ์ฅํ ๊ฐ์ ๋ค์ ์ฝ์ด์ฌ ์ ์๋ค.

๊ทธ๋ ๋ค.

์ด๋ฐ์์ผ๋ก ๊ฐ ๋ชจ๋์ ํ๋ก์ธ์ค๋ก ๋์ฐ๊ณ ํ๋ก์ธ์ค๊ฐ ํต์ ์ ํตํด IPC๋ฅผ ์ํํ๋๊ฒ ์ฃผ๋ ์ปจ์ ์ด๋ค.
์ฐธ์กฐ
https://www.erlang.org/
https://www.tutorialspoint.com/erlang/erlang_otp.htm
https://learnyousomeerlang.com/building-applications-with-otp