콘솔 기반으로 동작하는 게시판 프로그램입니다.
글 작성, 목록 조회, 상세 보기, 수정, 삭제, 검색, 정렬, 조회수 관리, 저장/불러오기 기능을 제공합니다.
- 기능별로 개발 범위를 분리하고, 각자 구현 후 Git으로 병합
- 기능별 TDD 방식으로 테스트 케이스 작성 및 검증
- Java 기반 CLI 프로그램 구조 설계 및 유닛 테스트 적용
| 기능 |
명령어 |
| 게시글 목록 보기 |
list |
| 게시글 작성 |
write → 제목 → 내용 입력 |
| 게시글 상세 보기 |
detail [id] |
| 게시글 수정 |
update [id] → 제목 → 내용 입력 |
| 게시글 삭제 |
delete [id] |
| 게시글 검색 |
search [keyword] |
| 게시글 정렬 |
sort [sortType] [sortOrder]
sortType: id, title, regDate, count
sortOrder: asc, desc |
| 게시글 저장 |
save |
| 프로그램 종료 |
exit |
📌 상세보기(detail) 명령어를 실행하면 조회수가 1 증가하며, 누적됩니다.
프로그램 시작/종료 및 명령어 입력 처리
| 메소드명 |
설명 |
SystemController() |
AppContext로부터 Scanner를 주입받아 초기화합니다. |
start() |
프로그램 시작 메시지를 출력합니다. |
stop() |
프로그램 종료 메시지를 출력하고 Scanner를 닫습니다. |
getCommand() |
사용자로부터 명령어를 입력받아 Rq 객체로 파싱해 반환합니다. |
명령어 파싱 및 파라미터 추출
| 메소드명 |
설명 |
Rq(String cmd) |
명령어를 공백 기준으로 분리하여 actionName과 params를 초기화합니다. |
getActionName() |
명령어에서 추출한 액션 이름을 반환합니다. 예: "list", "detail" 등 |
getParams() |
명령어에 포함된 파라미터 리스트를 반환합니다. 예: ["3"] |
getParam(int index, String defaultValue) |
특정 인덱스의 파라미터 값을 문자열로 반환합니다. 없으면 기본값 반환 |
getParamAsInt(int index, int defaultValue) |
특정 인덱스의 파라미터 값을 정수형으로 반환합니다. 변환 실패 시 기본값 반환 |
명령어에 따라 게시글 로직 분기 및 처리
| 메소드명 |
설명 |
writeArticle() |
사용자로부터 제목/내용을 입력받아 게시글을 작성합니다. |
updateArticle(Rq rq) |
ID를 통해 게시글을 찾아 제목과 내용을 수정합니다. |
deleteArticle(Rq rq) |
ID에 해당하는 게시글을 삭제합니다. 존재하지 않으면 오류 메시지를 출력. |
listArticles() |
전체 게시글 목록을 출력합니다. |
searchArticles(Rq rq) |
키워드를 포함하는 게시글 목록을 검색 및 출력합니다. |
sortArticles(Rq rq) |
ID, 제목, 등록일, 조회수 기준으로 오름차순/내림차순 정렬하여 출력합니다. |
showDetail(Rq rq) |
ID로 게시글 상세 정보를 출력하고 조회수를 1 증가시킵니다. |
saveArticles() |
게시글 데이터를 파일로 저장합니다. 실패 시 에러 메시지 출력. |
loadArticlesAndLastId() |
저장된 게시글과 마지막 ID 값을 로드합니다. |
printArticle(List<Article>) |
게시글 목록을 표 형식으로 콘솔에 출력합니다. |
printMessage(String msg) |
안내 메시지를 출력하는 유틸 메소드입니다. |
handleIOException(action, e) |
입출력 오류 발생 시 공통적으로 예외 메시지를 출력합니다. |
게시글 관련 비즈니스 로직 처리
| 메소드명 |
설명 |
writeArticle(title, content) |
제목과 내용을 기반으로 게시글을 생성하고 저장합니다. |
updateArticle(article, title, content) |
기존 게시글을 수정하고 저장합니다. |
deleteArticle(id) |
ID에 해당하는 게시글을 찾아 삭제합니다. 존재하지 않으면 false 반환. |
findById(id) |
ID에 해당하는 게시글을 찾아 반환합니다. |
findAndIncreaseViewCount(id) |
ID에 해당하는 게시글의 조회수를 1 증가시키고 반환합니다. |
getArticles() |
전체 게시글을 반환합니다. |
getArticles(keyword) |
키워드를 포함하는 게시글 목록을 반환합니다. |
getSortedArticles(sortType, sortOrder) |
정렬 기준과 순서에 따라 게시글을 정렬하여 반환합니다. |
save() |
게시글 데이터를 파일로 저장합니다. |
load() |
파일에서 게시글 데이터를 불러옵니다. |
게시글 데이터 저장/조회/파일 입출력
| 메소드명 |
설명 |
getArticleById(id) |
ID에 해당하는 게시글을 반환합니다. 존재하지 않으면 null 반환. |
deleteArticle(article) |
지정한 게시글을 리스트에서 제거합니다. |
saveArticle(article) |
새 게시글이면 ID와 등록일을 부여하고 저장합니다. |
getArticles(keyword) |
제목 또는 내용에 키워드를 포함한 게시글 리스트를 반환합니다. |
save() |
게시글 데이터를 JSON 파일로 저장합니다. |
load() |
JSON 파일로부터 게시글 데이터를 불러옵니다. |
getLastId() |
마지막으로 저장된 게시글의 ID를 반환합니다. |
게시글 도메인 객체(Entity)
| 필드명 |
설명 |
id |
게시글 고유 ID |
title |
게시글 제목 |
content |
게시글 내용 |
regDate |
게시글 등록일 (String 형태) |
count |
조회수 (기본값: 0) |
| 메소드명 |
설명 |
Article(title, content) |
제목과 내용을 기반으로 게시글 객체 생성 |
isNew() |
ID가 0이면 새로운 게시글로 판단 (@JsonIgnore) |
increaseCount() |
게시글의 조회수를 1 증가시킵니다. (@JsonIgnore) |
전역 객체 초기화 및 재생성 관리
| 필드명 |
설명 |
scanner |
사용자 입력을 위한 Scanner 객체입니다. |
filePath |
게시글 저장/불러오기용 JSON 파일 경로입니다. |
articleRepository |
게시글 데이터를 관리하는 Repository입니다. |
articleService |
게시글 도메인 로직을 처리하는 Service입니다. |
articleController |
게시글 관련 기능을 담당하는 Controller입니다. |
systemController |
시스템 전반 실행 및 사용자 입력 흐름을 제어하는 Controller입니다. |
| 메소드명 |
설명 |
renew(Scanner _scanner, String _filePath) |
Scanner, 파일 경로 등 주요 객체들을 새로 생성 및 초기화합니다. |
renew() |
기본 Scanner(System.in)와 파일 경로("db/articles.json")로 초기화합니다. |
기능 단위로 다음과 같은 테스트 케이스를 작성하였습니다.
- 게시글 목록 출력
- 게시글 등록 시 id 자동 증가
- 게시글 삭제
- 게시글 상세 보기 시 조회수 증가 및 누적
- 존재하지 않는 id 상세 보기
- 특정 키워드로 검색
- 일치하는 게시글이 없는 경우
- 빈 키워드 입력 시 에러
- 정상 작성 및 수정
- 숫자가 아닌 id 입력 시 예외
- 존재하지 않는 id 수정 시 예외
- 빈 제목/내용 작성 시 예외
- 게시글 저장 성공/실패
- 게시글 불러오기 성공/실패
- id, title, regDate 기준 정렬
- 잘못된 sortType 입력 시 예외
- 잘못된 sortOrder 입력 시 예외
📦 project-root
┣ 📂src
┃ ┣ 📂Domain.article # 게시글 관련 도메인
┃ ┃ ┣ 📂controller # 게시글 명령어 처리
┃ ┃ ┣ 📂service # 게시글 비즈니스 로직
┃ ┃ ┣ 📂repository # 게시글 데이터 저장 및 조회
┃ ┃ ┗ 📂entity # Article 객체 정의
┃ ┣ 📂system # 시스템 명령어 처리 (시작, 종료 등)
┃ ┃ ┗ 📂controller # 시스템 명령어 입력 처리
┃ ┣ 📂standard.util # 테스트용 Scanner, 콘솔 출력 유틸
┃ ┣ 📄App.java # 메인 루프 및 명령어 실행 로직
┃ ┣ 📄AppContext.java # Controller/Service/Repo 의존성 관리
┃ ┣ 📄Main.java # 프로그램 실행 진입점 (new App().run())
┃ ┗ 📄Rq.java # 명령어 파싱 및 파라미터 분리 객체
┣ 📂test # JUnit 기반 테스트 코드
┗ 📜README.md # 프로젝트 설명 문서
- 팀명: Object (5조)
- 개발 기간: 2025.08.04 ~ 2025.08.08
| 이름 |
담당 기능 |
| 김동엽 |
게시글 목록, 게시글 삭제 |
| 김은주 |
게시글 수정, 게시글 저장/불러오기 |
| 이해민 |
게시글 상세보기, 게시글 정렬 |
| 장근영 |
게시글 작성, 프로그램 종료 |
| 박세웅 |
게시글 조회수 기능, 게시글 검색 |
| 문제 상황 |
원인 및 해결 방법 |
담당자 |
| 조회수 증가 로직이 Service 단에서 setCount(getCount() + 1) 방식으로 처리됨 |
캡슐화가 부족하고 중복될 가능성이 있어, Entity에 increaseCount() 메서드를 추가하여 내부에서 직접 증가하도록 개선 |
박세웅 |
| 정렬 로직이 controller에 존재 |
책임 분리를 위해 Service 단으로 이동 |
이해민 |
| 정렬 테스트 시 순서가 고정되지 않음 |
contains() → containsExactly()로 변경하여 순서까지 검증 |
김동엽 |
| 저장/불러오기 실패 |
각자 만든 Repository에서 @NoArgsConstructor 누락으로 Jackson 역직렬화 실패 → 공통 Entity에 생성자 추가 |
김은주 |
| 출력 메시지가 일관되지 않음 |
메시지를 공통 메소드로 분리하여 통일 |
김은주 |
| 불필요한 반환값/파라미터 존재 |
코드 가독성과 유지보수를 위해 삭제 처리 |
김은주 장근영 |
| 목록, 검색, 정렬 출력 로직이 중복 |
각 기능의 출력 메소드를 통합하고, 공통 로직은 별도 메소드로 분리 |
김동엽 |
- 모든 명령어는 입력 후 줄바꿈(
Enter)으로 실행됩니다.
- 잘못된 명령이나 파라미터 입력 시 예외 메시지가 출력됩니다.