Files
frontend/docs/bbs/post-archi.md
T

18 KiB

게시물(Post) 관리 프로그램 아키텍처 문서

개요

이 문서는 게시물(Post) 관리 프로그램의 아키텍처와 소스 흐름에 대한 상세 설명입니다. 게시물 관리 기능은 게시판에 게시물을 등록, 조회, 수정, 삭제하는 기능을 제공하며, 다양한 유형의 게시물(일반, 이미지, 동영상, 공지사항 등)을 지원합니다.

기술 스택

  • 프레임워크: Next.js (App Router)
  • 상태 관리: React Query, Zustand(useMenuStore, useUserStore)
  • UI 컴포넌트: @common/components
  • 테이블 관리: TanStack Table
  • 폼 관리: React Hook Form, Zod
  • API 통신: Axios
  • 파일 업로드: 커스텀 파일 업로더 컴포넌트

디렉토리 구조

frontend/
├── apps/
│   └── cs/
│       ├── app/
│       │   └── (with-base-layout)/
│       │       └── bbs/
│       │           └── (post)/      # 게시물 관련 페이지
│       ├── src/
│       │   ├── entities/
│       │   │   ├── post/
│       │   │   │   ├── api/
│       │   │   │   │   └── post-service.ts       # 게시물 API 호출 함수
│       │   │   │   └── model/
│       │   │   │       └── post-interface.ts     # 게시물 인터페이스 정의
│       │   │   └── posting/
│       │   │       ├── api/
│       │   │       │   └── posting-service.ts    # 게시 관련 API 호출 함수
│       │   │       ├── model/
│       │   │       │   └── posting-interface.ts  # 게시 관련 인터페이스 정의
│       │   │       └── ui/
│       │   │           └── posting-dialog.tsx    # 게시 관련 다이얼로그 컴포넌트
│       │   ├── pages/
│       │   │   └── (post)/
│       │   │       ├── image/
│       │   │       │   └── ui/
│       │   │       │       └── image-post.tsx    # 이미지 게시물 컴포넌트
│       │   │       ├── movie/
│       │   │       │   └── ui/
│       │   │       │       └── movie-post.tsx    # 동영상 게시물 컴포넌트
│       │   │       ├── normal/
│       │   │       │   └── ui/
│       │   │       │       └── normal-post.tsx   # 일반 게시물 컴포넌트
│       │   │       └── notice/
│       │   │           └── ui/
│       │   │               └── notice-post.tsx   # 공지사항 게시물 컴포넌트
│       │   └── widgets/
│       │       └── post/
│       │           ├── model/
│       │           │   ├── post-table-columns.tsx      # 게시물 테이블 컬럼 정의
│       │           │   └── grid-view-table-columns.tsx # 그리드 뷰 테이블 컬럼 정의
│       │           └── ui/
│       │               ├── post-action.tsx             # 게시물 액션 컴포넌트
│       │               ├── post-comment.tsx            # 게시물 댓글 컴포넌트
│       │               ├── post-form.tsx               # 게시물 등록/수정 폼
│       │               ├── post-page.tsx               # 게시물 목록 페이지
│       │               ├── post.tsx                    # 게시물 상세 컴포넌트
│       │               └── posting-period-selector.tsx # 게시 기간 선택기

데이터 모델

게시물(Post) 인터페이스

export interface Post {
  rowNo: number;          // 행 번호
  bbsId: number;          // 게시판 ID
  pstNo: number;          // 게시물 번호
  pstTtl: string;         // 게시물 제목
  pstCn: string;          // 게시물 내용
  inqNocs: number;        // 조회수
  rfrncUrl: string;       // 참조 URL
  popupYn: string;        // 팝업 여부
  upndFixYn: string;      // 상단 고정 여부
  prdPstgYn: string;      // 기간 게시 여부
  rootPath: string;       // 루트 경로
  pstPath: string;        // 게시물 경로
  ansPstn: number;        // 답변 위치
  wrtrNm: string;         // 작성자명
  wrtrCplc: string;       // 작성자 소속
  atflCd: string;         // 첨부파일 코드
  regDt: string;          // 등록일시
  rgtrNm: string;         // 등록자명
  cmntCnt: number;        // 댓글 수
}

