티스토리 뷰
Github Repo
https://github.com/wanted-wecode-subjects/eight-percent-subject
개요
- 회원, 계좌, 입/출금 API 만들기
기간
- 2021.11.11 - 2021.11.13
개발 환경
- TypeScript
- NestJS
- Sqlite3
사용 라이브러리
- bcrypt
- passport
- typeorm
- class-validator
- class-transformer
- passport-jwt
- moment
구현 사항
요구사항
- sqlite 사용
- 거래내역 조회
- 계좌의 소유주만 요청 가능
- 거래일시 필터링
- 출금/입금 필터링
- 페이지네이션
- 거래일시, 거래금액, 잔액, 거래종류(출금/입금), 적요
- 입금
- 계좌의 소유주만 요청 가능
- 출금
- 계좌의 소유주만 요청 가능
- 계좌 잔액 내에서만 출금 가능
- 잔액을 넘긴 출금 요청에 적절한 에러처리
- 기타
- 유닛 테스트 구현
- functional test 구현
- 거래내역이 1억건 넘어갈 때를 고려
- 1억건이 넘는 조회에 대한 설계 작성
DB 모델링
typeOrm foreign key가 안 들어올 때
@GetUser 데코레이터로 user에 대한 정보를 받아서 account 서비스에 넘긴 뒤 account를 생성하였는데 실제 테이블에 들어가서 확인해보니 NULL값으로 되어 있었습니다.
즉, foreign key가 제대로 입력되지 않았습니다.
그래서 jwtStrategy로 가서 user에 대한 정보를 모두 리턴하였습니다.
jwt.strategy.ts
async validate(payload: any) {
const { user_id, loginedAt } = payload;
const user = await this.usersService.findOneByUserId(user_id);
const tokenLoginedAt = new Date(loginedAt).getTime();
const userLoginedAt = new Date(user.loginedAt).getTime();
if (tokenLoginedAt !== userLoginedAt) {
throw new UnauthorizedException('올바르지 않은 토큰입니다');
}
return { ...user };
}
이후 테이블로 가서 확인해보니 해당 데이터가 입력되었습니다.
하지만 쓸데없는 정보나 보안상 이슈가 될 수 있는 비밀번호 같은 데이터가 들어가 논란이 생길 수 있었습니다.
그래서 기존에 줘야하던 정보(user_id, loginedAt) 이외에 user의 id 값을 넘겨보았습니다.
async validate(payload: any) {
const { user_id, loginedAt } = payload;
const user = await this.usersService.findOneByUserId(user_id);
const tokenLoginedAt = new Date(loginedAt).getTime();
const userLoginedAt = new Date(user.loginedAt).getTime();
if (tokenLoginedAt !== userLoginedAt) {
throw new UnauthorizedException('올바르지 않은 토큰입니다');
}
return { id: user.id, user_id, loginedAt };
}
이후 account를 생성한 뒤 테이블을 확인한 결과, 해당 row에 foreign key가 입력이 된 것을 확인할 수 있었습니다.
회고
Fact(사실)
- 저번 프로젝트에서 비즈니스 로직을 컨트롤러 단에서 처리하였다.
Feeling(느낀점)
- 해당 기능과 관련있는 커스텀 repository를 생성하지 않아 헷갈려서 비즈니스 로직을 컨트롤러 단에서 처리한 점이 아쉬웠다.
Finding(교훈)
- 커스텀 repository를 정의하여 위와 같은 이슈가 발생하지 않도록 해야 겠다.
Future action(향후 계획)
- 비즈니스 로직은 서비스 단에서 처리한다.
- 트랜잭션을 사용하는 기능은 서비스 단에서 처리한다.
- 도메인별 커스텀 repository를 정의한다.
Feedback(피드백)
- 컨트롤러에서는 외부 요청과 응답에 대한 부분을 담당한다.
- 서비스에서는 비즈니스 로직을 처리한다.
- repository에서는 DB를 통해 데이터를 가져오거나 처리한다.
Comments