스파르타 최종 프로젝트 2주차 회고

이정기·2023년 4월 17일
0

TIL

목록 보기
55/71
post-thumbnail

2주차부턴 정신없이 프로젝트가 진행됐었다. 내가 맡은 부분을 기간내에 끝내려 하니 주말도 제대로 쉬지 못했다. 벨로그도 쓸 시간이 없어 프로젝트를 마무리 하고 주 단위로 회고를 작성하기로 했다.

2주차 시작

2주차엔 간트차트를 작성하고, 자신이 맡은 부분을 개발해 나아갔다. 우리는 프로젝트를 더 첼린지하기 위해 테이블과 기능들을 늘려나갔다. 난 특별히 맡고 싶었던 부분은 여러 테이블과 관계를 가지고 있는 파티와 관련된 기능들 이였다. 왜냐하면 저번 프로젝트가 끝나고 3계층을 나누며 실력을 향상한 나를 도전적인 코딩을 하고 싶었다.

파티는 썸네일, 파티멤버, 태그, 유저, 찜목록 등 여러 테이블과 1:N 또는 N:M 관계를 가지고 있어 Nest.js의 DI 에 대한 이해와, 여러 테이블의 정보를 같이 불러오고 같이 수정해 나가는 방법을 알아야 했다.

어려웠던 부분들

전 프로젝트에서 sequelize 의 메서드를 활용했던 것 처럼, typeorm 의 Repository API 를 활용해 (find, findOne, insert, update) 해결될줄 알았다. 하지만 그것은 너무 단순한 생각이란걸 삽질 후 깨달았다.

문제는 파티를 만들 때, 썸네일과 태그를 함께 저장하는 파티 생성과 수정 API 에서 막혔다. 클라이언트에서 썸네일에 대한 배열과 태그에 대한 배열, 파티의 정보를 JSON 형태로 보내줄 때, 각각의 정보들을 create API 로 테이블에 넣어줬다. 여기까진 문제 없었다.

파티 생성 문제코드

async createParty(party) {
        const saveParty = await this.partyRepository.save(party);

        await this.thumbnailsRepository.save({
            partyId: saveParty.id,
            thumbnail: saveParty.thumbnail,
        });

        const saveTag = await this.tagsRepository.save({
            partyId: saveParty.id,
            tagName: saveParty.tagName,
        });

        await this.partyTagMapping.save({
            partyId: saveParty.id,
            tagId: saveTag.id,
        });
    }

이렇게 저장하는 경우, 클라이언트에서 가져올 때 파티, 썸네일, 태그를 모두 가져와야 하는데 파티만 가져오는 현상이 발생했다. 이것은 업데이트 부분도 마찬가지 였다. 그렇게 팀원들과 알아보니 Nest.js 에서는 독특하게 새로운 객체를 생성하고 해당 객체에 데이터를 넣어준 뒤 저장한다는 것을 알았다.

const thumbnail = new Thumbnail();
thumbnail.url = partyInfo.thumbnail.url;

const tags = partyInfo.tags.map(tagInfo => {
  const tag = new Tag();
  tag.name = tagInfo.name;
  return tag;
});


const party = new Party();
party.user = user;
party.title = partyInfo.title;
party.content = partyInfo.content;
party.maxMember = partyInfo.maxMember;
party.address = partyInfo.address;
party.date = partyInfo.date;
party.thumbnail = partyInfo.thumbnail;
party.tags = partyInfo.tags

const newParty = await queryRunner.manager.save(party);

각 테이블 thumbnail 과 tags에 대한 새로운 객체를 만들어주고 해당 객체의 속성에 할당해준 뒤, party 객체 속성에 새로운 객체들을 할당 해준다.

해당코드는 썸네일을 받지 않았을 경우나, 중복된 태그가 있을 때 처리되는 부분은 뺏지만, 이렇게 맵핑해 줌으로써 파티를 불러왔을 때, 파티와 관련된 속성들을 모두 불러올 수 있었고, 삭제 할 때 또한 연관된 정보가 삭제되었다.

파티 업데이트 문제

