215 lines
17 KiB
Plaintext
215 lines
17 KiB
Plaintext
# 서버 프로그램 개선 사항 정리
|
|
|
|
1. 코드 개선 사항
|
|
1.1. ReadOnly 를 사용 하자.
|
|
- 객체 풀을 사용하지 않을 것이므로 객체 생성자 시점에 맴버들을 ReadOnly 설정 하면
|
|
객체 생성 시간이 빠르다.
|
|
1.2. 객체 지향 프로그래밍(OOP)과 SOLID 정책을 활용하여 설계하고 구현하자.
|
|
- 서버 각 프로세스내에 네트워크 Session 객체가 여러가지 로직 처리를 담당 하고 있는데,
|
|
여러가지 역할을 단일 역할 객체로 각각 분리 하여 복잡한 로직들을 분리 한다.
|
|
1.3. 관리되지 않는 리소스를 사용한다면 Using 을 사용하자
|
|
- 파일, 폰트, 각종 Kernel 연동 Connection 객체들을 사용한다면 Using 을 통해 사용후
|
|
Dispose가 호출 될 수 있다.
|
|
1.4. Class 맴버 변수는 기본적으로 private 엑세스 한정자로 설정한다.
|
|
- 현재 전체적으로 대부분의 Class 맴버 변수들은 public 으로 설정되어 있어서
|
|
프로그래머가 실수로 맴버 변수의 값에 접근이 가능하기 때문에 위험하다.
|
|
|
|
== 신규 추가 ==
|
|
1.5. primitive 타입이나 사용자 정의된 타입들에 대해 신뢰성 체크를 해야 한다면
|
|
extension function 을 이용하자
|
|
- extension function 기능을 통해 중복된 코드를 방지하고 좀 더 가독성 높은 코드를 작성할 수 있다.
|
|
1.6. 패킷 정의시 시간과 관련 타입은 Google Protobuf의 Timestamp 타입을 사용 한다.
|
|
- 시간값의 크기에 따라 패킷내의 변수 크기를 4 Byte or 8 Byte 가변적으로 설정해 주는 장점이 있다.
|
|
1.7. ProudNet 관련 초기화 절차에서 Nagle 알고리즘을 사용하지 않도록 설정 해야 한다.
|
|
- 클라이언트 & 서버 모두 비활성화 설정을 해야 한다.
|
|
|
|
2. 설계 & 알고리즘 개선 사항
|
|
2.1. 패킷 헤더부를 별도로 정의하고, 패킷 분석 및 전달 하는 코드를
|
|
Packet Handler 관리 및 호출 구조로 변경 해야한다.
|
|
- 패킷 헤더부가 별도로 없이 바디부내의 2개의 필드 타입을 파악하여 패킷 정보를 확인 하는
|
|
구조로 되어 있어서 패킷을 새로 추가할 때마다 패킷을 분석 및 전달 하는 코드를
|
|
개발시 유사 코드를 지속적으로 추가해야 하는 불편함이 있다.
|
|
(개발시 패킷 가독성도 상당히 떨어져 비효율적임, 패킷 정의시 발생 순서대로 연관된 것 끼리)
|
|
2.2. 비지니스 로직 & DB 쿼리 & 비지니스 로그 들을 하나의 트랜젝션으로 묶고
|
|
Batch 화 해주는 구조를 만들어야 한다.
|
|
- 여러개의 작업 단위들이 실행되어 모두 반영되던가 아니면 모두 반영되지 않도록
|
|
처리 하는 구조가 전혀 없다.
|
|
해당 관련 작업을 진행 하는 프로그래머가 어렵지 않게 구현 할 수 있도록 구조화 해서
|
|
제공해 주어야 한다.
|
|
2.3. 서버->클라이언트로 보내는 Notify 패킷은 클라이언트의 대상 엔티티의 어떤 상태일때
|
|
전송 시켜야 하는지 약속된 시점에 보내야 한다.
|
|
- 현재 게임 서버 로그인시 Notify 송신, Response 송신, Notify 송신,
|
|
이 순서로 클라이언트에게 패킷을 송신해 주고 있는데, Response 패킷이 로그인 완료의 의미로
|
|
쓰인 다면 Notify 패킷을 Response 패킷 송신전에 송신 하도록 수정 해야 한다.
|
|
(Login Response 후에, Ack
|
|
2.4. 서버에서 Thread 가 대량으로 생성될 수 있는 로직은 구현하면 않된다.
|
|
- 게임 서버에서 로그인 패킷 처리중에 별도의 Task 를 생성 하여
|
|
주기적으로 5초마다 Redis 에 인증키 정보를 저장 하고 있는데, CPU 자원 낭비로 연결되어,
|
|
최대 동접수 만큼 Thread 가 생성될 수도 있다.
|
|
클라이언트->서버 Ping 패킷 수신시 Redis 에 인증키 정보를 저장 하는 로직으로 수정 한다.
|
|
IOCP 를 이용하여 패킷 처리할 경우 일정 개수의 Thread 만 생성 하므로
|
|
안정적인 Thread 관리를 보장 한다.
|
|
2.5. 주요 컨텐츠 정보를 캐싱 했거나 DB 서버에 저장된 정보중에 정보의 파괴 정책이
|
|
있는 경우, 일정한 시점을 정하여 저장된 정보를 삭제해 주는 로직을 개발 해야한다.
|
|
- 현재 파괴 정책에 의한 삭제해 주는 로직이 전혀 없다.
|
|
서버 런칭 시점, 서버 동접이 적인 시간대의 시점, 유저 접속 시점에 로직을 구현 해야 한다.
|
|
참고로 클라이언트에 의존적인 파괴 로직만으로 모든 예외 상황을 해결 할 수 없다.
|
|
2.6. 패킷 설계시 되도록 이면 최대 1.024 MB 이내로 적재 되도록 설계 한다.
|
|
- 패킷 크기가 클 경우 특정 네트워크 세션이 IO를 독점할 수 있으므로
|
|
가변 패킷 설계시 서버에서 클라이언트로 전송시 패킷이 분산 되어 전송될 수 있도록
|
|
보수적 관점에서 패킷량을 예측 하여 설계 해야 한다.
|
|
아울러 패킷 송신시 함수내부에서 송신 패킷을 개산하여 권장크기를 초과할 경우
|
|
해당 패킷의 간략한 내용을 경고성 로그로 작성해 주도록 한다.
|
|
|
|
== 신규 추가 ==
|
|
2.7. Lambda 함수는 재사용적 가능성이 거의 없고, 함수내의 범위에서 확장성 없이 사용될 경우만 사용하자.
|
|
- 전체적으로 거의 모든 로직에 Lambda 형태의 로직들이 작성 되고 있다.
|
|
- Lambda 함수는 개발자 간의 커뮤니케이션시에도 효율적이지 못하다.
|
|
2.8. 게임 치트 시스템 설계를 일반화 하자.
|
|
- 게임 치트 시스템 설계를 일반화하여 게임 치트 개발 생산성을 향상시킬 수 있다.
|
|
- 게임 치트 시스템 설계안 작성 한다.
|
|
2.9. 단위 테스트용 클라이언트 처리 기능과 게임 치트 처리 구조를 통합 한다.
|
|
- 게임 치트와 연동되는 로직과 단위 테스트 로직을 단일화하면 단위적 코드 검수 구조를 일원화 하면 개발 공정이 단순해져
|
|
코드 검수 과정이 유연해 지고, 유지 보수도 용이해진다.
|
|
- 기본적인 로그인, 캐릭터 생성 및 선택 과정을 자동화하는 스크립트를 제공 하자.
|
|
2.10. 절차상 중요한 단계의 요청 패킷은 응답 패킷에 서버측 처리 시간을 작성하여 보낸다.
|
|
- 캐릭터 생성 및 선택 절차들은 처리 공정상 컨텐츠가 추가될 수록 처리 시간이 늦어질 가능성이 크기 때문에
|
|
로딩 절차를 진행하는 함수내부에서도 제한시간 보다 지연될 경우 경고성 로그를 작성해야 하며,
|
|
그 소요시간도 클라이언트측에 알려주는 것이 좋다.
|
|
2.11. Redis에 저장시키는 정보가 접속자에게만 참조되는 정보가 아닌 다른 접속자들도 참조해야 하는 정보일 경우
|
|
참조되는 빈도를 고려하여 Redis 성능에 우려될 수준이라면 다른 관리 방법을 고려 해야 한다.
|
|
2.12. 개발용 로그와 운영용 로그(Business Log)를 분리 하기위해 Business Log 구조를 추가 한다.
|
|
- 현재 설계되어 Log 구조는 개발용 로그와 운영용 로그(Business Log)와 구조적으로 분리되어 있지 않아서
|
|
개발용 정의한 내용이 변경될 경우 운영 시스템도 수정해야 할 수 있다.
|
|
2.13. 개발시 되도록이면 정책 기반으로 설계하고, 관련 정책을 데이터화 및 로직화 해서 개발 한다.
|
|
- 기획서 상에 명세화 여부와 상관 없이 개발자 능동적으로 판단하여
|
|
필요시 기획 담당자에게 효율적인 커뮤니케이션 과정을 통해 해당 정책의 데이터화 필요성을
|
|
리뷰해 주고, 설득 과정을 통해 공감을 얻어내야 한다.
|
|
2.14. 프로토콜 계층 구조와 ProudNet PIDL을 여러 개로 나누어 연결 하는 구조로 리뉴얼해 보자.
|
|
- 네트워크 프로토콜 구조가 3계층으로 되어 있어서 관리시 제약사항이 많아 개선 한다.
|
|
- 프로토콜 그룹 관리 정책에 따라 복수개로 ProudNet Stub & Proxy 관리가 가능하도록 개선 한다.
|
|
2.15. 유저 상태에 의해 패킷 처리 가능 여부를 체크할 수 있는 기반 구조를 만든다.
|
|
- 수신된 패킷을 매번 수신 패킷 핸들러내에서 유저의 상태를 체크하여 예외 처리하는 구조는 안정성있는 로직 관리가 쉽지 않다.
|
|
- 유저 상태별 패킷 처리 가능한 목록 관리 구조를 만들어 패킷 수신시 네트워크 로직 내부에서 예외 처리되도록 개선 한다.
|
|
2.16. 인벤토리 시스템 리뉴얼 <- 인테리어 프로젝트 시스템을 위한 확장 고려
|
|
2.17. 아이템 시스템 리뉴얼 <- 기획서상의 각종 아이템 효과를 위한 확장 고려
|
|
2.18. 능력치 효과 시스템 리뉴얼
|
|
2.19. 이펙트 시스템 개발 <- 버프 효과를 위한 이펙트 베이스 시스템 구조 고려 및
|
|
추후 엑티브 & 페시브 스킬 및 다양한 충돌체도 고려할 것인가?
|
|
2.20. 각종 저장 데이터의 키 구조를 재정의 한다.
|
|
- 키 구조 설계시 효율적인 형태로 되어 있는지 체크하여 되도록이면 Document 형태의 저장은 지양 하도록 한다.
|
|
|
|
3. 주요 정의 관리 개선 사항
|
|
3.1. 기획 도메인에 해당 하는 주요 정의는
|
|
별도 기획 상수데이터 테이블을 만들어 관리 하도록 한다.
|
|
- 현재 상수 데이터를 관리하는 데이터 테이블이 없다.
|
|
3.2. 프로그램 도메인에 해당 하는 주요 정의는
|
|
Protobuf 파일로 정의 하여 관리 하도록 한다.
|
|
- 현재 프로그램 코드에 하드 코딩으로 작성 되어 있다.
|
|
클라이언트/서버 공용적 상수값들은 클라이언트/서버 각각 하드 코딩으로 작성 되어 있다.
|
|
|
|
== 신규 추가 ==
|
|
3.3. 서버/클라이언트 버전 관리 정책 및 시스템 설계를 해야 한다.
|
|
- 현재 클라이언트 접속시 클라이언트 버전을 체크해서 접속 허용 여부를 판단 하는 절차가 없다.
|
|
- 클라이언트 런처를 통해 클라이언트 패치 여부를 선행 판단 하겠지만, 개발 버전은 런처 없이 인증 서버에 접속 하므로
|
|
클라이언트 버전 체크하는 절차를 인증 절차 보다 먼저 체크 하도록 한다.
|
|
|
|
3.4. ServiceType 으로 로직의 분기용으로 사용하지 말자
|
|
- ServiceType 에 의해 로직이 실행이 제한되는 의존성 강한 로직이 발생하기 때문에,
|
|
ServiceType 이 추가, 변경될 경우 코드도 수정해야 하는 문제가 발생 한다.
|
|
해당 분기로직은 별도의 직접적인 정보를 추가하여 실행될 수 있도록 해야 한다.
|
|
|
|
|
|
4. 파일 및 코드 관리 개선 사항
|
|
4.1. Class 별로 내부 로직이 많을 경우 partial 키워드를 활용, 별도 로직별 파일로
|
|
분리 하여 관리 하도록 한다.
|
|
- 현재 Class 파일내에 너무 많은 코드들이 모여 있다.
|
|
4.2. 각 비주얼 스튜디오 프로젝트별 프로그램 파일들을 카테고리별로 구분하여
|
|
프로그램 파일들을 관리 하도록 한다.
|
|
- 현재 일부만 카테고리 구분이 있고, 나머지는 모두 프로젝트별 Root 경로에 모여 있다.
|
|
|
|
== 신규 추가 ==
|
|
|
|
5. 메타 데이터 개선 사항
|
|
5.1. 메타 Table 데이터를 Record ReadOnly 로 변경한다.
|
|
- 현재 JSON 데이터로 읽은 Table 데이터는 일반적인 클래스 정보에 캐싱하여 데이터 참조가
|
|
필요하게 되면 접근하여 읽고 있는데, 이때 프로그래머 실수로 데이터 변경도 가능하다.
|
|
이 위험성을 근본적으로 차단하기 위해 Record ReadOnly 객체로 캐싱하도록 수정 한다.
|
|
5.2. 메타 Table 데이터 스키마 파일을 추가해 주면 서버 프로그램 코드 수정 없이 로딩 되도록 수정하자.
|
|
- 현재 JSON 데이터를 서버 프로그램에서 로딩할 때 일일 코딩된 단위로 로딩 하고 있어서
|
|
데이터 스키마가 추가될 때마다 로딩 함수를 수정해 줘야 한다.
|
|
Reflection API 를 활용하여 로딩 함수 수정 없이 로딩 되도록 수정 한다.
|
|
5.3. 메타 데이터의 무결성을 체크해 주는 공용 모듈을 만들자.
|
|
- 각 테이블에 저장값들이 무결성을 체크 하여 오류의 내용과 수정 방향을 로그로 작성해 주도록 한다.
|
|
5.4. 동일한 메타 테이블 엑셀 파일을 폴더내에 여러개로 분산 관리하더래도 하나의 메타 데이터로 로딩 되도록 하자.
|
|
- 동일한 메타 테이블 엑셀 파일을 여러명의 기획 담당자가 동시에 관리할 경우 데이터 충돌 이슈로 관리에
|
|
어려움이 따를 수 있으니 n개의 이상의 파일을 로딩할 수 있는 구조로 개발 한다. 분산 설정 파일을 제공하여
|
|
분산할 파일에 개별 메타 ID 범위를 제한, 분산할 파일명을 제한하는 설정도 추가 한다.
|
|
|
|
== 신규 추가 ==
|
|
|
|
6. 툴 개선 사항
|
|
6.1. 현재의 GMTool을 서버 모니터링 툴로 리뉴얼 한다.
|
|
- 서버 프로세스를 제어하는 ServerControl Agent 프로세스를 개발 한다.
|
|
- 서버 모니터 시스템 개발 기획서를 작성 한다.
|
|
- ServerControl Agent를 관리하는 ServerMonitorServer 를 개발 한다.
|
|
- ServerMonitorServer를 제어하는 ServerMonitorTool 을 개발 한다.
|
|
- 주요 기능은 서버 시작, 서버 종료 서버 자동재시작, 서버 시스템 및 컨텐츠 주요 정보 조회 및 서버 덤프파일 출력
|
|
- 모두 .Net C# 기반으로 개발 한다.
|
|
6.2. 서버 검수용 봇을 리뉴얼 한다.
|
|
- ClosedProject에 있는 봇 리뉴얼 프로젝트를 재개발 한다.
|
|
- 봇 시스템 개발 기획서를 작성 한다.
|
|
- 봇 프로세스를 제어하는 BotMonitorServer 를 추가로 개발 한다.
|
|
|
|
7. 서버 안정성 검수를 위한 기능
|
|
7.1. 서버 모니터링 툴에서 네트워크 수신 패킷 처리시 or DB 쿼리 요청시 처리를 인위적으로 지연시켜
|
|
서버의 각 공정별 응답 지연을 발생시키고 지연 시간의 범위에 따라 서버 안정성을 검수 한다.
|
|
- 서버 모니터링 시스템에서 해당 서버들에 대해 패킷 수신 및 DB 요청의 처리 지연 기능을 추가 한다.
|
|
|
|
8. 편의 기능
|
|
8.1. 로그인시 계정 자동 생성 로그인 옵션 기능 추가한다.
|
|
- 로그인시 사용자의 계정이 없을 경우 요청한 계정으로 자동 생성해 주고
|
|
비밀 번호는 체크 하지 않는다. <= Only 각종 테스트 및 시연시 활용
|
|
8.2. 로그인시 체크할 접속 관리용 IP 대역 체크 기능 추가한다.
|
|
- 로그인시 접속이 가능한 IP 인지 접속 관리용 IP 대역 데이터를 읽고 판단 하여
|
|
접속을 허용 여부를 판단 한다.
|
|
|
|
== 신규 추가 ==
|
|
8.3. 기획 담당자가 데이터 테스트를 빠르게 할 수 있도록 런타임 기획 데이터 패치 기능을 기획 치트로 추가 하자.
|
|
- DB 에 저장된 메타 데이터와 메타 파일에 있는 데이터 불일치할 경우에 대한 예외 처리를
|
|
서버 런칭전에 체크할 방법을 고민해야 한다.
|
|
|
|
9. 환경 개선 사항
|
|
9.1. 빌드 및 배포 시스템 구축
|
|
- 서버 빌드 시스템을 Jenkins 환경으로 구축 한다.
|
|
- 빌드 성공후 특정 시간에 대상 머신에 배포 되는 환경을 구축 한다.
|
|
|
|
== 신규 추가 ==
|
|
9.2. 이슈 대응 및 성능 검수를 위해 Front-End & Back-end 각 서버 종류별 AWS CloudWatch 조회를 위한 Metric 설정 파일을 만들자
|
|
- 서버 구축을 자동화 할때 효율적이고 명확하다.
|
|
9.3. Visual Studio C# 빌드 Configuration 정보를 Debug, Release, Shipping 으로 구분하여 빌드 관리 하도록 한다.
|
|
- Debug : 개발자 테스트를 위한 빌드 설정
|
|
- Release : 개발팀 테스트를 위한 빌드 설정
|
|
- Shipping : 정식 서비스를 위한 빌드 설정
|
|
9.4. 개발 서버 이슈 발생시 슬랙 채널로 이슈내용 전송 기능을 추가 하자.
|
|
- 개발 서버 상황을 적극적으로 대응하기 위해 슬랙 채널을 활용 하도록 하자.
|
|
|
|
|
|
10. 기타 버그 및 이상 현상
|
|
- 상기 개선 사항에 해당 하는 이슈로 발생할 것으로 예상되는 버그도 포함 한다.
|
|
10.1. ChatServer 의 경우 클라이언트로 부터 LeaveChatRoomReq 를 수신하지 못한다면
|
|
챗룸이 파괴 되지 않는다.
|
|
10.2. DocumentBatchWrite.ExecuteAsync() 처리시 CancellationToken 을 활용한
|
|
DB 예외 처리가 필요하다.
|
|
|
|
== 신규 추가 ==
|
|
10.3. 서버측에 좀비 세션이 잔류되는 지 체크해야 한다.
|
|
- 봇 테스트 과정중에 봇 세션들을 모두 제거 했는데, 서버에 세션이 파괴되지 않고 좀 상태를 유지하는 것으로 예상된다.
|
|
- ProudNet 에서 적절하게 제거해주는지 설정된 시간으로 테스트 해보고, 예외 없이 제거되지 않는다면
|
|
별도 KeepAlive 패킷을 추가하여 Logout 처리를 할 수 있도록 한다.
|
|
|
|
|
|
|
|
|
|
|