← 개발 로그 목록

my-blog: 블로그 포스트 페이징 및 API 시퀀스 다이어그램 추가

/ 8분 분량 / 개발 로그

이번 커밋은 블로그 포스트 목록에 페이징 기능을 추가하고, API 호출 흐름을 시각화하기 위한 시퀀스 다이어그램을 문서화했습니다.

my-blog: 블로그 포스트 페이징 및 API 시퀀스 다이어그램 추가

이번 커밋은 블로그 포스트 목록에 페이징 기능을 추가하고, API 호출 흐름을 시각화하기 위한 시퀀스 다이어그램을 문서화했습니다.

요약

이번 커밋에서는 블로그 포스트 목록에 페이징 기능을 구현하여 사용자 경험을 개선하고, API의 작동 방식을 명확히 이해할 수 있도록 상세한 시퀀스 다이어그램을 문서에 추가했습니다. SEQUENCE_DIAGRAMS.md 파일이 새로 생성되었고, 백엔드 postService.js와 postController.js 파일에서 페이징 관련 로직이 추가되었습니다. 총 698라인이 추가되었으며 23라인이 삭제되었습니다.

배경 및 목적

기존 블로그는 모든 포스트를 한 번에 불러와서 표시했습니다. 포스트 수가 많아질수록 초기 로딩 시간이 길어지고 성능 문제가 발생할 가능성이 있었습니다. 이를 해결하기 위해 페이징 기능을 도입하여 한 번에 표시되는 포스트 수를 제한하고, 사용자가 페이지를 넘겨가며 콘텐츠를 탐색할 수 있도록 개선하고자 했습니다.

또한, 프로젝트의 API 호출 흐름을 명확하게 파악하고 공유하는 것이 중요하다고 판단했습니다. 특히, 여러 서비스와 DB가 연동되는 복잡한 API 요청들을 시각적으로 이해하기 쉽게 설명하기 위해 시퀀스 다이어그램을 작성하게 되었습니다.

구현 내용

주요 변경사항 상세 설명

  • 블로그 포스트 페이징 구현: backend/services/postService.js 파일에 getPostsPaginated 함수를 추가했습니다. 이 함수는 페이지 번호와 제한 개수를 인자로 받아 해당 페이지의 포스트 목록과 총 페이지 수를 계산하여 반환합니다. backend/controllers/postController.js 파일에서는 /api/posts 엔드포인트에 쿼리 파라미터 page와 limit가 존재할 경우 getPostsPaginated 함수를 사용하도록 로직을 수정했습니다. 기본적으로 페이지당 10개의 포스트를 불러오며, 최대 100개까지 제한합니다.
  • API 시퀀스 다이어그램 문서화: SEQUENCE_DIAGRAMS.md 파일을 새로 생성하고, 사용자 요청부터 API 서버, DB까지 각 컴포넌트 간의 상호작용을 시각적으로 표현하는 Mermaid 시퀀스 다이어그램을 작성했습니다. 홈 페이지 방문, 블로그 목록 조회, 글 상세 조회, 로그인, 글 작성, 글 수정, 글 삭제, 프로젝트 목록 조회, 프로젝트 상세 조회, 프로젝트 추가, 프로젝트 수정, 프로젝트 삭제 등 주요 API 흐름에 대한 다이어그램이 포함되었습니다. 각 다이어그램은 참여자, 요청, 응답, 주요 로직 등을 상세하게 설명합니다.

변경된 파일 목록

  • SEQUENCE_DIAGRAMS.md (신규 추가)
  • backend/controllers/postController.js
  • backend/services/postService.js
  • frontend/src/pages/blog.astro (추정: 페이징 UI 관련 변경이 있을 수 있으나, 제공된 diff에서는 직접적인 변경사항이 확인되지 않음)

추가/삭제된 코드 라인 수

  • 추가 라인: 698
  • 삭제 라인: 23

핵심 코드 설명

backend/services/postService.js의 getPostsPaginated 함수:

export const getPostsPaginated = async (page, limit) => {
  try {
    const offset = (page - 1) * limit;
    const [rowsResult, countResult] = await Promise.all([
      pool.query(
        'SELECT * FROM posts ORDER BY date DESC, id DESC LIMIT 2',
        [limit, offset]
      ),
      pool.query('SELECT COUNT(*) FROM posts'),
    ]);
    const total = parseInt(countResult.rows[0].count, 10);
    return {
      posts: rowsResult.rows,
      total,
      page,
      totalPages: Math.ceil(total / limit),
    };
  } catch (error) {
    console.error('Error in getPostsPaginated service:', error);
    throw error;
  }
};

이 코드는 Promise.all을 사용하여 DB에서 포스트 목록과 전체 포스트 수를 비동기적으로 가져옵니다. LIMIT와 OFFSET 절을 사용하여 요청된 페이지에 맞는 데이터만 선택합니다.

backend/controllers/postController.js의 getPosts 함수 수정:

export const getPosts = async (req, res) => {
  try {
    if (req.query.page !== undefined) {
      const page = Math.max(1, parseInt(req.query.page, 10) || 1);
      const limit = Math.min(100, parseInt(req.query.limit, 10) || 10);
      const result = await getPostsPaginated(page, limit);
      res.json(result);
    } else {
      const posts = await getAllPosts();
      res.json(posts);
    }
  } catch (error) {
    console.error('Error fetching posts:', error);
    res.status(500).json({ error: 'Failed to fetch posts' });
  }
};

이 컨트롤러 함수는 req.query.page 존재 여부에 따라 기존의 getAllPosts 함수 또는 새로 추가된 getPostsPaginated 함수를 호출하도록 변경되었습니다. 페이지와 제한 값을 안전하게 파싱하여 전달합니다.

배운 점 및 개선점

이번 작업을 통해 백엔드 API에 페이징 기능을 추가하는 방법을 학습했습니다. 특히 Promise.all을 사용하여 여러 DB 쿼리를 병렬로 처리하는 효율성을 경험했습니다. 또한, 복잡한 시스템의 흐름을 명확하게 문서화하는 것의 중요성을 다시 한번 느꼈습니다. 시퀀스 다이어그램은 개발자 간의 소통을 원활하게 하고, 새로운 참여자가 프로젝트를 이해하는 데 큰 도움을 줄 것이라고 생각합니다.

아직 프론트엔드에서는 이 페이징 기능을 활용하는 UI 컴포넌트나 로직이 추가되지 않았습니다. 추후 frontend/src/pages/blog.astro 파일에서 페이징 네비게이션 버튼과 페이지 변경 시 API 요청을 처리하는 로직을 구현해야 합니다. 또한, 각 API 엔드포인트에 대한 더 많은 예외 처리 및 유효성 검사 로직을 추가할 필요가 있습니다.

참고 자료