Flask + React 연동하기

ch_yerini·2022년 10월 9일
4
post-thumbnail

이 게시글은
Flask + React 프로젝트를 만드는 방법 | 파이썬 백엔드 + 리액트 프론트엔드
영상을 정리한 글입니다.

React와 Flask 웹 서버를 연동한 웹 애플리케이션 프로젝트를 만들어보자!

Flask 백엔드

프로젝트 폴더에 flask-server 폴더를 생성한다.
이 파일에 서버와 관련된 파일들이 들어가게 될 것이다.

패키지 설치와 가상환경 설정

1. 가상환경 만들기

생성한 flask-server 폴더에 가상환경을 생성해보자

(1) 가상환경 생성

flask-server 폴더에 들어간 후 터미널에서

python3 -m venv venv

명령어를 실행하여 venv 라는 가상환경을 만든다.

(2) 가상환경 실행

터미널에서 아래의 명령어를 통해 venv 가상환경을 실행한다.

source venv/bin/activate

2. flask 설치

가상환경을 실행한 상태에서 flask를 설치한다.

pip3 install Flask

이제 python 파일 안에 flask를 import 하면 flask 사용이 가능하다!

오류
flask import를 해도 VScode에서 설치한 flask를 인식하지 못하는 오류가 발생했는데

VScode로 flask-server 파일을 바로 열면 해당 문제가 발생하지 않는다.

심지어 실행에도 전혀 문제가 없어 더 자세한 이유는 찾아봐야 할 것 같다...

서버 파일 작성하고 실행하기

간단한 user 데이터를 client와 주고 받을 수 있도록 서버 파일을 생성해보자.

1. 서버 파일

(1) 코드 작성

flask-server 폴더 안에 server.py 파일을 하나 생성하여 아래 코드를 작성한다.

from flask import Flask # Flask

app = Flask(__name__)

@app.route('/users')
def users():
	# users 데이터를 Json 형식으로 반환한다
    return {"members": [{ "id" : 1, "name" : "yerin" },
    					{ "id" : 2, "name" : "dalkong" }]}
           

if __name__ == "__main__":
    app.run(debug = True)
    

(2) 서버 실행

python server.py

위 명령을 실행하여 서버 파일을 실행한다.

http://127.0.0.1:5000 에서 서버가 돌아가고 있음을 알 수 있다.

(3) Json 데이터 확인

127.0.0.1:5000/users 를 통해 (1)에서 작성한 코드에 따라 users Json 데이터에 접근할 수 있다.

React 프론트엔드

React 시작하기

1. React 파일

(1) create-react-app

프로젝트 파일 안에서 아래의 명령어를 터미널에서 실행한다.

npx create-react-app client

client 라는 이름의 react 프로젝트가 만들어졌다.

npm start 명령어를 실행하면

localhost:3000 에서 웹이 실행되는 것을 확인할 수 있으며 해당 주소로 접속하면 아래와 같은 화면을 볼 수 있다.

(2) 불필요한 파일 삭제

React 프로젝트 파일 안에 index.css, logo.svg, App.test.js 같은 파일은 삭제하고 다른 파일 안에 삭제한 파일들을 import하는 코드도 삭제한다.

Flask 와 React 연동하기

React에서 Flask 서버에 접근할 수 있도록 설정한다.

React 프로젝트에 flask 서버 연결

1. proxy 구성

React 프로젝트 안에서 htttp://127.0.0.1:5000 주소에 직접 접근하려고 하면 오류가 발생한다. (CORS issues)

이를 해결하기 위해 React에 proxy를 구성해주어야 한다.

(1) package.json 파일 수정

package.json 파일에 proxy를 추가해준다.
flask 서버의 주소를 값으로 넣어준다.

2. 결과 확인하기

(1) App.js 코드 작성하기

이제 "/users" 주소를 이용하여 "htttp://127.0.0.1:5000/users" 에 있는 데이터에 접근할 수 있다.

