ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 항해 99 5기 TIL_66
    항해 99 2022. 3. 17. 04:14

    ▶ Today I Learned

     

    <실전 프로젝트>

     

    [MySQL, Sequelize 실행 및 이해하기]

    MySQL 과 Sequelize에 대해 어제 배운 것을 오늘 본격적으로 활용해보고 있다.

     

    Sequelize로 MySQL에 DB를 만들 때는 이전에 MongoDB를 썼을 때와는 달리

    해당 DB가 자동으로 만들어지진 않는다고 한다.

    우선 테이블을 다음의 구문을 터미널에 입력 및 실행해야 한다.

    npx sequelize db:create

    그런 다음 npm run dev를 실행하면 해당 DB 내 테이블이 생성된다.

     

    [user모델과 badge모델의 연결]

     

    그리고 user.js라는 스키마 파일에 다음과 같은 코드를 넣어두었다.

    User.associate = (db) => {
        db.User.belongsToMany(db.Badge, { through: "UserBadge", as: "MyBadges", onDelete: "CASCADE" });
        ...
      };

    현재 user와 badge라는 모델은 일대다 관계 (한 명의 유저가 여러 개의 뱃지를 가질 수 있음)인 상태이다.

     

    Badge.js에는 아래의 코드가 들어가 있다.

    Badge.associate = (db) => {
        db.Badge.belongsToMany(db.User, { through: "UserBadge", as: "Challengers" });
        ...
      };

     

    여기서 만약 Controller에서 특정 유저가 가진 뱃지를 보려면 user.getMyBadges()라고 하면 된다.

    이는 해당 컨트롤러 내 정의된 특정 유저가 UserBadge라는 join된 관계로 형성된 테이블의 요소를 모두 들고 올 수 있는 것이다.

    반대로 badge.getChallengers() 라고 한다면 특정 뱃지를 가지고 있는 유저를 가져올 것이다.

     

     

    [뱃지 DB 내 생성]

     

    로그인의 경우 카카오 로그인을 예시로 들자면 이렇게 되어있다.

    // *****ch: 로그인과 관련된 뱃지들 지급*****
          
          // 선착순 뱃지 지급 + 인원 100 명 까지만 추가해야함!
          //선착순 뱃지 이름을 firstCome 이라고 가정, 실제로 DB에 badge 테이블에 name 넣어주어야 함
          const firstComeBadge = await Badge.findOne({
            where: {
              name: "firstCome",
            },
          })
          const myBadges = await user.getMyBadges({
            where: {
              badgeId: firstComeBadge.id
            }
          }) // 특정 유저의 뱃지 리스트를 가져옴, user 모델에서 MyBadges로 정의된 상태
    
          if (!myBadges) {
            // 카카오로 로그인한 사람에게만 지급
            // 특정 유저에게 선착순 뱃지가 없으므로 해당 유저의 아이디에 선착순 유저 뱃지 지급
            await user.addMyBadges(
              firstComeBadge 
            )
          }

     

    카테고리별의 경우 아래와 같이 되어있다.

    if (category === "beauty") {
            // Badge 테이블에 등록된 해당 뱃지 가져와야 함
            theBadge = await Badge.findOne({
              where: {
                name: "beauty", // 해당 뱃지 이름이나 id로 찾아야 함
              },
            })
    
            if (100 <= theRecords[category] && !myBadges.includes(theBadge.id)) {
              // 해당 카테고리 기준을 충족하고 해당 뱃지가 해당 유저에게 없을 경우 그 유저에게 뱃지 추가
              await thatUser.addMyBadges(theBadge.id)
            }

    여기서 myBadges.includes() 대신 카카오 로그인 처럼 where을 써서 그 유저가 특정 뱃지를 가지고 있는지 골라내려고 한다.

    myBadges가 배열의 형태로 반환될 것이라 생각했는데 우리가 아는 것처럼 includes()를 쓸 수가 없었다는 팀원 분의 의견이 있었다.

    그래서 좀 더 확실하게 처음에 찾을 때 부터 특정 유저가 가지고 있는 badgeId 리스트에서 해당 뱃지가 있는지를 찾는 것이다.

    없다면 제대로 된 값이 반환되지 않아 if문에서 !(false)이기에 true가 되어 뱃지가 지급될 것이다.

     

     

    [현재 뱃지에 대한 전체적인 생각]

     

    /* 
            오픈되지 않은 뱃지는 자물쇠 처리
            - 프론트에 S3로 자물쇠 이미지 링크만 전달 드리면 될듯, 기본 값으로 설정해두었다가 카테고리 및 해당 뱃지 이미지 링크 드리면 바꾸기
    
            어느 시점에 뱃지를 지급하게 할건가?
            - batch를 이용하여 매 5초마다 확인하는 방법도 있겠지만 몇 개 안되는 뱃지를 위해 많은 작업을 하는 것은 불필요해 보인다.
            따라서 출석을 했을 때나 방을 나갔을 떄 해당 이벤트를 발생시켜 체크하게 하는 것이 어떨까?
            보통은 방 안에서 활동을 하고 기록이 쌓이므로 방을 나갈 때 기록 측정 후 지급하기로 한다.
            다만 출석을 했을 떄도 체크하는 이유는 간혹 사용자가 강제종료를 할 수 있기 때문이다.
            
            그 외 버그 제보와 같은 특이 케이스는 해당 버튼을 누르면 뱃지를 지급하는 방식을 채택한다.
            결국 실시간으로 바로 뱃지를 지급하기 위해서는 해당 기준을 충족하고 어떤 이벤트를 발생시킬 때가 가장 좋다.
    
            ex) 운동 뱃지 - 운동 카테고리 방에서 나왔을 때 누적 참여 시간이 100시간 이상일 경우
    
            <뱃지의 분류 - 현재 뱃지 총 8개>
    
            1) 로그인과 관련된 것 - 선착순, 1개
            2) 시간과 관련된 것 - 카테고리별, 6개, 방을 나갈 때 (강제종료 로그인을 할 떄도 같이 체크해줘야 한다.-> 강제종료 시에도 시간이 기록된다면 해줘야하지만 아니라면 기준을 충족하지 못할 것이므로 그럴 필요가 없다.)
            3) 버그 제보와 같은 특이케이스, 1개
            방안 [1] admin 페이지 - 관리자만이 접근 가능한 페이지에서 지급하기 [2] 해당 이벤트 발생하자마자 지급 (ex: 버그 제보 버튼 누르자마자 제출)
            현재로서는 특이케이스가 하나뿐이기에 버그 제출 시 발생하도록 하는 것이 좋을 듯, 만약 유의미한 버그 내용인지 확인 후 승인받은 사람에게만 지급하고 싶다면 [1]을 해야함
    
            그 외 고려할 것
            - 자물쇠로 잠겨있는 뱃지에 커서를 올렸을 떄 힌트 보여주는 것, 어떻게 구현할 것인가? (추후 문제인듯)
            - DB 내 뱃지 기본 값 seeders에 채워보기
            - 모든 컨트롤러에서 includes 구문 수정())
            - 선착순 뱃지는 선착순 100명 까지만 주도록 하기
            - S3로 이미지 올려서 링크따오고 공유제대로 되는 지 확인! (공개 범위 보안 설정 필요)
            - 새로 업데이트 된 것 커밋하기 (로그인 방식 쿠키 사용 안하는 버전있으며 그 외에도 뱃지와 연동된 부분 바뀔 수 있으니 코드 수정 필요해질듯)
            - 강제 종료 시 시간 기록 여부 파악하기
            */

     

    그 외 고려할 것들의 부분들을 어서 마저 구현해보아야 겠다.

     

    ▶ 느낀 점

     

    간단해 보이는 기능에도 고려할 것은 생각보다 많다.

    이는 이미 로그인 같은 기본적인 CRUD를 하면서도 느꼈다.

    개발은 하면 할 수록 여전히 내가 모르는 것이 많고 리팩토링 해나갈 부분이 눈에 보이는 것 같다.

    그래도 이 과정은 나름 재미있다. 게다가 혼자하는 것이 아니다.

    오늘도 개발을 더욱 잘하시는 팀원 분께서 코드를 같이 리뷰해주시고 개선할 부분이나 추가 지식을 알려주셨다.

    나도 계속 열심히해서 다른 분들에게 지식을 공유하고 서로의 코드를 같이 개선해 나갈 수 있는 사람이 되자고 다시 한 번

    다짐하게 되는 오늘이었다.

     

    ▶ 공부 시 참고 링크들

     

    https://velog.io/@muchogusto/ERD-%EA%B7%B8%EB%A6%AC%EA%B8%B0

     

    ERD 그리기

    https://www.erdcloud.comhttps://dbdiagram.io/?utm_source=holistics&utm_medium=rails_erd_bloghttps://freehoon.tistory.com/60

    velog.io

     

    https://spicycookie.me/Nodejs/sequelizecrud/

     

    Home

    React & RN 개발자

    spicycookie.me

     

    '항해 99' 카테고리의 다른 글

    항해 99 5기 TIL_68  (0) 2022.03.18
    항해 99 5기 TIL_67  (0) 2022.03.18
    항해 99 5기 TIL_65  (0) 2022.03.16
    항해 99 5기 TIL_64  (0) 2022.03.15
    항해 99 5기 TIL_63  (0) 2022.03.13
Designed by Tistory.