HTTP Post 요청을 처리하는 기능들을 구현하다가 문득 개발할 때 일종의 패턴이 보여 적어보려합니다.
1. 아이템 정보 가져오기
2. 강화 가능 여부 및 최대 강화 수치 확인
3. 강화 시도 및 성공 여부 결정
4. 골드 및 아이템 업그레이드 수치 조정
5. 강화 이력 데이터 입력 및 롤백 처리
1. 클라이언트로 부터 `ItemId`, `GameUserId`를 받으면
2. 해당 값으로 DB에 접근하여 `ItemCode`, `EnhancementCount` 로드
- 이 때 일치하는 row가 없다면 잘못된 접근
3. 아이템 코드를 가지고 마스터 데이터를 확인하여 `강화 가능 여부`, `최대 강화 수치` 확인
4. 가능하다면 강화 시도. 성공률, 재화 소모
5. `user_data` 테이블에서 `Gold` 수치 조정
6. `owned_item` 테이블에서 `ItemId`로 접근하여 `강화 수치` 조정
- 실패 시 5번 롤백
7. `enhancement_history` 테이블에 row 삽입
- 실패시 5번, 6번 롤백
enhancement_history 테이블 생성
데이터베이스를 처음 접하고 설계를 하다 보니 부족한 점이 많았습니다. 초기 설계의 잘못된 부분이 많아 컨텐츠를 구현하면서 수정해야할 부분이 발견될 때가 많았습니다.
데이터베이스에 관한 내용은 별도의 게시물로 다룰 예정입니다.
DB 변경에 따른 DAO 코드 수정 등,
public interface IEnhancementService
{
public Task<ErrorCode> ValidateEnoughGoldAsync(Int32 gameUserId, Int64 cost);
public Task<ErrorCode> UpdateGoldAsync(Int32 gameUserId, Int32 gold);
public Task<ErrorCode> UpdateEnhancementResultAsync(Int32 gameUserId, Int64 itemId, Int32 enhancementCount, Int32 attributeCode, Int32 attack, Int32 defense);
public Task<ErrorCode> InsertEnhancementHistoryAsync(Int32 gameUserId, Int64 itemId, Int32 enhancementCount, Boolean isSuccess);
public Task<ErrorCode> RollbackUpdateMoneyAsync(Int32 gameUserId, Int32 gold);
public Task<ErrorCode> RollbackUpdateEnhancementCountAsync(Int64 itemId, Int32 attributeCode, Int32 attack, Int32 defense, Int32 enhancementCount);
}
함수 구현 후 더 필요한 함수, 클래스가 있다면 생성
테스트를 하고 오타나 잘못된 로직 수정
함수를 보기 좋게 줄이고 클래스가 SOLID 원칙을 따르도록 리팩토링
좋은 코드를 작성하지 못하는 이유
에서 자세히 다룹니다.
API 서버를 구현하면서 요청을 처리하는 프로세스도 하나의 패턴을 띄게 되었는데 다음과 같습니다.
데이터 검증: 유저 ID, 아이템 ID 등의 입력 데이터를 검증하며, 필요한 경우 에러 코드를 반환합니다. 이 단계에서는 데이터베이스에서 아이템 정보를 가져오기도 합니다.
로직 처리: 강화 가능 여부, 골드 변경, 아이템 업그레이드 등의 로직을 처리합니다. 이 과정에서 마스터 데이터를 참조하거나 확률 계산을 수행하기도 합니다.
데이터베이스 업데이트: 변경된 정보를 데이터베이스에 반영합니다. 성공 여부에 따라 롤백 처리를 준비합니다.
에러 처리와 로깅: 요청 처리 중 에러가 발생하면 이를 처리하고 로그를 남깁니다. 필요에 따라 원하는 지점에 로그를 추가합니다.
롤백 처리: 데이터베이스 업데이트 과정에서 문제가 발생할 경우, 이전 상태로 되돌리는 롤백 처리를 수행합니다.
결과 반환: 마지막으로 작업의 성공 여부에 따라 에러 코드를 반환합니다.