240913 TIL 우리들의 풋살온라인 - 풋살매니저?!

LIHA·7일 전
0

내일배움캠프

목록 보기
49/54
post-thumbnail

아이템 시뮬레이터

리프레시 토큰? 액세스 토큰? 대체 뭐야?

리프레시 토큰까지 만료되면 로그인을 다시 해야하고, 리프레시 토큰만 남아있다면 액세스 토큰을 재발급 하는 방식... 제발 이젠 좀 이해좀 하자... 🥶

아이템 - 인벤토리는 관계를 맺어도 되고 안 맺어도 된다?

수빈님은 인벤토리랑 인벤토리 아이템 테이블을 따로 줬다.
그냥 인벤토리는 칸이 여러개지만, 각 칸에는 한개만 올수 있기 때문에 한 칸에 아이템 한 개라는 식으로 연결해둔 것.
인벤토리 아이템 조회할때 이름이랑 아이템 코드랑 갯수 리턴해달라고 했다.
원본템이랑 획득템이랑 따로 있다.

Prisma의 upsert는 where절에 반드시 @unique 필드를 걸어야 한다

릴레이션 설정해놓으면 조인하겠다는 얘기가 된다! -> 갖다 붙이는 것!

autoincrement는 한 컬럼밖에 적용 안되더라

itemCount가 1씩 증가하겠다
장비아이템이면 장착할때 카운터가 -1이 되게 해주게 하는 것이다.
생성을 할때 값을 줘야 하는 것.

프리즈마의 @map("명칭")은 Row Query 쓸 때를 대비해 스네이크케이스로 써줘야 한다

여기다 한글 쓰면 작살난다!

지금 내가 생각하는 인벤토리 개념은 큰 배낭 하나를 가질 수 있다는 개념인거고, 거기서 더 가질수가 없다.
그래서 인벤토리 슬롯 테이블을 하나 만들어서 인벤토리 테이블이랑 연결시켜 주는게 어떨까? 라고 현권님이 추천? 해주셨다.

PK만 가져와서 테이블에 컬럼 안넣고 불러오고 싶으면 - SELECT문 안에 또 SELECT문을 하면 된다!

중첩 SELECT 문이 있었는데 내가 잊고있었다 -> 이게 약간 JOIN 개념이었던 것 같다!
'평탄화' 라는게 있었다.

upsert는 왜 똑바로 돌아가질 않을까

와... 같이 항해를 했던 대현님의 블로그에서 이 답을 찾다니. 반가운 출처

upsert는 단순히 data : {} 하고 써주는게 아니라 create 조건과 update 조건을 다 걸어줘야 하는 것이었다. 아래와 같다.

client.user.upsert({
	where: {
      ...payload,
    },
  	create: {
      //code
    },
  	update: {
      //code
    }
});

내가 upsert를 사용하는 용도는 인벤토리 구현이었다. 아이템을 구매할 때 인벤토리에 그게 없거든 만들어주고, 있거든 수량만 변경해줘라 하는 것이었다. 지금 고민하는 건 과연 여기에 upsert를 쓰는게 맞는지 모르겠다.


SA

우리들의 풋살온라인

게임은 상태동기화가 정말 중요하다. 충돌처리 같은 것도 처리해줘야 한다.
선수 스탯에 가중치를 부여해 곱한 정규화를 선수마다 계산해서 총점을 낸다.
맥스스코어에 룰렛을 걸어 총점이 더 높은 쪽이 이기는걸로? 나쁘지 않겠다.

가챠는 어떻게 구현하지?

구매는 account의 cash를 가지고 Player(선수) 중 한명을 뽑을 것이다.
Product 테이블은 상품의 내용물을 같이 담고있어야 한다. 보상으로 뭘 줄건지.

Product라는게 결국 Players의 데이터를 가져오는 것이다.
그러면 거기서 PlayersId만 배열로 받아온다.
받아온 Id에 어차피 Players에 정보가 있을테니까

내가 무엇을 놓치고 있는걸까? 이해가 잘 안돼😥

  • DB에서 연관관계를 가지는 것과 로직에서 값을 불러오는 것은 별개다.
  • 뽑기 기능을 구현하고 싶은데, 관련 정보가 DB에 저장되었으면 좋겠어요! -> 필요한 것만 저장하면 된다. 관계형 DB라고 해서 모든게 다 연결될 필요는 없다!

피드백

창민 튜터님 피드백

전반적으로 개선이 많이 필요하다.

어카운트

accountInfo 나누지말고 한꺼번에 넣어도 된다. 테이블을 나누면 불필요한 JOIN을 하게 된다.

