클래스 문법을 활용해보려고 컨트롤러의 비즈니스 로직에서 중복되는 코드나
함수 같은 부분을 모듈화해서 모은 서비스 클래스를 구현해보았습니다.
클래스의 메소드를 사용할려면 인스턴스를 생성해야하는데
컨트롤러마다 각각의 서비스 클래스의 인스턴스를 생성하면
보기도 그렇고 성능적으로도 좋을 것 같진 않아서 관련 정보를 찾아보니
싱글톤 패턴이라는 개념이 있어서 적용해보려고 했습니다.
class AccountService {
constructor(prisma) {
if (AccountService.instance) {
return AccountService.instance;
}
this.prisma = prisma;
AccountService.instance = this;
}
...
}
const accountService = new AccountService(prisma);
export default accountService;
처음엔 어떻게 구현해야할지 모르겠어서 검색하면서 찾아보니
생성자에서 인스턴스가 존재하면 인스턴스를 다시 반환하게 구현하고
클래스 파일 내에서 인스턴스를 생성해놓으면 다른 곳에서도
파일마다 인스턴스를 생성하지 않고 정적 메소드처럼 사용할 수 있었습니다.
데이터베이스를 설계할 때 DB들을 정규화해서 설계를 했더니
참조하는 데이터를 prisma에서 계속 새로 조회를 반복하면서
타고 타고 들어가서 정보를 가져와야하는게 헷갈리고
코드 구조상 좋아보이지 않아서 prisma 공식 문서를 찾아봤습니다.
관계형 쿼리라는 부분에 include라는 속성이 있었는데
스키마를 정의할 때 관계 설정을 해놓은 데이터를 가져올 수 있는 속성이였습니다.
const lineup = await prisma.lineup.findMany({
where: { accountId: away.accountId },
include: {
account: { select: { id: true, rankScore: true } },
roster: { include: { player: true } },
},
});
이런 식으로 조회를 하면 lineup.roster.player 이런 방식으로 선수 데이터에 접근할 수 있었습니다.
이전에는
const lineup = await prisma.lineup.findfirst({
where: { accountId: away.accountId }
});
const roster = await prisma.roster.findfirst({
where: { accountId: away.accountId, rosterId: lineup.rosterId }
});
const player = await prisma.players.findfirst({
where: { playerId: roster.playerId }
});
이런식으로 정보를 각각 저장해놓고 사용했었습니다.
로컬에서 테스트를 전부 마치고 aws ec2에 도메인을 연결하고
의존성 패키지, git clone 등 초기 설정을 끝내고 서버 환경에서 테스트도
새로 진행했습니다. 다른 곳에서는 문제가 없었는데 게임 매치에서
rankScore를 ELO 레이팅 방식으로 계산해서 반환하는 부분에서 정수 타입이 반환되어야하는데
{} 빈객체가 반환되어 트랜잭션이 롤백되는 현상이 발생했습니다.
calculateElo 메소드의 비동기 문제인 줄 알고 await을 붙여서 다시 시도해보았지만 여전히
빈객체만 반환되어 에러가 반복되는 상황이였습니다.
console.log로 과정에 사용되는 변수들과 계산 후 값을 로그를 통해 확인해보려 했지만
git bash에서 로그를 볼 방법이 없어서 찾아보았는데 winston 등의 로그 라이브러리를 사용해야해서 다른 방법을 찾아보았습니다.
이것저것 시도 해본 끝에 pm2 log에서 에러가 나왔는데
0|app | Error: listen EADDRINUSE: address already in use :::3000
0|app | at Server.setupListenHandle [as _listen2]
포트가 이미 사용중이라는 에러였습니다.
sudo lsof -i :3000
로 조회를 하니 nodex20이 사용중이였습니다.
이건 현재 돌아가고 있는 pm2 서버라고 생각했지만 일단
sudo kill -9 PID
로 프로세스를 죽이고 새로 서버를 시작하고 테스트 해보았지만 여전히 빈객체만 반환될 뿐이였습니다.
그럼 다른 포트로 테스트 해봐야겠다고 생각해서 ec2 보안그룹에 3001번을 추가하고
3001번 포트로 변경 후에 테스트를 해보니 정수 값이 반환되어 로직이 정상적으로 돌아가는
것을 보니 정말 허탈했습니다. 혹시나 싶어서
:3000번 포트가 여전히 사용 중인지 조회하니 사용 중이 아니였고 3001번에 nodex20이 존재했습니다.
원인은 모르겠지만 결국엔 해결된 찜찜한 경우였습니다.
어제 팀원인 송승환님의 요청으로 dev를 잠시 디폴트 브랜치로 변경하고
오늘 작업이 마무리돼서 main을 다시 디폴트 브랜치로 변경하고 dev를 main으로
풀 리퀘스트롤 올렸더니 충돌로 병합을 해야하는데 웹과 깃허브 데스크탑에서 병합 편집기를 열 수가 없었습니다.
설명에서는 cli에서 병합을 진행하라는 설명이 있어서 진행했는데
과정에서 실수로 dev에 main을 pull해서 병합을 진행하고 merge까지 진행해버렸습니다.
직후 서버를 실행 시켰더니 에러가 무더기로 발생해서 원인을 살펴보니 병합하는 과정에서
여러 파일들이 유실되었고 있던 파일에도 import가 많이 빠져있는 등 많은 문제가 발생했습니다.
하지만 dev와 main 브랜치 모두 같은 내용이였고 하나하나 새로 만들고 수정할 수는 없어서
이전 merge로 되돌아가려고 reset을 사용하려고 깃 로그를 보니 기록이 제대로 안남아있어서
돌아갈 방법을 찾을 수 없었습니다. 그러던 중 승환님이 이전 버전을 로컬에 가지고 있었고
이전 버전에 pull을 하고 revert로 main과 dev를 병합하기 이전 시점으로 돌아가서
원래 데이터로 돌아올 수 있었습니다.
매 페이즈마다 공을 얼마나 이동하면 좋을지?,
상위권 팀과 중위권 팀, 하위권 팀의 스탯 차이가 어느 정도 나면 좋을지,
슛을 시도했을때 성공 확률이 어느 정도를 평균으로 잡을지,
페이즈마다 스탯 감소량을 몇으로 할지 등 수학적으로 접근해야할 곳이 많아 힘들었습니다.
여타 게임들에서 왜 밸런스를 맞추기 힘들어하는지 편린을 엿본 듯한 느낌이 많이 났습니다.
각 요소마다 수치 조정과 테스트를 병행하며 나름대로 맞추어보았지만
지금에 와서도 맞는 수치인지 잘 모르겠습니다.
테스트 플레이가 더 많이 필요함을 느꼈고 왜 다른 게임들이 출시전에 클로즈베타 등의 테스트 플레이를 많이 배포하는지 와닿았던 것 같습니다.