게시물 상세 정보(PostInfo) 인터페이스

export interface PostInfo extends Post {
  pstCn: string;          // 게시물 내용
  rgtr: string;           // 등록자
  mdfcnDt: string;        // 수정일시
  mdfr: string;           // 수정자
}

최근 게시물(RecentPost) 인터페이스

export interface RecentPost extends Post {
  bbsNm: string;          // 게시판명
  bbsTypeCd: string;      // 게시판 유형 코드
}

게시물 이동(MovePost) 인터페이스

export interface MovePost {
  fromBbsId: number;      // 출발 게시판 ID
  toBbsId?: number;       // 도착 게시판 ID
  pstNo: number;          // 게시물 번호
}

게시물 삭제(DeletePost) 인터페이스

export interface DeletePost {
  bbsId: number;          // 게시판 ID
  pstNo: number;          // 게시물 번호
  delRsn?: string;        // 삭제 사유
}

게시물 검색 파라미터(PostParams) 인터페이스

export interface PostParams extends PageableParams {
  keywordType?: string;   // 검색 키워드 유형 (제목, 내용, 작성자 등)
  keyword?: string;       // 검색 키워드
  popupYn?: string;       // 팝업 여부
  upndFixYn?: string;     // 상단 고정 여부
  prdPstgYn?: string;     // 기간 게시 여부
  siteId?: string;        // 사이트 ID
  bbsTypeCd?: string;     // 게시판 유형 코드
}

최근 게시물 검색 파라미터(RecentPostParams) 인터페이스

export interface RecentPostParams extends PageableParams {
  keywordType?: string;   // 검색 키워드 유형
  keyword?: string;       // 검색 키워드
  bbsId?: number | null;  // 게시판 ID
  delYn?: string;         // 삭제 여부
  frDateYmd?: string;     // 시작 날짜
  toDateYmd?: string;     // 종료 날짜
}

게시물 폼 데이터(PostFormData) 인터페이스

Zod 스키마를 사용하여 폼 데이터의 유효성 검증을 수행합니다.

export const postFormSchema = z.object({
  bbsId: z.number(),                      // 게시판 ID
  pstTtl: z.string().nonempty(),          // 게시물 제목
  pstCn: z.string().nullish(),            // 게시물 내용
  rfrncUrl: z.string().nullish(),         // 참조 URL
  popupYn: z.string().nullish(),          // 팝업 여부
  popupYnEtc: z.array(postEtcSchema).nullish(), // 팝업 관련 추가 정보
  upndFixYn: z.string().nullish(),        // 상단 고정 여부
  upndFixYnEtc: z.array(postEtcSchema).nullish(), // 상단 고정 관련 추가 정보
  prdPstgYn: z.string().nullish(),        // 기간 게시 여부
  prdPstgYnEtc: z.array(postEtcSchema).nullish(), // 기간 게시 관련 추가 정보
  pstPswd: z.string(),                    // 게시물 비밀번호
  wrtrNm: z.string().nullish(),           // 작성자명
  wrtrCplc: z.string().nullish(),         // 작성자 소속
  atflCd: z.string().nullish(),           // 첨부파일 코드
  parentPstNo: z.number().nullish(),      // 부모 게시물 번호
});

API 기능

게시물 관리 API는 다음과 같은 기능을 제공합니다:

1. 게시물 목록 조회

getPostList: async (bbsId: number, params: PostParams): Promise<PostList> => {
  const response = await client.get<PostList>(
    `${ENDPOINT.BOARD_SERVICE.POSTS}/${bbsId}`,
    { params },
  );
  return response.data;
}
  • 설명: 특정 게시판의 게시물 목록을 페이지네이션과 함께 조회합니다.
  • 파라미터: bbsId (게시판 ID), PostParams (검색 조건)
  • 반환값: 페이지네이션된 게시물 목록 (PostList)

