체스
체스 미션에는 가비와 페어가 매칭되었다!
체스는 이전 미션들보다 훨씬 복잡한 도메인이었다.
하지만 가비와 나는 체스 도메인이 익숙해서 더 편한 마음으로 시작할 수 있었다.
미션을 진행하면서 어려웠던 부분은 기물의 이동, 이동시 경로에 기물이 존재하는지 확인하는 부분이었다.
가비가 집에가서도 기물의 이동 관련해 생각 정리한 글을 보내줘서 더욱 빨리 진행할 수 있었다.
최종적으로 결정한 부분은 다음과 같다.
각 기물의 이동 가능여부
Rank와 File은 각각 위치값을 가지고 있고, 값의 차이를 이용해서 각 기물의 이동 가능 여부를 계산했다.
직선 → Rank와 File 차이 중 하나가 0이어야 한다.
대각선 → Rank와 File 차이의 절대값이 같아야 한다. ex) abs(-2) == abs(2)
나이트 → 차이의 절대값이 하나는 2 나머지 하나는 1이어야 한다.
도착 칸의 기물 여부
아군 → 이동이 불가능하다.
적군 → 이동이 가능하다. 적군을 잡는다.
중간에 기물 존재 여부
이동 경로에 기물이 존재하면 안된다.
데이터베이스 사용
체스 미션은 특별하게 데이터베이스와 연결하는 부분이 있었다.
체스 게임의 상태를 다음의 두가지 방법으로 정할 수 있다고 생각했다.
- 기물 전체를 저장하는 방법
- 기보를 저장하고 게임을 불러와 기보대로 이동시키는 방법
기물이 이동할 때마다 값을 저장하고 싶었고, 기보를 저장하는 방법을 선택했다.
기물 전체를 저장하지 않은 이유는 다음과 같다.
- 턴과 같은 부가적인 요소를 저장해야 한다.
- 이동을 할 때 기물이 잡히는 경우 update 쿼리(이동 기물)와 delete(잡힌 기물) 2개의 쿼리를 날려야 한다.
- 현재 구조에서 도메인의 변경이 크게(초기 상태를 구성하는 부분) 일어나야 한다.
정리하자면 기물 전체 저장과 기보 저장은 다음과 차이가 있다.
보드저장: 초기상태에서 32개의 Insert 쿼리(기물의 위치) + 기물 이동 시 움직임 변경(잡히는 경우 2개의 쿼리)
기보저장: 초기상태 애플리케이션에서 구성 + 저장된 기보를 select 쿼리로 조회해서 사용(1회) + insert 쿼리(이동 당 1회)
추가로 기보저장이 구현도 더욱 간단하다. 👍
부가적인 부분
리뷰어인 찰리🍫가 동시에 여러 게임이 진행된다면 어떨지? 에 대한 코멘트를 남겨주셔서 다양한 시도를 해봤다.
- 누누의 도움으로 ConnectionPool 구현
- ThreadLocal 사용해서 쓰레드 별 세션 관리
- 실제로 애플리케이션 내에서 체스 게임이 진행되는 Board를 ConcurrentHashMap으로 저장(사실 이 부분은 현재 구조에서 필요없지만 2명이 서로 게임하는 경우를 생각해서 넣어보았다.)
두 명이 서로 같은 방에 입장하여 게임을 진행한다면 출력하는 부분이 까다로워질 것 같다고 예상되어(Board에 옵저버 패턴을 사용해야되나?) 해볼 엄두가 나지 않았다.