SlideShare a Scribd company logo
1 of 72
Mobile SNG Network
2017.08 Bob
이 자료는
• 모바일 SNG 게임 네트워크 통신 구현 사례
• 미루고 미루다가 더 이상 미루면, 기억이 가루가 될 것 같아서 쓰는 자료
결론
• 비동기 네트워크 통신은 구질구질함
• 4줄 요약
• Action은 동기/비동기 구분
• 순서 보장을 위해, Queue에 쌓아서 보냄
• 재시도 처리를 위해, 고유 번호를 할당
• 쌓인 Action은 한 번에 보냄
목차
1. 게임 특징 소개
2. 기본적인 네트워크 구조
3. 재시도 구조
4. 서비스 오픈 후 발생한 문제점
5. 통신 구조 개선 사례
6. 추가 개선
#1 게임 소개
SNG 농장 게임
게임 특징
• Mobile
• Social Network Game
• Farm Simulation
게임 특징: Mobile
• Mobile
• 네트워크 환경이 나쁠 수 있다
• 서버에 사용자 데이터 저장
• 거의 모든 사용자 동작을 서버에 전송
• Social Network Game
• Farm Simulation
게임 특징: SNG
• Mobile
• Social Network Game
• 다른 사용자 간의 데이터 참조 및 간섭
• 여러 사용자의 데이터 동시성 문제 발생
• Farm Simulation
게임 특징: Farm
• Mobile
• Social Network Game
• Farm Simulation
• 수확, 생산이 잘 돌아가야 함
• 서버 응답을 꼭 기다릴 필요 없는 통신이 많음
게임 특징
• Mobile
• Social Network Game
• Farm Simulation
• 핵심 요구사항 정리
그런 거 모르겠고 그냥 언제 어디서나
빠르고 잘 돌아갔으면 좋겠다.
+AWS 구조 참조
+기술 스펙 참조
• 이후에 AWS Elastic Beanstalk로 개선함
• User DB는 NoSQL(DynamoDB) JSON
• 필요에 따라 MySQL, Redis 도 적절히 사용
• 서버-클라 통신은 HTTPS (JSON)
#2 Network 구조
Action
• 서버에 저장해야 하는
사용자의 모든 동작을
Action이라고 명명함
• Ex. 로그인, 생산, 수확, 건설, 판매, 뽑기, 거래, 선물 등등
Action 기본 통신 구조
사용자 입력
빵 생산
서버 데이터 처리
[생산]
밀가루 -1
빵 생산 시작
게임 연출
밀가루 소모 연출
+
빵 생산 연출
게임 내 사용자 경험
• 기존 처리 완료를 기다려야
다음 요청을 처리할 수 있음
• 응답이 오기전 까지, 사용자의 입력을 막고 대기
• 네트워크 지연 시, 사용자 경험이 매우 나빠짐
동기 / 비동기 Action 구분
• 서버 응답을 기다려야 하는지를 기준으로
동기 / 비동기 Action 두 종류로 구분함
• 동기 Action: 서버 응답 대기
Ex. 친구정보, 거래, 선물, 뽑기 등
• 비동기 Action: 클라 우선 예측 처리
Ex. 생산, 수확, 아이템 판매 등
동기 Action 동작 예시
사용자 입력
밀가루 수확
빵 생산
서버 데이터 처리
[생산]
밀가루 -1
빵 생산 시작
[수확]
밀가루 +1
게임 연출
밀가루 획득 연출
밀가루 소모 연출
+
빵 생산 연출
서버 데이터 처리
[생산]
밀가루 -1
빵 생산 시작
[수확]
밀가루 +1
비동기 Action 동작 예시
사용자 입력
밀가루 수확
빵 생산
게임 연출
밀가루 획득 연출
밀가루 소모 연출
+
빵 생산 연출
비동기 Action 요약
• 그림으로 그리니까 너무 어려운데
• 서버 응답을 예측(Action 미리 실행)해서
• 게임 클라이언트에서 우선 연출
• 서버 응답은 오든가 말든가 게임은 계속 진행
• 통신 중에는 화면 구석에 동기화 아이콘 표기
• 서버 응답이 에러 발생이면, 게임 정지 / 동기화
비동기 Action 장점
• 게임 특성상, 상당히 많은 Action 비동기 처리
• 사용자 터치 막을 필요 없어짐
• 사용자 유저 경험 매우 좋아짐
• Case. 12층에서 1층 가는 차폐 엘리베이터에서도 게임이 끊어지지 않고 플레이 가능함
+비동기 Action 주의점
• 모든 Action의 서버 처리 순서 보장필요
• Action Queue에 쌓아서 순서대로 처리
• UI 동기화 처리 복잡도 증가
• 현재 표기 값과 현재 확정 값이 다름.
• 재화는 항상 대입보다 증감으로 처리 해야 함.
• 예측 불가 Client rand() != Server rand()
• 서버에서 Random값 참조하는 경우를 비동기 action 처리했다가
random 결과가 달라서 버그가 발생함.
• Random seed를 맞추려다가 그냥 동기 action으로 처리함
#3 Request Numbering
재시도 처리
• 네트워크의 일시적 오류의 대응을 위해
• 서버 응답이 안 오면, 재요청을 하도록 함
재시도 처리 버그
• 해당 요청이 소실된 경우가 아니라면
• 빵을 한 번 생산했는데, 서버에 두 번 들어옴!
Request Numbering
• 클라이언트에서 요청마다 고유 번호를 붙임
• 서버에서는 Redis로 동시성 제어
• 요청이 들어오면, 처리 중 Flag 표기
• 처리가 완료되면, 서버 응답 저장
• 재요청의 경우, 기존에 저장된 응답을 바로 출력
Request Numbering 장점
• 재시도 버그 해결
• 서버의 응답을 10분 정도 보존 (expire)
• 개발 시, 디버깅에도 도움 됨
+Request Numbering 주의점
• 한 유저가 여러 device로 로그인 하면?
• 정책적 처리가 필요
• Redis 부하에 대해서 적절히 잘 처리해야 함
정리
• 대충 이 정도 하고
• CBT 하고 서비스 오픈
Network 통신 구조 정리
https://draw.io
#4 오픈 후 발생 문제
User Report
• 게임이 자꾸 롤백 돼요
• 네트워크 너~~~무 느려요
Rollback?
• 우리는 롤백 기능 같은 거 만든 적 없는데…
서버 응답속도는 정상
• ELB 평균 응답 100ms ~ 250ms
• 서버는 문제 없음. 클라 버그네, 클라 버그여
Client Network 통계
• 클라이언트에서 측정 해 보자!
• 요청 시, 아래 내용 전송
• Action Queue Length
• Action 응답 속도 통계
Client Network data 참조1
• 모든 요청마다 0.1% 수준으로 기록 (Sampling)
• 평균 1300ms (=1.3초)
• 정규분포 가정 시 84%의 요청이 2500ms, 97% 요청은 3670ms
Queue 길이 1 2 3
표본 수 788574
(97.80%)
11158
(1.38%)
3418
(0.42%)
최소 605 602 565
최대 5353 5454 5647
평균 1320 1358 1329
표준편차 1175 1246 1301
Client Network 통계 평균
• 클라이언트가 받는 응답속도는 평균 1300ms
• 서버는 200ms 만에 보냈는데,
• 네트워크가 잘못했네
• 멍청하게도 3G, LTE, WIFI 구분 안 했음
Client Network data 참조2
• Sampling 중에서 Queue길이가 10 이상인 경우 기록
• Action이 100개가 넘게 쌓이는 경우도 있다!?
Queue Count Queue Count Queue Count
11 85 21 5 33 1
12 65 22 5 34 1
13 38 23 1 38 1
14 36 24 2 49 1
15 20 25 2 50 1
16 22 27 3 55 1
17 10 28 3 56 1
18 12 30 1 58 1
19 5 31 1 117 1
20 9 32 2 134 1
Client Network 발견한 문제
• 동기 Action을 수행하려면
• 기존에 쌓여있던 Action 들이
• 순서대로 전부 수행되고 나서야 수행 가능
• 비동기 Action이 발생하자마자 서버 요청을 시작 하는데도
30개 정도는 어렵지 않게 쌓임
• 요청 100개가 쌓여있으면, 평균 1.3초 가정 시
130초 동안 빙글빙글 돌면서 멈춤
User Case
• 게임에 로그인해서
• 생산/수확 한참 하고 나서
• 거래소나 친구 집에 가면
• 게임이 멈춰서 껐다 켰더니
• 생산/수확 요청이 처리 안 되어 있어요
•> 롤백 돼요
기술 용어로 해석
• 게임에 로그인해서 생산/수확 한참 하고 나서
• 비동기 Action을 한 번에 100개쯤 하고
• 거래소나 친구 집에 가면
• 동기 Action을 수행하면 네트워크 응답이 오래 걸리고
• 네트워크 응답이 없어서 껐다 켰더니
• 유저가 네트워크 대기화면에서 게임이 멈춘 거로 인식하고
• 생산/수확 요청이 처리 안 되어 있어요
• 해당 요청이 서버에 안 와서 처리가 안 돼요
좋은 해결 방법
Network 동기화 중
15% 완료
게임의 전원을 끄지 마십시오
대안
• Queue에 쌓여 있는 Action을
한 번에 여러 개 보내보자
• 완전 다른 Action을 묶어서 처리 가능한가요?
• 다행히 서버 설계가 Action 공통 처리 가능한 구조
• 공돌이를 갈면 가능함
#5 Batching Requests
Batching Requests
• 사실 이 정리 자료의 핵심
• 한번 여러 요청이 묶이도록
통신 구조를 거의 다 뜯어야 했음
• 다른 게임에서는 이걸 뭐라고 부르나 몰라서
내부에서는 Bulk processing, network batching 등 여러 가지 이름으로 부름.
적절한 표현이 있다면 알려주세요
기존 평균 응답속도 (REAL)
Client Server
요청600ms
응답 600ms
수행
250ms
기존 통신 3번 일어난다면
Client Server
요청600ms
응답 600ms
수행
250ms
요청600ms
응답 600ms
수행
250ms
요청600ms
응답 600ms
수행
250ms
모아서 보내서, 이렇게 줄여보자
Client Server
요청600ms 수행
250ms
수행
250ms
응답 600ms
수행
250ms
개선 목표
• 서버 내 처리보다 (100ms ~ 250ms)
• 네트워크 전송이 오래 걸리므로 (1300ms)
• 요청을 n 개를 모아서 한 번에 처리하자
• 문제는 밖에 있었다. 서버 최적화 괜히 했어
#5’ DB 처리 개선
Batching 작업 하다가 발견한 다른 장점
이 부분은 패스 하셔도 됩니다.
해당 작업 중 발견한 다른 이점
• 사용자 데이터를
Json format으로
NoSQL 에서 한 번에 관리하고 있었음.
• 통신 구조 상 DB 처리에도 이득
+ 유저 Main DB NoSQL을 쓴 다는 것…
• 주의. 장점 만큼 단점도 많은 방식입니다.
• 장점은 AWS summit 발표자료...
`게임 고객 사례를 통해 살펴보는 AWS 활용 전략` 참조
• 단점은 개인 문의 바람… 여백이 부족하군요. 하하하
통신 처리 (Dev)
Client Server
요청
응답
수행
수행 과정을 자세히 나누면
Server DB
Request Parse
Execute
Serialize
Write User
Deserialize
Client
Response
Fetch User
DB
통신 3번이 일어나면 (기존)
Client Server
DB
개선 통신 처리 (batched)
Client Server
DB 처리 감소 이득
• 별생각 없었는데, 구현하면서 보니 꿀 이득
• 로직과 관련 없는 DB 처리도 (Fetch/Deserialize/Serialize/Write 등등)
한 번만 하면 되더라
Server DB
Request Parse
Execute
Serialize
Write User
Deserialize
Response
Fetch User
Execute
Execute
함정 카드 발동
• 여러 요청 중간에 에러가 발생하면,
마지막 정상 요청까지의 상태를 저장해야 함.
• DB 처리를 무조건 건너 뛸 수는 없음
새로운 이슈
• 작업하면서, 내부 소요 시간도 측정 하다 보니
• Serialize가 공통 병목 구간으로 확인됨
Server DB
Request Parse
Execute
Serialize
Write User
Deserialize
Response
Fetch User
Execute
Execute
Serialized 대책
• 대안
1. Fetch는 한번, Write는 매번 하기
2. Serialized 된 string만 cache 해 두기
3. Memory transaction 으로 변경 추적하기
4. User 객체 deep copy로 보존
• 다른 대안이 조금씩 애매해서, 일단 포기하고 2번
• 난 포기가 빠른 남자니까
• 테스트 상 ExpressionTree로 DeepCopy 하는 게 가장 빠르긴 했음
• http://stackoverflow.com/questions/852064/faster-deep-cloning
DB 처리 개선 정리
• 작업 하다 보니까, DB 처리도 개선되더라
• 처리 속도가 엄청 빨라졌음
• 그런데, 해당 적용으로는 에러 발생시 버그 유발
• 그래서 엄청 빠르게는 못하고, 조금 개선 함
원래 하던 얘기로 돌아가서
• 요청이 100개씩 밀리는 경우가 발생
• 여러 Action을 한 번에 보내면 좋을 것 같아서
• 묶어서 보냄 (= Batching Requests)
• 통신 횟수도 감소, 내부 처리 로직도 개선
모아서 보내는 기준은?
• 100개가 쌓여있다고 100개를 한 번에?!
• 일단 최대 8개씩 보내도록 해봄
• 이후 해당 부분을 수정할 의지가 없어져서 평생 8개씩 보내게 됨
개선 시도 후 테스트
• 기존 150ms 정도 걸리던 요청 (dev서버 기준)
• 첫 Action 만 150ms 정도가 소요되고
• 묶어서 보낸 다른 Action은 10ms 안에 끝남
서비스 적용 후 상황
• 0.1% 샘플링
• 대부분의 요청이 2개씩 묶어서 처리됨.
Batching 적용 효과
• 일단 체감 효과가 좋아짐
• 네트워크 지연 상황을 재현하기도 어려워짐
• 해당 적용 효과 통계 자료가 분실됨…
#6 Future work
Requests Preserve
• 목적: 미요청 데이터 롤백 상황 방지
• 게임을 새로 켜는 순간
전송하지 않은 Request가 남아있다면
해당 정보를 보내고 게임에 진입하면 어떨까?
• 문제가 너무 많이 예상되어서 해보진 못함
정리
• SNG 게임 네트워크 사례
• Action은 동기/비동기 구분
• 순서 보장을 위해, Queue에 쌓아서 보냄
• 재시도 처리를 위해, 고유 번호를 할당
• 쌓인 Action은 한 번에 보냄
끝
프로젝트는 죽어서 기술 자료를 남긴다.
모바일 SNG 비동기 네트워크 통신 사례

