ChatGPT와의 대화
getPostInfo를 QueryBuilder 기반으로 만들고, 여러 postId를 한 번에 넘겨서 IN (...)으로 조회하는 방식은 "모듈화"와 "성능"을 모두 잡는 절충안이에요. 왜냐하면:
✅ 장점 요약
async getPostInfos(postIds: number[]): Promise<{
postId: number;
postDatetime: Date;
decoCard: string;
enterComp: string;
groupName: string;
memberName: string;
collectionName: string;
nickname: string;
likeCount: number;
}[]> {
if (postIds.length === 0) return [];
const result = await this.dataSource.query(`
SELECT
p.id AS postId,
p.postDatetime,
dc.decoCard,
a.entertainmentCompany AS enterComp,
a.groupName,
pc.memberName,
pc.collectionName,
u.nickname,
COUNT(l2.post_id) AS likeCount
FROM post p
INNER JOIN user u ON p.userId = u.id
INNER JOIN deco_card dc ON dc.postId = p.id
INNER JOIN photo_card pc ON dc.photoCardId = pc.id
INNER JOIN artist a ON pc.photoCard = a.photoCard
LEFT JOIN likes l2 ON l2.post_id = p.id
WHERE p.id IN (${postIds.map(() => '?').join(',')})
GROUP BY p.id, p.postDatetime, dc.decoCard, a.entertainmentCompany, a.groupName, pc.memberName, pc.collectionName, u.nickname
`, postIds);
return result.map((row) => ({
postId: row.postId,
postDatetime: row.postDatetime,
decoCard: row.decoCard,
enterComp: row.enterComp,
groupName: row.groupName,
memberName: row.memberName,
collectionName: row.collectionName,
nickname: row.nickname,
likeCount: Number(row.likeCount),
}));
}
async getPostsLiked(userId: number, sort: 'oldest' | 'newest' | 'most_liked' | 'least_liked' = 'newest') {
const user = await this.usersRepository.findOne({ where: { id: userId } });
if (!user) {
throw new Error('사용자를 찾을 수 없습니다.');
}
let orderBy = '';
switch (sort) {
case 'oldest':
orderBy = 'p.postDatetime ASC';
break;
case 'newest':
orderBy = 'p.postDatetime DESC';
break;
case 'most_liked':
orderBy = 'likeCount DESC';
break;
case 'least_liked':
orderBy = 'likeCount ASC';
break;
}
const postIdRows = await this.dataSource.query(`
SELECT p.id AS postId
FROM post p
INNER JOIN likes l ON l.post_id = p.id
WHERE l.user_id = ?
ORDER BY ${orderBy.replace('likeCount', '(SELECT COUNT(*) FROM likes WHERE post_id = p.id)')}
LIMIT 5
`, [userId]);
const postIds = postIdRows.map((row) => row.postId);
const postInfos = await this.getPostInfos(postIds);
// 정렬 기준이 likeCount 관련이면 JS에서 정렬 한 번 더 확인
if (sort === 'most_liked') {
postInfos.sort((a, b) => b.likeCount - a.likeCount);
} else if (sort === 'least_liked') {
postInfos.sort((a, b) => a.likeCount - b.likeCount);
}
return {
'like-list': postInfos,
};
}
if (sort === 'most_liked') {
postInfos.sort((a, b) => b.likeCount - a.likeCount);
} else if (sort === 'least_liked') {
postInfos.sort((a, b) => a.likeCount - b.likeCount);
}
| 구문 | 의미 | 결과 |
|---|---|---|
| a.likeCount - b.likeCount | a가 b보다 좋아요가 적으면 음수, 같으면 0, 많으면 양수 | 오름차순 정렬 |
| b.likeCount - a.likeCount | 반대로 계산 | 내림차순 정렬 |
postInfos.sort((a, b) => b.likeCount - a.likeCount);
좋아요 수가 큰 것부터 작은 순으로 정렬
즉, 좋아요 많이 받은 포스트가 위에 옴
🧪 예:
[{ id: 1, likeCount: 10 }, { id: 2, likeCount: 5 }]
postInfos.sort((a, b) => a.likeCount - b.likeCount);
좋아요 수가 작은 것부터 큰 순으로 정렬
즉, 좋아요 적게 받은 포스트가 위에 옴
🧪 예:
[{ id: 2, likeCount: 5 }, { id: 1, likeCount: 10 }]
getPostsLiked(userId, sort)
│
├── DB에서 user가 좋아요 누른 postId 목록만 가져옴 (LIMIT 5)
│
├── postIds → getPostInfos(postIds) 호출
│ └─> DB에서 post 정보 + like 수 한 번에 조회
│
└── 결과를 정렬 후 프론트로 반환
const postIdRows: { postId: number }[] = await this.dataSource.query(`
SELECT p.id AS postId
FROM post p
INNER JOIN likes l ON l.post_id = p.id
WHERE l.user_id = ?
ORDER BY ${orderBy}
LIMIT 5
`, [userId]);
예: 무한 스크롤 초기 5개 불러오기
먼저 5개만 가져오고, 그 이후는 다음 페이지에서 추가 요청 (페이징) 하는 구조가 일반적이에요
우리 프로젝트의 경우 무한스크롤을 적용할 것이므로,
offset 기반 무한 스크롤을 구현하고자 한다.
OFFSET 방식: 페이지당 개수(limit)와 현재 페이지(offset)를 기준으로 슬라이싱
무한 스크롤 방식(offset/limit) 적용은 다음 포스트에 이어서...
+) 추가
postInfos를 다른 함수에서 사용할 때 타입을 알려주는 코드
