SlideShare a Scribd company logo
1 of 78
Download to read offline
<달빛조각사>
Elixir를 이용한 MMORPG 서버 개발
엑스엘게임즈
김민욱
소개
프로그래머
2017 달빛 조각사 (C#,Elixir)
2013 문명 온라인 (C++)
2008 더데이 온라인 (C#,C++)
2007 마비노기2 (C#,C++)
2004 SUN 온라인 (C++)
2002 묵향 온라인 (C++)
2002 디지몬 카드 배틀 for PC (C,C++)
2002 건담 G-Generation for PC (C,C++)
Elixir 엘릭서
신생 언어 (2011) - José Valim
생소한 언어
함수형 언어
어느 것 하나 실무, 업계에서 접하기 힘든...
사실 저도 달빛조각사 팀에 합류하기 전까지 잘 몰랐습니다.
고민
다양한 주제 영역
함수형 언어, Elixir 언어, 서버 설계 및 개발
키워드
세션 목적
`Elixir` 함수형 언어의 심리적 장벽 낮춤
새로운 언어 패러다임에 대한 소개
게임 개발 언어로서 선택 가능성
새로운 것에 대한 영감, 사고 전환
서버 개발에서 느꼈던 핵심적인 부분에 집중
너무 다양한 주제를 다루다 보니 이해하기 힘들거나
빠르게 지나갈 수 있으니 먼저 양해 부탁드립니다.
진행 순서
함수형 언어 Elixir
Elixir 특징
Elixir 서버 구조 설계
Elixir 도입 결과
마무리
프로젝트 소개 `달빛조각사`
정통 MMORPG 의 경험을 모바일에서 구현 목표
쿼터뷰 시점이고 존을 이동해 가는 게임 플레이 형태 서버 설계 관점에서 보자면
초기 개발 환경
클라이언트 언리얼 엔진 C++ 언어
서버 C# 언어
개발 진행 중간
클라이언트 유니티 엔진 C# 언어
서버 Elixir 언어
다양하고 복합적인 이유가 있지만
이 세션을 통해서 그 이유를 짐작할 수 있도록…
멋진 언어로
한번 만들어
보자.
이렇게 말씀하시지는 않았습니다.
함수형 언어 Elixir
Elixir
함수형 언어 특징적인 3가지
1. 데이터 구조
2. 순수한 함수
3. 재귀
데이터 구조 data type
리스트, 튜플, 맵
# 리스트
[1, 2, “문자열”]
# 튜플
{1, 2, “문자열”}
# 맵
%{name: “이름”, id: 1002}
state = %State{
char: %Char{
name: "캐릭터이름",
id: 1002,
hp: 100,
items: %{
11 => %Item{id: 11, type: 2003, count: 1, slot: 1},
22 => %Item{id: 22, type: 2004, count: 1, slot: 1}
},
guild: %Guild{id: 4000, name: "길드이름", level: 3},
quests: %{ ... },
skills: %{ ... },
buffs: %{ ... },
}
} assert state.char.name == “캐릭터이름”
assert state.char.items[11].type == 2003
assert state.char.guilds.name == “길드이름”
데이터 immutability
변수값은 불변
메모리 공간에 저장된 내용이 변하지 않음
객체지향 언어
객체 상태, 접근 함수, scope, 캡슐화 … 상태를 제어하기 위한 노력
함수형 언어
데이터 상태를 함수의 입력 / 출력에 의해 제어
순수하다 pureness
함수안에서 사용되는 인자를 입력에 의존
외부 요인에 의해 출력이 달라지지 않음
= 참조 투명성 (referential transparency)
= 부작용이 없다 (no side-effect)
= 결정론적인 함수 (deterministic)
재귀 recursion
재귀 함수가 코드를 오히려 지저분하게 하기도 함
재귀 함수를 함수로 치환 가능
꼬리 재귀 최적화 tail recursion
- 추가적인 스택 사용 안함
Elixir 특징
Elixir 첫번째 특징
현대적이고 생산적인 언어
최신? 기능을 갖추고 있음
빌드
배포
유닛 테스트
패키지 매니저
문서화
통합 빌드 툴 mix
프로젝트 생성
빌드
실행
의존성 관리
배포
유닛테스트
$ mix new hello_world
$ mix compile
$ mix run
$ mix deps.get [clean, update, compile]
$ mix release
$ mix test
엄브렐라 프로젝트 umbrella
• 다양한 하위(서브) 프로젝트들을 관리
• visual studio 솔루션과 프로젝트의 관계와 비슷
q5 엄브렐라 프로젝트
- common 하위 프로젝트
- protocol
- world_server
- login_server
- command_center
인클루드 없다.
하위 프로젝트 간 참조 설정만으로 접근하고 함수 호출!
# mix.exs
def deps do
{`common`, in_umbrella: true}
end
# login.ex
defmoule Login do
def process_login(id, pw) do
… 중략 …
Common.Login.authenticate(id, pw)
end
end
파이프 연산자 pipe
코드를 줄여주기도 하지만
코드를 좀 더 읽기 쉽게 해준다.
# a.txt
1,a1,b1,c1
2,a2,b2,c2
# 중첩된 함수 호출은 읽기 어렵다
list = String.split(String.split(File.read(“a.txt”), “n”), “,”)
[1, a1, b1, c1, 2, a2, b2, c2]
# 파이프 연산자
list = File.read(“a.txt”) |> String.split(“n”) |> String.split(“,”)
[1, a1, b1, c1, 2, a2, b2, c2]
패턴 매칭 pattern matching
위 - 아래
읽어가는 순서로 매칭
에러 처리를 쉽게 도와줌
with :ok <- can_authenticate(user_id, user_pw),
:ok <- can_allow_ip(ip),
{:ok, user} <- load_user(user_id) do
put_in(state.user, user)
else
{:error_login_invalid, reason} ->
send_login_error(state.socket, ...)
{:error_login_depulicated, reason} ->
send_login_error(state.socket, ...)
{:error_allow_ip, reason} ->
send_login_error(state.socket, ...)
{:db_error, reason} ->
send_login_error(state.socket, ...)
end
자동 코드 포맷팅
컨벤션 강제
동일한 코드 스타일로 가독성 증가
불 필요한 논쟁에서 벗어남!
아... 이 코드 짠
사람 얼굴을
보고 싶다.
컴파일 속도가 빠르다
Erlang VM위에 동작하는 bytecode로 빌드
현재 달빛 조각사 약 11 만줄 컴파일 20초 내외 끝
Elixir 2번째 특징
안정적인 얼랭 기반 위의 견고한 언어
수십년된 얼랭의 생태계를 이용
Erlang 잠깐소개
에릭슨(통신회사)가 만든 함수형 언어
1986 발표
1998 오픈
수십동안 현장에서 분산 성능 안정성이 검증된 언어
가용성 99.9999999%
경량화된 프로세스 light-weight process
수천~ 수십만개 프로세스 생성 가능
전투적으로 치열하게 검증된 선점형 스케쥴링
프로세스 모델
액터 기반 모델
프로세스 간 메시지 통신
process = actor
mailbox
메시지를 주고 받는 간단한 서버
defmodule TcpServer do
def start(port) do
{:ok, socket} = :gen_tcp.listen(port, [:binary, packet: 0, active: false, reuseaddr: true])
loop_accept(socket)
end
defp loop_accept(socket) do
{:ok, conn} = :gen_tcp.accept(socket)
spawn_link(fn -> recv(conn) end)
loop_listen(socket)
end
defp loop_recv(conn) do
case :gen_tcp.recv(conn, 0) do
{:ok, data} ->
:gen_tcp.send(conn, data)
loop_recv(conn)
{:error, :closed} ->
:ok
end
end
end
마이크로 서비스
비즈니스 로직을 잘게 프로세스로 나누어 처리
가장 무서워 하는 단어 down
항상 서비스 직전의 마음가짐은 조마조마
D-Day가 다가올 수 도록 소화가 잘 안됨
서버 다운됐어요!
한번 살펴 볼께요
서버 프로그래머가
Let it Crash!
비즈니스 로직은 언제나 문제가 생길 수 있음
문제가 있으니 죽은 것!
죽었으니 살리면 되지?
장애 복원하는 감시자 supervisor
https://learnyousomeerlang.com/supervisors
문명 온라인 AI 서버에서 효과 봄
깨끗하게 재시작
빈도수가 극히 드문 복잡한 예외 처리
➔ 복잡성 증가가 성능 하락
➔ 유지 보수 어려움
1. 길드원인 캐릭터가 캐릭터 선택하여 인게임으로 진입
2. 길드장이 길드를 파괴
3. 길드원이 인게임 진입하면서 길드 프로세스에 접근하려고 함
4. 길드원 프로세스 크래시 후 재시작
만약 크래시가 나지 않도록 했다면 클라이언트는 이미 길드 정보를 받았지만 길드는 없는 상태
데이터의 무결성이 깨진 상황
클라가
멈췄는데요?
이제는 안심할 수 있다.
와이 파이가
끊어진 거
아니예요?
서버 다운됐어요!
자네만
끊어졌네요.
1주일 에 여러 번 팀 테스트
ETS Erlang Term Storage
얼랭 OTP 내장 메모리 캐시 시스템
튜플 데이터를 테이블에 저장
Constant time 에 가져올 수 있는 매우 빠른 메모리 저장 구조
생성한 프로세스와 Life Cycle 동일
> :ets.new(:user, [:public, :named_table])
> :ets.insert(:user, {“유저1”, user_value, …})
> :ets.lookup(:user, “유저1”)
유닛 테스트
코드 상에 샘플 코드를 작성한 후 유닛테스트로 활용
@doc """
add new timer.
## Examples
iex> state = %{ timers: [], elapsed: 0 }
iex> state = ExTimer.add(state, {:handler, :name, "uhaha"}, 2000)
iex> [timer] = state.timers
iex> timer.msg == {:handler, :name, "uhaha"}
true
iex> timer.delay == 2000/1000
true
"""
@spec add(state, tuple | atom, integer) :: state
def add(state, msg, delay) when is_tuple(msg) or is_atom(msg) do
문서화
코드 함수 타입 스펙 정의
여러 마리 토끼 잡기 - 컴파일 에러 + 정적 분석 (dialyzer) + 문서화
@doc """
add new timer.
## Examples
iex> state = %{ timers: [], elapsed: 0 }
iex> state = ExTimer.add(state, {:handler, :
iex> [timer] = state.timers
iex> timer.msg == {:handler, :name, "uhaha"}
"""
@spec add(state, tuple | atom, integer) :: state
def add(state, msg, delay) when is_tuple(msg) or is_atom(msg) do
러닝 커브
생각 보다 학습 난이도가 낮다 (개인적인 생각일지도)
• 함수형 언어
• 매크로
• 얼랭
매크로
얼랭
Elixir 서버 구조 설계
프로세스를 나누는 기준
프로세스간 인터렉션이 많지 않는 로직
명확하게 분리 가능한 콘텐츠
비동기로 동작하는 로직
메시지 전달 비용 로직 처리 비용
유저 프로세스
접속된 수백 ~ 수천의 클라이언트 : 프로세스 = 1:1
대부분의 클라이언트 요청 패킷은 인터렉션이 없는 액션들
일부 클라이언트의 crash 가 전체 서비스에 영향을 주지 않음
유저(캐릭터) 프로세스클라이언트
TCP 소켓 통신
몬스터 그룹 프로세스
몬스터 AI 담당
플레이어와 대부분 동일한 로직으로 동작
지역별로 몬스터 그룹으로 관리
유저와 인접한 몬스터들과의 메시지 인터렉션 수 줄임
프로세스를 찾는 디렉토리 서비스
콘텐츠 별 많고 다양한 프로세스가 존재
콘텐츠 ID 로 pid (process id) + 캐시된 정보를 찾는 메커니즘이 필요
char_id ➔ 유저 프로세스
chan_id ➔ 채널 프로세스
guild_id ➔ 길드 프로세스
party_id ➔ 파티 프로세스
user_pid = UserDirectory.find(char_id)
alive? = UserDirectory.alive?(char_id)
UserDirectory.send(char_id, {:system_msg, “test”})
초기 프로세스 구조
지역 프로세스
인터랙션용 캐릭터
유저(캐릭터) 프로세스유저 프로세스의 이동, 공격 인터랙션
➔ 지역(채널) 프로세스
이동, 공격 인터렉션
서버 부하의 대부분을 차지
채널 프로세스로 동기화 비용 올라감
채널 프로세스로 부하가 집중
지역 프로세스
유저(캐릭터) 프로세스
개선1 프로세스 구조
액터 모델 극대화
➔ 지역 프로세스 집중 부하 분산
유저 프로세스 간 직접 인터렉션
유저 프로세스 간 공격
1. 대상 프로세스로 공격 메시지 전달은 디렉토리 서비스로
2. 유저 프로세스 데이터 변경 주체 (ownership)는 자기자신
CharDirectory.send(target_id, {:attack, attacker, 1002})
피격자 데이터 변경
공격 {:attack, attacker, attack_type} 데미지 계산 (block, miss, critical …)
데미지 후 효과 (버프, 상태, 스탯 계산 …)
피격자 프로세스
공격자 정보를 가지고 피격자는 데미지 처리하고 효과 적용
공격 응답에 대한 패킷 브로드 캐스팅
공격자 프로세스
공격 패킷을 받아서 피격자 프로세스로 전달
공격자 데이터 변경
공격 {:attack, attacker, attack_type} 데미지 계산 (block, miss, critical …)
데미지 후 효과 (버프, 상태, 스탯 계산 …)
공격자에 대해 카운터 버프 걸기!
공격자 프로세스
공격 응답에 대한 정보를 토대로 버프 걸기, 공격자의 상태 변경
공격응답 {:attack_reply, damage_list}
공격응답 {:attack_reply, damage_list}
복수 대상 공격
공격 {:attack, attacker, attack_type}
피격자 프로세스 리스트 로 공격 패킷 만 보내면?
공격자의 공격 ID 발급
공격 {:attack, attack_id, attacker, attack_type}
피격자 프로세스 리스트 로 공격 패킷 만 보내면?
공격응답 {:attack_reply , attack_id, damage_list}
유저 프로세스에서 이동
# 이동 패킷 핸들러
def process_move(state, pos, rot) do
old_pos = state.char.pos
# 새로운 이동 정보 변경
state = put_in(state.char.pos, pos)
state = put_in(state.char.rot, rot)
# 지역 관리 프로세스로 이동
Grid.move_char(state.char, old_pos, pos)
# 주변 브로드캐스팅
Broadcast.do(state, {:move, state.char.char_id, pos, rot})
end
개선2 지역 관리 프로세스
지역이동 빈도 < 브로드캐스팅 빈도
인터랙션 행위 자체가 메시지
➔ 메시지 병목
주변에 누가 누가 있는지?
유저 프로세스에서 브로드캐스팅 목록 유지
효과
1. 채널 프로세스의 집중되는 병목 분산
2. 채널 프로세스 버그에 의한 서비스 Down 사라짐
3. 채널 프로세스 비대화된 코드 제거
성능, 안정성, 생산성 증가
Elixir 그 외 여러가지
개발에서 배포까지 OTP 로
OTP (open telecom platform)
서버 구축에 필요한 일련의 라이브러리 모음, 프레임워크
GenServer - Generic Server
Memory Storage - ETS (erlang term storage)
Database - Mnesia (distributed DBMS)
Profiling system, debugger
Crypto, Internet protocol
매크로 macro meta programming
AST라는 문법으로 런타임 시 코드를 생성 컴파일 실행 가능
DSL (domain Specific Language) 정의 가능
달빛. 치트 정의를 매크로를 이용해 단순화
인터렉티브 모드 iex
서버를 인터렉티브 모드(shell)로 실행 가능
Shell에서 함수를 호출하여 바로 결과를 확인
프로세스 메트릭 확인 가능
프로세스 트리 확인
프로세스별 성능 / 메모리
동적 코드 리로딩
클라이언트가 접속한 상태에서 실시간 코드를 수정하여 리로딩
이리저리 고쳐가면서 테스트
iex> r Item
warning: redefining module Item (current version loaded from _build/dev/lib/item/ebin/Elixir.Item.beam)
lib/item.ex:1
{:reloaded, Item, [Item]}
실시간 코드 패치
간편한 분산 서버 구성
기존의 프로세스간 메시지 커뮤니케이션을 그대로 이용
로컬(개발) 프로세스 모드를 리모트 모드로 간단히 변경
Login Process
Login Server
Login Process
World Server
Elixir 도입 결과
아직은 마이너 언어
많이 알려지지 않았음
다른 프로젝트,
다른 회사에서 사용할 수 있을까?
매년 Erlang, Elixir 컨퍼런스가 개최
반년 주기로 메이저 업데이트
stack overflow Developer Survey Results 2019
https://insights.stackoverflow.com/survey/2019#technology
느슨한 타입 검사
런타임시 발견되는 예외와 에러
Elixir 감시자 프로세스로 시간을 벌어줌
코드 짜놓고
한번은 테스트
하잖아요?
도구로 부터 도움
Error Tracking System
사이드 이펙트 없는 코드
한번이상 실행되면 대부분 발견되는 문제
충분한 QA로 대부분의 에러를 잡아냄
우리가 노력해야 할 것
유닛 테스트로 코드 커버리지를 높여 두는 것
콘텐츠 마다 담당 개발자가 작성하는 유닛 테스트
유닛테스트 실패는 곧 배포 실패
여러 곳에서 활용
• 인스턴스 메시징 서버 (Elixir, Erlang)
• 메시지 큐 (Erlang)
• 채팅 서버 (Erlang)
• 소셜 네트워크 서비스 (Elixir)
생산성 증가
빠른 빌드. 클린 빌드 15초 내외
군더더기 없는 문법 (우연적 복잡성을 줄여줌)
2019.3월
파일수 라인수 언어
달빛 500개 11만줄 Elixir
문명 3,300개 65만줄 C++
배타적인 기능 제외
빠른 이터레이션
적극적 유닛 테스트 활용
현재 기본 로그인, 인게임 전투, 각종 기본 콘텐츠에 대한 유닛테스트 200여 가지
로그인이
안되요.
입장이 안되요. 전투가
안되요.
서버로 인한 이런 문제는 이제 잘 없는데... 사람들은 잘 모름 흐흐
소소한 행복
메모리 문제에서 해방 메모리 릭은 해결 못함
메모리 침범에 의한 알수 없는 크래시 없음
순수한 함수 덕택에 발생한 것은 재현하기 쉬움
타이밍 문제로 인한 고생이 덜함
삶의 질이
나아지는 듯
마무리
Elixir
Erlang의 기능
분산 메커니즘
내결함성
고가용성
Elixir의 기능
언어 스타일
패키지 매니저
코드 생산성
얼랭의
생태계
현대적인
기능과
생산성
서버 개발 시 고려
많은 수의 프로세스를 만든다는 가정하에 접근, 설계
프로세스를 어떻게 나눌지 결정
논리적으로 고립될 수 있고 독립적인 로직
프로세스가 헤비 로드 Heavy Load 를 가지지 않도록 분배
프로세스간 메시지를 Compact 하게 유지
이런 개발자 분에게 추천
높은 가용성 을 가진 서버를 만들고 싶은 분
유닛 테스트를 제대로 활용해보고 싶은 욕구가 있는 분
빠른 개발, 빠른 이터레이션에 목마른 분
이런 서버 개발에 추천
REST API 사용하는 Stateless 게임 서버
스케일 아웃 가능한 벡엔드 서버
MO 형태의 게임 서버
MMO 서버는 달빛 조각사에서 합니다.
Elixir
멀티 코어 시대
Free lunch is over (herb sutter 2005)
하드웨어 리소스 어떻게 활용할지 이슈
Elixir가 그 대안이 되지 않을까 기대합니다.
감사합니다.
달빛 조각사에서 개발자를 모십니다.

More Related Content

What's hot

MMOG Server-Side 충돌 및 이동처리 설계와 구현
MMOG Server-Side 충돌 및 이동처리 설계와 구현MMOG Server-Side 충돌 및 이동처리 설계와 구현
MMOG Server-Side 충돌 및 이동처리 설계와 구현YEONG-CHEON YOU
 
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019devCAT Studio, NEXON
 
Windows IOCP vs Linux EPOLL Performance Comparison
Windows IOCP vs Linux EPOLL Performance ComparisonWindows IOCP vs Linux EPOLL Performance Comparison
Windows IOCP vs Linux EPOLL Performance ComparisonSeungmo Koo
 
NDC 11 자이언트 서버의 비밀
NDC 11 자이언트 서버의 비밀NDC 11 자이언트 서버의 비밀
NDC 11 자이언트 서버의 비밀승명 양
 
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...Amazon Web Services Korea
 
온라인 게임 처음부터 끝까지 동적언어로 만들기
온라인 게임 처음부터 끝까지 동적언어로 만들기온라인 게임 처음부터 끝까지 동적언어로 만들기
온라인 게임 처음부터 끝까지 동적언어로 만들기Seungjae Lee
 
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버Heungsub Lee
 
테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템QooJuice
 
중앙 서버 없는 게임 로직
중앙 서버 없는 게임 로직중앙 서버 없는 게임 로직
중앙 서버 없는 게임 로직Hoyoung Choi
 
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기Jaeseung Ha
 
게임서버프로그래밍 #8 - 성능 평가
게임서버프로그래밍 #8 - 성능 평가게임서버프로그래밍 #8 - 성능 평가
게임서버프로그래밍 #8 - 성능 평가Seungmo Koo
 
파이썬 생존 안내서 (자막)
파이썬 생존 안내서 (자막)파이썬 생존 안내서 (자막)
파이썬 생존 안내서 (자막)Heungsub Lee
 
[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기
[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기
[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기MinGeun Park
 
NoSQL 위에서 MMORPG 개발하기
NoSQL 위에서 MMORPG 개발하기NoSQL 위에서 MMORPG 개발하기
NoSQL 위에서 MMORPG 개발하기Hoyoung Choi
 
Ndc14 분산 서버 구축의 ABC
Ndc14 분산 서버 구축의 ABCNdc14 분산 서버 구축의 ABC
Ndc14 분산 서버 구축의 ABCHo Gyu Lee
 
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)Heungsub Lee
 
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기강 민우
 
고려대학교 컴퓨터학과 특강 - 대학생 때 알았더라면 좋았을 것들
고려대학교 컴퓨터학과 특강 - 대학생 때 알았더라면 좋았을 것들고려대학교 컴퓨터학과 특강 - 대학생 때 알았더라면 좋았을 것들
고려대학교 컴퓨터학과 특강 - 대학생 때 알았더라면 좋았을 것들Chris Ohk
 
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019devCAT Studio, NEXON
 
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3Heungsub Lee
 

What's hot (20)

MMOG Server-Side 충돌 및 이동처리 설계와 구현
MMOG Server-Side 충돌 및 이동처리 설계와 구현MMOG Server-Side 충돌 및 이동처리 설계와 구현
MMOG Server-Side 충돌 및 이동처리 설계와 구현
 
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
 
Windows IOCP vs Linux EPOLL Performance Comparison
Windows IOCP vs Linux EPOLL Performance ComparisonWindows IOCP vs Linux EPOLL Performance Comparison
Windows IOCP vs Linux EPOLL Performance Comparison
 
NDC 11 자이언트 서버의 비밀
NDC 11 자이언트 서버의 비밀NDC 11 자이언트 서버의 비밀
NDC 11 자이언트 서버의 비밀
 
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
 
온라인 게임 처음부터 끝까지 동적언어로 만들기
온라인 게임 처음부터 끝까지 동적언어로 만들기온라인 게임 처음부터 끝까지 동적언어로 만들기
온라인 게임 처음부터 끝까지 동적언어로 만들기
 
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
 
테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템
 
중앙 서버 없는 게임 로직
중앙 서버 없는 게임 로직중앙 서버 없는 게임 로직
중앙 서버 없는 게임 로직
 
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
 
게임서버프로그래밍 #8 - 성능 평가
게임서버프로그래밍 #8 - 성능 평가게임서버프로그래밍 #8 - 성능 평가
게임서버프로그래밍 #8 - 성능 평가
 
파이썬 생존 안내서 (자막)
파이썬 생존 안내서 (자막)파이썬 생존 안내서 (자막)
파이썬 생존 안내서 (자막)
 
[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기
[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기
[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기
 
NoSQL 위에서 MMORPG 개발하기
NoSQL 위에서 MMORPG 개발하기NoSQL 위에서 MMORPG 개발하기
NoSQL 위에서 MMORPG 개발하기
 
Ndc14 분산 서버 구축의 ABC
Ndc14 분산 서버 구축의 ABCNdc14 분산 서버 구축의 ABC
Ndc14 분산 서버 구축의 ABC
 
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
 
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
 
고려대학교 컴퓨터학과 특강 - 대학생 때 알았더라면 좋았을 것들
고려대학교 컴퓨터학과 특강 - 대학생 때 알았더라면 좋았을 것들고려대학교 컴퓨터학과 특강 - 대학생 때 알았더라면 좋았을 것들
고려대학교 컴퓨터학과 특강 - 대학생 때 알았더라면 좋았을 것들
 
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
 
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3
 

Similar to 김민욱, (달빛조각사) 엘릭서를 이용한 mmorpg 서버 개발, NDC2019

GKAC 2014 Nov. - 안드로이드 스튜디오로 생산성 올리기
GKAC 2014 Nov. - 안드로이드 스튜디오로 생산성 올리기GKAC 2014 Nov. - 안드로이드 스튜디오로 생산성 올리기
GKAC 2014 Nov. - 안드로이드 스튜디오로 생산성 올리기GDG Korea
 
I phone 2 release
I phone 2 releaseI phone 2 release
I phone 2 releaseJaehyeuk Oh
 
NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스Sungik Kim
 
Scala, Scalability
Scala, ScalabilityScala, Scalability
Scala, ScalabilityDongwook Lee
 
카사 공개세미나1회 W.E.L.C.
카사 공개세미나1회  W.E.L.C.카사 공개세미나1회  W.E.L.C.
카사 공개세미나1회 W.E.L.C.Ryan Park
 
Advanced nGrinder
Advanced nGrinderAdvanced nGrinder
Advanced nGrinderJunHo Yoon
 
Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005Ryan Park
 
NDC13: DVCS와 코드리뷰 그리고 자동화를 통한 쾌속 개발
NDC13: DVCS와 코드리뷰 그리고 자동화를 통한 쾌속 개발NDC13: DVCS와 코드리뷰 그리고 자동화를 통한 쾌속 개발
NDC13: DVCS와 코드리뷰 그리고 자동화를 통한 쾌속 개발Jinuk Kim
 
About Visual C++ 10
About  Visual C++ 10About  Visual C++ 10
About Visual C++ 10흥배 최
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기현철 조
 
XECon2015 :: [2-1] 정광섭 - 처음 시작하는 laravel
XECon2015 :: [2-1] 정광섭 - 처음 시작하는 laravelXECon2015 :: [2-1] 정광섭 - 처음 시작하는 laravel
XECon2015 :: [2-1] 정광섭 - 처음 시작하는 laravelXpressEngine
 
처음 시작하는 라라벨
처음 시작하는 라라벨처음 시작하는 라라벨
처음 시작하는 라라벨KwangSeob Jeong
 
안드로이드 빌드: 설탕없는 세계
안드로이드 빌드: 설탕없는 세계안드로이드 빌드: 설탕없는 세계
안드로이드 빌드: 설탕없는 세계Leonardo YongUk Kim
 

Similar to 김민욱, (달빛조각사) 엘릭서를 이용한 mmorpg 서버 개발, NDC2019 (20)

강의자료 2
강의자료 2강의자료 2
강의자료 2
 
GKAC 2014 Nov. - 안드로이드 스튜디오로 생산성 올리기
GKAC 2014 Nov. - 안드로이드 스튜디오로 생산성 올리기GKAC 2014 Nov. - 안드로이드 스튜디오로 생산성 올리기
GKAC 2014 Nov. - 안드로이드 스튜디오로 생산성 올리기
 
I phone 2 release
I phone 2 releaseI phone 2 release
I phone 2 release
 
NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스
 
Scalability
ScalabilityScalability
Scalability
 
Scala, Scalability
Scala, ScalabilityScala, Scalability
Scala, Scalability
 
카사 공개세미나1회 W.E.L.C.
카사 공개세미나1회  W.E.L.C.카사 공개세미나1회  W.E.L.C.
카사 공개세미나1회 W.E.L.C.
 
Advanced nGrinder
Advanced nGrinderAdvanced nGrinder
Advanced nGrinder
 
Manage book project
Manage book projectManage book project
Manage book project
 
Manage book project
Manage book projectManage book project
Manage book project
 
Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005
 
NDC13: DVCS와 코드리뷰 그리고 자동화를 통한 쾌속 개발
NDC13: DVCS와 코드리뷰 그리고 자동화를 통한 쾌속 개발NDC13: DVCS와 코드리뷰 그리고 자동화를 통한 쾌속 개발
NDC13: DVCS와 코드리뷰 그리고 자동화를 통한 쾌속 개발
 
Java the good parts
Java the good partsJava the good parts
Java the good parts
 
About Visual C++ 10
About  Visual C++ 10About  Visual C++ 10
About Visual C++ 10
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
 
5 swift 기초함수
5 swift 기초함수5 swift 기초함수
5 swift 기초함수
 
XECon2015 :: [2-1] 정광섭 - 처음 시작하는 laravel
XECon2015 :: [2-1] 정광섭 - 처음 시작하는 laravelXECon2015 :: [2-1] 정광섭 - 처음 시작하는 laravel
XECon2015 :: [2-1] 정광섭 - 처음 시작하는 laravel
 
처음 시작하는 라라벨
처음 시작하는 라라벨처음 시작하는 라라벨
처음 시작하는 라라벨
 
llvm 소개
llvm 소개llvm 소개
llvm 소개
 
안드로이드 빌드: 설탕없는 세계
안드로이드 빌드: 설탕없는 세계안드로이드 빌드: 설탕없는 세계
안드로이드 빌드: 설탕없는 세계
 

김민욱, (달빛조각사) 엘릭서를 이용한 mmorpg 서버 개발, NDC2019

  • 1. <달빛조각사> Elixir를 이용한 MMORPG 서버 개발 엑스엘게임즈 김민욱
  • 2. 소개 프로그래머 2017 달빛 조각사 (C#,Elixir) 2013 문명 온라인 (C++) 2008 더데이 온라인 (C#,C++) 2007 마비노기2 (C#,C++) 2004 SUN 온라인 (C++) 2002 묵향 온라인 (C++) 2002 디지몬 카드 배틀 for PC (C,C++) 2002 건담 G-Generation for PC (C,C++)
  • 3. Elixir 엘릭서 신생 언어 (2011) - José Valim 생소한 언어 함수형 언어 어느 것 하나 실무, 업계에서 접하기 힘든... 사실 저도 달빛조각사 팀에 합류하기 전까지 잘 몰랐습니다.
  • 4. 고민 다양한 주제 영역 함수형 언어, Elixir 언어, 서버 설계 및 개발 키워드
  • 5. 세션 목적 `Elixir` 함수형 언어의 심리적 장벽 낮춤 새로운 언어 패러다임에 대한 소개 게임 개발 언어로서 선택 가능성 새로운 것에 대한 영감, 사고 전환
  • 6. 서버 개발에서 느꼈던 핵심적인 부분에 집중 너무 다양한 주제를 다루다 보니 이해하기 힘들거나 빠르게 지나갈 수 있으니 먼저 양해 부탁드립니다.
  • 7. 진행 순서 함수형 언어 Elixir Elixir 특징 Elixir 서버 구조 설계 Elixir 도입 결과 마무리
  • 8. 프로젝트 소개 `달빛조각사` 정통 MMORPG 의 경험을 모바일에서 구현 목표 쿼터뷰 시점이고 존을 이동해 가는 게임 플레이 형태 서버 설계 관점에서 보자면
  • 9. 초기 개발 환경 클라이언트 언리얼 엔진 C++ 언어 서버 C# 언어
  • 10. 개발 진행 중간 클라이언트 유니티 엔진 C# 언어 서버 Elixir 언어 다양하고 복합적인 이유가 있지만 이 세션을 통해서 그 이유를 짐작할 수 있도록… 멋진 언어로 한번 만들어 보자. 이렇게 말씀하시지는 않았습니다.
  • 12. Elixir 함수형 언어 특징적인 3가지 1. 데이터 구조 2. 순수한 함수 3. 재귀
  • 13. 데이터 구조 data type 리스트, 튜플, 맵 # 리스트 [1, 2, “문자열”] # 튜플 {1, 2, “문자열”} # 맵 %{name: “이름”, id: 1002} state = %State{ char: %Char{ name: "캐릭터이름", id: 1002, hp: 100, items: %{ 11 => %Item{id: 11, type: 2003, count: 1, slot: 1}, 22 => %Item{id: 22, type: 2004, count: 1, slot: 1} }, guild: %Guild{id: 4000, name: "길드이름", level: 3}, quests: %{ ... }, skills: %{ ... }, buffs: %{ ... }, } } assert state.char.name == “캐릭터이름” assert state.char.items[11].type == 2003 assert state.char.guilds.name == “길드이름”
  • 14. 데이터 immutability 변수값은 불변 메모리 공간에 저장된 내용이 변하지 않음 객체지향 언어 객체 상태, 접근 함수, scope, 캡슐화 … 상태를 제어하기 위한 노력 함수형 언어 데이터 상태를 함수의 입력 / 출력에 의해 제어
  • 15. 순수하다 pureness 함수안에서 사용되는 인자를 입력에 의존 외부 요인에 의해 출력이 달라지지 않음 = 참조 투명성 (referential transparency) = 부작용이 없다 (no side-effect) = 결정론적인 함수 (deterministic)
  • 16. 재귀 recursion 재귀 함수가 코드를 오히려 지저분하게 하기도 함 재귀 함수를 함수로 치환 가능 꼬리 재귀 최적화 tail recursion - 추가적인 스택 사용 안함
  • 18. Elixir 첫번째 특징 현대적이고 생산적인 언어 최신? 기능을 갖추고 있음 빌드 배포 유닛 테스트 패키지 매니저 문서화
  • 19. 통합 빌드 툴 mix 프로젝트 생성 빌드 실행 의존성 관리 배포 유닛테스트 $ mix new hello_world $ mix compile $ mix run $ mix deps.get [clean, update, compile] $ mix release $ mix test
  • 20. 엄브렐라 프로젝트 umbrella • 다양한 하위(서브) 프로젝트들을 관리 • visual studio 솔루션과 프로젝트의 관계와 비슷 q5 엄브렐라 프로젝트 - common 하위 프로젝트 - protocol - world_server - login_server - command_center
  • 21. 인클루드 없다. 하위 프로젝트 간 참조 설정만으로 접근하고 함수 호출! # mix.exs def deps do {`common`, in_umbrella: true} end # login.ex defmoule Login do def process_login(id, pw) do … 중략 … Common.Login.authenticate(id, pw) end end
  • 22. 파이프 연산자 pipe 코드를 줄여주기도 하지만 코드를 좀 더 읽기 쉽게 해준다. # a.txt 1,a1,b1,c1 2,a2,b2,c2 # 중첩된 함수 호출은 읽기 어렵다 list = String.split(String.split(File.read(“a.txt”), “n”), “,”) [1, a1, b1, c1, 2, a2, b2, c2] # 파이프 연산자 list = File.read(“a.txt”) |> String.split(“n”) |> String.split(“,”) [1, a1, b1, c1, 2, a2, b2, c2]
  • 23. 패턴 매칭 pattern matching 위 - 아래 읽어가는 순서로 매칭 에러 처리를 쉽게 도와줌 with :ok <- can_authenticate(user_id, user_pw), :ok <- can_allow_ip(ip), {:ok, user} <- load_user(user_id) do put_in(state.user, user) else {:error_login_invalid, reason} -> send_login_error(state.socket, ...) {:error_login_depulicated, reason} -> send_login_error(state.socket, ...) {:error_allow_ip, reason} -> send_login_error(state.socket, ...) {:db_error, reason} -> send_login_error(state.socket, ...) end
  • 24. 자동 코드 포맷팅 컨벤션 강제 동일한 코드 스타일로 가독성 증가 불 필요한 논쟁에서 벗어남! 아... 이 코드 짠 사람 얼굴을 보고 싶다.
  • 25. 컴파일 속도가 빠르다 Erlang VM위에 동작하는 bytecode로 빌드 현재 달빛 조각사 약 11 만줄 컴파일 20초 내외 끝
  • 26. Elixir 2번째 특징 안정적인 얼랭 기반 위의 견고한 언어 수십년된 얼랭의 생태계를 이용
  • 27. Erlang 잠깐소개 에릭슨(통신회사)가 만든 함수형 언어 1986 발표 1998 오픈 수십동안 현장에서 분산 성능 안정성이 검증된 언어 가용성 99.9999999%
  • 28. 경량화된 프로세스 light-weight process 수천~ 수십만개 프로세스 생성 가능 전투적으로 치열하게 검증된 선점형 스케쥴링
  • 29. 프로세스 모델 액터 기반 모델 프로세스 간 메시지 통신 process = actor mailbox
  • 30. 메시지를 주고 받는 간단한 서버 defmodule TcpServer do def start(port) do {:ok, socket} = :gen_tcp.listen(port, [:binary, packet: 0, active: false, reuseaddr: true]) loop_accept(socket) end defp loop_accept(socket) do {:ok, conn} = :gen_tcp.accept(socket) spawn_link(fn -> recv(conn) end) loop_listen(socket) end defp loop_recv(conn) do case :gen_tcp.recv(conn, 0) do {:ok, data} -> :gen_tcp.send(conn, data) loop_recv(conn) {:error, :closed} -> :ok end end end
  • 31. 마이크로 서비스 비즈니스 로직을 잘게 프로세스로 나누어 처리
  • 32. 가장 무서워 하는 단어 down 항상 서비스 직전의 마음가짐은 조마조마 D-Day가 다가올 수 도록 소화가 잘 안됨 서버 다운됐어요! 한번 살펴 볼께요 서버 프로그래머가
  • 33. Let it Crash! 비즈니스 로직은 언제나 문제가 생길 수 있음 문제가 있으니 죽은 것! 죽었으니 살리면 되지? 장애 복원하는 감시자 supervisor https://learnyousomeerlang.com/supervisors 문명 온라인 AI 서버에서 효과 봄
  • 34. 깨끗하게 재시작 빈도수가 극히 드문 복잡한 예외 처리 ➔ 복잡성 증가가 성능 하락 ➔ 유지 보수 어려움 1. 길드원인 캐릭터가 캐릭터 선택하여 인게임으로 진입 2. 길드장이 길드를 파괴 3. 길드원이 인게임 진입하면서 길드 프로세스에 접근하려고 함 4. 길드원 프로세스 크래시 후 재시작 만약 크래시가 나지 않도록 했다면 클라이언트는 이미 길드 정보를 받았지만 길드는 없는 상태 데이터의 무결성이 깨진 상황
  • 35. 클라가 멈췄는데요? 이제는 안심할 수 있다. 와이 파이가 끊어진 거 아니예요? 서버 다운됐어요! 자네만 끊어졌네요. 1주일 에 여러 번 팀 테스트
  • 36. ETS Erlang Term Storage 얼랭 OTP 내장 메모리 캐시 시스템 튜플 데이터를 테이블에 저장 Constant time 에 가져올 수 있는 매우 빠른 메모리 저장 구조 생성한 프로세스와 Life Cycle 동일 > :ets.new(:user, [:public, :named_table]) > :ets.insert(:user, {“유저1”, user_value, …}) > :ets.lookup(:user, “유저1”)
  • 37. 유닛 테스트 코드 상에 샘플 코드를 작성한 후 유닛테스트로 활용 @doc """ add new timer. ## Examples iex> state = %{ timers: [], elapsed: 0 } iex> state = ExTimer.add(state, {:handler, :name, "uhaha"}, 2000) iex> [timer] = state.timers iex> timer.msg == {:handler, :name, "uhaha"} true iex> timer.delay == 2000/1000 true """ @spec add(state, tuple | atom, integer) :: state def add(state, msg, delay) when is_tuple(msg) or is_atom(msg) do
  • 38. 문서화 코드 함수 타입 스펙 정의 여러 마리 토끼 잡기 - 컴파일 에러 + 정적 분석 (dialyzer) + 문서화 @doc """ add new timer. ## Examples iex> state = %{ timers: [], elapsed: 0 } iex> state = ExTimer.add(state, {:handler, : iex> [timer] = state.timers iex> timer.msg == {:handler, :name, "uhaha"} """ @spec add(state, tuple | atom, integer) :: state def add(state, msg, delay) when is_tuple(msg) or is_atom(msg) do
  • 39. 러닝 커브 생각 보다 학습 난이도가 낮다 (개인적인 생각일지도) • 함수형 언어 • 매크로 • 얼랭 매크로 얼랭
  • 41. 프로세스를 나누는 기준 프로세스간 인터렉션이 많지 않는 로직 명확하게 분리 가능한 콘텐츠 비동기로 동작하는 로직 메시지 전달 비용 로직 처리 비용
  • 42. 유저 프로세스 접속된 수백 ~ 수천의 클라이언트 : 프로세스 = 1:1 대부분의 클라이언트 요청 패킷은 인터렉션이 없는 액션들 일부 클라이언트의 crash 가 전체 서비스에 영향을 주지 않음 유저(캐릭터) 프로세스클라이언트 TCP 소켓 통신
  • 43. 몬스터 그룹 프로세스 몬스터 AI 담당 플레이어와 대부분 동일한 로직으로 동작 지역별로 몬스터 그룹으로 관리 유저와 인접한 몬스터들과의 메시지 인터렉션 수 줄임
  • 44. 프로세스를 찾는 디렉토리 서비스 콘텐츠 별 많고 다양한 프로세스가 존재 콘텐츠 ID 로 pid (process id) + 캐시된 정보를 찾는 메커니즘이 필요 char_id ➔ 유저 프로세스 chan_id ➔ 채널 프로세스 guild_id ➔ 길드 프로세스 party_id ➔ 파티 프로세스 user_pid = UserDirectory.find(char_id) alive? = UserDirectory.alive?(char_id) UserDirectory.send(char_id, {:system_msg, “test”})
  • 45. 초기 프로세스 구조 지역 프로세스 인터랙션용 캐릭터 유저(캐릭터) 프로세스유저 프로세스의 이동, 공격 인터랙션 ➔ 지역(채널) 프로세스
  • 46. 이동, 공격 인터렉션 서버 부하의 대부분을 차지 채널 프로세스로 동기화 비용 올라감 채널 프로세스로 부하가 집중 지역 프로세스 유저(캐릭터) 프로세스
  • 47. 개선1 프로세스 구조 액터 모델 극대화 ➔ 지역 프로세스 집중 부하 분산 유저 프로세스 간 직접 인터렉션
  • 48. 유저 프로세스 간 공격 1. 대상 프로세스로 공격 메시지 전달은 디렉토리 서비스로 2. 유저 프로세스 데이터 변경 주체 (ownership)는 자기자신 CharDirectory.send(target_id, {:attack, attacker, 1002})
  • 49. 피격자 데이터 변경 공격 {:attack, attacker, attack_type} 데미지 계산 (block, miss, critical …) 데미지 후 효과 (버프, 상태, 스탯 계산 …) 피격자 프로세스 공격자 정보를 가지고 피격자는 데미지 처리하고 효과 적용 공격 응답에 대한 패킷 브로드 캐스팅 공격자 프로세스 공격 패킷을 받아서 피격자 프로세스로 전달
  • 50. 공격자 데이터 변경 공격 {:attack, attacker, attack_type} 데미지 계산 (block, miss, critical …) 데미지 후 효과 (버프, 상태, 스탯 계산 …) 공격자에 대해 카운터 버프 걸기! 공격자 프로세스 공격 응답에 대한 정보를 토대로 버프 걸기, 공격자의 상태 변경 공격응답 {:attack_reply, damage_list}
  • 51. 공격응답 {:attack_reply, damage_list} 복수 대상 공격 공격 {:attack, attacker, attack_type} 피격자 프로세스 리스트 로 공격 패킷 만 보내면?
  • 52. 공격자의 공격 ID 발급 공격 {:attack, attack_id, attacker, attack_type} 피격자 프로세스 리스트 로 공격 패킷 만 보내면? 공격응답 {:attack_reply , attack_id, damage_list}
  • 53. 유저 프로세스에서 이동 # 이동 패킷 핸들러 def process_move(state, pos, rot) do old_pos = state.char.pos # 새로운 이동 정보 변경 state = put_in(state.char.pos, pos) state = put_in(state.char.rot, rot) # 지역 관리 프로세스로 이동 Grid.move_char(state.char, old_pos, pos) # 주변 브로드캐스팅 Broadcast.do(state, {:move, state.char.char_id, pos, rot}) end
  • 54. 개선2 지역 관리 프로세스 지역이동 빈도 < 브로드캐스팅 빈도 인터랙션 행위 자체가 메시지 ➔ 메시지 병목 주변에 누가 누가 있는지? 유저 프로세스에서 브로드캐스팅 목록 유지
  • 55. 효과 1. 채널 프로세스의 집중되는 병목 분산 2. 채널 프로세스 버그에 의한 서비스 Down 사라짐 3. 채널 프로세스 비대화된 코드 제거 성능, 안정성, 생산성 증가
  • 56. Elixir 그 외 여러가지
  • 57. 개발에서 배포까지 OTP 로 OTP (open telecom platform) 서버 구축에 필요한 일련의 라이브러리 모음, 프레임워크 GenServer - Generic Server Memory Storage - ETS (erlang term storage) Database - Mnesia (distributed DBMS) Profiling system, debugger Crypto, Internet protocol
  • 58. 매크로 macro meta programming AST라는 문법으로 런타임 시 코드를 생성 컴파일 실행 가능 DSL (domain Specific Language) 정의 가능 달빛. 치트 정의를 매크로를 이용해 단순화
  • 59. 인터렉티브 모드 iex 서버를 인터렉티브 모드(shell)로 실행 가능 Shell에서 함수를 호출하여 바로 결과를 확인 프로세스 메트릭 확인 가능 프로세스 트리 확인 프로세스별 성능 / 메모리
  • 60. 동적 코드 리로딩 클라이언트가 접속한 상태에서 실시간 코드를 수정하여 리로딩 이리저리 고쳐가면서 테스트 iex> r Item warning: redefining module Item (current version loaded from _build/dev/lib/item/ebin/Elixir.Item.beam) lib/item.ex:1 {:reloaded, Item, [Item]}
  • 62. 간편한 분산 서버 구성 기존의 프로세스간 메시지 커뮤니케이션을 그대로 이용 로컬(개발) 프로세스 모드를 리모트 모드로 간단히 변경 Login Process Login Server Login Process World Server
  • 64. 아직은 마이너 언어 많이 알려지지 않았음 다른 프로젝트, 다른 회사에서 사용할 수 있을까? 매년 Erlang, Elixir 컨퍼런스가 개최 반년 주기로 메이저 업데이트 stack overflow Developer Survey Results 2019 https://insights.stackoverflow.com/survey/2019#technology
  • 65. 느슨한 타입 검사 런타임시 발견되는 예외와 에러 Elixir 감시자 프로세스로 시간을 벌어줌 코드 짜놓고 한번은 테스트 하잖아요?
  • 66. 도구로 부터 도움 Error Tracking System 사이드 이펙트 없는 코드 한번이상 실행되면 대부분 발견되는 문제 충분한 QA로 대부분의 에러를 잡아냄
  • 67. 우리가 노력해야 할 것 유닛 테스트로 코드 커버리지를 높여 두는 것 콘텐츠 마다 담당 개발자가 작성하는 유닛 테스트 유닛테스트 실패는 곧 배포 실패
  • 68. 여러 곳에서 활용 • 인스턴스 메시징 서버 (Elixir, Erlang) • 메시지 큐 (Erlang) • 채팅 서버 (Erlang) • 소셜 네트워크 서비스 (Elixir)
  • 69. 생산성 증가 빠른 빌드. 클린 빌드 15초 내외 군더더기 없는 문법 (우연적 복잡성을 줄여줌) 2019.3월 파일수 라인수 언어 달빛 500개 11만줄 Elixir 문명 3,300개 65만줄 C++ 배타적인 기능 제외
  • 70. 빠른 이터레이션 적극적 유닛 테스트 활용 현재 기본 로그인, 인게임 전투, 각종 기본 콘텐츠에 대한 유닛테스트 200여 가지 로그인이 안되요. 입장이 안되요. 전투가 안되요. 서버로 인한 이런 문제는 이제 잘 없는데... 사람들은 잘 모름 흐흐
  • 71. 소소한 행복 메모리 문제에서 해방 메모리 릭은 해결 못함 메모리 침범에 의한 알수 없는 크래시 없음 순수한 함수 덕택에 발생한 것은 재현하기 쉬움 타이밍 문제로 인한 고생이 덜함 삶의 질이 나아지는 듯
  • 73. Elixir Erlang의 기능 분산 메커니즘 내결함성 고가용성 Elixir의 기능 언어 스타일 패키지 매니저 코드 생산성 얼랭의 생태계 현대적인 기능과 생산성
  • 74. 서버 개발 시 고려 많은 수의 프로세스를 만든다는 가정하에 접근, 설계 프로세스를 어떻게 나눌지 결정 논리적으로 고립될 수 있고 독립적인 로직 프로세스가 헤비 로드 Heavy Load 를 가지지 않도록 분배 프로세스간 메시지를 Compact 하게 유지
  • 75. 이런 개발자 분에게 추천 높은 가용성 을 가진 서버를 만들고 싶은 분 유닛 테스트를 제대로 활용해보고 싶은 욕구가 있는 분 빠른 개발, 빠른 이터레이션에 목마른 분
  • 76. 이런 서버 개발에 추천 REST API 사용하는 Stateless 게임 서버 스케일 아웃 가능한 벡엔드 서버 MO 형태의 게임 서버 MMO 서버는 달빛 조각사에서 합니다.
  • 77. Elixir 멀티 코어 시대 Free lunch is over (herb sutter 2005) 하드웨어 리소스 어떻게 활용할지 이슈 Elixir가 그 대안이 되지 않을까 기대합니다.