More Related Content

What's hot

How To Become A DevOps Engineer | Who Is A DevOps Engineer? | DevOps Engineer...
How To Become A DevOps Engineer | Who Is A DevOps Engineer? | DevOps Engineer...How To Become A DevOps Engineer | Who Is A DevOps Engineer? | DevOps Engineer...
How To Become A DevOps Engineer | Who Is A DevOps Engineer? | DevOps Engineer...Simplilearn
 
Provisioning on Libvirt with Foreman
Provisioning on Libvirt with ForemanProvisioning on Libvirt with Foreman
Provisioning on Libvirt with ForemanNikhil Kathole
 
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3Heungsub Lee
 
AWS 를 활용한 저지연 라이브 (Low Latency Live) 서비스 구현 - 류재춘 컨설턴트/에반젤리스트, GS Neot다 :: AW...
AWS 를 활용한 저지연 라이브 (Low Latency Live) 서비스 구현 - 류재춘 컨설턴트/에반젤리스트, GS Neot다 :: AW...AWS 를 활용한 저지연 라이브 (Low Latency Live) 서비스 구현 - 류재춘 컨설턴트/에반젤리스트, GS Neot다 :: AW...
AWS 를 활용한 저지연 라이브 (Low Latency Live) 서비스 구현 - 류재춘 컨설턴트/에반젤리스트, GS Neot다 :: AW...Amazon Web Services Korea
 
