🔴 실시간 채팅 서버 구축 (Erlang)

Erlang 예제

중급 난이도
예제 타입
10/28 등록일

실시간 채팅 서버 구축 (Erlang)

중급
태그
예제 실습 프로젝트 채팅 동시성 분산
## 프로젝트 개요
채팅 기능을 요구하는 분산 시스템에서 실시간 메시지 전송 및 사용자 관리를 구현합니다. Erlang의 동시성과 네트워크 처리 능력을 활용하여 확장 가능한 구조를 설계했습니다.

## 주요 기능
- 클라이언트 연결 관리
- 실시간 메시지 브로드캐스트
- 사용자 접속/해제 이벤트 처리
- 네트워크 오류 대응

## 사용 방법
1. `erl` 명령어로 Erlang 쉘 실행
2. 셋업: `c(chat_server).` 로 모듈 컴파일
3. 서버 시작: `chat_server:start(8080).`
4. 클라이언트 연결 테스트: `telnet localhost 8080`
5. 메시지 입력 시 'msg' 명령어 사용

## 확장 가능성
- 사용자 인증 추가
- 채팅룸 분리 기능 구현
- 메시지 로그 저장 및 검색
코드 예제
-module(chat_server).
-export([start/1, init/1]).

-record(state, {pid = none, clients = []}).

start(Port) ->
    {ok, LS} = gen_server:start({local, ?MODULE}, ?MODULE, [Port], []),
    LS.

init([Port]) ->
    { ok, _ } = application:ensure_all_started(inets),
    { ok, _ } = application:ensure_all_started(ssl),
    { ok, _ } = application:ensure_all_started(crypto),
    { ok, _ } = application:ensure_all_started(sasl),

    {ok, Socket} = ssl:listen(Port,
        [ {certfile, "cert.pem"},
          {keyfile, "key.pem"},
          {password, "securepass"},
          {reuseaddr, true},
          {active, false}
        ]),

    spawn_link(fun() -> accept(Socket, #state{pid = self(), clients = []}) end),
    {ok, #state{}}.

accept(Socket, State) ->
    case ssl:wait(Socket, accept) of
        {ok, Pid, _} ->
            spawn_link(fun() -> handle_client(Pid, State) end),
            accept(Socket, State);
        {error, Reason} ->
            error_logger:error_msg("accept failed: ~p~n", [Reason]),
            ok
    end.

handle_client(ClientPid, State) ->
    receive
        {ssl, ClientPid, {data, Bin}} ->
            case parse_message(Bin) of
                {ok, Msg} ->
                    broadcast(Msg, State);
                {error, Reason} ->
                    error_logger:error_msg("메시지 파싱 실패: ~p~n", [Reason])
            end,
        {ssl, ClientPid, closed} ->
            ok;
        _ ->
            handle_client(Client, State)
    end.

parse_message(Bin) ->
    case binary:split(Bin, <<"\r
">>, [global]) of
        [Msg, _] -> {ok, string:trim(Msg)};
        _ -> {error, invalid_format}
    end.

broadcast(Msg, #state{clients = Clients}) ->
    lists:foreach(fun(Client) ->
        ssl:send(Client, <<Msg/binary, "\r
">>)
    end, Clients).

%% 클라이언트 테스트 (erl 쉘에서)
-module(chat_client).
-export([connect/1, send_msg/2]).

connect(Port) ->
    {ok, Socket} = ssl:connect("localhost", Port, [binary, {active, false}]),
    spawn(fun() -> loop(Socket) end),
    ok.

loop(Socket) ->
    receive
        {ssl, Socket, {data, Bin}} ->
            io:format("메시지 수신: ~s~n", [binary_to_list(Bin)]);
        {ssl, Socket, closed} ->
            ok;
        send(Msg) ->
            ssl:send(Socket, <<Msg/binary, "\r
">>),
            loop(Socket)
    end.

send_msg(Socket, Msg) ->
    ssl:send(Socket, <<Msg/binary, "\r
">>).
등록일: 2025년 10월 28일 02:37
언어 정보
언어
Erlang
카테고리
Functional
인기도
#28
학습 팁
코드를 직접 실행해보세요
변수를 바꿔가며 실험해보세요
오류가 나도 포기하지 마세요
다른 예제도 찾아보세요