[알토르] #20 시간당 질문 갯수 제한, 모달창

Hyungjun·2024년 7월 23일
0

알토르

목록 보기
22/23

Mission

  • ip조회해서 제한 걸어보기 (예시. 시간당 5번만 요청 가능하게)
  • 챗봇 모달창 만들기

배경지식

#1 쿠키, 세션, 캐시

  1. 쿠키는 내가 들고다니고 사이트를 방문할때 보여줌.
    내가 수정할 수도 있고 남들에게 노출되기도 쉬움 -> 중요한 내용은 적지 못한다.

  2. 세션
    세션은 사이트에 필요한 내용의 정보들을 저장한다. 서버는 브라우저에 짧은 임시키 하나를 보내 쿠키로 저장한다.
    브라우저는 사이트를 돌아다닐때 http 요청에 이 키(세션 아이디)를 실어서 전송하고 서버가 그 키를 보고 사용자를 알아차려 사용자의 내용을 알려줌
    세션은 서비스 제공자가 직접 관리해야 할 정보들로, 서버에서 다뤄진다.

  3. 캐시
    가져오는데 비용이 드는 데이터를 한번 가져온 뒤에는 임시로 저장해두는 것. flask

실습

로직

  1. request_log에 client_ip에 대한 요청 기록을 가져오고 없으면 배열을 만듬
  2. 1시간 내의 요청 기록만 유지한다.
  3. 요청 갯수가 5개보다 크거나 같으면 질문을 하지 못하게 막는다.
  4. 현재 시간을 request_log에 추가해줌.
  5. request_log를 캐시에 저장해줌. (키:client_ip, 값:request_log, 한정시간: 1시간)
  6. 질문에 대한 답변을 받아옴

#1 코드

from flask_caching import Cache

app.config['CACHE_TYPE'] = 'SimpleCache'  # 사용할 캐시 타입
app.config['CACHE_DEFAULT_TIMEOUT'] = 60 * 60
cache = Cache(app)

TIME_WINDOW = 60 * 60
MAX_REQUESTS = 5

current_time = time.time()
    
# IP에 대한 요청 기록을 캐시에서 가져옴
request_log = cache.get(client_ip) or []

# 타임 윈도우 내의 요청만 유지
request_log = [log for log in request_log if current_time - log < TIME_WINDOW]

# 요청 횟수 검사
if len(request_log) >= MAX_REQUESTS:
	return jsonify({"response": "1시간에 5번만 질문할 수 있습니다.}), 429

# 요청 기록 갱신
request_log.append(current_time)
cache.set(client_ip, request_log, timeout=TIME_WINDOW)

# 질문 코드 위치

결과 : 5개 이상 질문하니 답변 생성을 막히는 것을 볼 수 있다.

#2 다음 질문가능 시간 알림


# 요청 횟수 검사
if len(request_log) >= MAX_REQUESTS:
	last_request_time = max(request_log)
	next_available_time = last_request_time + TIME_WINDOW
	next_available_datetime = datetime.fromtimestamp(next_available_time)
	formatted_next_available_time = next_available_datetime.strftime('%Y-%m-%d %H:%M:%S')
    
	return jsonify({"response": f"1시간에 5번만 질문할 수 있습니다. {formatted_next_available_time}에 다시 질문할 수 있습니다."}), 429

결과 : 이제 다시 질문이 가능해 지는 시간까지 알려준다.

#3 배포

local 컴퓨터에서 잘 작동되는 것을 확인했으니
1. git push를 하고 EC2에 접속해 기존 프로세스를 종료한다.
2. git pull을 하고 nohup로 백그라운드 실행을 하면 배포완료.

결과 : 영어로 질문해도 알아서 영어로 답변을 해준다.

결과 : 1시간 후에 다시 물어보니 답변을 해주겠다고 한다.

실습2 - 모달창

#1 로직

  1. 현재 airesume 화면은 page.jsx 파일 하나로 만들어져있다.
    하지만 모달창을 따로 만드는 것보다 미리 만들어진 코드를 사용하면 좋으니, 채팅창을 하나의 컴포넌트인 ChatWindow로 빼주었다.

  2. 그 후 Modal.jsx 컴포넌트를 만들어서 버튼을 눌렀을 때, children인 ChatWindow 컴포넌트가 나오도록 해주었다.

#2 코드

  1. modal.jsx 컴포넌트
import React from "react";
const Modal = ({ isVisible, onClose, children }) => {
  if (!isVisible) return null;

  const handleClose = (e) => {
    if (e.target === e.currentTarget) {
      onClose();
    }
  };

  return (
		<div
			className="container fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center z-50"
			onClick={handleClose}
		>
			<div className="rounded-lg bg-white p-6 max-w-4xl w-full max-h-screen overflow-auto shadow-lg">
				<button
					className="absolute top-2 right-2 text-lg font-semibold"
					onClick={onClose}
				>
					X
				</button>
				{children}
			</div>
		</div>
  );
};

export default Modal;
  1. 기존에 있던 hero.jsx 컴포넌트에 modal button 추가하기.
  2. ChatWindow.jsx 는 기존에 있던 airesume 폴더의 page.jsx 코드와 동일
  3. page.jsx 코드 내용은 간단해짐.
import React from "react";
import ChatWindow from "/components/ChatWindow";

const Airesume = () => {
  return (
    <div>
      <ChatWindow />
    </div>
  );
};

export default Airesume;

#3 결과

챗봇의 기능을 모달창으로도 구현이 완료되었다.

profile
Cloud Security Expert

0개의 댓글