본문 바로가기

파이썬

Flask를 이용해 ChatGPT를 이용한 챗봇이 있는 웹페이지 만들어보기 3 [Python, OpenAI, Flask, Svelte, Routify, Cursor IDE]

반응형
터미널에서 입력하는 명령어일 경우
>
로 작성함

해당 포스팅의 경우 따라해보기이기 때문에 개념이나 기타 지식에 대한 설명이 부족할 수 있습니다.

이전 포스팅에서 그냥 Python이랑 Flask만 사용해서 프로젝트를 구성하려고 했더니 프론트 라이브러리/프레임워크 붙이는 게 녹록치 않아서.. 아예 백엔드랑 프론트엔드를 분리해 프로젝트를 구성해보려고 한다.

 

프론트는 Svelte를 사용해보자.

 

우선 nodejs를 다운로드 받는다. 

https://nodejs.org/en

최근 버전 중 추천되는 버전을 다운로드 받자.

 

msi파일이 다운로드되면 실행해서 node를 설치한다. 변경할거없이 그냥 계~~~~~~~~~~속 다음버튼을 누르자

 

터미널에

> node -v

를 쳤을 때 20.11.0이라고 나오면 설치가 잘 된거다.


참고한 글

https://cabreraalex.medium.com/svelte-js-flask-combining-svelte-with-a-simple-backend-server-d1bc46190ab9

https://v3.routify.dev/docs/guide/installation/manual-installation

https://freeseamew.gitbook.io/svelte/4./bind


 

1. 프로젝트 폴더 경로로 터미널 경로도 맞춰준다 (main.py 파일이 있는 폴더에 들어간다)

원래 있던 파일들중에서는 main.py, venv 폴더, .env 빼고 모두 지우자.

ex)

C:\Users\User\.cursor-tutor\prj가 프로젝트 경로라면

터미널에서 경로도 위와 같도록 맞춰준다.

상위 폴더로(한 단계 바깥폴더로)

> cd ..

하위 폴더로(한 단계 안쪽폴더로)

> cd prj

 

2. sveltjs 및 routify 설치 (sveltjs 및 routify 가 client폴더 하위에 설치된다.)

> npm init routify@latest

둘 중 하나로 선택하면 되는데 나는 3으로 함. 엔터누르자
원하는 프론트엔드 서버 폴더 명을 입력한다. 나는 client로 입력함
특별한 게 없다면 starter-basic인 상태로 엔터를 누르자. 기본 프로젝트 구성을 만들어준다.
examples로 해도 되는데, 나는 components로 진행했다. 예시 부분 템플릿을 만들어준다.
편한대로 하면 되는데 이 포스팅만 보고 따라왔다면 npm으로 선택하자
라이브러리 설치중.. 생각보다 한참 걸리니 기다리자.


설정이 완료됐다. 친절하게도 다음 순서를 알려준다. cd {폴더명}을 입력해 이동하고 npm run dev를 입력해주면 서버가 실행된다.

> cd client

* client 경로는 각각 만든 폴더명으로 바꿔 입력하면 됨. 앞으로 만든 폴더명은 client로 작성하겠음

> npm run dev

실행됐다. 브라우저에 http://localhost:1337을 입력하고 들어가보자
그럼 routify에서 생성해준 샘플 페이지가 노출된다.

그리고나서는 우선 터미널에서 Ctrl + C 를 눌러 프론트엔드 서버를 종료하자.

 

3. IDE로 돌아와 prj/client/src 폴더를 확인해보자.

이런 구조로 되어있는데, 각각 파일 및 폴더는 아래와 같은 역할을 한다.

3-1. components

- 재사용할 템플릿을 넣는다. 예를 들면 Header, Footer, Nav, ProgressBar, List, Table 등등 공통 템플릿을 넣는다고 보면 된다.

 

3- 2. routes

- routify는 기본적으로 routes 하위 폴더 구조를 기준으로 라우팅해준다. 그리고 그 폴더의 index.svelte를 라우팅해주는거다. * routes/index.svelte/경로에서 보여준다.

- 이게 무슨소리냐면 현재 routes/examples/[mode]/{하위폴더들.. 예를들어 history}로 되어있는데 이는 브라우저에 http://localhost:1337/examples/[mode]/history를 입력하면 examples안에 있는 [mode]안에 있는 history폴더를 바라보겠다는 뜻이다.

- [mode]는 무엇이냐하면 파라미터다. mode라는 이름으로 파라미터를 받겠다는거다.

브라우저에  http://localhost:1337/examples/full/history 이라고 입력하면 /routes/examples/[mode] 폴더 내의 _module.svelte에서는 mode라는 변수를 받을 수 있는데 여기에 바로 full이라는 값이 들어가 있다.