원장테이블 통계를 필요할때마다 내는게 좋다. MMR이 있는건 좋다. (잘 넣은듯?)
팀덱 팀인포 로스터의 상관관계를 보고 있는데, 잘 모르겠다고 하신다.
팀덱과 팀인포? 합쳐주는게 나을 것 같다. -> 팀테이블 하나로!

팀덱에 accountId를 넣으면 팀덱Id로 조회했을때 팀이 나오게 하는 것이?
구단 이름이나 가치는 더하거나 뺄때마다 add, substract 하는게 나을것.
Players는 게임DB 느낌이고, Roaster는 UserPlayers인 느낌.
구현 상으로는 팀덱은 한개만 가질 수 있다. -> 그렇다면 accountId 자체가 PK여도 상관없지 않나? teamId는 굳이? 라는 느낌.

매치결과

player1도 accountId에 참조무결성 제약조건이 걸리고, player2도 참조무결성 제약조건이 걸려있으면 된다.

강화

  • 강화가 왜 어렵냐면, 강화는 철저하게 테이블 기반으로 계산되어야 한다. 이런식으로 스냅샷을 뜰 필요가 없다.
  • PlayerId와 강화레벨을 키로 모든 정보를 다 가져올 수 있어야 한다. 확률까지도 전부다 정의해줘야 한다.

상점

  • 지금 당장은 players랑 굳이 연결되지 않아도 될거 같은데. 지금 당장은.
  • 가챠에 티어를 줄거면 Players에서 그 티어 이상의 플레이어에서 랜덤으로 가져오는 식으로 구현해야 한다.
  • 가챠를 할거면 내가 뽑을 플레이어의 단서는 있어야 한다!

호영 튜터님 피드백

호날두 프리킥 110으로 만들었는데 나중에 너프한다고 치자. 그러면 스냅샷 떠오는 식으로 개인의 소유선수 테이블이 죄다 따로 존재한다면 어떻게 할건지? -> 이건 말이 안된다! 누가 호날두 몇개 들고 있을줄 알고.

요주는 복사하지 않고 내가 필요할 때만 저 테이블에서 조회하면 되지 않을까? 라는 것.
게임에서 스탯이 필요할 때가 언제일까? 플레이 할때랑 강화할 때다.

강화에 대한 모든 정보를 기록해야 한다고 하셨는데 맞는 말이다. 강화 데이터에 대한 테이블 따로 있어야 한다.
1강에 10씩 올려준다고 하자, 각 강화 단계에 따라 모든 수치와 확률이 다 테이블에 적용되어 있어야 한다.

어떤 한 기능을 만들땐 그 기능을 정의할 수 있는 데이터 테이블이 무조건 있어야 한다. 만약 경기시간을 90분, 45분, 30분, 15분 이런 식으로 변동할 수 있다면 그 경기시간에 대한 테이블도 다 있어야 한다.

마비노기, 메이플처럼 수치가 랜덤하게 오르는건 최소 최대가 있는 것임.
지금 우리는 포지션이 빠졌는데 포지션마다 스탯이 오르는 것도 달라야 한다.

그래서 보통 자주 쓰는 데이터는 서버 메모리에 가지고 있다. 그러다 수정할게 있으면 핫픽스 해서 빌드 다시 뽑고 테스트 다시 하는 것임.
레디스같은 거 써도 되지만 어려우면 하지말고, 변수 하나 선언하고 그 값을 계속 받아오는 식으로 해도 상관없다.

8시까지 이 과제를 해보자 -> 호영 튜터님의 SA 과제

로그라이크 할때처럼 턴제로 하는걸 응용해보자. 한 팀에 5명이라는 식으로.
경기시간은 30분으로 고정 -> 30턴으로, 우리 로그라이크 게임처럼 공격한다고 해보자.
스피드 피니시 슛파워 디펜스 스태미나 이런 식으로 스탯이 있다고 해보자.

공격수는 스피드 피니시 슛파워 같은걸 높여주자 -> 골을 넣을 확률
미드필더는 공격하거나 막거나 니까 슛파워, 디펜스 -> 수비/공격값 반반
수비수는 디펜스를 높여주도록 하자 -> 수비하는 값만 가질 수 있게

그렇게 총 60턴을 하면 총 10몇대 20몇으로 값이 나올거다. 그러고 나면 돈바르면 이기는 게임이 아니라 진짜 확률 싸움이 돼서 재밌을 것.

그리고 웅상님 등산 과제처럼 턴마다 촥촥촥촥 보여주면 재밌을 것이다.


새로 고쳐진 (테이블축구 같은) 우리의 풋살매니저 아이디어 기록

