refactor: 코드 정리 및 버그 수정
- AlbumGallery.jsx: useEffect 의존성 버그 수정 (id→name) - AlbumGallery.jsx: 미사용 useMemo import 제거 - albums.js: 중복 코드를 getAlbumDetails 헬퍼 함수로 추출 - albums.js: 163줄 → 115줄 (48줄 감소)
This commit is contained in:
parent
3339b281c7
commit
ae898d01ad
2 changed files with 56 additions and 100 deletions
|
|
@ -3,10 +3,59 @@ import pool from "../lib/db.js";
|
|||
|
||||
const router = express.Router();
|
||||
|
||||
// 앨범 상세 정보 조회 헬퍼 함수 (트랙, 티저, 컨셉포토 포함)
|
||||
async function getAlbumDetails(album) {
|
||||
// 트랙 정보 조회 (가사 포함)
|
||||
const [tracks] = await pool.query(
|
||||
"SELECT * FROM tracks WHERE album_id = ? ORDER BY track_number",
|
||||
[album.id]
|
||||
);
|
||||
album.tracks = tracks;
|
||||
|
||||
// 티저 이미지 조회
|
||||
const [teasers] = await pool.query(
|
||||
"SELECT image_url FROM album_teasers WHERE album_id = ? ORDER BY sort_order",
|
||||
[album.id]
|
||||
);
|
||||
album.teasers = teasers.map((t) => t.image_url);
|
||||
|
||||
// 컨셉 포토 조회 (멤버 정보 포함)
|
||||
const [photos] = await pool.query(
|
||||
`SELECT
|
||||
p.id, p.photo_url, p.photo_type, p.concept_name, p.sort_order,
|
||||
GROUP_CONCAT(m.name ORDER BY m.id SEPARATOR ', ') as members
|
||||
FROM album_photos p
|
||||
LEFT JOIN album_photo_members pm ON p.id = pm.photo_id
|
||||
LEFT JOIN members m ON pm.member_id = m.id
|
||||
WHERE p.album_id = ?
|
||||
GROUP BY p.id
|
||||
ORDER BY p.sort_order`,
|
||||
[album.id]
|
||||
);
|
||||
|
||||
// 컨셉별로 그룹화
|
||||
const conceptPhotos = {};
|
||||
for (const photo of photos) {
|
||||
const concept = photo.concept_name || "Default";
|
||||
if (!conceptPhotos[concept]) {
|
||||
conceptPhotos[concept] = [];
|
||||
}
|
||||
conceptPhotos[concept].push({
|
||||
id: photo.id,
|
||||
url: photo.photo_url,
|
||||
type: photo.photo_type,
|
||||
members: photo.members,
|
||||
sortOrder: photo.sort_order,
|
||||
});
|
||||
}
|
||||
album.conceptPhotos = conceptPhotos;
|
||||
|
||||
return album;
|
||||
}
|
||||
|
||||
// 전체 앨범 조회 (트랙 포함)
|
||||
router.get("/", async (req, res) => {
|
||||
try {
|
||||
// 앨범 목록 조회
|
||||
const [albums] = await pool.query(
|
||||
"SELECT id, title, album_type, album_type_short, release_date, cover_url FROM albums ORDER BY release_date DESC"
|
||||
);
|
||||
|
|
@ -27,10 +76,9 @@ router.get("/", async (req, res) => {
|
|||
}
|
||||
});
|
||||
|
||||
// 앨범명(slug)으로 조회
|
||||
// 앨범명으로 조회
|
||||
router.get("/by-name/:name", async (req, res) => {
|
||||
try {
|
||||
// URL 디코딩된 앨범명으로 조회
|
||||
const albumName = decodeURIComponent(req.params.name);
|
||||
const [albums] = await pool.query("SELECT * FROM albums WHERE title = ?", [
|
||||
albumName,
|
||||
|
|
@ -40,53 +88,7 @@ router.get("/by-name/:name", async (req, res) => {
|
|||
return res.status(404).json({ error: "앨범을 찾을 수 없습니다." });
|
||||
}
|
||||
|
||||
const album = albums[0];
|
||||
|
||||
// 트랙 정보 조회 (가사 포함)
|
||||
const [tracks] = await pool.query(
|
||||
"SELECT * FROM tracks WHERE album_id = ? ORDER BY track_number",
|
||||
[album.id]
|
||||
);
|
||||
album.tracks = tracks;
|
||||
|
||||
// 티저 이미지 조회
|
||||
const [teasers] = await pool.query(
|
||||
"SELECT image_url FROM album_teasers WHERE album_id = ? ORDER BY sort_order",
|
||||
[album.id]
|
||||
);
|
||||
album.teasers = teasers.map((t) => t.image_url);
|
||||
|
||||
// 컨셉 포토 조회 (멤버 정보 포함)
|
||||
const [photos] = await pool.query(
|
||||
`SELECT
|
||||
p.id, p.photo_url, p.photo_type, p.concept_name, p.sort_order,
|
||||
GROUP_CONCAT(m.name ORDER BY m.id SEPARATOR ', ') as members
|
||||
FROM album_photos p
|
||||
LEFT JOIN album_photo_members pm ON p.id = pm.photo_id
|
||||
LEFT JOIN members m ON pm.member_id = m.id
|
||||
WHERE p.album_id = ?
|
||||
GROUP BY p.id
|
||||
ORDER BY p.sort_order`,
|
||||
[album.id]
|
||||
);
|
||||
|
||||
// 컨셉별로 그룹화
|
||||
const conceptPhotos = {};
|
||||
for (const photo of photos) {
|
||||
const concept = photo.concept_name || "Default";
|
||||
if (!conceptPhotos[concept]) {
|
||||
conceptPhotos[concept] = [];
|
||||
}
|
||||
conceptPhotos[concept].push({
|
||||
id: photo.id,
|
||||
url: photo.photo_url,
|
||||
type: photo.photo_type,
|
||||
members: photo.members,
|
||||
sortOrder: photo.sort_order,
|
||||
});
|
||||
}
|
||||
album.conceptPhotos = conceptPhotos;
|
||||
|
||||
const album = await getAlbumDetails(albums[0]);
|
||||
res.json(album);
|
||||
} catch (error) {
|
||||
console.error("앨범 조회 오류:", error);
|
||||
|
|
@ -94,7 +96,7 @@ router.get("/by-name/:name", async (req, res) => {
|
|||
}
|
||||
});
|
||||
|
||||
// 특정 앨범 조회 (트랙 및 상세 정보 포함)
|
||||
// ID로 앨범 조회
|
||||
router.get("/:id", async (req, res) => {
|
||||
try {
|
||||
const [albums] = await pool.query("SELECT * FROM albums WHERE id = ?", [
|
||||
|
|
@ -105,53 +107,7 @@ router.get("/:id", async (req, res) => {
|
|||
return res.status(404).json({ error: "앨범을 찾을 수 없습니다." });
|
||||
}
|
||||
|
||||
const album = albums[0];
|
||||
|
||||
// 트랙 정보 조회 (가사 포함)
|
||||
const [tracks] = await pool.query(
|
||||
"SELECT * FROM tracks WHERE album_id = ? ORDER BY track_number",
|
||||
[album.id]
|
||||
);
|
||||
album.tracks = tracks;
|
||||
|
||||
// 티저 이미지 조회
|
||||
const [teasers] = await pool.query(
|
||||
"SELECT image_url FROM album_teasers WHERE album_id = ? ORDER BY sort_order",
|
||||
[album.id]
|
||||
);
|
||||
album.teasers = teasers.map((t) => t.image_url);
|
||||
|
||||
// 컨셉 포토 조회 (멤버 정보 포함)
|
||||
const [photos] = await pool.query(
|
||||
`SELECT
|
||||
p.id, p.photo_url, p.photo_type, p.concept_name, p.sort_order,
|
||||
GROUP_CONCAT(m.name ORDER BY m.id SEPARATOR ', ') as members
|
||||
FROM album_photos p
|
||||
LEFT JOIN album_photo_members pm ON p.id = pm.photo_id
|
||||
LEFT JOIN members m ON pm.member_id = m.id
|
||||
WHERE p.album_id = ?
|
||||
GROUP BY p.id
|
||||
ORDER BY p.sort_order`,
|
||||
[album.id]
|
||||
);
|
||||
|
||||
// 컨셉별로 그룹화
|
||||
const conceptPhotos = {};
|
||||
for (const photo of photos) {
|
||||
const concept = photo.concept_name || "Default";
|
||||
if (!conceptPhotos[concept]) {
|
||||
conceptPhotos[concept] = [];
|
||||
}
|
||||
conceptPhotos[concept].push({
|
||||
id: photo.id,
|
||||
url: photo.photo_url,
|
||||
type: photo.photo_type,
|
||||
members: photo.members,
|
||||
sortOrder: photo.sort_order,
|
||||
});
|
||||
}
|
||||
album.conceptPhotos = conceptPhotos;
|
||||
|
||||
const album = await getAlbumDetails(albums[0]);
|
||||
res.json(album);
|
||||
} catch (error) {
|
||||
console.error("앨범 조회 오류:", error);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useState, useEffect, useCallback, useMemo } from 'react';
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { X, ChevronLeft, ChevronRight, Download } from 'lucide-react';
|
||||
|
|
@ -72,7 +72,7 @@ function AlbumGallery() {
|
|||
console.error('앨범 데이터 로드 오류:', error);
|
||||
setLoading(false);
|
||||
});
|
||||
}, [id]);
|
||||
}, [name]);
|
||||
|
||||
// 라이트박스 열기
|
||||
const openLightbox = (index) => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue