From 3a8499b7af7edb6f1085bf56262f7b12f5f5274c Mon Sep 17 00:00:00 2001 From: OhDongI Date: Tue, 11 Feb 2025 17:17:04 +0900 Subject: [PATCH 1/7] =?UTF-8?q?FIX:=20=EB=8C=93=EA=B8=80=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/services/comment.service.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/services/comment.service.js b/src/services/comment.service.js index ef9f504..02734a6 100644 --- a/src/services/comment.service.js +++ b/src/services/comment.service.js @@ -17,10 +17,6 @@ try { const momentExists = await prisma.moment.findUnique({ where: { id: data.momentId }, }); - - if (!data.userId) { - throw new Error("userId가 요청되지 않았습니다."); - } if (!momentExists) { throw new momentIdNotFoundError(data); } From abe492ba616e714c3fa6d19dfd69e0197adbc6b3 Mon Sep 17 00:00:00 2001 From: OhDongI Date: Tue, 11 Feb 2025 17:22:20 +0900 Subject: [PATCH 2/7] =?UTF-8?q?FIX:=20=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/errors.js | 5 ++--- src/services/like.service.js | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/errors.js b/src/errors.js index 0161e5b..c3ea36e 100644 --- a/src/errors.js +++ b/src/errors.js @@ -184,13 +184,12 @@ export class LikeIdMissingError extends Error { } } -//entityId, entityType 또는 userId가 누락 -export class ValidationError extends Error{ +export class EntityValidationError extends Error{ errorCode = "L005"; statusCode = 400; // Bad Request constructor(data) { - const reason = 'entityId, entityType 또는 userId가 누락되었습니다.'; + const reason = 'entityId 또는 entityType가가 누락되었습니다.'; super(reason); this.reason = reason; this.data = data; diff --git a/src/services/like.service.js b/src/services/like.service.js index ac6b1e7..615c660 100644 --- a/src/services/like.service.js +++ b/src/services/like.service.js @@ -1,5 +1,5 @@ import { - ValidationError, + EntityValidationError, DuplicateLikeMomentError, momentIdNotFoundError, LikeIdNotExistError, @@ -24,8 +24,8 @@ const handleDatabaseError = (error, message) => { export const likeMoment = async (data) => { try { // 입력값 검증 - if (!data.entityId || !data.entityType || !data.userId) { - throw new ValidationError(data); + if (!data.entityId || !data.entityType ) { + throw new EntityValidationError(data); } // 게시글 존재 여부 확인 From c143a0bf774bdca0af26b3f270c1a1852b1b9d33 Mon Sep 17 00:00:00 2001 From: OhDongI Date: Thu, 13 Feb 2025 23:04:16 +0900 Subject: [PATCH 3/7] =?UTF-8?q?Refactor:=20=EC=A2=8B=EC=95=84=EC=9A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20request=20body?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/like.controller.js | 2 -- src/dtos/like.dto.js | 3 +-- src/repositories/like.repository.js | 3 +-- src/services/like.service.js | 1 - 4 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/controllers/like.controller.js b/src/controllers/like.controller.js index d7fc9ac..130fb21 100644 --- a/src/controllers/like.controller.js +++ b/src/controllers/like.controller.js @@ -29,7 +29,6 @@ export const handleLikeMoment = async (req, res, next) => { type: "object", properties: { id: { type: "integer", description: "Moment ID" }, - userId: { type: "integer", description: "Moment 작성자 ID" }, entityType: { type: "string", default: "moment", description: "엔터티 유형" } }, required: ["id", "userId"] @@ -39,7 +38,6 @@ export const handleLikeMoment = async (req, res, next) => { example: { moment: { id: 1, - userId: 1, entityType: "moment" } } diff --git a/src/dtos/like.dto.js b/src/dtos/like.dto.js index d8f5329..da4fc2c 100644 --- a/src/dtos/like.dto.js +++ b/src/dtos/like.dto.js @@ -1,7 +1,6 @@ export const bodyToLike = ({ moment }, userId) => { return { - fromUserId: userId, - userId: moment.userId, + fromUserId: userId, //좋아요 누른 사람 entityId: moment.id, entityType: moment.entityType || "moment", }; diff --git a/src/repositories/like.repository.js b/src/repositories/like.repository.js index a44cbb1..b5206bc 100644 --- a/src/repositories/like.repository.js +++ b/src/repositories/like.repository.js @@ -19,8 +19,7 @@ export const addMomentLike = async (data) => { const newLike = await prisma.like.create({ data: { entityType: data.entityType, - entityId: data.entityId, - user: { connect: { id: data.userId } }, + entityId: data.entityId, fromUser: { connect: { id: data.fromUserId } }, }, }); diff --git a/src/services/like.service.js b/src/services/like.service.js index 615c660..fc22552 100644 --- a/src/services/like.service.js +++ b/src/services/like.service.js @@ -8,7 +8,6 @@ import { DatabaseError, handleServerError } from "../errors.js"; - import { addMomentLike, removeMomentLike } from "../repositories/like.repository.js"; import { prisma } from "../db.config.js"; From c7525f709b6e99e04677077ec075a1d59ea737d0 Mon Sep 17 00:00:00 2001 From: OhDongI Date: Thu, 20 Feb 2025 21:03:27 +0900 Subject: [PATCH 4/7] =?UTF-8?q?Chore:=20=EA=B8=B0=EC=A1=B4=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=EB=A1=9C=20=EB=B3=B5=EA=B5=AC,=EC=98=A4=ED=83=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/like.controller.js | 6 +++--- src/dtos/like.dto.js | 22 +++++++++++----------- src/errors.js | 6 +++--- src/repositories/like.repository.js | 5 +++-- src/services/like.service.js | 11 ++++++----- 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/controllers/like.controller.js b/src/controllers/like.controller.js index e0cf9f0..d5187e6 100644 --- a/src/controllers/like.controller.js +++ b/src/controllers/like.controller.js @@ -29,7 +29,7 @@ export const handleLikeMoment = async (req, res, next) => { type: "object", properties: { id: { type: "integer", description: "Moment ID" }, - userId: { type: "integer", description: "Moment 작성자 ID" }, + userId: { type: "integer", description: "Moment 작성자 ID" }, entityType: { type: "string", default: "moment", description: "엔터티 유형" } }, required: ["id", "userId"] @@ -67,7 +67,7 @@ export const handleLikeMoment = async (req, res, next) => { */ try{ - console.log("Like를 요청했습니다!"); +// console.log("Like를 요청했습니다!"); const like = await likeMoment(bodyToLike(req.body,req.user.id)); res.status(StatusCodes.OK).success(like); } catch (error) { @@ -122,7 +122,7 @@ export const handleDeleteLikeMoment = async (req, res, next) =>{ */ try{ - console.log("Like 삭제를 요청했습니다!"); +// console.log("Like 삭제를 요청했습니다!"); const like = await deleteMomentLike(bodyToDeleteLike(req.body), req.user.id); res.status(StatusCodes.OK).success(like); } catch (error) { diff --git a/src/dtos/like.dto.js b/src/dtos/like.dto.js index 5fcaaab..df7987d 100644 --- a/src/dtos/like.dto.js +++ b/src/dtos/like.dto.js @@ -1,12 +1,12 @@ export const bodyToLike = ({ moment }, userId) => { - return { - fromUserId: userId, - userId: moment.userId, - entityId: moment.id, - entityType: moment.entityType || "moment", - }; - }; - - export const bodyToDeleteLike = ({ like }) => { - return { likeId: like?.likeId }; - }; \ No newline at end of file + return { + fromUserId: userId, + userId: moment.userId, + entityId: moment.id, + entityType: moment.entityType || "moment", + }; + }; + + export const bodyToDeleteLike = ({ like }) => { + return { likeId: like?.likeId }; + }; \ No newline at end of file diff --git a/src/errors.js b/src/errors.js index 440e5b0..69fcf62 100644 --- a/src/errors.js +++ b/src/errors.js @@ -141,7 +141,7 @@ export class DuplicateLikeMomentError extends Error { statusCode = 409; //Conflict constructor(data) { - const reason = '이미 존재하는 좋아요입니다다.'; + const reason = '이미 존재하는 좋아요입니다.'; super(reason); this.reason = reason; this.data = data; @@ -189,7 +189,7 @@ export class EntityValidationError extends Error{ statusCode = 400; // Bad Request constructor(data) { - const reason = 'entityId 또는 entityType가가 누락되었습니다.'; + const reason = 'entityId 또는 entityType가 누락되었습니다.'; super(reason); this.reason = reason; this.data = data; @@ -206,7 +206,7 @@ export class DatabaseError extends Error{ statusCode = 500; // Internal Server Error constructor(data) { - const reason = '데이터베이스 연결에 실패했습니다'; + const reason = '데이터베이스 연결에 실패했습니다.'; super(reason); this.reason = reason; this.data = data; diff --git a/src/repositories/like.repository.js b/src/repositories/like.repository.js index 04d2ac5..a44cbb1 100644 --- a/src/repositories/like.repository.js +++ b/src/repositories/like.repository.js @@ -5,6 +5,7 @@ export const addMomentLike = async (data) => { const existingLike = await prisma.like.findFirst({ where: { fromUserId: data.fromUserId, + userId: data.userId, entityId: data.entityId, entityType: data.entityType, user: { isDeleted: false }, //탈퇴 회원 배제 @@ -18,8 +19,8 @@ export const addMomentLike = async (data) => { const newLike = await prisma.like.create({ data: { entityType: data.entityType, - entityId: data.entityId, - user: { connect: { id: data.userId } }, + entityId: data.entityId, + user: { connect: { id: data.userId } }, fromUser: { connect: { id: data.fromUserId } }, }, }); diff --git a/src/services/like.service.js b/src/services/like.service.js index e415505..ac6b1e7 100644 --- a/src/services/like.service.js +++ b/src/services/like.service.js @@ -1,5 +1,5 @@ import { - EntityValidationError, + ValidationError, DuplicateLikeMomentError, momentIdNotFoundError, LikeIdNotExistError, @@ -8,6 +8,7 @@ import { DatabaseError, handleServerError } from "../errors.js"; + import { addMomentLike, removeMomentLike } from "../repositories/like.repository.js"; import { prisma } from "../db.config.js"; @@ -19,17 +20,17 @@ const handleDatabaseError = (error, message) => { throw new DatabaseError(message, error); }; + export const likeMoment = async (data) => { try { // 입력값 검증 - if (!data.entityId || !data.entityType ) { - throw new EntityValidationError(data); + if (!data.entityId || !data.entityType || !data.userId) { + throw new ValidationError(data); } // 게시글 존재 여부 확인 const momentExists = await prisma.moment.findUnique({ where: { id: data.entityId }, - select: { userId: true } , }); if (!momentExists) { @@ -55,7 +56,7 @@ export const likeMoment = async (data) => { } catch (error) { // 사용자의 잘못된 요청 - if (error instanceof EntityValidationError || + if (error instanceof ValidationError || error instanceof momentIdNotFoundError || error instanceof DuplicateLikeMomentError) { throw error; From 36eac618fcc4e9777c780c6df4dd93bcd226e4f9 Mon Sep 17 00:00:00 2001 From: OhDongI Date: Thu, 20 Feb 2025 21:23:37 +0900 Subject: [PATCH 5/7] =?UTF-8?q?Refactor:=20=EC=98=A4=ED=83=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/comment.controller.js | 6 +++--- src/errors.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/controllers/comment.controller.js b/src/controllers/comment.controller.js index 363f7c0..a458f3d 100644 --- a/src/controllers/comment.controller.js +++ b/src/controllers/comment.controller.js @@ -74,7 +74,7 @@ export const handleAddComment = async (req, res, next) => { */ try{ - console.log("댓글 추가를 요청했습니다!"); +// console.log("댓글 추가를 요청했습니다!"); const commentData = bodyToComment(req.body, req.user.id ,parseInt(req.params.momentId)); const newComment = await addUserComment(commentData); res.status(StatusCodes.OK).success(newComment); @@ -146,7 +146,7 @@ export const handleAddComment = async (req, res, next) => { */ try{ - console.log("댓글 수정 기능 요청했습니다!"); +// console.log("댓글 수정 기능 요청했습니다!"); const momentId = parseInt(req.params.momentId); const commentId = parseInt(req.params.commentId); const editData = bodyToEditComment(req.body, req.user.id, momentId, commentId); @@ -208,7 +208,7 @@ export const handleAddComment = async (req, res, next) => { */ try{ - console.log("댓글 삭제 기능 요청"); +// console.log("댓글 삭제 기능 요청"); const deleteData = bodyToDeleteComment(req.user.id, req.params.commentId); const deleteComment = await deleteUserComment(deleteData); res.status(StatusCodes.OK).success(deleteComment); diff --git a/src/errors.js b/src/errors.js index 3d518e1..2989711 100644 --- a/src/errors.js +++ b/src/errors.js @@ -177,7 +177,7 @@ export class LikeIdMissingError extends Error { statusCode = 400; // Bad Request constructor(data) { - const reason = 'likeId가 요청 데이터에 없습니다'; + const reason = 'likeId가 요청 데이터에 없습니다.'; super(reason); this.reason = reason; this.data = data; @@ -217,7 +217,7 @@ export class momentIdNotFoundError extends Error { statusCode = 404; // Not Found constructor(data) { - const reason = '존재하지 않는 게시글입니다'; + const reason = '존재하지 않는 게시글입니다.'; super(reason); this.reason = reason; this.data = data; From 92084fc18add17150b0deb26db2b2f0204c8e05e Mon Sep 17 00:00:00 2001 From: OhDongI Date: Thu, 20 Feb 2025 21:47:26 +0900 Subject: [PATCH 6/7] =?UTF-8?q?Refactor:=20=ED=95=A8=EC=88=98=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/services/like.service.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/like.service.js b/src/services/like.service.js index ac6b1e7..cd2a1fa 100644 --- a/src/services/like.service.js +++ b/src/services/like.service.js @@ -1,5 +1,5 @@ import { - ValidationError, + EntityValidationError, DuplicateLikeMomentError, momentIdNotFoundError, LikeIdNotExistError, @@ -25,7 +25,7 @@ export const likeMoment = async (data) => { try { // 입력값 검증 if (!data.entityId || !data.entityType || !data.userId) { - throw new ValidationError(data); + throw new EntityValidationError(data); } // 게시글 존재 여부 확인 @@ -56,7 +56,7 @@ export const likeMoment = async (data) => { } catch (error) { // 사용자의 잘못된 요청 - if (error instanceof ValidationError || + if (error instanceof EntityValidationError || error instanceof momentIdNotFoundError || error instanceof DuplicateLikeMomentError) { throw error; From 2d28571ed8d19912de36769eb48c429a169d2ade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9E=AC=EB=AF=BC?= <95125109+javor10@users.noreply.github.com> Date: Fri, 21 Feb 2025 02:38:16 +0900 Subject: [PATCH 7/7] =?UTF-8?q?Feat:=20=EB=8B=A4=EB=A5=B8=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90(=EC=B9=9C=EA=B5=AC=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80)=20momoment=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/moment.controller.js | 85 ++++++++++++-------- src/dtos/moment.dto.js | 61 ++++++++++----- src/index.js | 8 +- src/repositories/moment.repository.js | 107 +++++++++++++------------- src/services/moment.service.js | 59 +++++++++----- 5 files changed, 192 insertions(+), 128 deletions(-) diff --git a/src/controllers/moment.controller.js b/src/controllers/moment.controller.js index 5c063d3..7d915c4 100644 --- a/src/controllers/moment.controller.js +++ b/src/controllers/moment.controller.js @@ -3,16 +3,16 @@ import { bodyToCreateMoment, bodyToUpdateMoment, responseFromMyMomentDetail, - responseFromFriendsMoments, - responseFromFriendMomentDetail } from "../dtos/moment.dto.js"; + responseFromOtherUserMoments, + responseFromOtherUserMomentDetail } from "../dtos/moment.dto.js"; import { momentCreate, momentUpdate, momentDelete, getMyMoments, getMyMomentDetail, - getFriendsMoments, - getFriendMomentDetail } from "../services/moment.service.js"; + getOtherUserMoments, + getOtherUserMomentDetail } from "../services/moment.service.js"; export const handleCreateMoment = async (req, res, next) => { @@ -228,66 +228,83 @@ export const handleGetMyMomentDetail = async (req, res, next) => { } }; +export const handleGetOtherUserMoments = async (req, res, next) => { + try { + // userId 확인: 잘못된 값이 전달되는지 확인 + const userId = Number(req.params.userId); + console.log("Received userId from params:", req.params.userId); // 확인용 로그 추가 + if (isNaN(userId)) { + throw new Error("유효하지 않은 사용자 ID입니다."); + } -export const handleGetFriendsMoments = async (req, res, next) => { - /* - #swagger.tags = ['Moments'] - #swagger.summary = '친구의 Moment 목록 조회 API' - #swagger.description = '친구의 페이지에서 해당 친구의 Moment 게시물 목록을 조회합니다.' - #swagger.security = [{ - "bearerAuth": [] - }] - - */ + // getOtherUserMoments 함수에서 userId 확인 + const responseData = await getOtherUserMoments(userId); - try { - console.log("친구의 Moment 목록 조회 요청"); - const friendId = parseInt(req.params.friendId, 10); - const moments = await getFriendsMoments(friendId); res.status(StatusCodes.OK).json({ resultType: "SUCCESS", error: null, - success: { - data: responseFromFriendsMoments(moments) - } + success: { data: responseData } }); + } catch (error) { + console.error("❌ 특정 사용자의 Moment 목록 조회 오류:", error); next(error); } }; -export const handleGetFriendMomentDetail = async (req, res, next) => { + + + + + + + +export const handleGetOtherUserMomentDetail = async (req, res, next) => { /* #swagger.tags = ['Moments'] - #swagger.summary = '친구의 특정 Moment 상세 조회 API' - #swagger.description = '친구의 페이지에서 특정 Moment 게시물의 상세 정보를 조회합니다.' - #swagger.security = [{ - "bearerAuth": [] - }] + #swagger.summary = '특정 사용자의 특정 Moment 상세 조회 API' + #swagger.description = '특정 사용자의 페이지에서 특정 Moment 게시물의 상세 정보를 조회합니다.' + #swagger.security = [{ "bearerAuth": [] }] + #swagger.parameters['userId'] = { + in: "path", + required: true, + description: "조회할 사용자의 ID", + schema: { type: "integer", example: 1234 } + } #swagger.parameters['momentId'] = { in: "path", required: true, description: "조회할 Moment의 ID", schema: { type: "integer", example: 456 } } - */ try { - console.log("친구의 특정 Moment 상세 조회 요청"); - const friendId = parseInt(req.params.friendId, 10); - const momentId = parseInt(req.params.momentId, 10); - const moment = await getFriendMomentDetail(friendId, momentId); + console.log("특정 사용자의 Moment 목록 조회 요청"); + + const userId = parseInt(req.params.userId, 10); + if (isNaN(userId)) { + throw new Error("유효하지 않은 사용자 ID입니다."); + } + + const moments = await getOtherUserMoments(userId); + + // 🔍 responseFromOtherUserMoments() 변환 결과 확인 + const responseData = responseFromOtherUserMoments(moments); + console.log("Swagger 응답 데이터:", JSON.stringify(responseData, null, 2)); + res.status(StatusCodes.OK).json({ resultType: "SUCCESS", error: null, success: { - data: responseFromFriendMomentDetail(moment) + data: responseData } }); } catch (error) { + console.error("특정 사용자의 Moment 목록 조회 오류:", error); next(error); } -}; \ No newline at end of file +}; + diff --git a/src/dtos/moment.dto.js b/src/dtos/moment.dto.js index 77d001f..13ac790 100644 --- a/src/dtos/moment.dto.js +++ b/src/dtos/moment.dto.js @@ -194,33 +194,56 @@ export const responseFromMyMomentDetail = (moment) => { }; -// 친구의 Moment 목록 조회 DTO -export const responseFromFriendsMoments = (moments) => { - return moments.map(moment => ({ - userId: moment.userId, - momentId: moment.id, - title: moment.title, - status: moment.status, - createdAt: formatDateTime(moment.createdAt), - updatedAt: formatDateTime(moment.updatedAt), - thumbnailUrl: moment.momentContents[0]?.url || null - })); +export const responseFromOtherUserMoments = (moments) => { + if (!Array.isArray(moments)) { + console.error("❌ moments가 배열이 아님:", moments); + return []; + } + + return moments.map(moment => { + if (!moment || typeof moment.id === "undefined") { + console.error("❌ moment.id가 유실됨! 원인 추적 필요:", moment); + return null; + } + + const transformedMoment = { + userId: Number(moment.userId), // ✅ bigint 변환 + momentId: Number(moment.id), // ✅ bigint 변환 + title: moment.title, + date: moment.createdAt ? moment.createdAt.toISOString().split("T")[0] : "날짜 없음", + userName: moment.user?.name ?? "알 수 없음", + likingCount: Number(moment.likingCount ?? 0), + commentCount: Number(moment._count?.comments ?? 0), + thumbnailURL: moment.momentContents?.length > 0 ? moment.momentContents[0].url : null + }; + + return transformedMoment; + }).filter(moment => moment !== null); }; -// 친구의 moment 상세 조회 DTO -export const responseFromFriendMomentDetail = (moment) => { + + + + +// 친구의 Moment 상세 조회 DTO +export const responseFromOtherUserMomentDetail = (moment) => { + if (!moment || !moment.id) { + console.error("잘못된 moment 데이터:", moment); + return null; + } + return { userId: moment.userId, momentId: moment.id, title: moment.title, - status: moment.status, - plannerId: moment.plannerId || null, - createdAt: formatDateTime(moment.createdAt), - updatedAt: formatDateTime(moment.updatedAt), + date: formatDate(moment.createdAt), + plannerId: moment.plannerId ?? null, + createdAt: formatDateTime(moment.createdAt), + updatedAt: formatDateTime(moment.updatedAt), momentContents: moment.momentContents.map(content => ({ sortOrder: content.sortOrder, content: content.content, - url: content.url, + url: content.url ?? null })) }; -}; \ No newline at end of file +}; diff --git a/src/index.js b/src/index.js index 109390e..94ae062 100644 --- a/src/index.js +++ b/src/index.js @@ -187,8 +187,8 @@ import { handleDeleteMoment, handleGetMyMoments, handleGetMyMomentDetail, - handleGetFriendsMoments, - handleGetFriendMomentDetail + handleGetOtherUserMoments, + handleGetOtherUserMomentDetail } from "./controllers/moment.controller.js"; app.post("/moments", authenticateJWT, handleCreateMoment); //모먼트 생성 @@ -196,8 +196,8 @@ app.patch("/moments/:momentId", authenticateJWT, handleUpdateMoment); //모먼 app.delete("/moments/:momentId", authenticateJWT, handleDeleteMoment); //모먼트 삭제 app.get("/mypage/moments", authenticateJWT, handleGetMyMoments); //마이페이지에서 나의 moment게시글 목록 조회 app.get("/mypage/moments/:momentId", authenticateJWT, handleGetMyMomentDetail); //마이페이지에서 나의 특정 moment게시물 조회 -app.get("/friends/:friendId/moments", authenticateJWT, handleGetFriendsMoments) //친구페이지 moment게시물 목록 조회 -app.get("/friends/:friendId/moments/momentId", authenticateJWT, handleGetFriendMomentDetail); //친구페이지 특정 moment게시물 조회 +app.get("/users/:userId/moments", authenticateJWT, handleGetOtherUserMoments) //친구페이지 moment게시물 목록 조회 +app.get("/users/:userId/moments/momentId", authenticateJWT, handleGetOtherUserMomentDetail); //친구페이지 특정 moment게시물 조회 diff --git a/src/repositories/moment.repository.js b/src/repositories/moment.repository.js index 8ca9f3e..28f1c56 100644 --- a/src/repositories/moment.repository.js +++ b/src/repositories/moment.repository.js @@ -203,57 +203,60 @@ export const findMyMomentDetail = async (userId, momentId) => { }; -// 친구들의 Moment 목록 조회 (status: public만 조회) -export const findFriendsMoments = async (userId) => { - // 친구 목록 조회 - const friendIds = await prisma.friend.findMany({ - where: { - fromUserId: BigInt(userId), - isAccepted: true, - }, - select: { - toUserId: true, - }, - }); - - const friendUserIds = friendIds.map(friend => friend.toUserId); - - return await prisma.moment.findMany({ - where: { - userId: { in: friendUserIds }, - status: 'public', - }, - include: { - momentContents: true, - }, - orderBy: { - createdAt: 'desc', - }, - }); +export const findOtherUserMoments = async (userId) => { + try { + + const moments = await prisma.moment.findMany({ + where: { userId: BigInt(userId) }, + include: { + user: { select: { name: true } }, + momentContents: { select: { url: true }, take: 1 }, + _count: { select: { comments: true } } + }, + orderBy: { createdAt: "desc" }, + }); + + for (const moment of moments) { + const likesCount = await prisma.like.count({ + where: { + entityId: Number(moment.id), + entityType: "moment", + }, + }); + moment.likingCount = likesCount; + } + + return moments; + } catch (error) { + console.error("[findOtherUserMoments] DB 조회 오류:", error); + throw new Error("Moment 목록 조회 실패"); + } }; -// 친구의 특정 Moment 상세 조회 (status: public만 조회) -export const findFriendMomentDetail = async (userId, momentId) => { - // 친구인지 확인 - const isFriend = await prisma.friend.findFirst({ - where: { - fromUserId: BigInt(userId), - isAccepted: true, - }, - }); - - if (!isFriend) { - throw new Error("친구가 아닌 사용자입니다."); - } - - return await prisma.moment.findFirst({ - where: { - id: BigInt(momentId), - userId: isFriend.toUserId, - status: 'public', - }, - include: { - momentContents: true, - }, - }); -}; \ No newline at end of file + + + + +// 특정 사용자의 특정 Moment 상세 조회 +export const findOtherUserMomentDetail = async (userId, momentId) => { + try { + console.log(`[findOtherUserMomentDetail] API 호출됨! userId: ${userId}, momentId: ${momentId}`); + + const moment = await prisma.moment.findUnique({ + where: { id: BigInt(momentId) }, + include: { + momentContents: true, + planner: true + } + }); + + if (!moment) { + throw new Error("Moment를 찾을 수 없습니다."); + } + + return moment; + } catch (error) { + console.error("[findOtherUserMomentDetail] DB 조회 오류:", error.message); + throw error; + } +}; diff --git a/src/services/moment.service.js b/src/services/moment.service.js index 1df5ffa..fcf6755 100644 --- a/src/services/moment.service.js +++ b/src/services/moment.service.js @@ -4,8 +4,8 @@ import { deleteMomentFromDB, findMyMoments, findMyMomentDetail, - findFriendsMoments, - findFriendMomentDetail + findOtherUserMoments, + findOtherUserMomentDetail } from "../repositories/moment.repository.js"; import { @@ -13,8 +13,8 @@ import { responseFromUpdateMoment, responseFromMyMoments, responseFromMyMomentDetail, - responseFromFriendsMoments, - responseFromFriendMomentDetail + responseFromOtherUserMoments, + responseFromOtherUserMomentDetail } from "../dtos/moment.dto.js"; import { @@ -177,33 +177,54 @@ export const getMyMomentDetail = async (userId, momentId) => { }; - -export const getFriendsMoments = async (userId) => { +export const getOtherUserMoments = async (userId) => { try { - const friendsMoments = await findFriendsMoments(userId); - - if (!friendsMoments) { - throw new Error("친구의 Moment 목록 조회에 실패했습니다."); + // 인증되지 않은 사용자 처리 + if (!userId) { + throw new UnauthorizedAccessError(); } - return responseFromFriendsMoments(friendsMoments); + const otherUsersMoments = await findOtherUserMoments(userId); + + return responseFromOtherUserMoments(otherUsersMoments); } catch (error) { - console.error("친구의 Moment 목록 조회 중 오류 발생:", error.message); - throw new Error("친구의 Moment 목록 조회에 실패했습니다. 다시 시도해주세요."); + console.error("다른사람의 Moment 목록 조회 중 오류 발생:", error); + + if (error instanceof UnauthorizedAccessError) { + throw error; + } + + // 기타 예상치 못한 오류는 서버 오류로 처리 + throw new MomentServerError(); } }; -export const getFriendMomentDetail = async (userId, momentId) => { + +export const getOtherUserMomentDetail = async (userId, momentId) => { try { - const friendMomentDetail = await findFriendMomentDetail(userId, momentId); + // 유효하지 않은 momentId 체크 + if (isNaN(momentId) || !Number.isInteger(Number(momentId))) { + throw new InvalidMomentIdError(momentId); + } + + const otherUserMomentDetail = await findOtherUserMomentDetail(userId, BigInt(momentId)); - if (!friendMomentDetail) { - throw new Error("친구의 Moment 상세 조회에 실패했습니다."); + // 존재하지 않는 momentId 체크 + if (!otherUserMomentDetail) { + throw new MomentNotFoundError(momentId); } - return responseFromFriendMomentDetail(friendMomentDetail); + return responseFromOtherUserMomentDetail(otherUserMomentDetail); } catch (error) { console.error("친구의 Moment 상세 조회 중 오류 발생:", error.message); - throw new Error("친구의 Moment 상세 조회에 실패했습니다. 다시 시도해주세요."); + + // 존재하지 않는 moment 에러 + if (error instanceof MomentNotFoundError || error instanceof InvalidMomentIdError) { + throw error; + } + + // 기타 예상치 못한 오류는 서버 오류로 처리 + throw new MomentServerError("다른 사용자의의 Moment 상세 조회에 실패했습니다. 다시 시도해주세요.", { error }); } }; +