프로그램은 기본적으로 조건과 상황에 따른 판단과, 결정으로 이루어진다.
네트워크 프로그램은 클라이언트와 상호 작용하기 마련인데, 처음 서버 프로그램을 작성할 때 할 수 있는 실수는 클라이언트를 너무 쉽게 믿어버린 다는 것이다.
- 클라이언트가 이 약속을 안지키면 어떻게 할 것인가?
- 클라이언트에 버그가 있다면 어떻게 할 것인가?
- 정상적인 클라이언트를 이용하지 않는다면 어떻게 할 것인가??
서버는 반드시 방어적으로 동작해야 한다. 클라이언트가 잘못된 요청을 하더라도, 서버는 그 요청을 무시하거나, 잘못된 요청이라는 것을 알려주는 것에 그쳐야지 서버에 예외 또는 버그가 발생해선 절대 안된다.
다음은 직접 경험했던 상황들의 예이다. 직접 작성한 코드와, 유지 보수하던 코드에서 발생한 문제가 뒤섞여있지만, 클라이언트가 어떤 동작을 하던 서버는 잘못된 동작을 해선 안된다는 예가 될 수 있다고 본다.
순서가 있는 패킷이라도, 가정만 하지 말고 검사하자.
- 내가 만든 퀘스트 시스템의 경우 퀘스트를 받을 때, 퀘스트 정보 받아오기 패킷에서 퀘스트를 받을 수 있는지를 검사하고, 그 결과가 OK일떄만 새 퀘스트 받기가 올라오도록 되어있었다.
- 해결책은 새 퀘스트 받기 패킷이 올라왔을 때도, 퀘스트 받을 수 있는지 여부는 검사하는 방법으로 해결 할 수 있었다. 이 경우, 넷 리미터라는 프로그램을 통해서 패킷 보내기 사용량 제한을 걸어둔 후, 새 퀘스트 받기 버튼을 여러회 누른다. 그리고 패킷 보내기 제한을 풀어버리면, 새 퀘스트 받기 패킷만 여러번 올라와 퀘스트가 여러개 받아지게 된다.
아이템 장착 해제 시에는, 해당 아이템이 장착 중인지를 반드시 검사한다!
- 클라이언트가 중복 착용/해제 시도를 안 할거라는 확신을 하지 말아라. 확신은 서버에서 직접 검사를 한 후에 해라.
가정 하지 마라. 코드에서 직접 제약을 걸어라.
- 어떤 처리에 대한 클라이언트와의 규약 (예를 들면, 비번 방 지정은 방장만 할 수 있다던가, 게임 방에서만 가능하다던가 하는 가정)은 반드시 지켜질 수 있도록 코드에서 그 동작이 불가능 하도록 만들어라.
범위 검사도 확실히 해라.
- 클라이언트에서 올라온 모든 파라미터에 대해서는 유효성 검사를 하는 것이 좋다.