[URECA] Day 80 LabbitLog 블로그 만들기 #4
댓글 기능, 좋아요 기능, 글 수정 및 상세보기, UX 개선까지 포함된 의미 있는 날🔥
댓글 기능 전반 구현
1. 백엔드: comments 컬렉션 설계
MongoDB에 comments 컬렉션을 새로 만들고, Post와 User를 참조하는 구조로 설계했다.
// models/Comment.js
const commentSchema = new mongoose.Schema({
postId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Post',
required: true
},
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true
},
content: {
type: String,
required: true
},
createdAt: {
type: Date,
default: Date.now
}
});
2. REST API 설계
메서드 | 경로 | 설명 |
POST | /comments | 댓글 작성 |
GET | /comments/:postId | 해당 게시물 댓글 목록 조회 |
PUT | /comments/:commentId | 댓글 수정 |
DELETE | /comments/:commentId | 댓글 삭제 |
3. 프론트엔드 연동
- useEffect로 댓글 리스트 요청
- 댓글 없을 경우 "댓글이 없습니다" 메시지 표시
- 댓글 작성 후 리스트 자동 업데이트
useEffect(() => {
const fetchComments = async () => {
const res = await getComments(postId);
setComments(res);
};
fetchComments();
}, [postId]);
📌 핵심 포인트
postId 기반 조회로, 각 게시글마다 댓글이 독립적으로 연결
좋아요 기능 추가 + Redux 상태 유지
1. 기본 동작 흐름
- 게시글 카드에 좋아요 버튼 표시
- 버튼 클릭 시 좋아요 상태 토글 (toggleLike)
- 좋아요 수 + 사용자 상태 반영
2. Redux Store로 상태 관리
// redux/likesSlice.js
const initialState = {
likedPosts: []
};
export const likesSlice = createSlice({
name: 'likes',
initialState,
reducers: {
toggleLike: (state, action) => {
const postId = action.payload;
if (state.likedPosts.includes(postId)) {
state.likedPosts = state.likedPosts.filter(id => id !== postId);
} else {
state.likedPosts.push(postId);
}
}
}
});
- 앱 전역에서 좋아요 상태를 유지하려고 Redux 도입
- 새로고침 시에도 상태 유지를 위해 로컬스토리지 또는 서버 상태 동기화 고려 중
📌 핵심 포인트
단순 클릭 기능이 아니라 UX와 직접 연결된 부분. Redux 도입으로 상태 관리 일관성을 확보
글 수정 기능 & 상세 보기 페이지 연결
1. 카드 클릭 → 상세 페이지 이동
const handleClick = () => {
navigate(`/posts/${postId}`);
};
- React Router로 카드 클릭 시 postId 기반 URL로 이동
- 상세 페이지에서는 해당 게시글 내용을 useEffect로 불러옴
2. 글 수정하기
- 수정 페이지 진입 시 기존 내용을 input에 세팅
- 수정 완료 시 DB 반영 + 리다이렉션 처리
📌 핵심 포인트
사용자 입장에서 “게시글을 클릭 → 확인 → 수정” 흐름이 자연스러워지도록 설계
✨ UX 개선 사항
회원가입 실패 메시지 표시 오류 해결
- 기존엔 상태 변수를 잘못 관리해서 메시지가 표시되지 않음
- 조건 분기와 상태 초기화를 통해 해결 완료
스크롤 이슈 해결
- 게시글 리스트에서 스크롤이 작동하지 않던 문제
- overflow-y: auto 및 부모 요소의 max-height 설정으로 해결
글 작성 시 DB 반영 버그 수정
- 폼 전송 후 실제로 DB에 저장되지 않던 버그
- onSubmit 내에서 API 호출 누락되어 있었던 부분 수정
🎠회고
이번 작업을 하면서 단순히 기능만 구현하는 데서 그치는 게 아니라, 백엔드 API와 프론트엔드 UI가 어떻게 연결돼야 자연스러운 사용자 경험을 만들 수 있는지에 대해 더 깊이 고민해볼 수 있었다.
특히 댓글 기능이나 좋아요 기능처럼 사용자의 행동이 바로바로 화면에 반영돼야 하는 경우에는, 그냥 동작만 되면 되는 게 아니라 사용자가 보기에도 "오, 잘 작동하네!"라고 느낄 수 있는 피드백이 중요하다는 걸 확실히 느꼈다.
예를 들어, 댓글을 쓴 직후 리스트가 바로 갱신되지 않으면 '내가 제대로 작성한 게 맞나?' 싶은 불안감이 생길 수 있다. 그래서 그런 부분을 개선하기 위해 useEffect와 상태 갱신 로직을 잘 연결했고, 오류가 생겼을 때도 사용자 입장에서 알 수 있도록 메시지를 보여주도록 처리했다. 단순히 데이터를 주고받는 걸 넘어서, 사용자 흐름이 끊기지 않도록 설계하는 게 얼마나 중요한지 깨달았던 시간이었다.
또 하나, 이번에 처음으로 Redux를 적용해보면서 앱 전체 구조를 생각하는 눈도 조금 트인 것 같다. 좋아요 기능처럼 여러 컴포넌트에서 같은 데이터를 공유해야 하는 상황에서, props로 넘기고 관리하던 방식에는 확실히 한계가 있었다. Redux를 도입하고 나서는 전역 상태를 한 곳에서 깔끔하게 관리하면서, 필요한 컴포넌트에서 쉽게 꺼내 쓸 수 있는 흐름이 잡히는 경험을 할 수 있었다.
이 과정에서 Store를 어떻게 구성할지, action과 reducer는 어떤 역할을 하는지, 그리고 상태가 바뀌었을 때 전체 앱이 어떻게 반응하는지를 직접 다뤄보며 전보다 더 구조적인 사고를 할 수 있게 되었다.
정리하자면, 오늘의 작업은 단순히 "댓글 기능 만들었다", "좋아요 기능 완성했다"로 끝나는 날이 아니었다.
사용자 경험을 고려해서 UI를 구성하고, 백엔드와 프론트엔드가 자연스럽게 이어지도록 설계하고, 상태 관리에 대해 고민하며 앱 전체의 흐름을 생각해본 날이었다.
앞으로는 코드를 짤 때 단순히 '작동하냐'보다도,
"사용자는 이걸 보면서 어떤 생각이 들까?"
"이 흐름은 자연스러울까?"
이런 질문들을 더 자주 떠올리는 개발자가 되고 싶다.