Elasticsearch 엘라스틱서치 (검색서비스) 에 대해 알아보자.txt
Elasticsearch 엘라스틱서치 (검색서비스) 에 대해 알아보자.txtElasticsearch 엘라스틱서치 (검색서비스) 에 대해 알아보자.txt
Elasticsearch 엘라스틱서치 (검색서비스) 에 대해 알아보자.txt용진 조
 
Gaming on AWS - 1. AWS로 글로벌 게임 런칭하기 - 장르별 아키텍처 중심
Gaming on AWS - 1. AWS로 글로벌 게임 런칭하기 - 장르별 아키텍처 중심Gaming on AWS - 1. AWS로 글로벌 게임 런칭하기 - 장르별 아키텍처 중심
Gaming on AWS - 1. AWS로 글로벌 게임 런칭하기 - 장르별 아키텍처 중심Amazon Web Services Korea
 
Quic을 이용한 네트워크 성능 개선
 Quic을 이용한 네트워크 성능 개선 Quic을 이용한 네트워크 성능 개선
Quic을 이용한 네트워크 성능 개선NAVER D2
 
Chaos Engineering: Why the World Needs More Resilient Systems
Chaos Engineering: Why the World Needs More Resilient SystemsChaos Engineering: Why the World Needs More Resilient Systems
Chaos Engineering: Why the World Needs More Resilient SystemsC4Media
 
svn 능력자를 위한 git 개념 가이드
svn 능력자를 위한 git 개념 가이드svn 능력자를 위한 git 개념 가이드
svn 능력자를 위한 git 개념 가이드Insub Lee
 