업데이트 시 생각해야할 것들도 있었다. 우리는 파티 데이터들과 썸네일 배열, 태그 배열을 서버로 보내 저장 및 수정을 한다. 데이터베이스의 이미 있는 데이터를 변경하는건 어렵지 않았지만, 클라이언트에서 이미 있는 데이터 이외에 데이터를 추가 또는 삭제할 때 고민이 되었다.

  1. 파티 관계 테이블 업데이트 문제
  2. 업데이트 갯수 문제

1번의 문제는 위에 파티 생성을 할 때 처럼, save 메서드를 사용하면 됐었다.
(save메서드는 인자로 PK 키를 받았을 때 없으면 생성, 있으면 수정해준다.)

2번을 고민했었는데, 일단 내가 배운 수정기능은 기존 데이터를 수정하는 것밖에 하지 않았었다. 그렇다면

  1. 썸네일이 3장이 있을 때, 클라이언트가 모두 지우고 새로운 1장을 업로드한다면?
  2. 썸네일을 기존 3장에서 1개를 더 추가한다면?
  3. 썸네일을 1장만 지우고 1개를 새로 추가한다면?

이라는 생각때문에 이것을 모두 분기문을 줘야하나.. 클라이언트에선 어떻게 받아야하지.. 라는 고민에 빠져있다 영환이형한테 솔루션을 받은 것이

  1. 썸네일을 추가한 배열을 받는다.
  2. 썸네일을 삭제한 배열을 받는다.
  3. 태그를 추가한 배열을 받는다.
  4. 태그를 삭제한 배열을 받는다.

그리고 이 배열들을 모두 서버로 보내 삭제할 것들은 softDelete 와 filter 를 돌려 우리가 필요한 태그와 썸네일만 가져와 저장시켜 파티 수정 API를 완료했다.

업데이트 리펙토링 방향

이 부분은 클라이언트에서 어떻게 데이터를 보내야 하는지 생각하지 못해서 로직이 많이 복잡해진 경우이다. 아래와 같이 수정하면 코드가 더 간결해 질거라 예상한다.

  1. 클라이언트에서 모두 수정 된 배열을 서버에서 보내준다.
  2. 해당 파티의 기존에 있는 썸네일과, 태그 데이터는 삭제 후 새로운 배열을 저장한다.
  3. 클라이언트에서 태그와 이미지를 수정하지 않고 요청을 했다면, 기존 배열과 현재 저장 되어 있는 데이터를 비교해 같다면 2번이 실행되지 않게 한다.

유저 파티 신청 시, 유저의 상태 변경과 파티의 신청 유저 숫자 최신 업데이트

내가 알고리즘 공부가 필요하다고 느낀 API 부분이였다.
처음 생각은 '신청' 과 '거절' 을 눌렀을 때, 해당되는 상태만 변경되면 되겠지 라는 짧은 생각을 가지고 있었다.

하지만, 우리는 클라이언트에서 두 버튼을 토글버튼으로 구현을 해서 아래 조건을 모두 고려 했어야 했다.

파티 모집중 일 때만, 상태변경 가능

클라이언트 행동상태현재인원
기본 상태신청대기0
기본 상태에서 신청 눌렀을 때승낙+1
승낙 상태에서 신청 버튼을 눌렀을 때신청 대기-1
승낙 상태에서 거절 버튼을 눌렀을 때거절0
기본 상태에서 거절 눌렀을 때거절0
거절 상태에서 거절 버튼을 눌렀을 때신청 대기0
거절 상태에서 신청 버튼을 눌렀을 때승낙+1

클라이언트에서 받은 데이터에 해당하는 상태와 , 현재인원을 변경해줘야 했다.
그리고 리턴값을 보내 클라이언트 버튼 색깔을 변경해주었다.

처음엔
if모집중일 때 if클라이언트의 행동 if상태 if승낙 or if거절
이런식으로 여러 중첩의 if를 주었는데 값이 뒤죽박죽으로 나오는 경험을 했었다.

여러 메서드의 처리의 일관성을 부여해주는 transaction을 commitTransaction 해주지 않았던 것도 한몫 했던거같다. commit 을 빼먹었다고 해서 오류가 나진 않았었다...

if 문을 재 정의 해주고 return 하기 전에 commitTransaction 으로 문을 끝내 정상적으로 처리 되었다.

profile
Node.js 로 꿈을 꾸었다..

0개의 댓글