2. 최근 게시물 목록 조회

getRecentPostList: async (params?: RecentPostParams): Promise<RecentPostList> => {
  const response = await client.get<RecentPostList>(
    `${ENDPOINT.BOARD_SERVICE.POSTS}/recentPosts`,
    { params },
  );
  return response.data;
}
  • 설명: 최근 게시물 목록을 조회합니다.
  • 파라미터: RecentPostParams (검색 조건)
  • 반환값: 페이지네이션된 최근 게시물 목록 (RecentPostList)

3. 게시물 상세 조회

getPostInfo: async (bbsId: number, pstNo: number): Promise<PostInfo> => {
  const response = await client.get<PostInfo>(
    `${ENDPOINT.BOARD_SERVICE.POSTS}/${bbsId}/${pstNo}`,
  );
  return response.data;
}
  • 설명: 특정 게시물의 상세 정보를 조회합니다.
  • 파라미터: bbsId (게시판 ID), pstNo (게시물 번호)
  • 반환값: 게시물 상세 정보 (PostInfo)

4. 게시물 생성

createPost: async (data: PostFormData): Promise<Post> => {
  const validatedData = postFormSchema.parse(data);
  const response = await client.post<Post>(
    `${ENDPOINT.BOARD_SERVICE.POSTS}`,
    validatedData,
  );
  return response.data;
}
  • 설명: 새로운 게시물을 생성합니다.
  • 파라미터: PostFormData (게시물 생성 데이터)
  • 반환값: 생성된 게시물 정보 (Post)

5. 게시물 수정

updatePost: async (bbsId: number, pstNo: number, data: PostUpdateFormData): Promise<Post> => {
  const validatedData = postUpdateFormSchema.parse(data);
  const response = await client.put<Post>(
    `${ENDPOINT.BOARD_SERVICE.POSTS}/${bbsId}/${pstNo}`,
    validatedData,
  );
  return response.data;
}
  • 설명: 기존 게시물 정보를 수정합니다.
  • 파라미터: bbsId (게시판 ID), pstNo (게시물 번호), PostUpdateFormData (수정할 게시물 데이터)
  • 반환값: 수정된 게시물 정보 (Post)

6. 게시물 삭제

deletePost: async (bbsId: number, pstNo: number, delRsn?: string): Promise<void> => {
  await client.delete(`${ENDPOINT.BOARD_SERVICE.POSTS}/${bbsId}/${pstNo}`, {
    params: { delRsn },
  });
}
  • 설명: 게시물을 삭제합니다.
  • 파라미터: bbsId (게시판 ID), pstNo (게시물 번호), delRsn (삭제 사유, 선택적)
  • 반환값: void

7. 게시물 소프트 삭제 (여러 게시물)

softDeletePost: async (data: DeletePost[]): Promise<void> => {
  await client.post(`${ENDPOINT.BOARD_SERVICE.POSTS}/softDeleteSels`, data);
}
  • 설명: 여러 게시물을 소프트 삭제합니다 (실제 삭제하지 않고 삭제 표시만 함).
  • 파라미터: DeletePost[] (삭제할 게시물 목록)
  • 반환값: void

8. 게시물 하드 삭제 (여러 게시물)

hardDeletePost: async (data: DeletePost[]): Promise<void> => {
  await client.post(`${ENDPOINT.BOARD_SERVICE.POSTS}/hardDeleteSels`, data);
}
  • 설명: 여러 게시물을 하드 삭제합니다 (실제로 데이터베이스에서 삭제).
  • 파라미터: DeletePost[] (삭제할 게시물 목록)
  • 반환값: void

9. 게시물 이동

movePost: async (data: MovePost[]): Promise<void> => {
  await client.post(`${ENDPOINT.BOARD_SERVICE.POSTS}/movePstByBbsId`, data);
}
  • 설명: 게시물을 다른 게시판으로 이동합니다.
  • 파라미터: MovePost[] (이동할 게시물 정보 목록)
  • 반환값: void