Faster and Easier Software Development using Docker Platform
Faster and Easier Software Development using Docker PlatformFaster and Easier Software Development using Docker Platform
Faster and Easier Software Development using Docker Platformmsyukor
 
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개if kakao
 
시니어가 들려주는 "내가 알고 있는 걸 당신도 알게 된다면"
시니어가 들려주는 "내가 알고 있는 걸 당신도 알게 된다면"시니어가 들려주는 "내가 알고 있는 걸 당신도 알게 된다면"
시니어가 들려주는 "내가 알고 있는 걸 당신도 알게 된다면"InfraEngineer
 
devops 2년차 이직 성공기.pptx
devops 2년차 이직 성공기.pptxdevops 2년차 이직 성공기.pptx
devops 2년차 이직 성공기.pptxByungho Lee
 
DevOps with GitHub Actions
DevOps with GitHub ActionsDevOps with GitHub Actions
DevOps with GitHub ActionsNilesh Gule
 
Social network with microservices
Social network with microservicesSocial network with microservices
Social network with microservicesViet Tran
 
What is Jenkins | Jenkins Tutorial for Beginners | Edureka
What is Jenkins | Jenkins Tutorial for Beginners | EdurekaWhat is Jenkins | Jenkins Tutorial for Beginners | Edureka
What is Jenkins | Jenkins Tutorial for Beginners | EdurekaEdureka!
 
[부스트캠프 Tech Talk] 신원지_Wandb Visualization
[부스트캠프 Tech Talk] 신원지_Wandb Visualization[부스트캠프 Tech Talk] 신원지_Wandb Visualization
[부스트캠프 Tech Talk] 신원지_Wandb VisualizationCONNECT FOUNDATION
 
트위터의 추천 시스템 파헤치기
트위터의 추천 시스템 파헤치기트위터의 추천 시스템 파헤치기
트위터의 추천 시스템 파헤치기Yan So
 

What's hot (20)

How To Become A DevOps Engineer | Who Is A DevOps Engineer? | DevOps Engineer...
How To Become A DevOps Engineer | Who Is A DevOps Engineer? | DevOps Engineer...How To Become A DevOps Engineer | Who Is A DevOps Engineer? | DevOps Engineer...
How To Become A DevOps Engineer | Who Is A DevOps Engineer? | DevOps Engineer...
 
Provisioning on Libvirt with Foreman
Provisioning on Libvirt with ForemanProvisioning on Libvirt with Foreman
Provisioning on Libvirt with Foreman
 
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3
 
AWS 를 활용한 저지연 라이브 (Low Latency Live) 서비스 구현 - 류재춘 컨설턴트/에반젤리스트, GS Neot다 :: AW...
AWS 를 활용한 저지연 라이브 (Low Latency Live) 서비스 구현 - 류재춘 컨설턴트/에반젤리스트, GS Neot다 :: AW...AWS 를 활용한 저지연 라이브 (Low Latency Live) 서비스 구현 - 류재춘 컨설턴트/에반젤리스트, GS Neot다 :: AW...
AWS 를 활용한 저지연 라이브 (Low Latency Live) 서비스 구현 - 류재춘 컨설턴트/에반젤리스트, GS Neot다 :: AW...
 
Elasticsearch 엘라스틱서치 (검색서비스) 에 대해 알아보자.txt
Elasticsearch 엘라스틱서치 (검색서비스) 에 대해 알아보자.txtElasticsearch 엘라스틱서치 (검색서비스) 에 대해 알아보자.txt
Elasticsearch 엘라스틱서치 (검색서비스) 에 대해 알아보자.txt
 
Gaming on AWS - 1. AWS로 글로벌 게임 런칭하기 - 장르별 아키텍처 중심
Gaming on AWS - 1. AWS로 글로벌 게임 런칭하기 - 장르별 아키텍처 중심Gaming on AWS - 1. AWS로 글로벌 게임 런칭하기 - 장르별 아키텍처 중심
Gaming on AWS - 1. AWS로 글로벌 게임 런칭하기 - 장르별 아키텍처 중심
 
Quic을 이용한 네트워크 성능 개선
 Quic을 이용한 네트워크 성능 개선 Quic을 이용한 네트워크 성능 개선
Quic을 이용한 네트워크 성능 개선
 
Chaos Engineering: Why the World Needs More Resilient Systems
Chaos Engineering: Why the World Needs More Resilient SystemsChaos Engineering: Why the World Needs More Resilient Systems
Chaos Engineering: Why the World Needs More Resilient Systems
 
svn 능력자를 위한 git 개념 가이드
svn 능력자를 위한 git 개념 가이드svn 능력자를 위한 git 개념 가이드
svn 능력자를 위한 git 개념 가이드
 
Faster and Easier Software Development using Docker Platform
Faster and Easier Software Development using Docker PlatformFaster and Easier Software Development using Docker Platform
Faster and Easier Software Development using Docker Platform
 
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
 
시니어가 들려주는 "내가 알고 있는 걸 당신도 알게 된다면"
시니어가 들려주는 "내가 알고 있는 걸 당신도 알게 된다면"시니어가 들려주는 "내가 알고 있는 걸 당신도 알게 된다면"
시니어가 들려주는 "내가 알고 있는 걸 당신도 알게 된다면"
 
DevOps - A Gentle Introduction
DevOps - A Gentle IntroductionDevOps - A Gentle Introduction
DevOps - A Gentle Introduction
 
devops 2년차 이직 성공기.pptx
devops 2년차 이직 성공기.pptxdevops 2년차 이직 성공기.pptx
devops 2년차 이직 성공기.pptx
 
DevOps with GitHub Actions
DevOps with GitHub ActionsDevOps with GitHub Actions
DevOps with GitHub Actions
 
Social network with microservices
Social network with microservicesSocial network with microservices
Social network with microservices
 
What is Jenkins | Jenkins Tutorial for Beginners | Edureka
What is Jenkins | Jenkins Tutorial for Beginners | EdurekaWhat is Jenkins | Jenkins Tutorial for Beginners | Edureka
What is Jenkins | Jenkins Tutorial for Beginners | Edureka
 
