# 게시물(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) 인터페이스 ```typescript 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) 인터페이스 ```typescript export interface PostInfo extends Post { pstCn: string; // 게시물 내용 rgtr: string; // 등록자 mdfcnDt: string; // 수정일시 mdfr: string; // 수정자 } ``` ### 최근 게시물(RecentPost) 인터페이스 ```typescript export interface RecentPost extends Post { bbsNm: string; // 게시판명 bbsTypeCd: string; // 게시판 유형 코드 } ``` ### 게시물 이동(MovePost) 인터페이스 ```typescript export interface MovePost { fromBbsId: number; // 출발 게시판 ID toBbsId?: number; // 도착 게시판 ID pstNo: number; // 게시물 번호 } ``` ### 게시물 삭제(DeletePost) 인터페이스 ```typescript export interface DeletePost { bbsId: number; // 게시판 ID pstNo: number; // 게시물 번호 delRsn?: string; // 삭제 사유 } ``` ### 게시물 검색 파라미터(PostParams) 인터페이스 ```typescript export interface PostParams extends PageableParams { keywordType?: string; // 검색 키워드 유형 (제목, 내용, 작성자 등) keyword?: string; // 검색 키워드 popupYn?: string; // 팝업 여부 upndFixYn?: string; // 상단 고정 여부 prdPstgYn?: string; // 기간 게시 여부 siteId?: string; // 사이트 ID bbsTypeCd?: string; // 게시판 유형 코드 } ``` ### 최근 게시물 검색 파라미터(RecentPostParams) 인터페이스 ```typescript export interface RecentPostParams extends PageableParams { keywordType?: string; // 검색 키워드 유형 keyword?: string; // 검색 키워드 bbsId?: number | null; // 게시판 ID delYn?: string; // 삭제 여부 frDateYmd?: string; // 시작 날짜 toDateYmd?: string; // 종료 날짜 } ``` ### 게시물 폼 데이터(PostFormData) 인터페이스 Zod 스키마를 사용하여 폼 데이터의 유효성 검증을 수행합니다. ```typescript 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. 게시물 목록 조회 ```typescript getPostList: async (bbsId: number, params: PostParams): Promise => { const response = await client.get( `${ENDPOINT.BOARD_SERVICE.POSTS}/${bbsId}`, { params }, ); return response.data; } ``` - **설명**: 특정 게시판의 게시물 목록을 페이지네이션과 함께 조회합니다. - **파라미터**: `bbsId` (게시판 ID), `PostParams` (검색 조건) - **반환값**: 페이지네이션된 게시물 목록 (`PostList`) ### 2. 최근 게시물 목록 조회 ```typescript getRecentPostList: async (params?: RecentPostParams): Promise => { const response = await client.get( `${ENDPOINT.BOARD_SERVICE.POSTS}/recentPosts`, { params }, ); return response.data; } ``` - **설명**: 최근 게시물 목록을 조회합니다. - **파라미터**: `RecentPostParams` (검색 조건) - **반환값**: 페이지네이션된 최근 게시물 목록 (`RecentPostList`) ### 3. 게시물 상세 조회 ```typescript getPostInfo: async (bbsId: number, pstNo: number): Promise => { const response = await client.get( `${ENDPOINT.BOARD_SERVICE.POSTS}/${bbsId}/${pstNo}`, ); return response.data; } ``` - **설명**: 특정 게시물의 상세 정보를 조회합니다. - **파라미터**: `bbsId` (게시판 ID), `pstNo` (게시물 번호) - **반환값**: 게시물 상세 정보 (`PostInfo`) ### 4. 게시물 생성 ```typescript createPost: async (data: PostFormData): Promise => { const validatedData = postFormSchema.parse(data); const response = await client.post( `${ENDPOINT.BOARD_SERVICE.POSTS}`, validatedData, ); return response.data; } ``` - **설명**: 새로운 게시물을 생성합니다. - **파라미터**: `PostFormData` (게시물 생성 데이터) - **반환값**: 생성된 게시물 정보 (`Post`) ### 5. 게시물 수정 ```typescript updatePost: async (bbsId: number, pstNo: number, data: PostUpdateFormData): Promise => { const validatedData = postUpdateFormSchema.parse(data); const response = await client.put( `${ENDPOINT.BOARD_SERVICE.POSTS}/${bbsId}/${pstNo}`, validatedData, ); return response.data; } ``` - **설명**: 기존 게시물 정보를 수정합니다. - **파라미터**: `bbsId` (게시판 ID), `pstNo` (게시물 번호), `PostUpdateFormData` (수정할 게시물 데이터) - **반환값**: 수정된 게시물 정보 (`Post`) ### 6. 게시물 삭제 ```typescript deletePost: async (bbsId: number, pstNo: number, delRsn?: string): Promise => { await client.delete(`${ENDPOINT.BOARD_SERVICE.POSTS}/${bbsId}/${pstNo}`, { params: { delRsn }, }); } ``` - **설명**: 게시물을 삭제합니다. - **파라미터**: `bbsId` (게시판 ID), `pstNo` (게시물 번호), `delRsn` (삭제 사유, 선택적) - **반환값**: void ### 7. 게시물 소프트 삭제 (여러 게시물) ```typescript softDeletePost: async (data: DeletePost[]): Promise => { await client.post(`${ENDPOINT.BOARD_SERVICE.POSTS}/softDeleteSels`, data); } ``` - **설명**: 여러 게시물을 소프트 삭제합니다 (실제 삭제하지 않고 삭제 표시만 함). - **파라미터**: `DeletePost[]` (삭제할 게시물 목록) - **반환값**: void ### 8. 게시물 하드 삭제 (여러 게시물) ```typescript hardDeletePost: async (data: DeletePost[]): Promise => { await client.post(`${ENDPOINT.BOARD_SERVICE.POSTS}/hardDeleteSels`, data); } ``` - **설명**: 여러 게시물을 하드 삭제합니다 (실제로 데이터베이스에서 삭제). - **파라미터**: `DeletePost[]` (삭제할 게시물 목록) - **반환값**: void ### 9. 게시물 이동 ```typescript movePost: async (data: MovePost[]): Promise => { await client.post(`${ENDPOINT.BOARD_SERVICE.POSTS}/movePstByBbsId`, data); } ``` - **설명**: 게시물을 다른 게시판으로 이동합니다. - **파라미터**: `MovePost[]` (이동할 게시물 정보 목록) - **반환값**: void ### 10. 게시물 복구 ```typescript restorePost: async (data: DeletePost[]): Promise => { 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. 비로그인 사용자의 게시물 작성 시 비밀번호 관리에 주의가 필요합니다.