컬럼 순서를 배열로 저장하기로 했기 때문에 board의 서비스 계층에 다음과 같이 작성하였다.
const columnOrderArray = JSON.parse(updateColumnOrderDto.columnOrder);
if (!Array.isArray(columnOrderArray)) {
throw new BadRequestException('컬럼 순서 저장 오류가 발생했습니다.');
}
const columnIds = await this.columnRepository.find({
where: { id: In(columnOrderArray) }
});
이렇게 하면 텍스트로 받아온 데이터를 배열 형식으로 저장할 수 있으며, 올바른 배열 형식의 텍스트가 아닐 경우 에러를 발생시킨다.
만들다보니 예외처리를 해야 할 부분이 굉장히 많았음...
// ColumnOrder 업데이트
async updateColumnOrder(boardId: number, updateColumnOrderDto: UpdateColumnOrderDto): Promise<Board> {
let board;
try {
board = await this.boardRepository.findOneBy({ id: BigInt(boardId) });
} catch (error) {
throw new BadRequestException('보드 ID가 유효한 숫자 형식이 아닙니다.');
}
if (!board) {
throw new NotFoundException("존재하지 않는 보드입니다.");
}
let columnOrderArray: readonly any[] | FindOperator<any>;
try {
columnOrderArray = JSON.parse(updateColumnOrderDto.columnOrder);
} catch (error) {
throw new BadRequestException('제공된 컬럼 순서가 유효한 JSON 형식이 아닙니다.');
}
if (!Array.isArray(columnOrderArray)) {
throw new BadRequestException('컬럼 순서는 배열이어야 합니다.');
}
let columnIds: any[];
try {
columnIds = await this.columnRepository.find({
where: { id: In(columnOrderArray) }
});
} catch (error) {
throw new BadRequestException('컬럼 ID 조회 중 문제가 발생했습니다.');
}
const validColumnIds = columnIds.map(column => column.id.toString());
const isValidColumnOrder = columnOrderArray.every(id => validColumnIds.includes(id.toString()));
if (!isValidColumnOrder) {
throw new BadRequestException('존재하지 않는 컬럼이 지정되었습니다.');
}
board.columnOrder = JSON.stringify(columnOrderArray);
try {
await this.boardRepository.save(board);
} catch (error) {
throw new BadRequestException('보드 정보 업데이트 중 오류가 발생했습니다.');
}
return board;
}
배열을 저장하는 최종 코드는 이렇게 되었다. 이제 배열을 불러와서 올바른 컬럼 순으로 정렬해주는 방법을 생각해내면 된다.
const orderedQuery = this.columnRepository
.createQueryBuilder('column')
.where('column.boardId = :boardId', { boardId })
.orderBy(`FIELD(column.id, ${columnOrderArray.join(',')})`);
-- 이 부분을 SQL로 풀어 쓰면
SELECT * FROM column
WHERE column.boardId = 1
ORDER BY FIELD(column.id, '4','2','3');
ORDER BY FIELD(column.id, '4','2','3'); 부분이 배열로 저장된 order 데이터로 정렬하는 부분이다.
const columnOrder = await this.findColumnOrder(boardId);
const columns = await this.columnRepository.find({
where: { boardId: boardId },
});
const orderedColumns = columnOrder.map(id => columns.find(column => column.id === id)).filter(column => column !== undefined);
return orderedColumns;
원래 이렇게 map 함수를 사용하는 걸 고려했으나 양이 늘어나면 성능이 저하된다고 하여... 쿼리 빌더로 변경하였다. 그런데 사실 column은 그렇게 많이 생성될 것 같진 않아서 상관없으려나..
알림 기능을 어떻게 구현하면 좋을지 아직도 고민중...