Docker and Devops
Docker and DevopsDocker and Devops
Docker and Devops
 
[부스트캠프 Tech Talk] 신원지_Wandb Visualization
[부스트캠프 Tech Talk] 신원지_Wandb Visualization[부스트캠프 Tech Talk] 신원지_Wandb Visualization
[부스트캠프 Tech Talk] 신원지_Wandb Visualization
 
트위터의 추천 시스템 파헤치기
트위터의 추천 시스템 파헤치기트위터의 추천 시스템 파헤치기
트위터의 추천 시스템 파헤치기
 

Similar to 모바일 SNG 비동기 네트워크 통신 사례

KGC 2014: 분산 게임 서버 구조론
KGC 2014: 분산 게임 서버 구조론KGC 2014: 분산 게임 서버 구조론
KGC 2014: 분산 게임 서버 구조론Hyunjik Bae
 
게임 분산 서버 구조
게임 분산 서버 구조게임 분산 서버 구조
게임 분산 서버 구조Hyunjik Bae
 
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019devCAT Studio, NEXON
 
하드웨어 스타트업의 소프트웨어 이야기
하드웨어 스타트업의 소프트웨어 이야기하드웨어 스타트업의 소프트웨어 이야기
하드웨어 스타트업의 소프트웨어 이야기Mijeong Park
 
임태현, 서버점검 제로에의 도전, NDC2011
임태현, 서버점검 제로에의 도전, NDC2011임태현, 서버점검 제로에의 도전, NDC2011
임태현, 서버점검 제로에의 도전, NDC2011devCAT Studio, NEXON
 
로그 기깔나게 잘 디자인하는 법
로그 기깔나게 잘 디자인하는 법로그 기깔나게 잘 디자인하는 법
로그 기깔나게 잘 디자인하는 법Jeongsang Baek
 
Log Design Case Study
Log Design Case StudyLog Design Case Study
Log Design Case StudyDataya Nolja
 
NDC17 장창완(최종)
NDC17 장창완(최종)NDC17 장창완(최종)
NDC17 장창완(최종)창완 장
 
Pinpoint 도입기 - 2016 신림프로그래머 오픈 세미나
Pinpoint 도입기 - 2016 신림프로그래머 오픈 세미나Pinpoint 도입기 - 2016 신림프로그래머 오픈 세미나
Pinpoint 도입기 - 2016 신림프로그래머 오픈 세미나none
 
[아이펀팩토리] 클라이언트 개발자, 서버 개발 시작하기
[아이펀팩토리] 클라이언트 개발자, 서버 개발 시작하기 [아이펀팩토리] 클라이언트 개발자, 서버 개발 시작하기
[아이펀팩토리] 클라이언트 개발자, 서버 개발 시작하기 iFunFactory Inc.
 
임태현, MMO 서버 개발 포스트 모템, NDC2012
임태현, MMO 서버 개발 포스트 모템, NDC2012임태현, MMO 서버 개발 포스트 모템, NDC2012
임태현, MMO 서버 개발 포스트 모템, NDC2012devCAT Studio, NEXON
 
이승재, 마비노기 듀얼: 라이브 서비스 사건사고기록, NDC2016
이승재, 마비노기 듀얼: 라이브 서비스 사건사고기록, NDC2016이승재, 마비노기 듀얼: 라이브 서비스 사건사고기록, NDC2016
이승재, 마비노기 듀얼: 라이브 서비스 사건사고기록, NDC2016devCAT Studio, NEXON
 
[2A1]Line은 어떻게 글로벌 메신저 플랫폼이 되었는가
[2A1]Line은 어떻게 글로벌 메신저 플랫폼이 되었는가[2A1]Line은 어떻게 글로벌 메신저 플랫폼이 되었는가
[2A1]Line은 어떻게 글로벌 메신저 플랫폼이 되었는가NAVER D2
 
Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드
Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드
Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드cranbe95
 
멸종하는 공룡이 되지 않으려면
멸종하는 공룡이 되지 않으려면멸종하는 공룡이 되지 않으려면
멸종하는 공룡이 되지 않으려면Byeongsu Kang
 
실시간 게임 서버 최적화 전략
실시간 게임 서버 최적화 전략실시간 게임 서버 최적화 전략
실시간 게임 서버 최적화 전략YEONG-CHEON YOU
 
중앙 서버 없는 게임 로직
중앙 서버 없는 게임 로직중앙 서버 없는 게임 로직
중앙 서버 없는 게임 로직Hoyoung Choi
 
잭블랙이블랙잭을한다 - 최종발표
잭블랙이블랙잭을한다 - 최종발표잭블랙이블랙잭을한다 - 최종발표
잭블랙이블랙잭을한다 - 최종발표Seokmin No
 

Similar to 모바일 SNG 비동기 네트워크 통신 사례 (20)

KGC 2014: 분산 게임 서버 구조론
KGC 2014: 분산 게임 서버 구조론KGC 2014: 분산 게임 서버 구조론
KGC 2014: 분산 게임 서버 구조론
 
게임 분산 서버 구조
게임 분산 서버 구조게임 분산 서버 구조
게임 분산 서버 구조
 
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
 
하드웨어 스타트업의 소프트웨어 이야기
하드웨어 스타트업의 소프트웨어 이야기하드웨어 스타트업의 소프트웨어 이야기
하드웨어 스타트업의 소프트웨어 이야기
 
임태현, 서버점검 제로에의 도전, NDC2011
임태현, 서버점검 제로에의 도전, NDC2011임태현, 서버점검 제로에의 도전, NDC2011
임태현, 서버점검 제로에의 도전, NDC2011
 
Scalable webservice
Scalable webserviceScalable webservice
Scalable webservice
 
로그 기깔나게 잘 디자인하는 법
로그 기깔나게 잘 디자인하는 법로그 기깔나게 잘 디자인하는 법
로그 기깔나게 잘 디자인하는 법
 
Log Design Case Study
Log Design Case StudyLog Design Case Study
Log Design Case Study
 
