
MPA
서버에서 모든 페이지(리소스)를 랜더링해서 html로 응답
페이지가 이동할때마다 리소스를 서버에서 다시 받아오는 방식 : 실제 페이지 이동시 깜빡거리는 현상
server에서 템플릿엔진을 사용해서 html을 렌더링하여 html을 응답해준다.
SPA
페이지 이동시 마치 모바일 앱처럼 부드럽게 이동하는 현상, 컨텐츠만 바뀌게된다.
필요한 데이터들은 API로 가져와서 화면의 일부만 갱신한다.
보통 백엔드 서버는 api만 제공만하고 , 응답을 Json 형태로 해주기에 http 통신만 가능하다면 웹외에도 모바일 애플리케이션 등 다양한 클라이언트에서도 사용가능해서 유용하다.
ejs
템플릿 엔진중 하나로 서버에서 데이터를 HTML에 끼워 넣어 완성된 페이지를 만들어 주는 도구.
cors
CORS: 브라우저 정책. API 서버가 허용 헤더를 줘야 브라우저가 통과시킴
Promise
Promise: 비동기 결과를 안전하게 순서 있게 다루기 위한 도구(then/catch, async/await)
DBMS
DBMS (Database ManageMent System) : 데이터베이스 관리시스템 : 데이터를 저장/조회/수정/삭제 할수있는 인터페이스 제공해주는 소프트웨어
테이블 행/열 구조인 관계형 : mysql, PostgreSQL, Oracle
문서,키-값,그래프 구조인 비관계형 : MongoDB, Redis , Cassandra
WorkBench
workbench : DBMB를 조작하기 편한 GUI
ex) MySQL Workbench, MongoDB Compass
소스코드 접속
애플리케이션에서 DBMS랑 연결할 때 사용하는 방식
코드 안에서 직접 DB CRUD 작업 가능
MongoDB
대표적인 NoSQL DBMS 으로 Json과 비슷한 document로 데이터 저장
MongoDB 서버
└── 데이터베이스 (Database) : 테이블들이 모여있는 스키마와 비슷한 개념
└── 컬렉션 (Collection) : 데이터가 저장되는 테이블와 비슷한개념
└── 문서 (Document) : 레코드와 비슷한 개념
#Document
{
"name" : "Todd",
"age" : 25,
"skills" : ["JS","Python"]
}
MongoDB Atlas
MongoDB Atlas : MongoDB의 클라우드 서비스 : aws나 로컬저장소에 직접 db를 설치하지않고 Atlas가 서버와 DB를 대신 관리해준다.
cluster 클러스터
클러스터 : DB 시스템에서 여러대의 물리적 서버 컴퓨터(노드)를 묶어서 하나의 논리적데이터베이스 처럼 동작하게 하는 구조
물리적으로 여러컴퓨터를 이용하지만 코드에서 클러스터 uri 하나에 접속하여 하나의 mongoDB 서버처럼 이용가능하다.