- 여기서 또, 그럼 _module.svelte는 뭐냐? 바로 공통 레이아웃을 잡아주는 파일이다. 여기서 기본적인 틀을 잡는다.

 

폴더는 다 봤으니 파일을 보자

3- 3. App.svelte

- 가장~~~~~최상위의 컴포넌트라고 보면 된다. 딱히 건드릴 코드는 없으니 놔두자. 라우팅에 대한 코드가 들어가있다.

 

3- 4. main.js

- 실질적인 프론트엔드 서버라고 해야할까? 앱을 실행하면 가장 먼저 실행되는 코드다. 여기 또한 건드릴 게 딱히 없으니 놔두자.

 

3- 5. types.d.ts

- 흠 일단 무시하자 이번 포스팅들에서는 딱히 건드릴 일 없는 파일이다.

 

3- 6. package.json

- 실행 스크립트 및 의존성 등이 들어가있다. 웬만하면 건드리지 말자.

 

3- 7. index.html

- 가장 기본 틀이 될 html 마크업이다. 외부 css나 script를 불러오려면 여기에 추가하면 된다.

 

3- 8. tsconfig.json

- typescript에 대한 설정값인데 건드릴 부분이 크게 없다.

 

3- 9. vite.config.js

- vite.js에 대한 설정값인데 건드릴 부분이 크게 없다.


4. 그럼 semantic-ui를 먼저 추가하자.

/client/src/index.html 파일을 열어 jquery 및 css와 js를 불러오는 스크립트를 추가한다.

head 태그 내부의 <script type="module" src="/.routify/routify-init.js"></script> 아래에 추가한다.

<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.3/dist/semantic.min.css">
<script src="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.3/dist/semantic.min.js"></script>

 

5. 다음으로는 store 라는 것을 만들어줄건데, 이게 뭐냐면 svelte에서 사용하는 저장소?같은거라고 보면 된다.

왜 만드냐면 우리는 이제 페이지마다 들고 다녀야 하는 데이터가 있을 수 있다. 예를 들면 로그인한 회원의 닉네임이라던가, Header Title 이라던가.. 그리고 또 부모 컴포넌트와 자식 컴포넌트 사이에 데이터를 주고 받아야 할 일이 생길 것이기 때문에 만들어 보려고 한다.

/client/src/ 경로에 store.js 파일을 생성하고 아래 코드를 추가한다.

import { writable } from 'svelte/store'

export const headerName = writable('')
export const userName = writable('')

수정이 가능한 headerNameuserName을 만들었다.

 

6. 다음은 우선 레이아웃을 만들어보자. /client/src/ 경로에 components라는 폴더를 만들고 그 안에 Header.svelte, Footer.svelte 파일을 만들어주자. 내용은 나중에 입력하면 되니 대충 <div>header~</div>이나 <div>footer~</div> 같은 마크업만 넣어두자.

그리고서 /client/src/routes/_module.svelte 파일을 열어 아래 코드를 추가한다.

<script>
	import { headerName } from '../store.js'
	import Header from '../components/Header.svelte'
	import Footer from '../components/Footer.svelte'

    let headerValue;
    headerName.subscribe((data) => {
        headerValue = data;
    })
</script>

<div class="ui">
    <Header headerName={headerValue} />
    <slot />
    <Footer />
</div>

 

headerName.subscribe(()=>{}) 해당 부분이 바로 store에서 headerValue를 가져오는 코드다. 

아래 마크업쪽을 보면 <Header headerName={headerValue} />가 있는데 이게 바로 아까 components에 만든 Header를 불러와 HeaderName이라는 변수명으로 headerValue를 넘겨준다는 것이고, <slot />은 컨텐츠가 들어갈 곳이며 <Footer /> 또한 Footer 컴포넌트를 가져오는거다.

다른 페이지에 들어갔을 때 아래처럼 디폴트 레이아웃이 잡힌다는 뜻이다.

<div class="ui">
    <div>Header~</div>
    ....contents
    <div>Footer~</div>
</div>

 

자 그러면 Header 컴포넌트에 HeaderName을 넘겨주었기 때문에 Header에 해당 값을 뿌려줘보도록 하자.

Header.svelte 파일로 이동해 코드를 아래와 같이 수정한다.

<script>
	export let haderName;
</script>
<div>
	{headerName}
</div>

 

이러면 스크립트 단에서 변수로 받아온 headerName을 div에 보여줄 수 있다.

 

7. 메인 화면을 만들어보자.