10. 게시물 복구

restorePost: async (data: DeletePost[]): Promise<void> => {
  await client.post(`${ENDPOINT.BOARD_SERVICE.POSTS}/restoreSels`, data);
}
  • 설명: 소프트 삭제된 게시물을 복구합니다.
  • 파라미터: DeletePost[] (복구할 게시물 목록)
  • 반환값: void

프로그램 흐름

1. 게시물 목록 조회 흐름

  1. 사용자가 게시판 페이지에 접근
  2. useMenuStore를 통해 현재 게시판 정보 로드
  3. React Query를 사용하여 getPostList API 호출
  4. 상단 고정 게시물이 있는 경우 별도로 조회하여 목록 상단에 표시
  5. 검색 조건 변경 시 쿼리 파라미터 업데이트 및 API 재호출
  6. 응답 데이터를 TanStack Table을 사용하여 테이블 형태로 표시
  7. 게시판 유형에 따라 일반 테이블 또는 그리드 뷰로 표시

2. 게시물 상세 조회 흐름

  1. 사용자가 게시물 목록에서 특정 게시물 클릭
  2. 해당 게시물의 상세 페이지로 이동 (/bbs/{bbsId}/{pstNo})
  3. React Query를 사용하여 getPostInfo API 호출
  4. 게시물 상세 정보 및 첨부파일 정보 로드
  5. 게시판 유형에 따라 적절한 상세 보기 컴포넌트 렌더링
    • 일반 게시물: normal-post.tsx
    • 이미지 게시물: image-post.tsx
    • 동영상 게시물: movie-post.tsx
    • 공지사항: notice-post.tsx

3. 게시물 등록 흐름

  1. 사용자가 게시물 등록 버튼 클릭
  2. 게시물 등록 페이지로 이동 (/bbs/{bbsId}/register)
  3. React Hook Form과 Zod를 사용하여 폼 데이터 관리 및 유효성 검증
  4. 첨부파일 업로드 시 AttachmentApi를 통해 파일 업로드 및 atflCd 획득
  5. 저장 버튼 클릭 시 확인 다이얼로그 표시 후 createPost API 호출
  6. 성공 시 게시물 목록 페이지로 리다이렉트

4. 게시물 수정 흐름

  1. 사용자가 게시물 상세 페이지에서 수정 버튼 클릭
  2. 게시물 수정 페이지로 이동 (/bbs/{bbsId}/{pstNo}/modify)
  3. getPostInfo API를 호출하여 기존 게시물 데이터 로드
  4. 기존 첨부파일 정보 로드 및 표시
  5. 사용자가 데이터 수정 후 저장 버튼 클릭
  6. 확인 다이얼로그 표시 후 updatePost API 호출
  7. 성공 시 게시물 상세 페이지로 리다이렉트

5. 게시물 삭제 흐름

  1. 사용자가 게시물 상세 페이지에서 삭제 버튼 클릭 또는 목록에서 여러 게시물 선택 후 삭제 버튼 클릭
  2. 삭제 사유 입력 다이얼로그 표시
  3. 사용자가 삭제 사유 입력 후 확인
  4. 단일 게시물 삭제 시 deletePost API 호출, 여러 게시물 삭제 시 softDeletePost 또는 hardDeletePost API 호출
  5. 성공 시 게시물 목록 페이지로 리다이렉트 또는 목록 새로고침

주요 컴포넌트

1. PostPage 컴포넌트

게시물 목록을 조회하고 표시하는 페이지 컴포넌트입니다.

  • 기능:
    • 게시물 검색 (제목, 내용, 작성자 등)
    • 페이지네이션
    • 페이지 크기 조정
    • 게시물 목록 표시 (테이블 또는 그리드 뷰)
    • 게시물 등록 페이지로 이동
    • 게시물 상세 페이지로 이동 (행 클릭)
    • 선택한 게시물 삭제

