TIL | WIL

3/30 목 (Entity 관계 설정 다시 하고 발표 영상 피드백도 받다) TIL, TIT

깊은바다거북 2023. 4. 16. 03:02

(최종 프로젝트 마무리 중)

오늘 한 일:

  • requestList.ejs에서 ‘비로그인 상태에서는 getRequestsByCursor 불러오게 분기하기
  • entity들에서 ManyToOne, OneToMany cascade 옵션 뒤바꾸기

dbeaver에서 Ctrl+Shift+F 누르면 자동 정렬 된다.

  • 왜 쿼리는 조인해오는 테이블의 deleted_at=null도 조건으로 검사해오도록 짜여졌는데 왜 결과는 그게 아닌가? Left Join이 수상하다.

내일 할 일:

  • 피드백 받은 ‘재 페인팅해야 하는 컴퓨테이션을 제거 및 개선했다…’ 부분 알아보고 ppt 고치기

    (링크: https://docs.google.com/spreadsheets/d/13-EjXTbm2U_NYutdDJg7IfMNXWL5b3P1rdBrROmTAqU/edit?resourcekey#gid=1395401239

    [5:07] 유저 피드백 바차트를 DESC 오더로 포맷해주세요.

    [6:33] 페이지 리렌더링은 저렴한 작업이 아닙니다, 그래서 속도 개선보다는 페이지를 재 페인팅 해야되는 컴퓨테이션을 제거 및 개선했다고 언급하면 좋습니다.

    첫부분에 발표자와 ppt 드라이버와 싱크가 맞지 않는부분이 있고 그러므로 침묵이 있고 흐름이 약간 끊기는 상황 개선 부탁드립니다

    전반적으로 ppt 준비를 필요하고 유익한 내용만 넣으시고 작성을 잘 하셨습니다. 프로젝트 아이디어로 오프닝을 하고 기술적 의사결정을 말씀대로 짧고 굵게 오버뷰를 해주신 것도 내용 및 시간을 잘 맞춰주셨습니다. 트러블 슈팅 슬라이드도 유의미한 주요 내용만 포함하셨고 기술적인 도전과 계획도 퀄리티와 난이도가 높은 계획으로 잘 구성되어있습니다. 여러모러 굉장히 모범적인 ppt와 발표였다고 생각이 됩니다.

    )

  • 팀 공유 노션에 정리해볼 내용:
  • Redis - 메인 페이지 속도 개선과 오래된 캐시 히트 문제 개선에 사용된 redis에 대하여
  • 로컬 환경과 배포 환경에서 나타나는 Date 타입의 시간 차 ✔️
  • 웹으로 사용자 위치 인증시 실제 위치와 다른 IP로 뜨는 경우와 그 이유 ✔️
  • 오프셋 기반과 커서 기반 페이지네이션에 대하여 깊이. DB 인덱싱 개념까지. - 실제 코드 구현까지 설명이 가능하도록
  • HTTPS 프로토콜로 배포했으니까 이게 HTTP와 어떻게 다른 점이 있는지에 대하여. ✔️

보던 페이지:

  • “what exactly is 304 response”로 검색중이었음.
  • “user affordance(사용자 행동유도성)” - ‘더보기’ 버튼이 비활성화되어 있어야 ‘더 볼 게 없구나’ 라고 인식할 것이라는 프론트 디자인 맥락에서 나온 용어.


※ 이하는 스스로 공부하며 적어둔 노트이며 불확실한 내용이 있을 수 있습니다. 학습용으로 적합하지 않음을 유념해주세요. ※

에러: TypeORM에서 onDelete 등 cascade 옵션이 안먹히던 오류 해결 ✔️

User - Cat[]의 일대다 관계에서 User를 부모, Cat을 자식이라고 표현하겠다.

  • 부모 쪽에 cascade: ['insert', 'update', 'remove', 'soft-remove', 'recover'] 옵션을 걸어주는 게 맞다. (”내가 삽입/수정/삭제 되거든 자식들도…” 같은 의미)
  • 자식 쪽에 onDelete, onUpdate 옵션을 걸어주는 게 맞다. (자식인 내가 삭제되면,,, 내 부모도…? 이건 사실 잘 모르겠다.)

탈퇴하여 soft-delete된 유저가 작성한 모든 게시글과 고양이 프로필 등을 똑같이 soft-delete하여서, 프론트 페이지에 undefined 등으로 이상하게 나타나는 것을 막고 싶다”는 목적을 위한 실제 코드를 작성해보자.

