[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버Heungsub Lee
NDC14에서 발표한 "[야생의 땅: 듀랑고] 서버 아키텍처" 세션의 슬라이드입니다.
슬라이드에 설명이 많지 않은데, 디스이즈게임에서 발표 내용을 잘 정리해주었습니다. 기사도 함께 보시면 좋을 것 같습니다.
http://www.thisisgame.com/webzine/news/nboard/4/?n=54955
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버Heungsub Lee
NDC14에서 발표한 "[야생의 땅: 듀랑고] 서버 아키텍처" 세션의 슬라이드입니다.
슬라이드에 설명이 많지 않은데, 디스이즈게임에서 발표 내용을 잘 정리해주었습니다. 기사도 함께 보시면 좋을 것 같습니다.
http://www.thisisgame.com/webzine/news/nboard/4/?n=54955
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...Amazon Web Services Korea
서비스 런칭을 위해 라이온하트와 카카오게임즈가 어떻게 최적 성능의 인스턴스를 선택하고, Windows 운영 체제를 최적화하며, 왜 Amazon Aurora를 기본 데이터베이스로 채택하였는지를 설명합니다. 또한, 출시부터 운영까지의 과정에서 MMORPG가 어떻게 AWS 상에서 설계되고, 게임 서버 성능을 극대할 수 있었는지에 대해 전달해드립니다.
넥슨코리아 사내 발표자료로 왓 스튜디오에서 파이썬으로 《야생의 땅: 듀랑고》 서버를 비롯한 여러가지 도구를 만든 경험을 공유합니다.
- 게임서버와 각종 툴, 테스트/빌드/배포 시스템을 만들 때 사용한 재료
- 파이썬 코드 품질 개선, 디버깅, 프로파일링, 최적화
- 파이썬 오픈소스 생태계와 왓 스튜디오가 하는 오픈소스 활동
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...Amazon Web Services Korea
서비스 런칭을 위해 라이온하트와 카카오게임즈가 어떻게 최적 성능의 인스턴스를 선택하고, Windows 운영 체제를 최적화하며, 왜 Amazon Aurora를 기본 데이터베이스로 채택하였는지를 설명합니다. 또한, 출시부터 운영까지의 과정에서 MMORPG가 어떻게 AWS 상에서 설계되고, 게임 서버 성능을 극대할 수 있었는지에 대해 전달해드립니다.
넥슨코리아 사내 발표자료로 왓 스튜디오에서 파이썬으로 《야생의 땅: 듀랑고》 서버를 비롯한 여러가지 도구를 만든 경험을 공유합니다.
- 게임서버와 각종 툴, 테스트/빌드/배포 시스템을 만들 때 사용한 재료
- 파이썬 코드 품질 개선, 디버깅, 프로파일링, 최적화
- 파이썬 오픈소스 생태계와 왓 스튜디오가 하는 오픈소스 활동
이 발표는 [야생의 땅: 듀랑고]의 지형 배포 시스템과 생태계 시뮬레이션 자동화 시스템에 대한 이야기를 다룹니다. 듀랑고의 각 섬은 크기와 지형, 기후 조건이 다양하고 섬의 개수가 많아서 수동으로 관리하는 것은 사실상 불가능합니다. 몇번의 사내 테스트와 베타 테스트를 거치면서 이러한 문제를 해결해주는 자동화된 도구의 필요성이 절실해졌고, 작년에 NDC에서 발표했던 생태계 시뮬레이터와 Docker, 그리고 아마존 웹서비스(AWS)를 이용하여 수많은 섬들을 자동으로 생성하고 관리하는 자동화 시스템을 구축하게 되었습니다. 그 과정에서 했던 고민들, 기존의 애플리케이션을 "Dockerizing" 했던 경험, AWS의 각 서비스들을 적절히 활용했던 이야기, AWS의 각 지역별 요금이 상이하다는 점을 이용해서 비용을 절감한 사례, 그리고 자동화 시스템의 문제점과 앞으로의 방향에 대해서 이야기 할 계획입니다.
데브시스터즈의 Cookie Run: OvenBreak 에 적용된 Kubernetes 기반 다중 개발 서버 환경 구축 시스템에 대한 발표입니다.
Container orchestration 기반 개발 환경 구축 시스템의 필요성과, 왜 Kubernetes를 선택했는지, Kubernetes의 개념과 유용한 기능들을 다룹니다. 아울러 구축한 시스템에 대한 데모와, 작업했던 항목들에 대해 리뷰합니다.
*NDC17 발표에서는 데모 동영상을 사용했으나, 슬라이드 캡쳐로 대신합니다.
Backend.AI (https://backend.ai)는 클라우드 및 온-프레미스 환경에서 여러 사용자가 안전하고 효율적으로 컴퓨팅 자원을 공유할 수 있는 머신러닝에 특화된 인프라 관리 프레임워크입니다. 현재 널리 사용되고 있는 오픈소스 기술인 OpenStack, Kubernetes 등과 비교하여 어떤 특징과 차이점이 있는지 소개하고, 프레임워크의 구조와 기반 기술 및 응용 사례를 데모와 함께 소개합니다.
[17.01.19] docker introduction (Korean Version)Ildoo Kim
Docker(도커) 소개를 위해 사용했던 자료입니다.
제가 속한 개발팀에서는 도커 컨테이너를 기반으로 개발부터 배포까지 가능한 환경 및 인프라를 구축하여 개발팀에서 대다수의 오퍼레이션까지 관여하면서 Devops 형태로 운영합니다.
Docker(도커)를 처음 사용하거나 개념적으로 익숙하지 않은 초보를 위해 만든 자료입니다.
슬라이드에서 사용된 스크립트/코드는 아래에 있습니다.
https://github.com/ildoonet/docker_introduction
----
김일두, Software Engineer @ Kakao
Github : https://github.com/ildoonet
Linkedin : https://www.linkedin.com/in/ildoo-kim-56962034/
Momenti Seminar - 5 Years of RosettaStoneChris Ohk
Momenti Seminar에서 진행했던 "하스스톤 시뮬레이터 RosettaStone 개발 5년 간의 기록"의 발표 자료를 공유드립니다. 5년 동안 오픈 소스 프로젝트를 진행하면서 경험했던 일들을 정리하며 어떤 교훈을 얻었는지 생각해보는 시간이었습니다. 많은 분들에게 도움이 되었으면 합니다.
Evolving Reinforcement Learning Algorithms, JD. Co-Reyes et al, 2021Chris Ohk
RL 논문 리뷰 스터디에서 Evolving Reinforcement Learning Algorithms 논문 내용을 정리해 발표했습니다. 이 논문은 Value-based Model-free RL 에이전트의 손실 함수를 표현하는 언어를 설계하고 기존 DQN보다 최적화된 손실 함수를 제안합니다. 많은 분들에게 도움이 되었으면 합니다.
Adversarially Guided Actor-Critic, Y. Flet-Berliac et al, 2021Chris Ohk
RL 논문 리뷰 스터디에서 Adversarially Guided Actor-Critic 논문 내용을 정리해 발표했습니다. AGAC는 Actor-Critic에 GAN에서 영감을 받은 방법들을 결합해 리워드가 희소하고 탐험이 어려운 환경에서 뛰어난 성능을 보여줍니다. 많은 분들에게 도움이 되었으면 합니다.
Agent57: Outperforming the Atari Human Benchmark, Badia, A. P. et al, 2020Chris Ohk
RL 논문 리뷰 스터디에서 Agent57 논문 내용을 정리해 발표했습니다. Agent57은 NGU(Never Give Up)를 기반으로 몇 가지 기능을 개선해 57개의 Atari 게임 모두 인간보다 뛰어난 점수를 기록한 최초의 RL 알고리즘입니다. 많은 분들에게 도움이 되었으면 합니다.
GDG Gwangju DevFest 2019 - <하스스톤> 강화학습 환경 개발기Chris Ohk
강화학습에 관심을 갖게 되어 어떤 게임에 적용해볼까 고민하다가 평소 즐기던 '하스스톤'이라는 게임에 관심을 갖게 되어 2017년 말부터 하스스톤 강화 학습을 위한 API를 만들기 시작했습니다. 이 발표를 통해 평소 하스스톤과 같은 카드 게임 개발이나 게임에 강화학습을 적용하기 위한 환경을 구축하는데 관심을 갖고 있던 프로그래머들에게 조금이나마 도움이 되었으면 합니다.
모던 C++의 시초인 C++11은 C++ 코드 전반에 많은 변화를 가져왔습니다. 그리고 최근 C++20의 표준위원회 회의가 마무리되었습니다. 내년에 C++20이 도입되면 C++11이 처음 도입되었을 때와 비슷한 규모, 또는 그 이상의 변화가 있을 것이라고 예상하고 있습니다. C++20에는 Concepts, Contract, Ranges, Coroutine, Module 등 굵직한 기능 외에도 많은 기능들이 추가될 예정입니다. 이번 세션에서는 C++20에 추가될 주요 기능들을 살펴보고자 합니다.
GDG Campus Korea에서 개최한 'Daily 만년 Junior들의 이야기 : 델리만주' 밋업에서 발표했던 내용으로 대학원 석사 입학 후부터 오늘날까지 어떤 활동들을 했는지 정리했습니다. 대학원생 분들과 게임 프로그래머 취업을 준비하시는 분들께 많은 도움이 되었으면 합니다.
오픈소스 개발을 시작하기로 결정했더라도, 처음 개발하는 경우에는 막상 무엇을 개발할지, 그리고 어떻게 개발해야 할 지 막막하기만 합니다. 이 때는 기존에 공개되어 있는 오픈소스 프로젝트를 활용해 개선해나가는 프로젝트부터 시작하면 많은 도움이 됩니다. 이번 강연에서는 기존 오픈소스 프로젝트를 처음부터 새로 만들어가면서 개선해나갔던 경험을 이야기하고 어떻게 하면 오픈소스 개발에 쉽게 접근할 수 있는지를 알려줍니다.
1. Rust 크로스 플랫폼 프로그래밍
하나의 코드를 여기저기 써볼래요?
Momenti 옥찬호
2. 옥찬호 Chris Ohk
• 현 Momenti Engine Engineer
• 전 Nexon Korea Game Programmer
• Microsoft Developer Technologies MVP
• C Korea Founder Administrator
• Reinforcement Learning KR Administrator
• IT 전문서 집필 및 번역 다수
• 게임샐러드로 코드 한 줄 없이 게임 만들기 2013
• 유니티 Shader와 Effect 제작 2014
• 2D 게임 프로그래밍 2014 , 러스트 핵심 노트 2017
• 모던 C 입문 2017 , C 최적화 2019
utilForever gmail.com
utilForever
3. • Rust 언어의 핵심 기능을 가볍게 살펴봅니다. 자세하게 공부하고 싶다면 공식 문서를 참고하세요.
https://doc.rust lang.org/book/
• 발표 시간을 맞추기 위해 크로스 플랫폼 프로그래밍을 설명할 때 라이브러리/바이너리 파일을 만드는 단계까지만 설명하며,
iOS 앱 또는 웹 사이트랑 연동하는 부분은 저장소에서 별도로 설명합니다.
• 발표 자료와 예제 코드는 다음 저장소에서 확인 가능합니다.
https://github.com/utilForever/2022 INFCON Rust CrossPlatform
들어가며
4. 1
콘텐츠
목차
content
크로스 플랫폼 프로그래밍을 하게 된 이유
기존 개발 상황 및 문제점, 왜 Rust를 선택했는가
2 Rust 언어 소개
Rust 언어의 역사, 기본 문법 맛보기
3 Rust로 크로스 플랫폼 프로그래밍 해보기
Swift for iOS, WebAssembly for Web
4 몇 가지 팁들
애플리케이션 프리징, WebAssembly 디버깅
7. • 여러 플랫폼에서 사용할 수 있는 코어 엔진을 만들어주세요.
• iOS
• Android
• Backend
• Web
• …
이직 후 첫번째 업무
8. • 똑같은 기능을 하는 엔진 코드가 여러 플랫폼에 각각 구현되어 있었다.
• iOS 앱 C Objective C 기반
• 프론트엔드 TypeScript 기반
• 새로운 기능을 구현하거나 기존 기능을 수정해달라는 요청이 들어오면,
• iOS 앱 C 코드를 구현한 뒤, Objective C 코드를 통해 앱에 적용한다.
• 프론트엔드 TypeScript 코드를 구현해 웹에 적용한다.
기존에는 어떻게 개발되고 있었는가
9. • 어떤 기능을 추가/삭제하거나 변경해야 할 때 지원하는 플랫폼마다 작업을 해줘야 한다.
• 유지보수 측면에서 비효율적이다.
• 지원하는 플랫폼이 늘어날수록 작업량이 늘어난다.
• 똑같은 기능을 수행했을 때 플랫폼마다 동작 결과가 달라질 수 있다.
• 플랫폼마다 서로 다른 사람이 구현하기 때문에 발생하는 문제다.
• 서로 다른 동작으로 인해 사용자에게 불편을 초래할 수 있다.
문제점
10. • 플랫폼마다 로직을 구현하지 않고, 한 곳에서 작업하면 좋겠다.
• 다양한 플랫폼에 어떻게 대응해야 할까?
• iOS 앱 Swift API 제공
• Android 앱 Kotlin API 제공
• 백엔드 Elixir API 제공
• 웹 사이트 웹어셈블리 바이너리 파일 제공
어떻게 개선할 것인가
11. • 다양한 언어를 지원하기 위한 API와 웹 어셈블리 코드를 만들 수 있는 언어
• C , Rust, Java, Go, …
• Rust를 선택한 이유
• 타입 안전성
• 메모리 안전성
• 동시성 프로그래밍 안전성
• FFI를 통해 API 지원을 쉽게 할 수 있음
• WebAssembly 바이너리를 쉽게 만들 수 있음
왜 Rust를 선택했는가
12. • 같은 동작을 하는 프로그램을 여러 플랫폼에서 사용할 수 있도록 만들고 있다.
• iOS 앱 Swift
• Android 앱 Kotlin
• 프론트엔드 TypeScript
• 백엔드 Elixir
• 각 플랫폼에서 사용자 입력에 따라 로직을 처리하고 결과물을 보여주기 위한 코드를 개별적으로 작성한다.
프로젝트 구조
코어 엔진
Rust
FFI
Foreign Function Interface
트랜스파일 Transpile
Swift API
Kotlin API
Elixir API
WebAssembly
ReactiveX
14. Rust란?
• https://www.rust lang.org/
• 모질라 재단에서 2010년 7월 7일 처음 발표
• 현재는 러스트 재단으로 독립해서 개발되고 있다.
• Rust 언어의 특징
• 안전한 메모리 관리
• 철저한 예외나 에러 관리
• 특이한 enum 시스템
• 트레이트
• 하이지닉 매크로
• 비동기 프로그래밍
• 제네릭
15. • let 키워드를 사용
• 변수의 자료형을 대부분 유추할 수 있다.
• 변수 숨김 Variable Shadowing 을 지원
• 변수의 이름은 언제나 snake case 형태로 짓는다.
• Rust에서 변수는 기본적으로 변경 불가 Immutable 타입이다.
• 변경 가능 Mutable 한 값을 원한다면 mut 키워드로 표시해줘야 한다.
Rust 기본 문법 변수
16. • 상수는 변수와 달리 반드시 명시적으로 자료형을 지정해야 한다.
• 상수의 이름은 언제나 SCREAMING SNAKE CASE 형태로 짓는다.
Rust 기본 문법 상수
17. • switch를 대체하는 구문
• 모든 케이스를 빠짐 없이 처리해야 한다.
Rust 기본 문법 match
18. • null을 쓰지 않고도 Nullable한 값을 표현할 수 있는 내장된 Generic 열거체
Rust 기본 문법 Option
19. • 실패할 가능성이 있는 값을 반환할 수 있도록 해주는 내장된 Generic 열거체
Rust 기본 문법 Result
20. • 소유자가 함수의 인자로 전달되면, 소유권은 그 함수의 매개 변수로 이동 Move 된다.
• 이동된 이후에는 원래 함수에 있던 변수는 더 이상 사용할 수 없다.
• Rust의 참조 규칙
• 단 하나의 변경 가능한 참조 또는 여러개의 변경 불가능한 참조만 허용하며, 둘 다는 안된다.
• 참조는 그 소유자보다 더 오래 살 수 없다.
Rust 기본 문법 소유권
21. • Rust의 컴파일러는 모든 변수의 생명 주기를 이해하며 참조가 절대로 그 소유자보다 더 오래 존재하지 못하도록 검증을 시도한다.
• 함수에서는 어떤 매개 변수와 리턴 값이 서로 같은 생명 주기를 공유하는지 식별할 수 있도록
심볼로 표시해 명시적으로 생명 주기를 지정할 수 있다.
Rust 기본 문법 생명 주기
22. • Rust에서는 어떠한 방법으로도 데이터와 동작의 상속이 불가능하다.
• 구조체는 부모 구조체로부터 필드를 상속받을 수 없다.
• 구조체는 부모 구조체로부터 함수를 상속받을 수 없다.
• 대신 Rust는 트레잇으로 다형성을 지원한다. 트레잇은 다른 트레잇의 메소드들을 상속받을 수 있다.
Rust 기본 문법 OOP
24. • 다양한 플랫폼에서 Rust 라이브러리에 있는 add 함수와 sub 함수를 호출해 결과를 받은 뒤 출력하는 예제를 만들어 보자.
무엇을 만들 것인가
Rust
Swift
WebAssembly
TypeScript
Objective C
25. • rust cross : 핵심 코드를 구현하는 크레이트. add 함수와 sub 함수를 구현한다.
• rust cross ios : Swift API를 만들기 위한 코드를 구현하는 크레이트.
• rust cross web : WebAssembly로 트랜스파일하기 위한 코드를 구현하는 크레이트.
프로젝트 구조
Root
rust cross
Core Code
rust cross ios
Swift API
rust cross web
WebAssembly
26. • 빈 디렉토리에 Cargo.toml 파일을 만든 뒤 다음과 같이 입력한다.
프로젝트 구조 잡기
27. • cargo new 명령을 통해 만들 수 있다.
• 라이브러리 프로젝트를 만들려면 lib를 붙어야 한다.
• 그렇지 않으면, 바이너리 파일을 생성하는 프로젝트가 만들어진다.
새 Rust 라이브러리 프로젝트 만들기
28. • 외부에서 사용할 수 있도록 pub 키워드를 붙이자.
• 구현을 완료했다면 cargo build release 명령을 통해 빌드가 되는지 확인한다.
rust cross : add/sub 함수 구현하기
29. • Xcode를 설치한다.
• App Store에서 설치할 수 있다.
• Xcode 빌드 툴을 설치한다.
• xcode select install
• 그리고 크로스 컴파일이 가능하도록 iOS 아키텍처를 추가한다.
• rustup target add aarch64 apple ios aarch64 apple ios sim x86 64 apple ios
• 크로스 컴파일을 쉽게 할 수 있도록 도와주는 툴인 cargo lipo를 설치한다.
• cargo install cargo lipo
rust cross ios : iOS를 위한 라이브러리 빌드 준비
30. • Cargo.toml 파일을 연 뒤, 다음과 같이 수정한다.
• 정적/동적 라이브러리를 만들기 위해 lib 의 crate type을 staticlib , cdylib 로 설정한다.
• rust cross 크레이트에 있는 함수들을 사용하므로 dependencies 에 추가한다.
rust cross ios : 프로젝트 설정
31. • 함수의 이름이 맹글링되지 않도록 # no mangle 을 추가한다.
맹글링 Mangling 이란 소스 코드에 선언된 함수나 변수의 이름을 컴파일 단계에서 일정한 규칙을 갖고 변형하는 걸 말한다.
rust cross ios : C 브릿지에서 호출할 코드 작성
32. • Rust에서 사용한 매개 변수 타입과 리턴 타입에 호환되는 타입을 사용해야 한다.
• 예 : i32 또는 i64 int
• 구현을 완료했다면 cargo lipo release 명령을 통해 라이브러리 파일 .a 가 생성되는지 확인한다.
rust cross ios : C 브릿지 헤더 파일 작성
33. • Rust로 WebAssembly 바이너리 파일을 빌드해주는 툴인 wasm pack을 설치한다.
• curl https://rustwasm.github.io/wasm pack/installer/init.sh sSf sh
• JavaScript 번들러를 설치하고 실행할 수 있도록 패키지 매니저인 npm을 설치한다.
• npm install npm latest g
rust cross web : WebAssembly를 위한 라이브러리 빌드 준비
34. • Cargo.toml 파일을 연 뒤, 다음과 같이 수정한다.
• 동적 시스템/러스트 라이브러리를 만들기 위해 lib 의 crate type을 cdylib , rlib 로 설정한다.
• rust cross 크레이트에 있는 함수들을 사용하므로 dependencies 에 추가한다.
• WebAssembly 빌드를 위해 wasm bindgen을 dependencies 에 추가한다.
rust cross web : 프로젝트 설정
35. • 필요할 경우 Wrapper로 처리할 수 있도록 # wasm bindgen 을 추가한다.
• 구현을 완료했다면 wasm pack build 명령을 통해 wasm 파일이 생성되는지 확인한다.
rust cross web : WebAssembly로 빌드할 코드 작성
37. 애플리케이션 프리징 문제
• Swift 앱에서 어떤 동작을 수행하기 위해 UI에서 버튼을 누르면, 엔진에서 처리되는 동안에 앱이 멈추는 문제가 발생한다.
• 원인은 Swift에서 필요한 함수들을 직접 호출하며, 모든 함수 호출은 동기적으로 동작하기 때문이다.
Swift
Rust 인스턴스 포인터
Swift UI
Swift UI
Rust
Rust 코드
38. 애플리케이션 프리징 문제
• 이를 해결하려면, 엔진에 대한 모든 요청을 처리하는 워커를 구현해 백그라운드 스레드에서 동작하게 만들어야 한다.
• 백그라운드 스레드에서 워커 Worker 를 통해 요청들을 Job Queue에 넣으면 작업을 비동기적으로 수행한다.
Rust 인스턴스 포인터
Swift UI
Swift UI
Rust
Swift
백그라운드 스레드
워커 Worker
Job Queue
Fetch
Process
Rust 코드
39. WebAssembly에서의 함수 맹글링 문제
• Rust WebAssembly로 빌드하면 함수 이름들이 맹글링된다.
• 맹글링된 함수 이름 때문에 콜 스택을 제대로 확인할 수 없는 문제가 있다.
40. WebAssembly에서의 함수 맹글링 문제
• 이 문제를 해결하려면 WebAssembly 코드를 배포하는 크레이트의 Cargo.toml에 각 빌드에 따른 설정을 해줘야 한다.
디버깅을 위해, dev 빌드에서 demangle name section을 true로 설정하고 wasm opt에 플래그 _g를 추가한다.
• 이제 wasm 파일이 빌드되면 웹쪽 코드에 pkg 폴더를 붙여넣기하고 실행하면 된다.
41. • npm을 실행했을 때 Failed to decode custom name section 2024365; ignoring Maximum call stack size exceeded
오류가 발생하는 경우가 있다. 이 때는 node를 실행할 때 stack size 10000을 추가해서 스택 크기를 늘려야 한다.
• 하지만 보안 이슈로 인해 NODE OPTIONS를 사용할 수는 없고, package.json에서 npm start에 해당하는 부분에 추가하면 된다.
• 심볼 정보를 전부 포함한 채로 실행하기 때문에 불러오는데 꽤 오랜 시간이 걸릴 수 있다. 인내하고 기다리자!
WebAssembly에서의 함수 맹글링 문제
42. • 이제 잘 실행되고 디맹글링된 함수 이름들을 볼 수 있다.
WebAssembly에서의 함수 맹글링 문제
43. 모멘티와 함께 성장할 분들을 찾습니다!
https://rebrand.ly/momenti