Files
caliverse_doc/z. Shredder/서버 프로그램 개선 사항 정리-2.txt
2025-05-01 07:27:54 +09:00

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 처리를 할 수 있도록 한다.