Facts
-
프로젝트의 리팩토링을 전반적으로 맡으면서 여러 아이디어나 최적화 방법을 볼 수 있엇다.
-
이번에 주어진 조건들을 만족시키기 위해 여러 prisma의 문법이나 메서드를 배울 수 있었다.
-
코드를 팀원분들에게 설명을 해주며 프로젝트에 대한 이해도가 올라갔다.
Feelings
-
팀원분들과의 소통이 원활하여 프로젝트 진행이 순조로웠고, 그래서 기분좋게 마무리를 할 수 있었다.
-
리팩토링을 해가며 코드들을 이해하고 새로운 알고리즘을 짜는 기분이여서 뿌듯했다.
Finding
-
기획/발표와 관련된 일을 대부분 팀장님께 일임이라는 형태로 업무를 많이 드린 것 같아 죄송하다.
-
이번 경험을 통해 커뮤니케이션이 일의 효율에 얼마나 관여하는지를 다시금 깨닫게되었다.
Future
- 기록 습관을 들일 수 있도록 블로그 정리를 열심히 해야겠다.
오늘의 Troubleshooting
쁘띠 TFT 프로젝트
챔피언 뽑기 리팩토링
- 챔피언을 뽑았을 때, 이를 가지고 있는 챔피언인지 확인하고, 없으면 생성하는 로직에 upsert()라는 메서드를 적용하려 했다
=> upsert()는 where 에서 unique 속성이 있는 컬럼을 이용해 찾아보고 없으면 생성해주는 메서드다.
-
그러나.. myAgents 테이블엔 myAgentKey 라는 @id 빼곤 unique한 키가 없어 효율적으로 검색할 방법이 없다!
-
이로인해 깨닫게 된게 @id(PRIMARY KEY) 를 정할 때, N:M 테이블은 복합키를 이용해야 편하다는 것이었다..
=> 후에 합의하여 테이블을 바꿔 수정해주었다
// 기존의 테이블
model MyAgents {
myAgentKey Int @id @default(autoincrement()) @map("my_agent_key")
userKey Int @map("user_key")
agentKey Int @map("agent_key")
name String @map("name")
level Int @default(1) @map("level")
class Int @default(0) @map("class")
count Int @default(1) @map("count")
obtainedAt DateTime @updatedAt @map("obtained_at")
agent Agents @relation(fields: [agentKey], references: [agentKey], onDelete: Cascade)
user Users @relation(fields: [userKey], references: [userKey], onDelete: Cascade)
@@map("MyAgents")
}
// 수정된 테이블
model MyAgents {
userKey Int @map("user_key")
agentKey Int @map("agent_key")
name String @map("name")
level Int @default(1) @map("level")
class Int @default(0) @map("class")
count Int @default(1) @map("count")
obtainedAt DateTime @updatedAt @map("obtained_at")
agent Agents @relation(fields: [agentKey], references: [agentKey], onDelete: Cascade)
user Users @relation(fields: [userKey], references: [userKey], onDelete: Cascade)
@@id([userKey, agentKey])
@@map("MyAgents")
}
- 기존의 myAgent 생성/업데이트 코드
const existingAgent = await tx.myAgents.findFirst({
where: {
userKey: +userKey,
agentKey,
},
});
if (existingAgent) {
await tx.myAgents.update({
where: { myAgentKey: existingAgent.myAgentKey },
data: {
count: { increment: 1 },
},
});
} else {
await tx.myAgents.create({
data: {
userKey: +userKey,
agentKey,
count: 1,
level: 1,
class: 0,
name,
},
});
}
- 리팩토링한 코드
await tx.myAgents.upsert({
where: { userKey_agentKey : {userKey, agentKey}},
update: {
count: { increment: 1 }
},
create:{
userKey: +userKey,
agentKey,
count: 1,
level: 1,
class: 0,
name,
}
})
- 추가로 myAgentKey 가 사라져서 바꾸게 된 곳
// 관계성을 이용해 upadte를 동시에 작업하는 곳에서의 이전 버전
myAgent: {
update: {
where: { myAgentKey: myAgent.myAgentKey },
data: {
count: { decrement: +count },
},
},
}
// 수정 버전
myAgent: {
update: {
where: { userKey_agentKey: { agentKey: agent.agentKey, userKey: user.userKey } },
data: {
count: { decrement: +count },
},
},
}
프론트엔드 픽업 캐릭터 설정오류
-
프론트엔드에서 픽업 캐릭터를 가렌(S)으로 설정하였음에도, 세주아니(S) 가 더 자주 나오는 오류가 있었다!
-
그래서 챔피언 뽑기쪽 API를 확인 해보니 맨 아래에 무조건 적으로 마지막 S급을 반환하는 코드가 있었음
function getRandomAgent(agents, pickup = null) {
if (!pickup) return agents[Math.trunc(Math.random() * agents.length)];
// 기본 균등 확률
// 가중치 설정 prob1 = pickup 확률 prob2 = 나머지 s급 확률
const prob1 = 55;
const prob2 = Math.trunc((100 - prob1) / (agents.length - 1));
// 확률 계산
const weights = agents.map((agent) => agent.agentKey === pickup ? prob1 : prob2);
const random = Math.trunc(Math.random() * 100)
let cumulative = 0; // 이제 가중치를 모아서 어느수에 걸치는지 파악하기 위한 변수.
for (let i = 0; i < agents.length; i++) {
cumulative += weights[i]; //가중치를 모은다.
if (random <= cumulative) {
// 가중치가 랜덤에 걸렸을때.
return agents[i]; //그 가중치의 선수.
}
}
return agents[agents.length - 1]; //이건 만약 오류나면 그냥 마지막꺼 내놓음. << 이게 작동한거 같은데..
}
- 그래서 for문이 제대로 동작 안하는 것 같아 console.log를 사용해 random 값과 cumulative 값을 비교해 보았음!
for (let i = 0; i < agents.length; i++) {
cumulative += weights[i]; //가중치를 모은다.
if (random <= cumulative) {
// 가중치가 랜덤에 걸렸을때.
console.log(i, cumulative, random, prob2, agents.length)
return agents[i]; //그 가중치의 선수.
}
}
console.log(agent.agentKey === pickup, agent.agentKey, pickup,"비동작")
return agents[agents.length - 1];
- 확인을 해보니 확률을 조절하는 weights 에서 확률을 합친 값이 100이 안된 거 같다!
=> 그래서 더 살펴보니 agent.agentKey와 pickup가 똑같지 않다고 하는거다!(pickup이 아마 문자열로 들어온듯)
- 그렇게 pickup에 +를 붙여줘 INT 형식으로 바꿔 디버깅을 마무리하였다
개선점 분석
- 프로젝트 마무리 단계에서 아이디어를 내어 작업시간을 늘리지 말고,
중간 회의나 초반에 소통을 통해 아이디어나 의견을 주고 받을 수 있도록 노력해야겠다.