/client/src/routes/index.svelte 파일을 열어 아래 코드를 추가한다.

<script>
    import { onMount } from "svelte";
    import { headerName } from "../store";

    onMount(async () => {
        headerName.set('메인화면')
    })

</script>
<div>
    내용입니다
</div>

 그리고 서버를 실행한 뒤 브라우저에서 접속해보면 짜잔~

 

8. 이제 백엔드 서버와 API로 소통해보자.

우선 cors 설정을 위해 라이브러리 하나를 다운로드 받자.

> pip install flask_cors

main.py 파일을 열어 API를 하나 추가한다.

from flask import Flask,render_template,session, request, send_from_directory, make_response, jsonify
from openai import OpenAI
from dotenv import load_dotenv
from flask_cors import CORS
import os
import uuid

app = Flask(__name__)
#uuid로 변경
app.secret_key = uuid.uuid4().hex
#서로 다른 도메인인 url이라도 요청 가능하게 CORS처리 (중요)
CORS(app)

# First API
@app.route('/data')
def data():
    print('Request:: Data')
    try:
		return make_response(jsonify({"result": True, "resultCode": 200, "message": "와~ 성공!"}), 200)
    except Exception as e:
        print('-----------------------')
        print('Error:: Data')
        print(e)
        print('-----------------------')
        return make_response(jsonify({"result": False, "resultCode": 500, "message": "실패ㅠㅠ"}), 500)

 

실행한다.

이제 vite.config.js 파일을 열어 맨 하단으로 스크롤을 내려보자.

해당 부분을

이런식으로 바꿔준다. 포트는 그냥 내가 지정해둔거라 따라하시는 분들은 그냥 그대로 두셔도 무관함

	server: { 
        port: 3000,
        proxy: {
            '/api': {
                target: 'http://localhost:5000',
                changeOrigin: true,
                rewrite: path => path.replace(/^\/api/, ''),
                secure: false,
            }
        }
    },

 

이게 무슨 소리냐, 프론트엔드에서 /api/data 로 요청하면 /api는 공백으로 치환하고 localhost:5000의 /data로 요청한다는 뜻이다.

/api/data ▶ http://localhost:5000/api/data  ▶ http://localhost:5000/data로 요청

저장했으면 /client/src/routes/index.svelte로 이동해보자.

<script>    
    import { onMount } from "svelte";
    import { headerName } from "../store";

    onMount(async () => {
        headerName.set('메인화면')
    })

    let content = '내용입니다.';

    const getData = async () => {
        const response = await fetch('/api/data', {
				method: 'GET'
			})
			.then((response) => response.json())
			.then((data) => {
				if(data.result == true){
                    content = data.message
                }else{
                    content = '요청이 실패했어요..ㅠㅠ';
                }
			})
			.catch((error) => {
				console.error('error', error);
			});
    }

</script>
<div>
    <p>
        {content}
    </p>
    <button on:click={getData}>요청</button>
</div>

 

화면이 모두 그려지고나면 headerName을 "메인화면"으로 바꾸고, content에는 디폴트 값으로 "내용입니다." 를 넣어준다. 

그리고 [요청] 이라는 버튼을 만들어 클릭할 경우 getData()라는 함수를 실행해 api서버의 /data에 요청을 보내 값을 받아오고, 그 값을 content에 할당해 컨텐츠 내용을 바꿔주는 코드다.

우선 새 터미널을 하나 열어 프론트엔드 서버를 실행시켜주자.

새 터미널 여는 법~

그리고 경로를 ...\{프로젝트폴더}\{프론트엔드 서버 폴더(나는 client)}로 맞춰준 뒤 아래 명령어를 실행한다.

> npm run dev

그리고 브라우저에 url을 입력해보면? 짜잔~ (포트를 따로 수정하지 않았다면 http://localhost:1337)

요청을 한 번 눌러보자~

 

아까 python 코드로 리턴해줬던 문구로 변경되는 것을 볼 수 있다.

 

 

다음 포스팅에서는 위 내용들을 응용해 백엔드에서 ChatGPT와 소통하고 화면에 실시간으로 뿌려주는 것을 해 볼 예정이다.

 

 

다음 포스팅

2024.02.22 - [파이썬] - Flask를 이용해 ChatGPT를 이용한 챗봇이 있는 웹페이지 만들어보기 4 [Python, OpenAI, Flask, Svelte, Routify, Cursor IDE]

 

이전 포스팅

2024.01.30 - [파이썬] - Flask를 이용해 ChatGPT를 이용한 챗봇이 있는 웹페이지 만들어보기 2 [Python, OpenAI, Flask, Cursor IDE]