OPENAI_API_KEY = my_openAi_API_KEY
ASSISTANT_ID = my_assistant_id
MONGODB_URI = mongodb+srv://사용자아이디:사용자패스워드@cluster0.e7lzjav.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0
COLLECTION_NAME=chat_messages
pymongo : 파이썬용 몽고디비 공식드라이버 : 파이썬에서 몽고디비에 연결/crud 수행
datetime : 타임스탬프를 기록해주는 용도
# MongoDB 연결을 위한 모듈 추가
from pymongo import MongoClient
# 날짜/시간 처리를 위한 모듈 추가
from datetime import datetime
# MongoDB 연결 설정
MONGODB_URI = os.getenv('MONGODB_URI')
DATABASE_NAME = os.getenv('DATABASE_NAME', 'portfolio_chat')
COLLECTION_NAME = os.getenv('COLLECTION_NAME', 'chat_messages')
# MongoDB 클라이언트 생성 및 연결 테스트
try:
client_mongo = MongoClient(MONGODB_URI)
# 연결 테스트
client_mongo.admin.command('ping')
print("MongoDB 연결 성공!")
db = client_mongo[DATABASE_NAME]
collection = db[COLLECTION_NAME]
except Exception as e:
print(f"MongoDB 연결 실패: {e}")
client_mongo = None
db = None
collection = None
# 완전히 새로운 함수 추가 (라인 66-91)
def save_chat_to_mongodb(user_message, ai_response, thread_id):
"""
채팅 데이터를 MongoDB에 저장하는 함수
"""
if collection is None:
print("MongoDB 연결이 없어서 데이터를 저장할 수 없습니다.")
return False
try:
# 저장할 데이터 구조
chat_data = {
"user_message": user_message,
"ai_response": ai_response,
"thread_id": thread_id,
"timestamp": datetime.now(),
"created_at": datetime.now().isoformat()
}
# MongoDB에 데이터 삽입
result = collection.insert_one(chat_data)
print(f"채팅 데이터 저장 성공! ID: {result.inserted_id}")
return True
except Exception as e:
print(f"채팅 데이터 저장 실패: {e}")
return False
@app.route("/sendMessage", methods=["POST"])
def send_message():
"""
사용자 메시지를 받아서 OpenAI Assistant에 전달하고 응답을 반환하는 API 엔드포인트
"""
global thread_id # 전역 변수 thread_id를 사용
try:
# 클라이언트가 보낸 JSON 데이터를 파싱
data = request.get_json()
# JSON에서 'message' 키의 값을 가져옴 (사용자 입력 메시지)
message = data.get('message', '')
# 메시지가 비어있으면 에러를 반환
if not message:
return jsonify({"error": "메시지가 없습니다."}), 400
# 터미널에 받은 메시지를 출력 (디버깅용)
print(f"받은 메시지: {message}")
# 스레드가 없으면 새로 생성 (첫 번째 메시지인 경우)
if thread_id is None:
# 새로운 대화 스레드를 생성
thread = client.beta.threads.create()
# 생성된 스레드의 ID를 저장
thread_id = thread.id
print(f"새 스레드 생성: {thread_id}")
# 사용자 메시지를 스레드에 추가
client.beta.threads.messages.create(
thread_id=thread_id, # 대화 스레드 ID
role="user", # 메시지 역할 (사용자)
content=message # 메시지 내용
)
# Assistant를 실행하여 응답을 생성
run = client.beta.threads.runs.create(
thread_id=thread_id, # 대화 스레드 ID
assistant_id=ASSISTANT_ID # OpenAI 대시보드에서 생성한 Assistant ID
)
# Assistant가 응답을 완료할 때까지 기다림
while True:
# 현재 실행 상태를 확인
run_status = client.beta.threads.runs.retrieve(
thread_id=thread_id,
run_id=run.id
)
# 실행이 완료되면 루프를 종료
if run_status.status == "completed":
break
# 실행이 실패하면 에러를 반환
elif run_status.status == "failed":
return jsonify({"error": "Assistant 실행 실패"}), 500
# Assistant의 응답 메시지를 가져옴
messages = client.beta.threads.messages.list(thread_id=thread_id)
# 가장 최근 메시지(Assistant의 응답)를 가져옴
assistant_message = messages.data[0]
# 응답 내용을 추출
ai_response = assistant_message.content[0].text.value
# 참조 표시를 제거
cleaned_response = clean_response(ai_response)
# 터미널에 Assistant 응답을 출력 (디버깅용)
print(f"Assistant 응답 (원본): {ai_response}")
print(f"Assistant 응답 (정리됨): {cleaned_response}")
# MongoDB에 채팅 데이터 저장
save_success = save_chat_to_mongodb(message, cleaned_response, thread_id)
if save_success:
print("채팅 데이터가 MongoDB에 성공적으로 저장되었습니다.")
else:
print("채팅 데이터 저장에 실패했습니다.")
# 클라이언트에게 성공 응답을 JSON 형태로 반환
return jsonify({
"success": True,
"message": cleaned_response,
"original_message": message,
"saved_to_db": save_success
})
except Exception as e:
# 에러가 발생하면 터미널에 에러 메시지를 출력
print(f"에러 발생: {str(e)}")
# 클라이언트에게 에러 응답을 반환
return jsonify({"error": f"서버 에러: {str(e)}"}), 500