수빈님 아이디어-> 축구장처럼 [이팀|중간|저팀] 나눈다. 각자 골대가 있을 것.

  • 슈팅 -> 골대가 가까울수록 확률 올라감
  • 패스 -> 확률로 성공 실패. 상대방 수비수의 능력에 달려있는 것
    질주 -> 스태미나 소모가 심한 대신 성공확률이 높은 패스 일단 패스
    드리블 -> 스태미나 회복하는 대신 공뺏기면 턴 종료될 수 있음 (상대턴) 일단 패스

이때 공 위치는 이팀 중간 저팀 중 하나에 있을 것이고, Int값이든 뭐든 나타내면 될것.

  • 기본뼈대
    포지션에 따라 위치는 고정!
    A팀 | A팀수비 | A팀MF | A팀공격 | B팀
    골대| B팀공격 | B팀MF | B팀수비 | 골대

  • 특수 스킬?
    예를 들어 질주같은 게 추가가 돼서 마비 크리티컬마냥 확률적으로 터지면, 실제 위치를 바꾸는건 아니지만 A팀수비가 B팀골대 앞쪽에 가서 골넣는 시도를 한다는게 된다. 그러면 해당 위치의 높은 슈팅확률 보정을 받는 턴이 될것.
    -> 로직에서만 그렇게 짜줄거라는 것. 질주 터질 시 A팀수비 캐릭터의 위치는 A팀공격 위치이고, 거기서 슈팅확률

  • 상대 턴
    일때는 적당히 서로의 능력치에 따라 자동 진행... 하는걸로 일단 임시로 결정.

  • 행동 처리

  1. 슈팅
    아군 슈팅 성공시 -> 공 위치가 상대 골대 앞으로 무조건 이동
    아군 슈팅 실패시 -> 공 위치 이동없음
    적군 수비 성공시 -> 턴 뺏김
    적군 수비 실패시 -> 골 확률로? 골을 바로 처리?

정섭 튜터님의 첨언

  1. 상대방이 접속해있어야만 매치 신청을 할 수 있도록 하고
  2. 상대방이 신청을 수락해야만 매치를 할 수 있도록 할것

EC2 두대에다가 똑같은 서버를 배포해놨을 때, 서버1의 유저 A와 서버2의 유저 B 사이의 매칭을 어떻게 구현해야 할까? 같은 것 고민해보면 좋다!?


Git

git에 대한 궁금증 - 한 폴더는 한 리포인데, 그러면 브랜치는?🤔

로컬리포와 원격리포는 다르다. 근데 그러면 브랜치는 어떻게 관리하지?
로컬에 브랜치 만들고 원격브랜치를 git pull origin (브랜치 이름) 으로 땡겨와야 하는걸까?

  • 정섭 튜터님의 말씀

    땡겨오면 당연히 충돌이 나고, 그 코드를 머지하는 사람이 따로 있다.
    가장 먼저 완성한 사람이 머지를 할테니까, 그 뒤에 머지하는 사람들은 원본과 다른 곳에 머지하게 될것.
    그래서 이런건 보통 팀장급이 머지 작업만 한다.

내 생각: 로컬브랜치 만들고 작업마치고 푸쉬도 다하고, 원격브랜치별로 땡겨오면 되겠지?
실제: 나는 내 담당 브랜치에서만 작업할거기 때문에, 다른 브랜치는 신경 쓸 이유가 없다!

헷갈리는 것: 그럼 브랜치를 바꾸면? 코드도 바뀌나?
실제 테스트: 응 바뀐다! 단 이건 업스트림(원격 브랜치)을 설정했다는 전제하에!

-> 그래서 git push origin main/dev/feature 처럼 푸쉬때 업스트림만 잘 설정해 놓으면 각 브랜치별 별도 코드를 땡겨오는게 맞다.

error: GH013: Repository rule violations found for refs/heads -> 혹시 머지 전 PR하는 룰셋의 대상 브랜치를 잘못 걸지 않았는지?

브랜치 보호규칙 참고 블로

커밋까지는 됐는데, 푸쉬하려고 하니 이 메시지가 뜨면서 푸쉬가 되질 않았다. 팀원 웅상님만 그러신줄 알았는데 나도 마찬가지. 구글링 해봐도 뾰족한 결과는 나오지 않았고 답답하던 차에 문득 깨달았다.

처음에 브랜치 룰셋에서 머지 전에 PR을 날려야 하게 했는데, 이것의 브랜치 설정을 잘못 해놨다. main만 보호하려고 한건데 모든 브랜치에 죄다 걸어놓으니 커밋도 되지 않았던 것.

그래서 default(main) 브랜치에만 적용되도록 재설정 해놓으니 원하는 대로 작동했다!

profile
갑자기 왜 춤춰?

0개의 댓글