NDC17 장창완(최종)
NDC17 장창완(최종)NDC17 장창완(최종)
NDC17 장창완(최종)
 
Pinpoint 도입기 - 2016 신림프로그래머 오픈 세미나
Pinpoint 도입기 - 2016 신림프로그래머 오픈 세미나Pinpoint 도입기 - 2016 신림프로그래머 오픈 세미나
Pinpoint 도입기 - 2016 신림프로그래머 오픈 세미나
 
[아이펀팩토리] 클라이언트 개발자, 서버 개발 시작하기
[아이펀팩토리] 클라이언트 개발자, 서버 개발 시작하기 [아이펀팩토리] 클라이언트 개발자, 서버 개발 시작하기
[아이펀팩토리] 클라이언트 개발자, 서버 개발 시작하기
 
임태현, MMO 서버 개발 포스트 모템, NDC2012
임태현, MMO 서버 개발 포스트 모템, NDC2012임태현, MMO 서버 개발 포스트 모템, NDC2012
임태현, MMO 서버 개발 포스트 모템, NDC2012
 
이승재, 마비노기 듀얼: 라이브 서비스 사건사고기록, NDC2016
이승재, 마비노기 듀얼: 라이브 서비스 사건사고기록, NDC2016이승재, 마비노기 듀얼: 라이브 서비스 사건사고기록, NDC2016
이승재, 마비노기 듀얼: 라이브 서비스 사건사고기록, NDC2016
 
[2A1]Line은 어떻게 글로벌 메신저 플랫폼이 되었는가
[2A1]Line은 어떻게 글로벌 메신저 플랫폼이 되었는가[2A1]Line은 어떻게 글로벌 메신저 플랫폼이 되었는가
[2A1]Line은 어떻게 글로벌 메신저 플랫폼이 되었는가
 
Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드
Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드
Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드
 
최웅규
최웅규최웅규
최웅규
 
멸종하는 공룡이 되지 않으려면
멸종하는 공룡이 되지 않으려면멸종하는 공룡이 되지 않으려면
멸종하는 공룡이 되지 않으려면
 
실시간 게임 서버 최적화 전략
실시간 게임 서버 최적화 전략실시간 게임 서버 최적화 전략
실시간 게임 서버 최적화 전략
 
중앙 서버 없는 게임 로직
중앙 서버 없는 게임 로직중앙 서버 없는 게임 로직
중앙 서버 없는 게임 로직
 
잭블랙이블랙잭을한다 - 최종발표
잭블랙이블랙잭을한다 - 최종발표잭블랙이블랙잭을한다 - 최종발표
잭블랙이블랙잭을한다 - 최종발표
 