중요한 포인트가 3가지 있다.

  1. user.entity.ts(부모, ‘대 다’)에서 cascade: [’soft-remove’] 해주기.
    @OneToMany(() => Cat, (cat: Cat) => cat.user, {
      cascade: ['insert', 'update', 'remove', 'soft-remove', 'recover'],
    })
    cats: Cat[];
    • 중요한 것은 cascade: true로 해주면 ‘insert’, ‘update’만 해당되게 되는 것 같다는 점. (정말 delete에는 안 먹히는지 한 번 더 실험해보길 추천. 확실치 않다.)
    • 또 ‘recover’ 옵션은 설명서에 따르면 User(부모)가 다시 deleted_at=null로 돌아왔을 때 연관된 자식들도 다 되돌린다고 되어 있는데, 일단 DB에서 곧바로 User를 되살렸을 땐 안 먹혔다.

      → 이유1: User를 되살리는 게 아닌, 다시 soft-delete 상태로 만들 때도 똑같이 cascading이 적용 안 됨을 확인했다. DB에서 곧바로 User를 soft-delete하거나 취소할 땐 TypeORM 코드를 거치지 않아서 그런가 싶다. 이를 위해, delete querybuilder에 softDelete() 메소드와 쌍으로 recover() 메소드가 존재하는 것 같다.

  1. cat.entity.ts(자식, ‘일 대 ’)쪽에서는 아무것도 안 해줘도 된다.
    @ManyToOne(() => User, (user) => user.cats, {
      onUpdate: 'CASCADE',
      onDelete: 'CASCADE',
    })
    
    이렇게 남겨둬도 되고,
    
    @ManyToOne(() => User, (user) => user.cats)
    
    이렇게만 해도 상기한 목적은 달성된다. 

  1. users.service.ts에서 ‘유저 삭제’ 메소드에 꼭 이렇게 해줘야 한다 (중요)
    // 유저 정보 삭제
    async deleteUserById(id: number, userId: number) {
      const user = await this.userRepository.findOne({
        where: { user_id: id },
        select: ['user_id', 'status'],
        relations: [
          'cats',
          'products',
          'requests',
          'send_messages',
          'receive_messages',
          'post_comments',
          'posts',
        ],
      });
    
      if (user.user_id === Number(userId)) {
        // soft-delete cascading을 위해선 꼭 softRemove(Entity)로 해줘야 한다.
        // 이 Entity는 cascading을 끼칠 자식 relations를 포함하여 불러온 객체여야 한다.
        await this.userRepository.softRemove(user);
      } else {
        throw new BadRequestException('로그인한 아이디가 일치하지 않습니다.');
      }
    }

    ⇒ Entity 정의할 때 관계 설정을 아무리 잘 해줬어도 저렇게 ‘삭제할 User 객체’를 불러올 때 relations를 걸어 ‘영향을 끼치고 싶은 자식들을 전부 join’해주지 않으면 소용이 없다.

    ⇒ softDelete(userId)의 정확한 정의는, ‘cascading 효과 없이 딸랑 이 id에 해당하는 user만 soft-delete해주겠다’ 였다.

    ⇒ ‘cascading까지 포함한 soft-delete’을 하고 싶다면 softRemove(User)가 맞다. 그리고 상기한 것처럼 이 User 객체는, 똑같이 soft-delete로 만들고 싶은 모든 자식 Entity들을 join해 가져왔어야 한다. (다른 말로 하면, 영향을 미치고 싶지 않은 자식은 뺄 수도 있다는 얘기)

    • 의문: find가 아니라 findOne으로 충분한가…? 예를 들면 한 User가 고양이 두 마리 프로필을 갖고 있을 땐 find로 해서는 첫 번째 고양이까지만 join되어 가져올 수 있었다. 이 논리대로라면 이대로 이 유저를 삭제했을 때, 첫 번째 고양이만 soft-delete될 것인가?

      ⇒ 자유 게시판에 글 2개가 한꺼번에 지워지는 것을 확인했던 것 같다. findOne으로 충분한 것 같다.

일단 이렇게만 해주면 한 User를 soft-delete 했을 때 직접적으로 연결된 ‘cats’, ‘products’ 등의 Entity 데이터를 똑같이 soft-delete 해줄 수 있음을 확인하였다.


Uploaded by N2T