오늘도 CLI 게시판 프로그램 코드 작성..
print("-" 21)
print("== CLI 게시판 실행 ==")
print("-" 21)
from datetime import datetime #작성일시를 위한 함수 호출
num = 0
articles = [] # 게시글들용 딕셔너리 입니다.
users = [] # 회원들용 딕셔너리 입니다.
while True: # 참인 동안 아래 실행 ('exit' 입력 시 종료)
print("명령어 입력 = 회원'log in', 비회원 'user join'") # (비)회원 명령어
cmd = input("명령어 )") #명령어 입력
if cmd == "exit": #종료 명령
print("== CLI 게시판 종료 ==")
break
elif cmd == "log in": # 회원 인증
count = 0
while True: # 참인 동안 아래 실행 ('exit' 입력 시 종료)
revise_id = input("사용자 id를 입력하세요: ")
revise_pw = input("사용자 pw를 입력하세요: ")
# id 목록에 없는 경우 검증용 스위치.
is_revised = False
for id in uers:
# 꺼내온 글상자의 'id' 번호가 사용자가 입력한 revise_id와 일치하는지 검사합니다.
if users["id"] == revise_id & users["pw"] == revise_pw :
# 글생성 확인
print(f"{revise_id}님이 로그인 되었습니다.\n")
is_revised = True # 수정 후 찾았다고 스위치 참으로 변경
break
if is_revised == False:
print(f"{revise_id}는 회원 아니거나 비번이 틀립니다. 다시 입력 \n")
elif cmd == "user join": # 회원 가입
id = input("회원ID : ")
pw = input("비밀번호 : ")
nickname = input("별명 : ")
now_time = datetime.now().strftime("%Y년%m월%d일 %H시%M분%S초")
#게시글 작성 (시간을 자동 등록)
article_data = {
"id": id,
"pw": pw,
"nickname": nickname,
"date": now_time
}
# 코드 실행 시 게시물이 추가 누적
articles.append(article_data)
# 글생성 확인
print(f"{id}님의 회원 신청이 완료 되었습니다.\n")
else:
print("지원하지 않는 명령어 입니다.\n")
while True: # 참인 동안 아래 실행 ('exit' 입력 시 종료)
cmd = input("명령어 )") #명령어 입력
if cmd == "exit": #종료 명령
print("== CLI 게시판 종료 ==")
break
elif cmd == "a w": # article write: 게시글 작성
num += 1
title = input("제목 : ")
content = input("내용 : ")
now_time = datetime.now().strftime("%Y년%m월%d일 %H시%M분%S초") #추천 regDate
#게시글 작성 (시간을 자동 등록)
article_data = {
"id": num,
"title": title,
"content": content,
"date": now_time
}
# 코드 실행 시 게시물이 추가 누적
articles.append(article_data)
# 글생성 확인
print(f"{num}번 글이 생성 되었습니다.\n")
elif cmd == "a l": # article list: 전체 목록 보기
print("=" * 40)
print("번호/ 제목 / 내용")
# 딕셔너리에 저장된 게시글 출력
for art in articles[::-1]:
print(f"{art['id']} / {art['title']} / {art['content']}")
print("=" * 40)
elif cmd == "a v": # article detail view: 게시글의 상세보기
dread_id = int(input("상세보기 할 글 id 번호를 입력하세요: "))
is_dreaded = False
for art in articles:
# 선택 'id' 번호가 딕셔너리에 있는지 확인
if art["id"] == dread_id:
print (f"게시글 No: {art['id']}")
print (f"제 목 : {art['title']}")
print (f"내 용 : {art['content']}")
print (f"작성일시 : {art['date']}")
is_dreaded = True # 해당 글 찾았다고 스위치 참으로 변경
break
if is_dreaded == False: #목록에 번호에 없다고 출력
print(f"{dread_id}번 글은 목록에 없습니다.\n")
elif cmd == "a d": # delete article list (선택 삭제)
delete_id = int(input("삭제할 글 id 번호를 입력하세요: "))
# 목록 없음 구분자
is_deleted = False
for art in articles:
# 꺼내온 글상자의 'id' 번호가 사용자가 입력한 delete_id와 일치하는지 검사합니다.
if art["id"] == delete_id:
articles.remove(art)
print(f"{delete_id}번 글이 삭제되었습니다.\n")
is_deleted = True # 글을 성공적으로 찾아서 지웠다고 스위치를 켭니다.
break # 원하는 글을 지웠으므로 탐색 루프를 탈출합니다.
# id 리스트에 없는 경우 실행.
if is_deleted == False:
print(f"{delete_id}번 글은 목록에 없습니다.\n")
elif cmd == "a r": # article revise (선택 수정)
revise_id = int(input("수정할 글 id 번호를 입력하세요: "))
# id 목록에 없는 경우 검증용 스위치.
is_revised = False
for art in articles:
# 꺼내온 글상자의 'id' 번호가 사용자가 입력한 revise_id와 일치하는지 검사합니다.
if art["id"] == revise_id:
title = input("제목 : ")
content = input("내용 : ")
art["title"] = title
art["content"] = content
# 글생성 확인
print(f"{revise_id}번 글이 성공적으로 수정 되었습니다.\n")
is_revised = True # 수정 후 찾았다고 스위치 참으로 변경
break
if is_revised == False:
print(f"{revise_id}번 글은 목록에 없습니다.\n")
else:
print("지원하지 않는 명령어 입니다.\n")
from datetime import datetime
from dataclasses import dataclass # 파이썬에서 데이터를 담는 클래스를 쉽게 만들도록 도와주는 도구입니다.
@dataclass
class Article:
id: int # 글 번호 (정수)
regDate: str # 작성일 (문자열)
updateDate: str # 수정일 (문자열)
title: str # 제목 (문자열)
body: str # 내용 (문자열)
def now():
# 현재 시각을 "YYYY-MM-DD HH:MM:SS" 형태의 문자열로 만들어 반환합니다.
return datetime.now().strftime("%Y-%m-%d %H:%M:%S") #strftime = String Fomat Time
def parse_id(cmd):
# 사용자가 "article delete 3" 이라고 쳤을 때, 맨 뒤의 숫자 '3'만 안전하게 뽑아내는 함수입니다.
cmdBits = cmd.split(" ")
if len(cmdBits) < 3:
print("명령어를 확인해주세요(길이 모자람)")
return None
if not cmdBits[2].isdigit():
print("명령어를 확인해주세요(번호대신 str 입력)")
return None
return int(cmdBits[2])
def find_article(articles, article_id):
# 게시글 목록(articles)을 처음부터 끝까지 뒤지며, 내가 찾는 id와 일치하는 글을 찾아 돌려줍니다.
for article in articles:
# [핵심] 딕셔너리일 때는 article["id"] 였지만, 이제 클래스 객체이므로 점(.)을 찍어 article.id 로 접근합니다.
if article.id == article_id:
return article
return None
def format_date(regDate):
# 오늘 작성된 글이면 시간(12:12:12)만, 예전 글이면 날짜(2025-12-12)만 보여주는 센스 있는 포맷팅 함수입니다.
today = now().split(" ")[0]
datePart = regDate.split(" ")[0]
timePart = regDate.split(" ")[1]
if datePart == today:
return timePart
else:
return datePart
def makeTestData():
return [
Article(1, "2025-12-12 12:12:12", "2025-12-12 12:12:12", "제목1", "내용1"),
Article(2, now(), now(), "제목2", "내용2"),
Article(3, now(), now(), "제목3", "내용3")
]
print("== CLI 게시판 실행 ==")
last_article_id = 3
articles = makeTestData() # 위에서 만든 객체 3개를 게시글 가방(리스트)에 담습니다.
while True:
cmd = input("명령어 ) ").strip()
if cmd == "exit":
break
elif cmd == "article write":
last_article_id += 1
title = input("제목 : ")
body = input("내용 : ")
# [핵심] 딕셔너리를 만들던 코드 대신, Article 클래스를 불러와 새로운 객체를 한 줄로 뚝딱 만듭니다.
article = Article(last_article_id, now(), now(), title, body)
articles.append(article)
print("{}번 글이 생성되었습니다".format(last_article_id))
elif cmd == "article list":
if not articles:
print("게시글이 없습니다")
else:
print("=========================================")
print(" 번호 / 제목 / 내용 / 작성일 ")
for a in reversed(articles):
# 객체의 속성을 꺼낼 때는 a["title"] 이 아니라 a.title 처럼 마침표(.)를 사용합니다.
print(" {} / {} / {} / {} ".format(
a.id, a.title, a.body, format_date(a.regDate)))
print("=========================================")
elif cmd.startswith("article delete"):
deletedId = parse_id(cmd) # 공통 함수로 숫자만 빼옵니다.
if deletedId is None: continue
article = find_article(articles, deletedId) # 공통 함수로 지울 객체를 통째로 찾아옵니다.
if article is None:
print("{}번 글은 없습니다".format(deletedId))
continue
articles.remove(article) # 리스트에서 그 객체를 날려버립니다.
print("{}번 글이 삭제되었습니다".format(deletedId))
elif cmd.startswith("article edit"):
editedId = parse_id(cmd)
if editedId is None: continue
article = find_article(articles, editedId)
if article is None:
print("{}번 글은 없습니다".format(editedId))
continue
# 객체 안의 기존 값을 보여주고,
print("기존 제목 : {}".format(article.title))
print("기존 내용 : {}".format(article.body))
# 입력받은 새로운 값을 객체의 속성에 바로 덮어씌웁니다.
article.title = input("새 제목 : ")
article.body = input("새 내용 : ")
article.updateDate = now()
print("{}번 글이 수정되었습니다".format(editedId))
elif cmd.startswith("article detail"):
detailId = parse_id(cmd)
if detailId is None: continue
article = find_article(articles, detailId)
if article is None:
print("{}번 글은 없습니다".format(detailId))
continue
# 마침표(.)를 이용해 객체가 가진 모든 데이터를 쏙쏙 뽑아 출력합니다.
print("번호 : {}".format(article.id))
print("작성 날짜 : {}".format(article.regDate))
print("수정 날짜 : {}".format(article.updateDate))
print("제목 : {}".format(article.title))
print("내용 : {}".format(article.body))
else:
print("지원하지 않는 기능입니다")
print("== CLI 게시판 종료 ==")