아래와 같이 App.js 코드를 작성하여 데이터에 잘 접근되었는지 확인한다.

  • useEffect 를 이용하여 웹을 처음 실행할 때만 데이터를 받아오는 작업을 실행하도록 한다.
  • fetch 를 통해 주소에 있는 데이터를 GET 해온다.
import { useEffect } from 'react';
import './App.css';

function App() {
  useEffect(() => {
    fetch("/users").then(
      // response 객체의 json() 이용하여 json 데이터를 객체로 변화
      res => res.json()
    ).then(
      // 데이터를 콘솔에 출력
      data => console.log(data)
    )
  },[])
  
  return (
    <div className="App">
    </div>
  );
}

export default App;

⚠️ 오류
잘 연결되다가 가끔 http://127.0.0.1:5000/에 접근이 불가능하다고 뜨는 오류가 발생했다.

출처 에서 확인한 결과
맥북의 AirPlay 기능 때문에 발생한 오류여서 AirPlay 설정에 들어가 기능을 꺼주었다.

(2) 데이터 확인

React 앱을 실행하여 콘솔을 확인해보면
해당 주소의 데이터를 잘 받아온 것을 확인할 수 있다.

3. 브라우저 화면에 데이터 렌더링하기

(1) App.js 코드 작성

받은 데이터를 화면에 간단하게 출력해보자

  • useState 이용하여 data를 저장할 state 변수 data 와 state 변경 함수 setData 를 만든다.
  • fetch가 완료되어 데이터를 받아오면 setData 함수를 통해 data state를 변경해준다. -> 화면이 re-rendering 될 것이다.
  • 받아온 데이터를 map 함수를 이용하여 화면에 렌더링 한다.
import React from 'react';
import { useState, useEffect } from 'react';

function App() {
  // state
  const [data, setData] = useState([{}])

  useEffect(() => 
    {
    	fetch("/users").then(
          response => response.json()
        ).then(
          data => {
            // 받아온 데이터를 data 변수에
            setData(data);
          }
        ).catch(
          (err) => console.log(err)
        )
    }, [])

  return (
    <div className='App'>
      <h1>test 하는 중...</h1>
      <div>
        {data.users.map((u) => <p key={u.id}>{u.name}</p>)}
      </div>
    </div>
  )
}

export default App;

⚠️ 위의 처럼만 작성하면 화면에 아무것도 뜨지 않는다.

콘솔을 살펴보면
undefinedmap 를 적용할 수 없다는 오류가 뜬다.
data를 잘 받아왔는데 왜 data.usersundefined라는 걸까?

(2) 오류 해결

  • fetch는 비동기적으로 작동하기 때문에 실행이 완료되지 않아도 렌더링하는 코드가 먼저 실행될 수 있다.
  • 그렇게 되면 fetch가 완료되어 데이터를 다 받아오기 전까지 data.usersundefined 일 것이다.
  • 이런 상황에 대한 처리가 따로 필요하다. -> loading 중으로 화면에 표시
import React from 'react';
import { useState, useEffect } from 'react';

function App() {
  // state
  const [data, setData] = useState([{}])

  useEffect(() => 
    {
    	fetch("/users").then(
          response => response.json()
        ).then(
          data => {
            // 받아온 데이터를 data 변수에 update
            setData(data);
          }
        ).catch(
          (err) => console.log(err)
        )
    }, [])

  return (
    <div className='App'>
      <h1>test 하는 중...</h1>
      <div>
        {/* 삼항연산자 */}
        { (typeof data.users === 'undefined') ? (
          // fetch가 완료되지 않았을 경우에 대한 처리
          <p>loding...</p>
        ) : (
          data.users.map((u) => <p>{u.name}</p>)
        )}
      </div>
    </div>
  )
}

export default App;

(3) 결과 화면

다시 React를 실행하면 결과가 잘 나오는 것을 확인할 수 있다.

2개의 댓글

comment-user-thumbnail
2023년 10월 4일

좋은 정보 감사합니다

답글 달기
comment-user-thumbnail
2024년 1월 17일

@shell shockers 이 글을 쓴 작성자에게 진심으로 감사드립니다.

답글 달기