2. PostForm 컴포넌트

게시물 등록 및 수정에 사용되는 폼 컴포넌트입니다.

  • 기능:
    • 게시물 정보 입력/수정 (제목, 내용, 작성자 등)
    • 첨부파일 업로드 및 관리
    • 참조 URL 입력 (게시판 설정에 따라)
    • 팝업 게시 설정 (게시판 설정에 따라)
    • 상단 고정 설정 (게시판 설정에 따라)
    • 기간 게시 설정 (게시판 설정에 따라)
    • 저장 확인 다이얼로그
    • 취소 기능

3. Post 컴포넌트

게시물 상세 정보를 표시하는 컴포넌트입니다.

  • 기능:
    • 게시물 상세 정보 표시
    • 첨부파일 다운로드
    • 수정/삭제 버튼
    • 목록으로 돌아가기
    • 댓글 표시 및 관리 (게시판 설정에 따라)

4. PostComment 컴포넌트

게시물 댓글을 표시하고 관리하는 컴포넌트입니다.

  • 기능:
    • 댓글 목록 표시
    • 댓글 등록
    • 댓글 수정/삭제
    • 댓글 페이지네이션

5. PostingPeriodSelector 컴포넌트

게시 기간을 선택하는 컴포넌트입니다.

  • 기능:
    • 게시 기간 유형 선택
    • 시작일/종료일 선택
    • 게시 기간 설정

6. 게시물 유형별 컴포넌트

게시판 유형에 따라 다양한 게시물 컴포넌트를 제공합니다.

  • NormalPost: 일반 텍스트 게시물 컴포넌트
  • ImagePost: 이미지 게시물 컴포넌트 (이미지 갤러리 형태)
  • MoviePost: 동영상 게시물 컴포넌트 (동영상 플레이어 포함)
  • NoticePost: 공지사항 게시물 컴포넌트

아키텍처 특징

  1. 계층 분리: API, 모델, UI 컴포넌트가 명확히 분리되어 있습니다.
  2. 타입 안전성: TypeScript 인터페이스와 Zod 스키마를 통한 타입 검증을 제공합니다.
  3. 컴포넌트 재사용: 공통 컴포넌트를 활용하여 코드 중복을 최소화합니다.
  4. 유효성 검증: Zod 스키마를 사용하여 폼 데이터의 유효성을 검증합니다.
  5. 상태 관리: React Query를 통한 서버 상태 관리와 Zustand를 통한 클라이언트 상태 관리를 제공합니다.
  6. 조건부 렌더링: 게시판 설정에 따라 UI 요소를 조건부로 렌더링합니다.
  7. 다양한 게시물 유형 지원: 일반, 이미지, 동영상, 공지사항 등 다양한 게시물 유형을 지원합니다.

확장 가능성

  1. 다국어 지원: 게시물 내용의 다국어 지원 기능 추가
  2. 게시물 버전 관리: 게시물 수정 이력 관리 기능 추가
  3. 게시물 예약 발행: 특정 시간에 자동으로 게시되는 기능 추가
  4. 게시물 통계: 조회수, 좋아요 등 게시물 통계 기능 강화
  5. 게시물 공유: 소셜 미디어 공유 기능 추가
  6. 게시물 알림: 새 게시물 알림 기능 추가
  7. 게시물 태그: 게시물 태그 및 카테고리 기능 추가

주의사항

  1. 게시물 삭제 시 연관된 첨부파일, 댓글 등의 처리에 주의가 필요합니다.
  2. 게시물 이동 시 게시판 유형 간 호환성 문제가 발생할 수 있습니다.
  3. 첨부파일 업로드 시 파일 크기 및 유형 제한을 준수해야 합니다.
  4. 게시 기간 설정 시 시간대(timezone) 처리에 주의가 필요합니다.
  5. 비로그인 사용자의 게시물 작성 시 비밀번호 관리에 주의가 필요합니다.