query
값을 주지 않으면 400 ERROR가 발생하게 했음.기존 API를 유지하되, 페이징 관련 변수는 Optional로 주고
값이 안들어오는 경우는 전체를 내려주자!
기존 응답 스케마
export const EventPageResponseScheme = {
maxPage: z.number(),
totalEvent: z.number(),
event: z.object(EventResponseScheme),
};
maxPage
와 totalEvent
에 대한 정보가 필요 없다고 한다.그냥 페이징 없었던 때 처럼
Event[]
형태로 내려주는게 낫다!
기존에 있던EventResponseScheme
을 사용함.
(여기서는event: z.object(EventResponseScheme)
하나만들어간 형태)
원래 /events
는 전체 이벤트 내려주는 형태이고
/events-by-page
를 새로만들어 페이징 적용 후 내려주는 형태였는데
위의 1.1의 이슈로 페이징 적용 API를 /events
로 바꾸고,
기존에 전체 다 내려주는 API는 /event-old
로 바꿈!
/events
-> `/event-old/events
1.2 이슈에 따라 응답하는 형태도 Event[]
로 통일함
routes/events/getEventsbyPage.ts
export default defineRoute('get', '/events', schema, async (req, res) => {
const {userId} = req;
const {pageNum, pageSize} = req.query;
const eventInformation = await EventService.getEventsbyPage(userId, pageNum, pageSize); // 페이징 적용
return res.json(await Promise.all(eventInformation.map(e => e.toResponse(userId))));
});
query: {
pageNum: stringAsInt.optional(),
pageSize:stringAsInt.optional()
},
response: [EventResponseScheme]
export const EventResponseScheme = {
id: z.number(),
userId: z.number(),
nickname: z.string(),
profileImage: z.string().optional().nullable(),
title: z.string(),
host: z.string().optional().nullable(),
category: z.string(),
target: z.string(),
startAt: z.date(),
endAt: z.date().optional().nullable(),
contact: z.string().optional().nullable(),
location: z.string().optional().nullable(),
body: z.string(),
imageUuid: z.string().optional().nullable(),
imageUrl: z.string().optional().nullable(),
createdAt: z.date(),
/**
* 추가 속성.
*/
wroteByMe: z.boolean().optional().nullable(),
likedByMe: z.boolean().optional(),
notificationSetByMe: z.boolean().optional().nullable(),
notificationSetFor: z.string().optional().nullable(),
comments: z.number(),
views: z.number(),
likes: z.number(),
notifications: z.number(),
}
// 페이지 별로 이벤트 가져옴 NEW
async getEventsbyPage(userId?: number, pageNum?:number, pageSize?:number ): Promise<Event[]> {
if(pageNum == undefined || pageSize == undefined) { // 하나라도 비어있으면
pageNum = 0;
pageSize = 0; // 전체 가져오는걸로!
}
if (userId == null){ // 로그인 X.
return await this.getEventsRegardlessBlockingsbyPage(pageNum, pageSize); // 비회원은 전부
}else{ // 로그인 한 사용자.
return await this.getEventsWithoutBlockedUserbyPage(userId, pageNum, pageSize); // 로그인 한 사람은 blocking user 빼고
}
}
회원 비회원 여부 적용완료.
페이징 관련 변수가 들어오지 않는 경우 디폴트로 0을 주어, 전체를 내려주도록 함.
페이징 변수를 0을 만들어 무조건 함수에 넘겨주도록 함으로써,
2개 만드는 대신에 하나로 통일
private async getEventsRegardlessBlockingsbyPage(pageNum:number, pageSize:number): Promise<Event[]> {
return await Event.find(
{order: {id: 'DESC'},
skip: pageSize * pageNum, // 여기 추가됨!
take: pageSize,}); // 추가됨!
}
find
사용함 (간단한 경우)id
값 역순으로 가져온다.offset
(= pageSize * pageNum) 부터 시작해서pageSize
사이즈 만큼!pageSize = 0
이면 그냥 전체 가져오더라!QueryBuilder
사용함 (복잡한 경우)take(pageSize)
와 skip(pageSize * pageNum)
을 추가해주었다. // 차단된 사용자 제외하고 페이지 별로 내려주기 NEW
private async getEventsWithoutBlockedUserbyPage(requestorId: number, pageNum:number, pageSize:number ): Promise<Event[]> {
return await Event.createQueryBuilder('event')
/** relations 필드 가져오는 부분 */
.leftJoinAndSelect('event.user', 'user')
.leftJoinAndSelect('event.comments', 'comments')
.leftJoinAndSelect('event.likes', 'likes')
.leftJoinAndSelect('event.notifications', 'notifications')
/** where 절을 위한 join(select는 안 함) */
.leftJoin('event.user', 'event_composer')
.where(`event_composer.id NOT IN (
SELECT blocked_user_id
FROM block
WHERE block.blocking_user_id = :requestorId
)`, {requestorId})
.take(pageSize)
.skip(pageSize * pageNum) // 페이징 적용
.orderBy('event.id', 'DESC')
.getMany();
}
같은 방법으로 다른 라우터에도 모두 페이징 적용을 해 주었다!!