## DTO 유효성 검사 - cardId는 카드 엔티티, content 댓글 엔티티 - 엔티티가 서로 다른 요청 필드에 대해 어떻게 유효성 검사를 하는지? - 어떻게 validateIf를 사용하여야 groups와 같은 효과를 낼 수 있는지? ```javascript= router.post('/:cardId/comment', async (req, res) => { const commentService = CommentService.getInstance(); const userId = req.user.id; const { cardId } = req.params; const { content } = req.body; if (cardId === undefined || !isNumberString(cardId)) { throw new BadRequestError('Wrong params'); } if (content === undefined) { throw new BadRequestError('Empty content'); } const responseBody = await commentService.addComment({ userId, cardId, content }); res.status(201).json(responseBody); }); ``` ```javascript= export class CardDto { id; @ValidateIf((o) => o.title !== undefined) @IsString() @IsNotEmpty() title; @ValidateIf((o) => o.content !== undefined) @IsString() content; @ValidateIf((o) => o.position !== undefined) @IsNumber() position; @ValidateIf((o) => o.dueDate !== undefined) @IsISO8601() dueDate; @ValidateIf((o) => o.listId !== undefined) @IsNumber() listId; } ``` ## After Insert 이벤트를 통한 활동 기록 관리 - 활동기록을 저장하는 로직은 각 보드, 리스트, 카드 서비스와 분리되어야 하는가? ```javascript= @Transactional() async deleteCard({ userId, cardId }) { const card = await this.cardRepository .createQueryBuilder('card') .select('card.list') .innerJoinAndSelect('card.list', 'list') .where('card.id = :cardId', { cardId }) .getRawOne(); if (!card) throw new EntityNotFoundError(); const namespace = getNamespace('localstorage'); namespace?.set('userId', userId); namespace?.set('boardId', card.list_board_id); const boardService = BoardService.getInstance(); await boardService.checkForbidden(userId, card.list_board_id); await this.cardRepository.remove(await this.cardRepository.findOne(cardId)); } ``` ```javascript= async afterRemove(event) { const activityService = ActivityService.getInstance(); const userService = UserService.getInstance(); const namespace = getNamespace('localstorage'); const user = await userService.getUserById(namespace.get('userId')); await activityService.createActivity( namespace.get('boardId'), `${user.name}님이 카드 ${event.databaseEntity.title}을 삭제하였습니다.`, ); } ``` ## Frontend 피드백 - 리스트나 카드의 위치를 숫자를 통해서 옮기는 것은 직관적이지 않음 - 보드 화면에서 메인으로 돌아갈 때 진입점을 확실하게 - 보드 화면 왼쪽 상단에 보드 이름이 있는데, 보드 이름처럼 안 보임 - 오른쪽 사이드바 이름을 활동 기록이라는 직관적인 이름으로 변경 - 확장앱 자체의 기능이 없어서 아쉬움 - 강렬한 배경색을 톤다운하는 것이 좋아 보임 - 확장앱에서 카드 배열을 1열로 - 카드 댓글이 없는 경우 개수를 표시하지 말것 - 콜드 스타터를 위한 UI 진입장벽 개선 - "컬러와 여백"