모바일 SNG 비동기 네트워크 통신 사례

  • 2. 이 자료는 • 모바일 SNG 게임 네트워크 통신 구현 사례 • 미루고 미루다가 더 이상 미루면, 기억이 가루가 될 것 같아서 쓰는 자료
  • 3. 결론 • 비동기 네트워크 통신은 구질구질함 • 4줄 요약 • Action은 동기/비동기 구분 • 순서 보장을 위해, Queue에 쌓아서 보냄 • 재시도 처리를 위해, 고유 번호를 할당 • 쌓인 Action은 한 번에 보냄
  • 4. 목차 1. 게임 특징 소개 2. 기본적인 네트워크 구조 3. 재시도 구조 4. 서비스 오픈 후 발생한 문제점 5. 통신 구조 개선 사례 6. 추가 개선
  • 7. 게임 특징 • Mobile • Social Network Game • Farm Simulation
  • 8. 게임 특징: Mobile • Mobile • 네트워크 환경이 나쁠 수 있다 • 서버에 사용자 데이터 저장 • 거의 모든 사용자 동작을 서버에 전송 • Social Network Game • Farm Simulation
  • 9. 게임 특징: SNG • Mobile • Social Network Game • 다른 사용자 간의 데이터 참조 및 간섭 • 여러 사용자의 데이터 동시성 문제 발생 • Farm Simulation
  • 10. 게임 특징: Farm • Mobile • Social Network Game • Farm Simulation • 수확, 생산이 잘 돌아가야 함 • 서버 응답을 꼭 기다릴 필요 없는 통신이 많음
  • 11. 게임 특징 • Mobile • Social Network Game • Farm Simulation • 핵심 요구사항 정리 그런 거 모르겠고 그냥 언제 어디서나 빠르고 잘 돌아갔으면 좋겠다.
  • 13. +기술 스펙 참조 • 이후에 AWS Elastic Beanstalk로 개선함 • User DB는 NoSQL(DynamoDB) JSON • 필요에 따라 MySQL, Redis 도 적절히 사용 • 서버-클라 통신은 HTTPS (JSON)
  • 15. Action • 서버에 저장해야 하는 사용자의 모든 동작을 Action이라고 명명함 • Ex. 로그인, 생산, 수확, 건설, 판매, 뽑기, 거래, 선물 등등
  • 16. Action 기본 통신 구조 사용자 입력 빵 생산 서버 데이터 처리 [생산] 밀가루 -1 빵 생산 시작 게임 연출 밀가루 소모 연출 + 빵 생산 연출
  • 17. 게임 내 사용자 경험 • 기존 처리 완료를 기다려야 다음 요청을 처리할 수 있음 • 응답이 오기전 까지, 사용자의 입력을 막고 대기 • 네트워크 지연 시, 사용자 경험이 매우 나빠짐
  • 18. 동기 / 비동기 Action 구분 • 서버 응답을 기다려야 하는지를 기준으로 동기 / 비동기 Action 두 종류로 구분함 • 동기 Action: 서버 응답 대기 Ex. 친구정보, 거래, 선물, 뽑기 등 • 비동기 Action: 클라 우선 예측 처리 Ex. 생산, 수확, 아이템 판매 등
  • 19. 동기 Action 동작 예시 사용자 입력 밀가루 수확 빵 생산 서버 데이터 처리 [생산] 밀가루 -1 빵 생산 시작 [수확] 밀가루 +1 게임 연출 밀가루 획득 연출 밀가루 소모 연출 + 빵 생산 연출
  • 20. 서버 데이터 처리 [생산] 밀가루 -1 빵 생산 시작 [수확] 밀가루 +1 비동기 Action 동작 예시 사용자 입력 밀가루 수확 빵 생산 게임 연출 밀가루 획득 연출 밀가루 소모 연출 + 빵 생산 연출
  • 21. 비동기 Action 요약 • 그림으로 그리니까 너무 어려운데 • 서버 응답을 예측(Action 미리 실행)해서 • 게임 클라이언트에서 우선 연출 • 서버 응답은 오든가 말든가 게임은 계속 진행 • 통신 중에는 화면 구석에 동기화 아이콘 표기 • 서버 응답이 에러 발생이면, 게임 정지 / 동기화
  • 22. 비동기 Action 장점 • 게임 특성상, 상당히 많은 Action 비동기 처리 • 사용자 터치 막을 필요 없어짐 • 사용자 유저 경험 매우 좋아짐 • Case. 12층에서 1층 가는 차폐 엘리베이터에서도 게임이 끊어지지 않고 플레이 가능함
  • 23. +비동기 Action 주의점 • 모든 Action의 서버 처리 순서 보장필요 • Action Queue에 쌓아서 순서대로 처리 • UI 동기화 처리 복잡도 증가 • 현재 표기 값과 현재 확정 값이 다름. • 재화는 항상 대입보다 증감으로 처리 해야 함. • 예측 불가 Client rand() != Server rand() • 서버에서 Random값 참조하는 경우를 비동기 action 처리했다가 random 결과가 달라서 버그가 발생함. • Random seed를 맞추려다가 그냥 동기 action으로 처리함
  • 25. 재시도 처리 • 네트워크의 일시적 오류의 대응을 위해 • 서버 응답이 안 오면, 재요청을 하도록 함
  • 26. 재시도 처리 버그 • 해당 요청이 소실된 경우가 아니라면 • 빵을 한 번 생산했는데, 서버에 두 번 들어옴!
  • 27. Request Numbering • 클라이언트에서 요청마다 고유 번호를 붙임 • 서버에서는 Redis로 동시성 제어 • 요청이 들어오면, 처리 중 Flag 표기 • 처리가 완료되면, 서버 응답 저장 • 재요청의 경우, 기존에 저장된 응답을 바로 출력
  • 28. Request Numbering 장점 • 재시도 버그 해결 • 서버의 응답을 10분 정도 보존 (expire) • 개발 시, 디버깅에도 도움 됨
  • 29. +Request Numbering 주의점 • 한 유저가 여러 device로 로그인 하면? • 정책적 처리가 필요 • Redis 부하에 대해서 적절히 잘 처리해야 함
  • 30. 정리 • 대충 이 정도 하고 • CBT 하고 서비스 오픈
  • 31. Network 통신 구조 정리 https://draw.io
  • 32. #4 오픈 후 발생 문제
  • 33. User Report • 게임이 자꾸 롤백 돼요 • 네트워크 너~~~무 느려요
  • 34. Rollback? • 우리는 롤백 기능 같은 거 만든 적 없는데…
  • 35. 서버 응답속도는 정상 • ELB 평균 응답 100ms ~ 250ms • 서버는 문제 없음. 클라 버그네, 클라 버그여
  • 36. Client Network 통계 • 클라이언트에서 측정 해 보자! • 요청 시, 아래 내용 전송 • Action Queue Length • Action 응답 속도 통계
  • 37. Client Network data 참조1 • 모든 요청마다 0.1% 수준으로 기록 (Sampling) • 평균 1300ms (=1.3초) • 정규분포 가정 시 84%의 요청이 2500ms, 97% 요청은 3670ms Queue 길이 1 2 3 표본 수 788574 (97.80%) 11158 (1.38%) 3418 (0.42%) 최소 605 602 565 최대 5353 5454 5647 평균 1320 1358 1329 표준편차 1175 1246 1301
  • 38. Client Network 통계 평균 • 클라이언트가 받는 응답속도는 평균 1300ms • 서버는 200ms 만에 보냈는데, • 네트워크가 잘못했네 • 멍청하게도 3G, LTE, WIFI 구분 안 했음
  • 39. Client Network data 참조2 • Sampling 중에서 Queue길이가 10 이상인 경우 기록 • Action이 100개가 넘게 쌓이는 경우도 있다!? Queue Count Queue Count Queue Count 11 85 21 5 33 1 12 65 22 5 34 1 13 38 23 1 38 1 14 36 24 2 49 1 15 20 25 2 50 1 16 22 27 3 55 1 17 10 28 3 56 1 18 12 30 1 58 1 19 5 31 1 117 1 20 9 32 2 134 1
  • 40. Client Network 발견한 문제 • 동기 Action을 수행하려면 • 기존에 쌓여있던 Action 들이 • 순서대로 전부 수행되고 나서야 수행 가능 • 비동기 Action이 발생하자마자 서버 요청을 시작 하는데도 30개 정도는 어렵지 않게 쌓임 • 요청 100개가 쌓여있으면, 평균 1.3초 가정 시 130초 동안 빙글빙글 돌면서 멈춤
  • 41. User Case • 게임에 로그인해서 • 생산/수확 한참 하고 나서 • 거래소나 친구 집에 가면 • 게임이 멈춰서 껐다 켰더니 • 생산/수확 요청이 처리 안 되어 있어요 •> 롤백 돼요
  • 42. 기술 용어로 해석 • 게임에 로그인해서 생산/수확 한참 하고 나서 • 비동기 Action을 한 번에 100개쯤 하고 • 거래소나 친구 집에 가면 • 동기 Action을 수행하면 네트워크 응답이 오래 걸리고 • 네트워크 응답이 없어서 껐다 켰더니 • 유저가 네트워크 대기화면에서 게임이 멈춘 거로 인식하고 • 생산/수확 요청이 처리 안 되어 있어요 • 해당 요청이 서버에 안 와서 처리가 안 돼요
  • 43. 좋은 해결 방법 Network 동기화 중 15% 완료 게임의 전원을 끄지 마십시오
  • 44. 대안 • Queue에 쌓여 있는 Action을 한 번에 여러 개 보내보자 • 완전 다른 Action을 묶어서 처리 가능한가요? • 다행히 서버 설계가 Action 공통 처리 가능한 구조 • 공돌이를 갈면 가능함
  • 46. Batching Requests • 사실 이 정리 자료의 핵심 • 한번 여러 요청이 묶이도록 통신 구조를 거의 다 뜯어야 했음 • 다른 게임에서는 이걸 뭐라고 부르나 몰라서 내부에서는 Bulk processing, network batching 등 여러 가지 이름으로 부름. 적절한 표현이 있다면 알려주세요
  • 47. 기존 평균 응답속도 (REAL) Client Server 요청600ms 응답 600ms 수행 250ms
  • 48. 기존 통신 3번 일어난다면 Client Server 요청600ms 응답 600ms 수행 250ms 요청600ms 응답 600ms 수행 250ms 요청600ms 응답 600ms 수행 250ms
  • 49. 모아서 보내서, 이렇게 줄여보자 Client Server 요청600ms 수행 250ms 수행 250ms 응답 600ms 수행 250ms
  • 50. 개선 목표 • 서버 내 처리보다 (100ms ~ 250ms) • 네트워크 전송이 오래 걸리므로 (1300ms) • 요청을 n 개를 모아서 한 번에 처리하자 • 문제는 밖에 있었다. 서버 최적화 괜히 했어
  • 51. #5’ DB 처리 개선 Batching 작업 하다가 발견한 다른 장점 이 부분은 패스 하셔도 됩니다.
  • 52. 해당 작업 중 발견한 다른 이점 • 사용자 데이터를 Json format으로 NoSQL 에서 한 번에 관리하고 있었음. • 통신 구조 상 DB 처리에도 이득
  • 53. + 유저 Main DB NoSQL을 쓴 다는 것… • 주의. 장점 만큼 단점도 많은 방식입니다. • 장점은 AWS summit 발표자료... `게임 고객 사례를 통해 살펴보는 AWS 활용 전략` 참조 • 단점은 개인 문의 바람… 여백이 부족하군요. 하하하
  • 54. 통신 처리 (Dev) Client Server 요청 응답 수행
  • 55. 수행 과정을 자세히 나누면 Server DB Request Parse Execute Serialize Write User Deserialize Client Response Fetch User
  • 56. DB 통신 3번이 일어나면 (기존) Client Server
  • 57. DB 개선 통신 처리 (batched) Client Server
  • 58. DB 처리 감소 이득 • 별생각 없었는데, 구현하면서 보니 꿀 이득 • 로직과 관련 없는 DB 처리도 (Fetch/Deserialize/Serialize/Write 등등) 한 번만 하면 되더라 Server DB Request Parse Execute Serialize Write User Deserialize Response Fetch User Execute Execute
  • 59. 함정 카드 발동 • 여러 요청 중간에 에러가 발생하면, 마지막 정상 요청까지의 상태를 저장해야 함. • DB 처리를 무조건 건너 뛸 수는 없음
  • 60. 새로운 이슈 • 작업하면서, 내부 소요 시간도 측정 하다 보니 • Serialize가 공통 병목 구간으로 확인됨 Server DB Request Parse Execute Serialize Write User Deserialize Response Fetch User Execute Execute
  • 61. Serialized 대책 • 대안 1. Fetch는 한번, Write는 매번 하기 2. Serialized 된 string만 cache 해 두기 3. Memory transaction 으로 변경 추적하기 4. User 객체 deep copy로 보존 • 다른 대안이 조금씩 애매해서, 일단 포기하고 2번 • 난 포기가 빠른 남자니까 • 테스트 상 ExpressionTree로 DeepCopy 하는 게 가장 빠르긴 했음 • http://stackoverflow.com/questions/852064/faster-deep-cloning
  • 62. DB 처리 개선 정리 • 작업 하다 보니까, DB 처리도 개선되더라 • 처리 속도가 엄청 빨라졌음 • 그런데, 해당 적용으로는 에러 발생시 버그 유발 • 그래서 엄청 빠르게는 못하고, 조금 개선 함
  • 63. 원래 하던 얘기로 돌아가서 • 요청이 100개씩 밀리는 경우가 발생 • 여러 Action을 한 번에 보내면 좋을 것 같아서 • 묶어서 보냄 (= Batching Requests) • 통신 횟수도 감소, 내부 처리 로직도 개선
  • 64. 모아서 보내는 기준은? • 100개가 쌓여있다고 100개를 한 번에?! • 일단 최대 8개씩 보내도록 해봄 • 이후 해당 부분을 수정할 의지가 없어져서 평생 8개씩 보내게 됨
  • 65. 개선 시도 후 테스트 • 기존 150ms 정도 걸리던 요청 (dev서버 기준) • 첫 Action 만 150ms 정도가 소요되고 • 묶어서 보낸 다른 Action은 10ms 안에 끝남
  • 66. 서비스 적용 후 상황 • 0.1% 샘플링 • 대부분의 요청이 2개씩 묶어서 처리됨.
  • 67. Batching 적용 효과 • 일단 체감 효과가 좋아짐 • 네트워크 지연 상황을 재현하기도 어려워짐 • 해당 적용 효과 통계 자료가 분실됨…
  • 69. Requests Preserve • 목적: 미요청 데이터 롤백 상황 방지 • 게임을 새로 켜는 순간 전송하지 않은 Request가 남아있다면 해당 정보를 보내고 게임에 진입하면 어떨까? • 문제가 너무 많이 예상되어서 해보진 못함
  • 70. 정리 • SNG 게임 네트워크 사례 • Action은 동기/비동기 구분 • 순서 보장을 위해, Queue에 쌓아서 보냄 • 재시도 처리를 위해, 고유 번호를 할당 • 쌓인 Action은 한 번에 보냄
  • 71. 끝 프로젝트는 죽어서 기술 자료를 남긴다.