(최종 프로젝트 마무리 중)
오늘 한 일:
- requestList.ejs에서 ‘비로그인 상태에서는 getRequestsByCursor 불러오게 분기하기
- entity들에서 ManyToOne, OneToMany cascade 옵션 뒤바꾸기
dbeaver에서 Ctrl+Shift+F 누르면 자동 정렬 된다.
- 왜 쿼리는 조인해오는 테이블의 deleted_at=null도 조건으로 검사해오도록 짜여졌는데 왜 결과는 그게 아닌가? Left Join이 수상하다.
내일 할 일:
- 피드백 받은 ‘재 페인팅해야 하는 컴퓨테이션을 제거 및 개선했다…’ 부분 알아보고 ppt 고치기
[5:07] 유저 피드백 바차트를 DESC 오더로 포맷해주세요.
[6:33] 페이지 리렌더링은 저렴한 작업이 아닙니다, 그래서 속도 개선보다는 페이지를 재 페인팅 해야되는 컴퓨테이션을 제거 및 개선했다고 언급하면 좋습니다.
첫부분에 발표자와 ppt 드라이버와 싱크가 맞지 않는부분이 있고 그러므로 침묵이 있고 흐름이 약간 끊기는 상황 개선 부탁드립니다
전반적으로 ppt 준비를 필요하고 유익한 내용만 넣으시고 작성을 잘 하셨습니다. 프로젝트 아이디어로 오프닝을 하고 기술적 의사결정을 말씀대로 짧고 굵게 오버뷰를 해주신 것도 내용 및 시간을 잘 맞춰주셨습니다. 트러블 슈팅 슬라이드도 유의미한 주요 내용만 포함하셨고 기술적인 도전과 계획도 퀄리티와 난이도가 높은 계획으로 잘 구성되어있습니다. 여러모러 굉장히 모범적인 ppt와 발표였다고 생각이 됩니다.
)
- 팀 공유 노션에 정리해볼 내용:
- Redis - 메인 페이지 속도 개선과 오래된 캐시 히트 문제 개선에 사용된 redis에 대하여
- 로컬 환경과 배포 환경에서 나타나는 Date 타입의 시간 차 ✔️
- 웹으로 사용자 위치 인증시 실제 위치와 다른 IP로 뜨는 경우와 그 이유 ✔️
- 오프셋 기반과 커서 기반 페이지네이션에 대하여 깊이. DB 인덱싱 개념까지. - 실제 코드 구현까지 설명이 가능하도록
- HTTPS 프로토콜로 배포했으니까 이게 HTTP와 어떻게 다른 점이 있는지에 대하여. ✔️
- 프로젝트 발표가 아니라 면접과 인터뷰를 위해 조금 더 욕심을 낸다면.. Node js에서 비동기 함수 사용법에 대하여(promise기본, async/await 기본, 콜백을 활용하는 예시와 setTimeout 함수에 대하여, 그리고 비동기라는 개념 자체에 대하여) ✔️
자료 예)
보던 페이지:
- AWS S3 활용법에 대한, 의외로 좋았던 한국 공식 블로그 - https://aws.amazon.com/ko/blogs/korea/amazon-s3-15th-anniversary-voices-of-korean-customers/
- 노션을 ppt로 꽤 훌륭하게 만들어준다는 프로그램? https://wunderpresentation.notion.site/Wunderpresentation-Example-588e80f64e854ea98bcdc8d3d4d61089
- “what exactly is 304 response”로 검색중이었음.
- “user affordance(사용자 행동유도성)” - ‘더보기’ 버튼이 비활성화되어 있어야 ‘더 볼 게 없구나’ 라고 인식할 것이라는 프론트 디자인 맥락에서 나온 용어.
※ 이하는 스스로 공부하며 적어둔 노트이며 불확실한 내용이 있을 수 있습니다. 학습용으로 적합하지 않음을 유념해주세요. ※
에러: TypeORM에서 onDelete 등 cascade 옵션이 안먹히던 오류 해결 ✔️
에러: TypeORM에서 onDelete 등 cascade 옵션이 안먹히던 오류 해결 ✔️
User - Cat[]의 일대다 관계에서 User를 부모, Cat을 자식이라고 표현하겠다.
- 부모 쪽에 cascade: ['insert', 'update', 'remove', 'soft-remove', 'recover'] 옵션을 걸어주는 게 맞다. (”내가 삽입/수정/삭제 되거든 자식들도…” 같은 의미)
- 자식 쪽에 onDelete, onUpdate 옵션을 걸어주는 게 맞다. (자식인 내가 삭제되면,,, 내 부모도…? 이건 사실 잘 모르겠다.)
“탈퇴하여 soft-delete된 유저가 작성한 모든 게시글과 고양이 프로필 등을 똑같이 soft-delete하여서, 프론트 페이지에 undefined 등으로 이상하게 나타나는 것을 막고 싶다”는 목적을 위한 실제 코드를 작성해보자.
중요한 포인트가 3가지 있다.
- 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() 메소드가 존재하는 것 같다.
- cat.entity.ts(자식, ‘일 대 다’)쪽에서는 아무것도 안 해줘도 된다.
@ManyToOne(() => User, (user) => user.cats, { onUpdate: 'CASCADE', onDelete: 'CASCADE', }) 이렇게 남겨둬도 되고, @ManyToOne(() => User, (user) => user.cats) 이렇게만 해도 상기한 목적은 달성된다.
- 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으로 충분한 것 같다.
- 의문: find가 아니라 findOne으로 충분한가…? 예를 들면 한 User가 고양이 두 마리 프로필을 갖고 있을 땐 find로 해서는 첫 번째 고양이까지만 join되어 가져올 수 있었다. 이 논리대로라면 이대로 이 유저를 삭제했을 때, 첫 번째 고양이만 soft-delete될 것인가?
일단 이렇게만 해주면 한 User를 soft-delete 했을 때 직접적으로 연결된 ‘cats’, ‘products’ 등의 Entity 데이터를 똑같이 soft-delete 해줄 수 있음을 확인하였다.
Uploaded by N2T