SlideShare une entreprise Scribd logo
1  sur  69
Télécharger pour lire hors ligne
Go로 새 프로젝트 시작하기
Go로 모바일 게임 서버에 도전하면서 겪었던 고난과 역경의 분투기
DEVSISTERS 이준성
1
이준성
joonsung@devsisters.com
github.com/hodduc
2010~ | KAIST CS
| 개발 동아리 SPARCS
2012년 | ACM-ICPC 2012 Daejeon 1st place
2013년 6월 | ACM-ICPC 2013 World Final 48th place
2013~2014년 | 파이오링크
2014년 8월 | 데브시스터즈 입사, 쿠키런 서버 개발.
현재 | Go를 이용한 신규 프로젝트 진행 중
발표자 소개
Go로 새 프로젝트 시작하기 2
왜 Go인가요?
1
3
왜 Go인가요?
Go로 새 프로젝트 시작하기
기존 쿠키런 서버
and
4
왜 Go인가요?
Go로 새 프로젝트 시작하기
목표
복잡하지 않은 서버구조
Spring 부들부들…
모든 서버 컴포넌트를 Scalable하게 만들기
== MySQL 안 쓰거나 의존하지 않기
다른 언어와 잘 결합할 것
C++ (quic), lua (게임 로직), …
5
왜 Go인가요?
Go로 새 프로젝트 시작하기
후보군
6
왜 Go인가요?
Go로 새 프로젝트 시작하기
Type safety
7
왜 Go인가요?
Go로 새 프로젝트 시작하기
Type safety 멀티코어 활용
8
왜 Go인가요?
Go로 새 프로젝트 시작하기
Type safety 멀티코어 활용 IDE support
9
왜 Go인가요?
Go로 새 프로젝트 시작하기
Type safety 멀티코어 활용 IDE support 서드파티 완성도
10
왜 Go인가요?
Go로 새 프로젝트 시작하기
자…바를 써야하나!?
11
왜 Go인가요?
Go로 새 프로젝트 시작하기
개발하기 쉬운가?
어렵다
매우 쉽다
쉽다
12
왜 Go인가요?
Go로 새 프로젝트 시작하기
개발하기 쉬운가? 짜야 하는 코드의 양
어렵다
매우 쉽다
쉽다
매우 많다
매우 적다
적다고 생각했다
13
왜 Go인가요?
Go로 새 프로젝트 시작하기
개발하기 쉬운가? 짜야 하는 코드의 양 Deploy하기 쉬운가?
어렵다
매우 쉽다
쉽다
매우 많다
매우 적다
적다
어렵다
어렵다
매우 쉽다고 생각했다
14
왜 Go인가요?
Go로 새 프로젝트 시작하기
하고 싶은가?
15
왜 Go인가요?
Go로 새 프로젝트 시작하기 16
왜 Go인가요?
Go로 새 프로젝트 시작하기
Go를 선택해서 좋았던 점
17
왜 Go인가요?
Go로 새 프로젝트 시작하기
Go를 선택해서 좋았던 점
• Channel을 활용한 손쉬운 Concurrency 구현
18
왜 Go인가요?
Go로 새 프로젝트 시작하기
Go를 선택해서 좋았던 점
• Channel을 활용한 손쉬운 Concurrency 구현
• 가벼운 고루틴!
19
일회용으로 마구 만들어 써도 충분한 성능의 고루틴
→ 각 유저마다 각각 하나의 고루틴이 로직 담당
→ 자연스럽게 순차적인 요청 처리가 보장됨
왜 Go인가요?
Go로 새 프로젝트 시작하기
Go를 선택해서 좋았던 점
• Channel을 활용한 손쉬운 Concurrency 구현
• 가벼운 고루틴!
• 간결한 코드 사용으로 인한 생산성 향상
20
왜 Go인가요?
Go로 새 프로젝트 시작하기
Go를 선택해서 좋았던 점
• Channel을 활용한 손쉬운 Concurrency 구현
• 가벼운 고루틴!
• 간결한 코드 사용으로 인한 생산성 향상
• Interface의 편리성
21
특히 Cap’n proto나 protobuf와 같은 serialization library와의
궁합이 좋음
왜 Go인가요?
Go로 새 프로젝트 시작하기
Go를 선택해서 좋았던 점
• Channel을 활용한 손쉬운 Concurrency 구현
• 가벼운 고루틴!
• 간결한 코드 사용으로 인한 생산성 향상
• Interface의 편리성
• 빠른 컴파일 속도와 실행 속도 덕분에 테스트가 빠르고 쉬움
22
왜 Go인가요?
Go로 새 프로젝트 시작하기
Go를 선택해서 좋았던 점
• Channel을 활용한 손쉬운 Concurrency 구현
• 가벼운 고루틴!
• 간결한 코드 사용으로 인한 생산성 향상
• Interface의 편리성
• 빠른 컴파일 속도와 실행 속도 덕분에 테스트가 빠르고 쉬움
• 코딩 스타일을 알아서 맞춰줌
23
왜 Go인가요?
Go로 새 프로젝트 시작하기
고통받았던 부분들
24
왜 Go인가요?
Go로 새 프로젝트 시작하기
고통받았던 부분
• 쓸만한 Full-featured Debugger가 없다
the ability to use the debugger to understand a Go program's
full environment will likely never work, and improving gdb
support is not a priority for the team.
- Rob Pike, on March 2014
대부분의 Debugger (gdb, lldb, delve, godebug, …) 가
• 복잡한 상황에서 Go 객체 내부를 제대로 print하지 못하거나
• Function call 을 지원하지 않거나
• Goroutine이 여러 개일 때 제대로 동작하지 않는다
25
왜 Go인가요?
Go로 새 프로젝트 시작하기
고통받았던 부분
• 쓸만한 Full-featured Debugger가 없다
• 잊을 만하면 튀어나오는 서드파티 라이브러리 버그
26
왜 Go인가요?
Go로 새 프로젝트 시작하기 27
왜 Go인가요?
Go로 새 프로젝트 시작하기
고통받았던 부분
• 쓸만한 Full-featured Debugger가 없다
• 잊을 만하면 튀어나오는 서드파티 라이브러리 버그
• 상속 없는 것까진 괜찮은데…
Simple Typing이 언어 철학인 건 알겠는데…
그래도 Generic은 필요하다
Int8Contains, Int16Contains, Int32Contains, Int64Contains,
Int8Random, Int16Random, …을 하나하나 만드는건 좀…
28
왜 Go인가요?
Go로 새 프로젝트 시작하기
고통받았던 부분
• 쓸만한 Full-featured Debugger가 없다
• 잊을 만하면 튀어나오는 서드파티 라이브러리 버그
• 그래도 Generic은 필요하다
• 코드의 많은 부분이 에러 처리 코드다
if err := (…); err != nil { return err }
에러 처리 제대로 하다보면 코드가 생각보다 이쁘진 않다
29
삽질, 삽질, 삽질…
2
30
Concurrent Map
삽질, 삽질, 삽질…
Go로 새 프로젝트 시작하기 31
Go의 map은 thread-safe 하지 않다
Concurrent Map
삽질, 삽질, 삽질…
Go로 새 프로젝트 시작하기 32
type Director struct {
pidMap map[int]*Actor
}
func (d *Director) Start() (*Actor, Pid) {
pid := d.createPid()
actor := NewActor(pid)
d.pidMap[pid] = actor
return actor, pid
}
panic: runtime error: invalid memory address or nil pointer dereference
Concurrent Map
삽질, 삽질, 삽질…
Go로 새 프로젝트 시작하기 33
type Director struct {
sync.RWMutex
pidMap map[int]*Actor
}
func (d *Director) Start() (*Actor, Pid) {
pid := d.createPid()
actor := NewActor(pid)
d.Lock()
defer d.Unlock()
d.pidMap[pid] = actor
return actor, pid
}
Typed nil
삽질, 삽질, 삽질…
Go로 새 프로젝트 시작하기 34
func AssertPositive(i int) *MathError {
if i < 0 {
return &MathError{i}
}
return nil
}
func Root(i int) (int, error) {
err := AssertPositive(i)
if err != nil {
return 0, err
}
return int(math.Sqrt(float64(i))), err
}
func main() {
sqrt, err := Root(81)
if err != nil {
fmt.Println("error is not nil:", err)
} else {
fmt.Println(sqrt)
}
}
Typed nil
삽질, 삽질, 삽질…
Go로 새 프로젝트 시작하기 35
func AssertPositive(i int) *MathError {
if i < 0 {
return &MathError{i}
}
return nil
}
func Root(i int) (int, error) {
err := AssertPositive(i)
if err != nil {
return 0, err
}
return int(math.Sqrt(float64(i))), err
}
func main() {
sqrt, err := Root(81)
if err != nil {
fmt.Println("error is not nil:", err)
} else {
fmt.Println(sqrt)
}
}
Typed nil
삽질, 삽질, 삽질…
Go로 새 프로젝트 시작하기 36
func AssertPositive(i int) *MathError {
if i < 0 {
return &MathError{i}
}
return nil
}
func Root(i int) (int, error) {
err := AssertPositive(i)
if err != nil {
return 0, err
}
return int(math.Sqrt(float64(i))), err
}
func main() {
sqrt, err := Root(81)
if err != nil {
fmt.Println("error is not nil:", err)
} else {
fmt.Println(sqrt)
}
}
type: *MathError
Value: nil
type: error (interface)
Value: typed nil >.<
Error interface로 캐스팅될 때
값은 nil이지만 type이 nil이 아니므로
Interface nil과 같지 않다
Typed nil
삽질, 삽질, 삽질…
Go로 새 프로젝트 시작하기 37
func AssertPositive(i int) *MathError {
if i < 0 {
return &MathError{i}
}
return nil
}
func Root(i int) (int, error) {
err := AssertPositive(i)
if err != nil {
return 0, err
}
return int(math.Sqrt(float64(i))), nil
}
func main() {
sqrt, err := Root(81)
if err != nil {
fmt.Println("error is not nil:", err)
} else {
fmt.Println(sqrt)
}
}
Typed nil
삽질, 삽질, 삽질…
Go로 새 프로젝트 시작하기 38
func RootStr(s string) (int, error) {
i, err := strconv.Atoi(s)
if err != nil {
return 0, err
}
err = AssertPositive(i)
if err != nil {
return 0, err
}
return int(math.Sqrt(float64(i))), nil
}
func main() {
sqrt, err := RootStr("81")
if err != nil {
fmt.Println("error is not nil:", err)
} else {
fmt.Println(sqrt)
}
}
Typed nil
삽질, 삽질, 삽질…
Go로 새 프로젝트 시작하기 39
func RootStr(s string) (int, error) {
i, err := strconv.Atoi(s)
if err != nil {
return 0, err
}
err = AssertPositive(i)
if err != nil {
return 0, err
}
return int(math.Sqrt(float64(i))), nil
}
func main() {
sqrt, err := RootStr("81")
if err != nil {
fmt.Println("error is not nil:", err)
} else {
fmt.Println(sqrt)
}
}
Typed nil
삽질, 삽질, 삽질…
Go로 새 프로젝트 시작하기 40
Nil을 반환하는 상황에서는 “nil”이라는 상수를 사용할 것
(X) if err == nil { return response, err }
(O) if err == nil { return response, nil }
Typed nil
삽질, 삽질, 삽질…
Go로 새 프로젝트 시작하기 41
Nil을 반환하는 상황에서는 “nil”이라는 상수를 사용할 것
서로 다른 타입의 err 변수를 가급적 재사용하지 말 것
if err := Something(); err != nil { ... }
이 구문을 이용하면 if문 안에서 새로운 Scope가 생성되므로 보다 안전
Typed nil
삽질, 삽질, 삽질…
Go로 새 프로젝트 시작하기 42
Nil을 반환하는 상황에서는 “nil”이라는 상수를 사용할 것
서로 다른 타입의 err 변수를 가급적 재사용하지 말 것
특별한 이유가 없다면 모든 함수의 return type을 “error” 인터페이스로 통일할 것
삽질, 삽질, 삽질…
Go로 새 프로젝트 시작하기 43
코드로 코드 만들기
코드로 코드 만들기
삽질, 삽질, 삽질…
Go로 새 프로젝트 시작하기 44
//go:generate ./some_runnable_command_here.sh –opt1 --opt2=foobar
$ go generate
$ go build
$ go test
코드로 코드 만들기
삽질, 삽질, 삽질…
Go로 새 프로젝트 시작하기 45
cat <<< "
package generated
var BaseDir = "$BASEDIR"
var Version = struct {
ServerRevision string
ProtocolRevision string
DeployDate string
}{
"$SERVER_HASH",
"$PROTOCOL_HASH",
"$DEPLOY_DATE",
}
" > generated/version.go
코드로 코드 만들기
삽질, 삽질, 삽질…
Go로 새 프로젝트 시작하기 46
type Ints []int
func (a Ints) Val() []int
func (a Ints) Copy() Ints
func (a Ints) Cut(i int, j int)
func (a Ints) Insert(i int, x int) Ints
func (a Ints) Append(x ...int) Ints
func (a Ints) Reverse()
func (a Ints) Filter(f func(i int, value interface{}) bool) Ints
func (a Ints) Each(f func(i int, value interface{}))
func (a Ints) Map(f func(i int, value interface{}) int) Ints
Type Int32s []int32
......
Type Int64s []int64
코드로 코드 만들기
삽질, 삽질, 삽질…
Go로 새 프로젝트 시작하기 47
• shell script로 만들기
• 빌드 시점의 환경에 대한 정보가 필요할 때
• Go, Python 등을 이용해 프로그래밍하기
• 언어의 한계를 극복! 하거나, 실수하기 쉬운 단순 작업을 여
러 번 해야 할 때
• Go의 ast, parser 모듈이 유용함
• 내가 짠 코드를 ast, parser로 읽어서 적당한 기계 코드
를 패키지에 추가로 삽입
• 용도에 따라 외부 툴 이용하기 등등…
뭐뭐 쓰셨어요?
3
48
vim-go
우리가 사용한 라이브러리들
Go로 새 프로젝트 시작하기 49
Godeps
우리가 사용한 라이브러리들
Go로 새 프로젝트 시작하기 50
• Dependency Manager & Vendoring tool
• Copy all dependencies into Workspace
directory ( ~= virtualenv in Python )
• Fix Go version, Library version, …
{
"ImportPath": "github.com/devsisters/gb-server",
"GoVersion": "go1.4.2",
"Deps": [
{
"ImportPath": "golang.org/x/net/context",
"Rev": "0b492c5a9642fa1365f77ad20bbb259a25572507"
},
{
"ImportPath": "golang.org/x/oauth2",
"Rev": "ce5ea7da934b76b1066c527632359e2b8f65db97"
},
{
"ImportPath": "google.golang.org/api/googleapi",
"Rev": "c34364630fd76916db716b46fd3a75403b161768"
},
....
go-errors
우리가 사용한 라이브러리들
Go로 새 프로젝트 시작하기
var Crashed = errors.Errorf("oh dear")
func Crash() error {
return errors.New(Crashed)
}
if err != nil {
if errors.Is(err, crashy.Crashed) {
fmt.Println(err.(*errors.Error).ErrorStack())
} else {
panic(err)
}
}
51
GoConvey
우리가 사용한 라이브러리들
Go로 새 프로젝트 시작하기
http://goconvey.co/
52
GoConvey
우리가 사용한 라이브러리들
Go로 새 프로젝트 시작하기
http://goconvey.co/
53
GoConvey
우리가 사용한 라이브러리들
Go로 새 프로젝트 시작하기
http://goconvey.co/
54
Test function
testing/quick
우리가 사용한 라이브러리들
Go로 새 프로젝트 시작하기
func TestOddMultipleOfThree(t *testing.T) {
f := func(x int) bool {
y := OddMultipleOfThree(x)
return y%2 == 1 && y%3 == 0
}
if err := quick.Check(f, nil); err != nil {
t.Error(err)
}
}
Target function
Inject random
valid parameter
Check if target function
is working well
55
우리가 공개한 라이브러리들
(자랑) (뿌듯)
4
56
Cine
우리가 공개한 라이브러리들
Go로 새 프로젝트 시작하기
github.com/devsisters/cine
• Actor model for Go (like erlang)
• All actor is identified by unique PID
• Remote actor is treated same as local one
• Supports synchronous / asynchronous function call
Cine
Host 1 Host 2 Host 3
Actor Actor Actor Actor Actor
57
Cine
우리가 공개한 라이브러리들
Go로 새 프로젝트 시작하기
github.com/devsisters/cine
type Phonebook struct {
cine.Actor
book map[string]int
}
cine.Init("127.0.0.1:8000")
phonebook := Phonebook{cine.Actor{}, make(map[string]int)}
pid := cine.StartActor(&phonebook)
// For asynchronous call (ignore all errors)
cine.Cast(pid, nil, (*Phonebook).Add, "Jane", 1234)
// For synchronous call
ret, _ := cine.Call(pid, (*Phonebook).Lookup, "Jane")
number := ret[0].(int)
58
GoQuic
우리가 공개한 라이브러리들
Go로 새 프로젝트 시작하기
github.com/devsisters/goquic
https://www.youtube.com/watch?v=hQZ-0mXFmk8
59
우리가 공개한 라이브러리들
Go로 새 프로젝트 시작하기
QUIC vs TCP+TLS+SPDY/HTTP2
• 0-RTT support
• Multiplexing without Head-of-line blocking
• Forward error correction
• Connection Migration
60
GoQuic
우리가 공개한 라이브러리들
Go로 새 프로젝트 시작하기
github.com/devsisters/goquic
Chromium
Extract QUIC core devsisters/
libquic
Go binding w/ cgo devsisters/
goquic
devsisters.github.io/goquic
// server
goquic.ListenAndServe(":8080", 1, nil)
// client
client := &http.Client{
Transport: goquic.NewRoundTripper(false),
}
resp, err := client.Get("http://example.com/")
61
그래서……?
5
62
Q. 그래서 Go를 새 프로젝트에 써도 될까요?
그래서……?
Go로 새 프로젝트 시작하기 63
Q. 그래서 Go를 새 프로젝트에 써도 될까요?
그래서……?
Go로 새 프로젝트 시작하기
A. 여러가지 난관이 있었지만 데브시스터즈에서는
전체적으로 만족스럽게 개발 중
단, 프로젝트 셋업 초기에
시간 투자와 삽질은 각오할 것
64
Q. 그래서 쿠키런2 언제 나와요?
그래서……?
Go로 새 프로젝트 시작하기 65
Q. 그래서 쿠키런2 언제 나와요?
그래서……?
Go로 새 프로젝트 시작하기
A. 비밀입니다 (웃음)
66
Q. 그래서 Go 개발자 뽑나요?
그래서……?
Go로 새 프로젝트 시작하기 67
Go 개발자 모십니다
joonsung@devsisters.com
감사합니다

Contenu connexe

Tendances

オンプレミスRDBMSをAWSへ移行する手法
オンプレミスRDBMSをAWSへ移行する手法オンプレミスRDBMSをAWSへ移行する手法
オンプレミスRDBMSをAWSへ移行する手法Amazon Web Services Japan
 
Amazon OpenSearch Deep dive - 내부구조, 성능최적화 그리고 스케일링
Amazon OpenSearch Deep dive - 내부구조, 성능최적화 그리고 스케일링Amazon OpenSearch Deep dive - 내부구조, 성능최적화 그리고 스케일링
Amazon OpenSearch Deep dive - 내부구조, 성능최적화 그리고 스케일링Amazon Web Services Korea
 
강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019
강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019
강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019devCAT Studio, NEXON
 
20200708サーバーレスでのAPI管理の考え方
20200708サーバーレスでのAPI管理の考え方20200708サーバーレスでのAPI管理の考え方
20200708サーバーレスでのAPI管理の考え方Amazon Web Services Japan
 
IDC 서버 몽땅 AWS로 이전하기 위한 5가지 방법 - 윤석찬 (AWS 테크에반젤리스트)
IDC 서버 몽땅 AWS로 이전하기 위한 5가지 방법 - 윤석찬 (AWS 테크에반젤리스트) IDC 서버 몽땅 AWS로 이전하기 위한 5가지 방법 - 윤석찬 (AWS 테크에반젤리스트)
IDC 서버 몽땅 AWS로 이전하기 위한 5가지 방법 - 윤석찬 (AWS 테크에반젤리스트) Amazon Web Services Korea
 
KINX와 함께 하는 AWS Direct Connect 도입 - 남시우 매니저, KINX :: AWS Summit Seoul 2019
KINX와 함께 하는 AWS Direct Connect 도입 - 남시우 매니저, KINX :: AWS Summit Seoul 2019KINX와 함께 하는 AWS Direct Connect 도입 - 남시우 매니저, KINX :: AWS Summit Seoul 2019
KINX와 함께 하는 AWS Direct Connect 도입 - 남시우 매니저, KINX :: AWS Summit Seoul 2019Amazon Web Services Korea
 
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...Amazon Web Services Korea
 
Getting Started with Infrastructure as Code
Getting Started with Infrastructure as CodeGetting Started with Infrastructure as Code
Getting Started with Infrastructure as CodeWinWire Technologies Inc
 
DynamoDBの初心者に伝えたい初めて触るときの勘所
DynamoDBの初心者に伝えたい初めて触るときの勘所DynamoDBの初心者に伝えたい初めて触るときの勘所
DynamoDBの初心者に伝えたい初めて触るときの勘所Ryo Sasaki
 
Java EEを補完する仕様 MicroProfile
Java EEを補完する仕様 MicroProfileJava EEを補完する仕様 MicroProfile
Java EEを補完する仕様 MicroProfileNorito Agetsuma
 
AWS와 함께 한 쿠키런 서버 Re-architecting 사례 (Gaming on AWS)
AWS와 함께 한 쿠키런 서버 Re-architecting 사례 (Gaming on AWS)AWS와 함께 한 쿠키런 서버 Re-architecting 사례 (Gaming on AWS)
AWS와 함께 한 쿠키런 서버 Re-architecting 사례 (Gaming on AWS)Brian Hong
 
AWS를 활용한 글로벌 오피스 업무 환경 구축하기 - 류한진, 이랜드시스템스 :: AWS Summit Seoul 2019
AWS를 활용한 글로벌 오피스 업무 환경 구축하기 - 류한진, 이랜드시스템스 :: AWS Summit Seoul 2019AWS를 활용한 글로벌 오피스 업무 환경 구축하기 - 류한진, 이랜드시스템스 :: AWS Summit Seoul 2019
AWS를 활용한 글로벌 오피스 업무 환경 구축하기 - 류한진, 이랜드시스템스 :: AWS Summit Seoul 2019Amazon Web Services Korea
 
20200526 AWS Black Belt Online Seminar AWS X-Ray
20200526 AWS Black Belt Online Seminar AWS X-Ray20200526 AWS Black Belt Online Seminar AWS X-Ray
20200526 AWS Black Belt Online Seminar AWS X-RayAmazon Web Services Japan
 
Using AWS for Backup and Restore (backup in the cloud, backup to the cloud, a...
Using AWS for Backup and Restore (backup in the cloud, backup to the cloud, a...Using AWS for Backup and Restore (backup in the cloud, backup to the cloud, a...
Using AWS for Backup and Restore (backup in the cloud, backup to the cloud, a...Amazon Web Services
 
AWSのログ管理ベストプラクティス
AWSのログ管理ベストプラクティスAWSのログ管理ベストプラクティス
AWSのログ管理ベストプラクティスAkihiro Kuwano
 
Continuous Integration, Build Pipelines and Continuous Deployment
Continuous Integration, Build Pipelines and Continuous DeploymentContinuous Integration, Build Pipelines and Continuous Deployment
Continuous Integration, Build Pipelines and Continuous DeploymentChristopher Read
 
AWS 클라우드 기반 게임 아키텍처 사례 - AWS Summit Seoul 2017
AWS 클라우드 기반 게임 아키텍처 사례 - AWS Summit Seoul 2017AWS 클라우드 기반 게임 아키텍처 사례 - AWS Summit Seoul 2017
AWS 클라우드 기반 게임 아키텍처 사례 - AWS Summit Seoul 2017Amazon Web Services Korea
 

Tendances (20)

オンプレミスRDBMSをAWSへ移行する手法
オンプレミスRDBMSをAWSへ移行する手法オンプレミスRDBMSをAWSへ移行する手法
オンプレミスRDBMSをAWSへ移行する手法
 
Amazon OpenSearch Deep dive - 내부구조, 성능최적화 그리고 스케일링
Amazon OpenSearch Deep dive - 내부구조, 성능최적화 그리고 스케일링Amazon OpenSearch Deep dive - 내부구조, 성능최적화 그리고 스케일링
Amazon OpenSearch Deep dive - 내부구조, 성능최적화 그리고 스케일링
 
강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019
강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019
강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019
 
20200708サーバーレスでのAPI管理の考え方
20200708サーバーレスでのAPI管理の考え方20200708サーバーレスでのAPI管理の考え方
20200708サーバーレスでのAPI管理の考え方
 
AWS Lambdaを紐解く
AWS Lambdaを紐解くAWS Lambdaを紐解く
AWS Lambdaを紐解く
 
IDC 서버 몽땅 AWS로 이전하기 위한 5가지 방법 - 윤석찬 (AWS 테크에반젤리스트)
IDC 서버 몽땅 AWS로 이전하기 위한 5가지 방법 - 윤석찬 (AWS 테크에반젤리스트) IDC 서버 몽땅 AWS로 이전하기 위한 5가지 방법 - 윤석찬 (AWS 테크에반젤리스트)
IDC 서버 몽땅 AWS로 이전하기 위한 5가지 방법 - 윤석찬 (AWS 테크에반젤리스트)
 
KINX와 함께 하는 AWS Direct Connect 도입 - 남시우 매니저, KINX :: AWS Summit Seoul 2019
KINX와 함께 하는 AWS Direct Connect 도입 - 남시우 매니저, KINX :: AWS Summit Seoul 2019KINX와 함께 하는 AWS Direct Connect 도입 - 남시우 매니저, KINX :: AWS Summit Seoul 2019
KINX와 함께 하는 AWS Direct Connect 도입 - 남시우 매니저, KINX :: AWS Summit Seoul 2019
 
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
 
Getting Started with Infrastructure as Code
Getting Started with Infrastructure as CodeGetting Started with Infrastructure as Code
Getting Started with Infrastructure as Code
 
DynamoDBの初心者に伝えたい初めて触るときの勘所
DynamoDBの初心者に伝えたい初めて触るときの勘所DynamoDBの初心者に伝えたい初めて触るときの勘所
DynamoDBの初心者に伝えたい初めて触るときの勘所
 
Java EEを補完する仕様 MicroProfile
Java EEを補完する仕様 MicroProfileJava EEを補完する仕様 MicroProfile
Java EEを補完する仕様 MicroProfile
 
AWS와 함께 한 쿠키런 서버 Re-architecting 사례 (Gaming on AWS)
AWS와 함께 한 쿠키런 서버 Re-architecting 사례 (Gaming on AWS)AWS와 함께 한 쿠키런 서버 Re-architecting 사례 (Gaming on AWS)
AWS와 함께 한 쿠키런 서버 Re-architecting 사례 (Gaming on AWS)
 
AWS를 활용한 글로벌 오피스 업무 환경 구축하기 - 류한진, 이랜드시스템스 :: AWS Summit Seoul 2019
AWS를 활용한 글로벌 오피스 업무 환경 구축하기 - 류한진, 이랜드시스템스 :: AWS Summit Seoul 2019AWS를 활용한 글로벌 오피스 업무 환경 구축하기 - 류한진, 이랜드시스템스 :: AWS Summit Seoul 2019
AWS를 활용한 글로벌 오피스 업무 환경 구축하기 - 류한진, 이랜드시스템스 :: AWS Summit Seoul 2019
 
DevOps with Database on AWS
DevOps with Database on AWSDevOps with Database on AWS
DevOps with Database on AWS
 
20200526 AWS Black Belt Online Seminar AWS X-Ray
20200526 AWS Black Belt Online Seminar AWS X-Ray20200526 AWS Black Belt Online Seminar AWS X-Ray
20200526 AWS Black Belt Online Seminar AWS X-Ray
 
Using AWS for Backup and Restore (backup in the cloud, backup to the cloud, a...
Using AWS for Backup and Restore (backup in the cloud, backup to the cloud, a...Using AWS for Backup and Restore (backup in the cloud, backup to the cloud, a...
Using AWS for Backup and Restore (backup in the cloud, backup to the cloud, a...
 
Serverless Architectures.pdf
Serverless Architectures.pdfServerless Architectures.pdf
Serverless Architectures.pdf
 
AWSのログ管理ベストプラクティス
AWSのログ管理ベストプラクティスAWSのログ管理ベストプラクティス
AWSのログ管理ベストプラクティス
 
Continuous Integration, Build Pipelines and Continuous Deployment
Continuous Integration, Build Pipelines and Continuous DeploymentContinuous Integration, Build Pipelines and Continuous Deployment
Continuous Integration, Build Pipelines and Continuous Deployment
 
AWS 클라우드 기반 게임 아키텍처 사례 - AWS Summit Seoul 2017
AWS 클라우드 기반 게임 아키텍처 사례 - AWS Summit Seoul 2017AWS 클라우드 기반 게임 아키텍처 사례 - AWS Summit Seoul 2017
AWS 클라우드 기반 게임 아키텍처 사례 - AWS Summit Seoul 2017
 

Similaire à Go로 새 프로젝트 시작하기

청강대 특강 - 프로젝트 제대로 해보기
청강대 특강 - 프로젝트 제대로 해보기청강대 특강 - 프로젝트 제대로 해보기
청강대 특강 - 프로젝트 제대로 해보기Chris Ohk
 
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019devCAT Studio, NEXON
 
[Osxdev]4.swift
[Osxdev]4.swift[Osxdev]4.swift
[Osxdev]4.swiftNAVER D2
 
2011 H3 컨퍼런스-파이썬으로 클라우드 하고 싶어요
2011 H3 컨퍼런스-파이썬으로 클라우드 하고 싶어요2011 H3 컨퍼런스-파이썬으로 클라우드 하고 싶어요
2011 H3 컨퍼런스-파이썬으로 클라우드 하고 싶어요Yongho Ha
 
H3 2011 파이썬으로 클라우드 하고 싶어요
H3 2011 파이썬으로 클라우드 하고 싶어요H3 2011 파이썬으로 클라우드 하고 싶어요
H3 2011 파이썬으로 클라우드 하고 싶어요KTH
 
H3 2011 파이썬으로 클라우드 하고 싶어요_분산기술Lab_하용호
H3 2011 파이썬으로 클라우드 하고 싶어요_분산기술Lab_하용호H3 2011 파이썬으로 클라우드 하고 싶어요_분산기술Lab_하용호
H3 2011 파이썬으로 클라우드 하고 싶어요_분산기술Lab_하용호KTH, 케이티하이텔
 
[DS Meetup] iPad로 가벼운 분석환경 구축해보기
[DS Meetup] iPad로 가벼운 분석환경 구축해보기[DS Meetup] iPad로 가벼운 분석환경 구축해보기
[DS Meetup] iPad로 가벼운 분석환경 구축해보기Minho Lee
 
GDB와 strace로 Hang 걸린 Python Process 원격 디버깅
GDB와 strace로 Hang 걸린 Python Process 원격 디버깅GDB와 strace로 Hang 걸린 Python Process 원격 디버깅
GDB와 strace로 Hang 걸린 Python Process 원격 디버깅Youngmin Koo
 
Golang+on+analytics+and+blockchain
Golang+on+analytics+and+blockchainGolang+on+analytics+and+blockchain
Golang+on+analytics+and+blockchainNAVER Engineering
 
C++ 코드 품질 관리 비법
C++ 코드 품질 관리 비법C++ 코드 품질 관리 비법
C++ 코드 품질 관리 비법선협 이
 
200819 NAVER TECH CONCERT 07_신입 iOS 개발자 개발업무 적응기
200819 NAVER TECH CONCERT 07_신입 iOS 개발자 개발업무 적응기200819 NAVER TECH CONCERT 07_신입 iOS 개발자 개발업무 적응기
200819 NAVER TECH CONCERT 07_신입 iOS 개발자 개발업무 적응기NAVER Engineering
 
[Td 2015]windows, linux, mac 신경 안 쓴다. .net 2015와 더더 좋아지는 c# 살짝 훔쳐보기(김명신)
[Td 2015]windows, linux, mac 신경 안 쓴다. .net 2015와 더더 좋아지는 c# 살짝 훔쳐보기(김명신)[Td 2015]windows, linux, mac 신경 안 쓴다. .net 2015와 더더 좋아지는 c# 살짝 훔쳐보기(김명신)
[Td 2015]windows, linux, mac 신경 안 쓴다. .net 2015와 더더 좋아지는 c# 살짝 훔쳐보기(김명신)Sang Don Kim
 
ant로 안드로이드 앱을 자동으로 빌드하자
ant로 안드로이드 앱을 자동으로 빌드하자ant로 안드로이드 앱을 자동으로 빌드하자
ant로 안드로이드 앱을 자동으로 빌드하자Sewon Ann
 
GKAC 2014 Nov. - 그루비로 안드로이드 앱 개발하기
GKAC 2014 Nov. - 그루비로 안드로이드 앱 개발하기GKAC 2014 Nov. - 그루비로 안드로이드 앱 개발하기
GKAC 2014 Nov. - 그루비로 안드로이드 앱 개발하기GDG Korea
 
그루비로 안드로이드 앱 개발하기
그루비로 안드로이드 앱 개발하기그루비로 안드로이드 앱 개발하기
그루비로 안드로이드 앱 개발하기Sangkyoon Nam
 
[C++ Korea 3rd Seminar] 새 C++은 새 Visual Studio에, 좌충우돌 마이그레이션 이야기
[C++ Korea 3rd Seminar] 새 C++은 새 Visual Studio에, 좌충우돌 마이그레이션 이야기[C++ Korea 3rd Seminar] 새 C++은 새 Visual Studio에, 좌충우돌 마이그레이션 이야기
[C++ Korea 3rd Seminar] 새 C++은 새 Visual Studio에, 좌충우돌 마이그레이션 이야기Chris Ohk
 
TDD&Refactoring Day 03: TDD
TDD&Refactoring Day 03: TDDTDD&Refactoring Day 03: TDD
TDD&Refactoring Day 03: TDDSuwon Chae
 
송창규, unity build로 빌드타임 반토막내기, NDC2010
송창규, unity build로 빌드타임 반토막내기, NDC2010송창규, unity build로 빌드타임 반토막내기, NDC2010
송창규, unity build로 빌드타임 반토막내기, NDC2010devCAT Studio, NEXON
 

Similaire à Go로 새 프로젝트 시작하기 (20)

청강대 특강 - 프로젝트 제대로 해보기
청강대 특강 - 프로젝트 제대로 해보기청강대 특강 - 프로젝트 제대로 해보기
청강대 특강 - 프로젝트 제대로 해보기
 
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
 
[Osxdev]4.swift
[Osxdev]4.swift[Osxdev]4.swift
[Osxdev]4.swift
 
2011 H3 컨퍼런스-파이썬으로 클라우드 하고 싶어요
2011 H3 컨퍼런스-파이썬으로 클라우드 하고 싶어요2011 H3 컨퍼런스-파이썬으로 클라우드 하고 싶어요
2011 H3 컨퍼런스-파이썬으로 클라우드 하고 싶어요
 
H3 2011 파이썬으로 클라우드 하고 싶어요
H3 2011 파이썬으로 클라우드 하고 싶어요H3 2011 파이썬으로 클라우드 하고 싶어요
H3 2011 파이썬으로 클라우드 하고 싶어요
 
H3 2011 파이썬으로 클라우드 하고 싶어요_분산기술Lab_하용호
H3 2011 파이썬으로 클라우드 하고 싶어요_분산기술Lab_하용호H3 2011 파이썬으로 클라우드 하고 싶어요_분산기술Lab_하용호
H3 2011 파이썬으로 클라우드 하고 싶어요_분산기술Lab_하용호
 
[DS Meetup] iPad로 가벼운 분석환경 구축해보기
[DS Meetup] iPad로 가벼운 분석환경 구축해보기[DS Meetup] iPad로 가벼운 분석환경 구축해보기
[DS Meetup] iPad로 가벼운 분석환경 구축해보기
 
GDB와 strace로 Hang 걸린 Python Process 원격 디버깅
GDB와 strace로 Hang 걸린 Python Process 원격 디버깅GDB와 strace로 Hang 걸린 Python Process 원격 디버깅
GDB와 strace로 Hang 걸린 Python Process 원격 디버깅
 
Tdd ver.2
Tdd ver.2Tdd ver.2
Tdd ver.2
 
Golang+on+analytics+and+blockchain
Golang+on+analytics+and+blockchainGolang+on+analytics+and+blockchain
Golang+on+analytics+and+blockchain
 
TDD
TDDTDD
TDD
 
C++ 코드 품질 관리 비법
C++ 코드 품질 관리 비법C++ 코드 품질 관리 비법
C++ 코드 품질 관리 비법
 
200819 NAVER TECH CONCERT 07_신입 iOS 개발자 개발업무 적응기
200819 NAVER TECH CONCERT 07_신입 iOS 개발자 개발업무 적응기200819 NAVER TECH CONCERT 07_신입 iOS 개발자 개발업무 적응기
200819 NAVER TECH CONCERT 07_신입 iOS 개발자 개발업무 적응기
 
[Td 2015]windows, linux, mac 신경 안 쓴다. .net 2015와 더더 좋아지는 c# 살짝 훔쳐보기(김명신)
[Td 2015]windows, linux, mac 신경 안 쓴다. .net 2015와 더더 좋아지는 c# 살짝 훔쳐보기(김명신)[Td 2015]windows, linux, mac 신경 안 쓴다. .net 2015와 더더 좋아지는 c# 살짝 훔쳐보기(김명신)
[Td 2015]windows, linux, mac 신경 안 쓴다. .net 2015와 더더 좋아지는 c# 살짝 훔쳐보기(김명신)
 
ant로 안드로이드 앱을 자동으로 빌드하자
ant로 안드로이드 앱을 자동으로 빌드하자ant로 안드로이드 앱을 자동으로 빌드하자
ant로 안드로이드 앱을 자동으로 빌드하자
 
GKAC 2014 Nov. - 그루비로 안드로이드 앱 개발하기
GKAC 2014 Nov. - 그루비로 안드로이드 앱 개발하기GKAC 2014 Nov. - 그루비로 안드로이드 앱 개발하기
GKAC 2014 Nov. - 그루비로 안드로이드 앱 개발하기
 
그루비로 안드로이드 앱 개발하기
그루비로 안드로이드 앱 개발하기그루비로 안드로이드 앱 개발하기
그루비로 안드로이드 앱 개발하기
 
[C++ Korea 3rd Seminar] 새 C++은 새 Visual Studio에, 좌충우돌 마이그레이션 이야기
[C++ Korea 3rd Seminar] 새 C++은 새 Visual Studio에, 좌충우돌 마이그레이션 이야기[C++ Korea 3rd Seminar] 새 C++은 새 Visual Studio에, 좌충우돌 마이그레이션 이야기
[C++ Korea 3rd Seminar] 새 C++은 새 Visual Studio에, 좌충우돌 마이그레이션 이야기
 
TDD&Refactoring Day 03: TDD
TDD&Refactoring Day 03: TDDTDD&Refactoring Day 03: TDD
TDD&Refactoring Day 03: TDD
 
송창규, unity build로 빌드타임 반토막내기, NDC2010
송창규, unity build로 빌드타임 반토막내기, NDC2010송창규, unity build로 빌드타임 반토막내기, NDC2010
송창규, unity build로 빌드타임 반토막내기, NDC2010
 

Go로 새 프로젝트 시작하기

  • 1. Go로 새 프로젝트 시작하기 Go로 모바일 게임 서버에 도전하면서 겪었던 고난과 역경의 분투기 DEVSISTERS 이준성 1
  • 2. 이준성 joonsung@devsisters.com github.com/hodduc 2010~ | KAIST CS | 개발 동아리 SPARCS 2012년 | ACM-ICPC 2012 Daejeon 1st place 2013년 6월 | ACM-ICPC 2013 World Final 48th place 2013~2014년 | 파이오링크 2014년 8월 | 데브시스터즈 입사, 쿠키런 서버 개발. 현재 | Go를 이용한 신규 프로젝트 진행 중 발표자 소개 Go로 새 프로젝트 시작하기 2
  • 4. 왜 Go인가요? Go로 새 프로젝트 시작하기 기존 쿠키런 서버 and 4
  • 5. 왜 Go인가요? Go로 새 프로젝트 시작하기 목표 복잡하지 않은 서버구조 Spring 부들부들… 모든 서버 컴포넌트를 Scalable하게 만들기 == MySQL 안 쓰거나 의존하지 않기 다른 언어와 잘 결합할 것 C++ (quic), lua (게임 로직), … 5
  • 6. 왜 Go인가요? Go로 새 프로젝트 시작하기 후보군 6
  • 7. 왜 Go인가요? Go로 새 프로젝트 시작하기 Type safety 7
  • 8. 왜 Go인가요? Go로 새 프로젝트 시작하기 Type safety 멀티코어 활용 8
  • 9. 왜 Go인가요? Go로 새 프로젝트 시작하기 Type safety 멀티코어 활용 IDE support 9
  • 10. 왜 Go인가요? Go로 새 프로젝트 시작하기 Type safety 멀티코어 활용 IDE support 서드파티 완성도 10
  • 11. 왜 Go인가요? Go로 새 프로젝트 시작하기 자…바를 써야하나!? 11
  • 12. 왜 Go인가요? Go로 새 프로젝트 시작하기 개발하기 쉬운가? 어렵다 매우 쉽다 쉽다 12
  • 13. 왜 Go인가요? Go로 새 프로젝트 시작하기 개발하기 쉬운가? 짜야 하는 코드의 양 어렵다 매우 쉽다 쉽다 매우 많다 매우 적다 적다고 생각했다 13
  • 14. 왜 Go인가요? Go로 새 프로젝트 시작하기 개발하기 쉬운가? 짜야 하는 코드의 양 Deploy하기 쉬운가? 어렵다 매우 쉽다 쉽다 매우 많다 매우 적다 적다 어렵다 어렵다 매우 쉽다고 생각했다 14
  • 15. 왜 Go인가요? Go로 새 프로젝트 시작하기 하고 싶은가? 15
  • 16. 왜 Go인가요? Go로 새 프로젝트 시작하기 16
  • 17. 왜 Go인가요? Go로 새 프로젝트 시작하기 Go를 선택해서 좋았던 점 17
  • 18. 왜 Go인가요? Go로 새 프로젝트 시작하기 Go를 선택해서 좋았던 점 • Channel을 활용한 손쉬운 Concurrency 구현 18
  • 19. 왜 Go인가요? Go로 새 프로젝트 시작하기 Go를 선택해서 좋았던 점 • Channel을 활용한 손쉬운 Concurrency 구현 • 가벼운 고루틴! 19 일회용으로 마구 만들어 써도 충분한 성능의 고루틴 → 각 유저마다 각각 하나의 고루틴이 로직 담당 → 자연스럽게 순차적인 요청 처리가 보장됨
  • 20. 왜 Go인가요? Go로 새 프로젝트 시작하기 Go를 선택해서 좋았던 점 • Channel을 활용한 손쉬운 Concurrency 구현 • 가벼운 고루틴! • 간결한 코드 사용으로 인한 생산성 향상 20
  • 21. 왜 Go인가요? Go로 새 프로젝트 시작하기 Go를 선택해서 좋았던 점 • Channel을 활용한 손쉬운 Concurrency 구현 • 가벼운 고루틴! • 간결한 코드 사용으로 인한 생산성 향상 • Interface의 편리성 21 특히 Cap’n proto나 protobuf와 같은 serialization library와의 궁합이 좋음
  • 22. 왜 Go인가요? Go로 새 프로젝트 시작하기 Go를 선택해서 좋았던 점 • Channel을 활용한 손쉬운 Concurrency 구현 • 가벼운 고루틴! • 간결한 코드 사용으로 인한 생산성 향상 • Interface의 편리성 • 빠른 컴파일 속도와 실행 속도 덕분에 테스트가 빠르고 쉬움 22
  • 23. 왜 Go인가요? Go로 새 프로젝트 시작하기 Go를 선택해서 좋았던 점 • Channel을 활용한 손쉬운 Concurrency 구현 • 가벼운 고루틴! • 간결한 코드 사용으로 인한 생산성 향상 • Interface의 편리성 • 빠른 컴파일 속도와 실행 속도 덕분에 테스트가 빠르고 쉬움 • 코딩 스타일을 알아서 맞춰줌 23
  • 24. 왜 Go인가요? Go로 새 프로젝트 시작하기 고통받았던 부분들 24
  • 25. 왜 Go인가요? Go로 새 프로젝트 시작하기 고통받았던 부분 • 쓸만한 Full-featured Debugger가 없다 the ability to use the debugger to understand a Go program's full environment will likely never work, and improving gdb support is not a priority for the team. - Rob Pike, on March 2014 대부분의 Debugger (gdb, lldb, delve, godebug, …) 가 • 복잡한 상황에서 Go 객체 내부를 제대로 print하지 못하거나 • Function call 을 지원하지 않거나 • Goroutine이 여러 개일 때 제대로 동작하지 않는다 25
  • 26. 왜 Go인가요? Go로 새 프로젝트 시작하기 고통받았던 부분 • 쓸만한 Full-featured Debugger가 없다 • 잊을 만하면 튀어나오는 서드파티 라이브러리 버그 26
  • 27. 왜 Go인가요? Go로 새 프로젝트 시작하기 27
  • 28. 왜 Go인가요? Go로 새 프로젝트 시작하기 고통받았던 부분 • 쓸만한 Full-featured Debugger가 없다 • 잊을 만하면 튀어나오는 서드파티 라이브러리 버그 • 상속 없는 것까진 괜찮은데… Simple Typing이 언어 철학인 건 알겠는데… 그래도 Generic은 필요하다 Int8Contains, Int16Contains, Int32Contains, Int64Contains, Int8Random, Int16Random, …을 하나하나 만드는건 좀… 28
  • 29. 왜 Go인가요? Go로 새 프로젝트 시작하기 고통받았던 부분 • 쓸만한 Full-featured Debugger가 없다 • 잊을 만하면 튀어나오는 서드파티 라이브러리 버그 • 그래도 Generic은 필요하다 • 코드의 많은 부분이 에러 처리 코드다 if err := (…); err != nil { return err } 에러 처리 제대로 하다보면 코드가 생각보다 이쁘진 않다 29
  • 31. Concurrent Map 삽질, 삽질, 삽질… Go로 새 프로젝트 시작하기 31 Go의 map은 thread-safe 하지 않다
  • 32. Concurrent Map 삽질, 삽질, 삽질… Go로 새 프로젝트 시작하기 32 type Director struct { pidMap map[int]*Actor } func (d *Director) Start() (*Actor, Pid) { pid := d.createPid() actor := NewActor(pid) d.pidMap[pid] = actor return actor, pid } panic: runtime error: invalid memory address or nil pointer dereference
  • 33. Concurrent Map 삽질, 삽질, 삽질… Go로 새 프로젝트 시작하기 33 type Director struct { sync.RWMutex pidMap map[int]*Actor } func (d *Director) Start() (*Actor, Pid) { pid := d.createPid() actor := NewActor(pid) d.Lock() defer d.Unlock() d.pidMap[pid] = actor return actor, pid }
  • 34. Typed nil 삽질, 삽질, 삽질… Go로 새 프로젝트 시작하기 34 func AssertPositive(i int) *MathError { if i < 0 { return &MathError{i} } return nil } func Root(i int) (int, error) { err := AssertPositive(i) if err != nil { return 0, err } return int(math.Sqrt(float64(i))), err } func main() { sqrt, err := Root(81) if err != nil { fmt.Println("error is not nil:", err) } else { fmt.Println(sqrt) } }
  • 35. Typed nil 삽질, 삽질, 삽질… Go로 새 프로젝트 시작하기 35 func AssertPositive(i int) *MathError { if i < 0 { return &MathError{i} } return nil } func Root(i int) (int, error) { err := AssertPositive(i) if err != nil { return 0, err } return int(math.Sqrt(float64(i))), err } func main() { sqrt, err := Root(81) if err != nil { fmt.Println("error is not nil:", err) } else { fmt.Println(sqrt) } }
  • 36. Typed nil 삽질, 삽질, 삽질… Go로 새 프로젝트 시작하기 36 func AssertPositive(i int) *MathError { if i < 0 { return &MathError{i} } return nil } func Root(i int) (int, error) { err := AssertPositive(i) if err != nil { return 0, err } return int(math.Sqrt(float64(i))), err } func main() { sqrt, err := Root(81) if err != nil { fmt.Println("error is not nil:", err) } else { fmt.Println(sqrt) } } type: *MathError Value: nil type: error (interface) Value: typed nil >.< Error interface로 캐스팅될 때 값은 nil이지만 type이 nil이 아니므로 Interface nil과 같지 않다
  • 37. Typed nil 삽질, 삽질, 삽질… Go로 새 프로젝트 시작하기 37 func AssertPositive(i int) *MathError { if i < 0 { return &MathError{i} } return nil } func Root(i int) (int, error) { err := AssertPositive(i) if err != nil { return 0, err } return int(math.Sqrt(float64(i))), nil } func main() { sqrt, err := Root(81) if err != nil { fmt.Println("error is not nil:", err) } else { fmt.Println(sqrt) } }
  • 38. Typed nil 삽질, 삽질, 삽질… Go로 새 프로젝트 시작하기 38 func RootStr(s string) (int, error) { i, err := strconv.Atoi(s) if err != nil { return 0, err } err = AssertPositive(i) if err != nil { return 0, err } return int(math.Sqrt(float64(i))), nil } func main() { sqrt, err := RootStr("81") if err != nil { fmt.Println("error is not nil:", err) } else { fmt.Println(sqrt) } }
  • 39. Typed nil 삽질, 삽질, 삽질… Go로 새 프로젝트 시작하기 39 func RootStr(s string) (int, error) { i, err := strconv.Atoi(s) if err != nil { return 0, err } err = AssertPositive(i) if err != nil { return 0, err } return int(math.Sqrt(float64(i))), nil } func main() { sqrt, err := RootStr("81") if err != nil { fmt.Println("error is not nil:", err) } else { fmt.Println(sqrt) } }
  • 40. Typed nil 삽질, 삽질, 삽질… Go로 새 프로젝트 시작하기 40 Nil을 반환하는 상황에서는 “nil”이라는 상수를 사용할 것 (X) if err == nil { return response, err } (O) if err == nil { return response, nil }
  • 41. Typed nil 삽질, 삽질, 삽질… Go로 새 프로젝트 시작하기 41 Nil을 반환하는 상황에서는 “nil”이라는 상수를 사용할 것 서로 다른 타입의 err 변수를 가급적 재사용하지 말 것 if err := Something(); err != nil { ... } 이 구문을 이용하면 if문 안에서 새로운 Scope가 생성되므로 보다 안전
  • 42. Typed nil 삽질, 삽질, 삽질… Go로 새 프로젝트 시작하기 42 Nil을 반환하는 상황에서는 “nil”이라는 상수를 사용할 것 서로 다른 타입의 err 변수를 가급적 재사용하지 말 것 특별한 이유가 없다면 모든 함수의 return type을 “error” 인터페이스로 통일할 것
  • 43. 삽질, 삽질, 삽질… Go로 새 프로젝트 시작하기 43 코드로 코드 만들기
  • 44. 코드로 코드 만들기 삽질, 삽질, 삽질… Go로 새 프로젝트 시작하기 44 //go:generate ./some_runnable_command_here.sh –opt1 --opt2=foobar $ go generate $ go build $ go test
  • 45. 코드로 코드 만들기 삽질, 삽질, 삽질… Go로 새 프로젝트 시작하기 45 cat <<< " package generated var BaseDir = "$BASEDIR" var Version = struct { ServerRevision string ProtocolRevision string DeployDate string }{ "$SERVER_HASH", "$PROTOCOL_HASH", "$DEPLOY_DATE", } " > generated/version.go
  • 46. 코드로 코드 만들기 삽질, 삽질, 삽질… Go로 새 프로젝트 시작하기 46 type Ints []int func (a Ints) Val() []int func (a Ints) Copy() Ints func (a Ints) Cut(i int, j int) func (a Ints) Insert(i int, x int) Ints func (a Ints) Append(x ...int) Ints func (a Ints) Reverse() func (a Ints) Filter(f func(i int, value interface{}) bool) Ints func (a Ints) Each(f func(i int, value interface{})) func (a Ints) Map(f func(i int, value interface{}) int) Ints Type Int32s []int32 ...... Type Int64s []int64
  • 47. 코드로 코드 만들기 삽질, 삽질, 삽질… Go로 새 프로젝트 시작하기 47 • shell script로 만들기 • 빌드 시점의 환경에 대한 정보가 필요할 때 • Go, Python 등을 이용해 프로그래밍하기 • 언어의 한계를 극복! 하거나, 실수하기 쉬운 단순 작업을 여 러 번 해야 할 때 • Go의 ast, parser 모듈이 유용함 • 내가 짠 코드를 ast, parser로 읽어서 적당한 기계 코드 를 패키지에 추가로 삽입 • 용도에 따라 외부 툴 이용하기 등등…
  • 49. vim-go 우리가 사용한 라이브러리들 Go로 새 프로젝트 시작하기 49
  • 50. Godeps 우리가 사용한 라이브러리들 Go로 새 프로젝트 시작하기 50 • Dependency Manager & Vendoring tool • Copy all dependencies into Workspace directory ( ~= virtualenv in Python ) • Fix Go version, Library version, … { "ImportPath": "github.com/devsisters/gb-server", "GoVersion": "go1.4.2", "Deps": [ { "ImportPath": "golang.org/x/net/context", "Rev": "0b492c5a9642fa1365f77ad20bbb259a25572507" }, { "ImportPath": "golang.org/x/oauth2", "Rev": "ce5ea7da934b76b1066c527632359e2b8f65db97" }, { "ImportPath": "google.golang.org/api/googleapi", "Rev": "c34364630fd76916db716b46fd3a75403b161768" }, ....
  • 51. go-errors 우리가 사용한 라이브러리들 Go로 새 프로젝트 시작하기 var Crashed = errors.Errorf("oh dear") func Crash() error { return errors.New(Crashed) } if err != nil { if errors.Is(err, crashy.Crashed) { fmt.Println(err.(*errors.Error).ErrorStack()) } else { panic(err) } } 51
  • 52. GoConvey 우리가 사용한 라이브러리들 Go로 새 프로젝트 시작하기 http://goconvey.co/ 52
  • 53. GoConvey 우리가 사용한 라이브러리들 Go로 새 프로젝트 시작하기 http://goconvey.co/ 53
  • 54. GoConvey 우리가 사용한 라이브러리들 Go로 새 프로젝트 시작하기 http://goconvey.co/ 54
  • 55. Test function testing/quick 우리가 사용한 라이브러리들 Go로 새 프로젝트 시작하기 func TestOddMultipleOfThree(t *testing.T) { f := func(x int) bool { y := OddMultipleOfThree(x) return y%2 == 1 && y%3 == 0 } if err := quick.Check(f, nil); err != nil { t.Error(err) } } Target function Inject random valid parameter Check if target function is working well 55
  • 57. Cine 우리가 공개한 라이브러리들 Go로 새 프로젝트 시작하기 github.com/devsisters/cine • Actor model for Go (like erlang) • All actor is identified by unique PID • Remote actor is treated same as local one • Supports synchronous / asynchronous function call Cine Host 1 Host 2 Host 3 Actor Actor Actor Actor Actor 57
  • 58. Cine 우리가 공개한 라이브러리들 Go로 새 프로젝트 시작하기 github.com/devsisters/cine type Phonebook struct { cine.Actor book map[string]int } cine.Init("127.0.0.1:8000") phonebook := Phonebook{cine.Actor{}, make(map[string]int)} pid := cine.StartActor(&phonebook) // For asynchronous call (ignore all errors) cine.Cast(pid, nil, (*Phonebook).Add, "Jane", 1234) // For synchronous call ret, _ := cine.Call(pid, (*Phonebook).Lookup, "Jane") number := ret[0].(int) 58
  • 59. GoQuic 우리가 공개한 라이브러리들 Go로 새 프로젝트 시작하기 github.com/devsisters/goquic https://www.youtube.com/watch?v=hQZ-0mXFmk8 59
  • 60. 우리가 공개한 라이브러리들 Go로 새 프로젝트 시작하기 QUIC vs TCP+TLS+SPDY/HTTP2 • 0-RTT support • Multiplexing without Head-of-line blocking • Forward error correction • Connection Migration 60
  • 61. GoQuic 우리가 공개한 라이브러리들 Go로 새 프로젝트 시작하기 github.com/devsisters/goquic Chromium Extract QUIC core devsisters/ libquic Go binding w/ cgo devsisters/ goquic devsisters.github.io/goquic // server goquic.ListenAndServe(":8080", 1, nil) // client client := &http.Client{ Transport: goquic.NewRoundTripper(false), } resp, err := client.Get("http://example.com/") 61
  • 63. Q. 그래서 Go를 새 프로젝트에 써도 될까요? 그래서……? Go로 새 프로젝트 시작하기 63
  • 64. Q. 그래서 Go를 새 프로젝트에 써도 될까요? 그래서……? Go로 새 프로젝트 시작하기 A. 여러가지 난관이 있었지만 데브시스터즈에서는 전체적으로 만족스럽게 개발 중 단, 프로젝트 셋업 초기에 시간 투자와 삽질은 각오할 것 64
  • 65. Q. 그래서 쿠키런2 언제 나와요? 그래서……? Go로 새 프로젝트 시작하기 65
  • 66. Q. 그래서 쿠키런2 언제 나와요? 그래서……? Go로 새 프로젝트 시작하기 A. 비밀입니다 (웃음) 66
  • 67. Q. 그래서 Go 개발자 뽑나요? 그래서……? Go로 새 프로젝트 시작하기 67