프로젝트

Flask와 MySQL을 사용한 간단한 사용자 관리 API 구현

Chansman 2025. 4. 18. 21:37

Flask와 MySQL을 사용한 간단한 사용자 관리 API 구현

1. 개요

이 블로그에서는 Flask와 MySQL을 사용하여 간단한 사용자 관리 API를 만드는 방법을 설명합니다. 이 API는 사용자 목록을 조회하고, 새로운 사용자를 추가하고, 기존 사용자 정보를 업데이트하거나 삭제하는 기능을 제공합니다. 또한, Flask-Smorest를 사용하여 API 문서화도 설정할 수 있습니다.

2. 전체 코드

app.py:

  • Flask, MySQL, Flask-Smorest를 사용하여 애플리케이션을 구성합니다.
  • MySQL 연동 설정을 통해 데이터베이스와 연결하고, Flask-Smorest로 API 문서화를 설정합니다.
  • user_routes.py에서 정의한 user_blp를 등록하여 사용자 관련 라우트를 관리합니다.
  • /users_interface 경로에서는 HTML 페이지를 렌더링하여 사용자 인터페이스를 제공합니다.
from flask import Flask, render_template
from flask_mysqldb import MySQL
from flask_smorest import Api
from user_routes import create_user_blueprint

app = Flask(__name__)

# MySQL 연동 설정
app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = '7722'
app.config['MYSQL_DB'] = 'oz'

mysql = MySQL(app)

# blueprint 설정 및 등록
app.config["API_TITLE"] = "My API"
app.config["API_VERSION"] = "v1"
app.config["OPENAPI_VERSION"] = "3.1.3"
app.config["OPENAPI_URL_PREFIX"] = "/"
app.config["OPENAPI_SWAGGER_UI_PATH"] = "/swagger-ui"
app.config["OPENAPI_SWAGGER_UI_URL"] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist/"

api = Api(app)

user_blp = create_user_blueprint(mysql)
api.register_blueprint(user_blp)

# html 코드로 flask-mysql 테스트
@app.route('/users_interface')  # 수정: 경로 앞에 슬래시 추가
def user_interface():
    return render_template('users.html')

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

 

Flask MySQL API 구축 블로그 포맷

목표

이 블로그에서는 Flask와 MySQL을 연동하여 간단한 RESTful API를 구축하고, flask-smorest 라이브러리를 사용하여 API 문서화 및 Swagger UI를 설정하는 방법을 다룹니다. 또한, Flask에서 MySQL 데이터베이스를 활용하여 데이터를 저장하고 조회하는 방법을 실습할 것입니다.


1. 프로젝트 설정 및 라이브러리 설치

먼저, Flask, MySQL, flask-smorest 라이브러리를 설치합니다. 프로젝트에 필요한 라이브러리는 다음과 같습니다.

pip install Flask flask-mysqldb flask-smorest

2. Flask 애플리케이션 생성

Flask 애플리케이션을 생성하고, MySQL을 연동하여 데이터베이스를 사용할 수 있도록 설정합니다. 또한, API 문서화를 위한 flask-smorest를 설정합니다.

from flask import Flask, render_template
from flask_mysqldb import MySQL
from flask_smorest import Api
from user_routes import create_user_blueprint

app = Flask(__name__)

Flask 객체는 웹 애플리케이션을 생성하는 핵심 객체입니다. 이 객체를 이용해 라우팅, 템플릿 렌더링, 데이터베이스 연결 등을 관리합니다.

3. MySQL 연동 설정

MySQL 데이터베이스를 사용하기 위해 flask-mysqldb를 설치하고, 이를 애플리케이션에 설정합니다.

# MySQL 연동 설정
app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = '7722'
app.config['MYSQL_DB'] = 'oz'

mysql = MySQL(app)
  • MYSQL_HOST: MySQL 서버의 호스트 주소 (일반적으로 localhost).
  • MYSQL_USER: MySQL 사용자 이름.
  • MYSQL_PASSWORD: MySQL 비밀번호.
  • MYSQL_DB: 사용할 데이터베이스 이름.

이 설정을 통해 mysql 객체가 생성되고, 애플리케이션과 MySQL 데이터베이스가 연결됩니다.

4. API 문서화 설정 (flask-smorest)

flask-smorest는 API 문서화 및 버전 관리를 도와주는 라이브러리입니다. Swagger UI를 통해 API를 시각적으로 볼 수 있도록 설정합니다.

# API 문서화 설정
app.config["API_TITLE"] = "My API"
app.config["API_VERSION"] = "v1"
app.config["OPENAPI_VERSION"] = "3.1.3"
app.config["OPENAPI_URL_PREFIX"] = "/"
app.config["OPENAPI_SWAGGER_UI_PATH"] = "/swagger-ui"
app.config["OPENAPI_SWAGGER_UI_URL"] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist/"

api = Api(app)
  • API_TITLE: API 문서의 제목.
  • API_VERSION: API의 버전.
  • OPENAPI_VERSION: OpenAPI 버전.
  • OPENAPI_SWAGGER_UI_PATH: Swagger UI를 확인할 경로.
  • OPENAPI_SWAGGER_UI_URL: Swagger UI를 로드할 URL.

이 설정을 통해, /swagger-ui 경로에서 API 문서를 시각적으로 확인할 수 있습니다.

5. Blueprint 설정 및 등록

Blueprint는 Flask 애플리케이션의 코드 구조를 모듈화할 수 있게 도와주는 객체입니다. user_routes.py에서 사용자 관련 라우트와 로직을 정의하여 Blueprint로 관리합니다.

user_blp = create_user_blueprint(mysql)
api.register_blueprint(user_blp)
  • create_user_blueprint(mysql): 사용자 관련 API 라우트가 포함된 Blueprint 객체를 생성합니다.
  • api.register_blueprint(user_blp): 생성된 Blueprint를 Flask API에 등록하여 사용할 수 있게 합니다.

6. 사용자 인터페이스 페이지

사용자가 인터페이스를 확인할 수 있는 간단한 HTML 페이지를 제공합니다. render_template() 함수는 지정한 템플릿 파일을 렌더링하여 응답으로 반환합니다.

@app.route('/users_interface')
def user_interface():
    return render_template('users.html')

위의 코드는 /users_interface 경로로 접속할 때 users.html 템플릿 파일을 렌더링하여 클라이언트에게 반환합니다.

7. 애플리케이션 실행

마지막으로, Flask 애플리케이션을 실행하여 API와 웹 페이지를 확인할 수 있습니다.

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

app.run(debug=True)는 개발 환경에서 Flask 애플리케이션을 실행하고, 코드 변경 시 자동으로 서버가 재시작됩니다. debug=True는 오류 메시지를 자세히 출력하게 합니다.

 

user_routes.py:

  • Flask-Smorest를 이용해 Blueprint를 정의하고 사용자 관련 API 엔드포인트를 만듭니다.
  • GET, POST, PUT, DELETE HTTP 메서드를 사용하여 사용자 데이터를 조회, 추가, 수정, 삭제하는 기능을 제공합니다.
  • MySQL 쿼리문을 사용하여 데이터베이스와 상호작용하고, jsonify를 사용하여 JSON 형식으로 응답을 반환합니다.
 
from flask_smorest import Blueprint, abort
from flask import request, jsonify

def create_user_blueprint(mysql):
    # Blueprint 객체 생성, name을 __name__으로 올바르게 설정
    user_blp = Blueprint("user_routes", __name__, url_prefix="/users", description="Operations on users")

    # 전체 유저 데이터를 불러오는 코드
    @user_blp.route("/", methods=["GET"])
    def get_users():
        cursor = mysql.connection.cursor()
        cursor.execute("SELECT * FROM users")
        users = cursor.fetchall()
        cursor.close()

        users_list = []
        for user in users:
            users_list.append({
                "id": user[0],
                "name": user[1],
                "email": user[2]
            })

        return users_list
    
    # 유저 데이터를 추가하는 코드
    @user_blp.route("/", methods=["POST"])
    def add_user():
        if not request.json:
            abort(400, message="No JSON data found in request")  # 요청에 JSON이 없으면 400 오류

        user_data = request.json
        
        cursor = mysql.connection.cursor()
        cursor.execute("INSERT INTO users (name, email) VALUES (%s, %s)", (user_data["name"], user_data["email"]))
        mysql.connection.commit()
        cursor.close()

        return jsonify({"message": "User added successfully"}), 201
    
    # 유저를 업데이트하는 함수 (UPDATE)
    @user_blp.route('/<int:user_id>', methods=['PUT'])
    def update_user(user_id):
        if not request.json:
            abort(400, message="No JSON data found in request")

        user_data = request.json
        cursor = mysql.connection.cursor()
        cursor.execute("UPDATE users SET name = %s, email = %s WHERE id = %s",
                       (user_data['name'], user_data['email'], user_id))
        mysql.connection.commit()
        cursor.close()

        return jsonify({'message': 'User updated successfully'})
      
    # 유저를 삭제하는 함수 (DELETE)
    @user_blp.route('/<int:user_id>', methods=['DELETE'])
    def delete_user(user_id):
        cursor = mysql.connection.cursor()
        cursor.execute("DELETE FROM users WHERE id = %s", (user_id,))
        mysql.connection.commit()
        cursor.close()
        return jsonify({'message': 'User deleted successfully'})
    
    return user_blp

Flask MySQL API - 사용자 CRUD 구현

이 코드에서는 Flask를 사용하여 MySQL 데이터베이스와 연결하고, flask-smorest를 이용해 사용자 CRUD(Create, Read, Update, Delete) 기능을 구현하는 방법을 다룹니다. 각 기능은 Blueprint를 사용하여 모듈화하고, API로 노출할 수 있습니다.


1. Blueprint 생성

Blueprint는 Flask에서 기능을 모듈화하는 방법입니다. 이를 통해 다양한 라우트를 그룹화하고, 다른 파일에서 쉽게 관리할 수 있습니다.

from flask_smorest import Blueprint
from flask import request, jsonify

def create_user_blueprint(mysql):
    # Blueprint 객체 생성, name을 __name__으로 올바르게 설정
    user_blp = Blueprint("user_routes", __name__, url_prefix="/users", description="Operations on users")
  • Blueprint: Blueprint 객체는 user_routes라는 이름을 가지고 있으며, /users라는 URL prefix를 사용하여 모든 사용자 관련 라우트들을 /users 경로에 매핑합니다.
  • url_prefix: /users로 시작하는 모든 경로에 대한 라우트를 정의하게 됩니다.
  • description: API 문서에서 Blueprint에 대한 설명을 추가합니다.

2. 유저 데이터 조회 (GET)

유저 목록을 데이터베이스에서 가져오는 API를 정의합니다. GET 요청을 처리하며, 모든 사용자의 정보를 반환합니다.

@user_blp.route("/", methods=["GET"])
def get_users():
    cursor = mysql.connection.cursor()
    cursor.execute("SELECT * FROM users")
    users = cursor.fetchall()
    cursor.close()

    users_list = []
    for user in users:
        users_list.append({
            "id": user[0],
            "name": user[1],
            "email": user[2]
        })

    return users_list
  • cursor.execute(): SQL 쿼리로 데이터베이스에서 users 테이블의 모든 데이터를 가져옵니다.
  • cursor.fetchall(): 쿼리 결과를 리스트 형태로 반환합니다.
  • JSON 응답: 각 사용자의 정보를 JSON 형식으로 응답합니다.

3. 유저 추가 (POST)

새로운 유저를 데이터베이스에 추가하는 API입니다. POST 요청을 처리하며, 클라이언트에서 전달된 JSON 데이터를 사용하여 새로운 유저를 추가합니다.

@user_blp.route("/", methods=["POST"])
def add_user():
    if not request.json:
        abort(400, message="No JSON data found in request")  # 요청에 JSON이 없으면 400 오류

    user_data = request.json
    
    cursor = mysql.connection.cursor()
    cursor.execute("INSERT INTO users (name, email) VALUES (%s, %s)", (user_data["name"], user_data["email"]))
    mysql.connection.commit()
    cursor.close()

    return jsonify({"message": "User added successfully"}), 201
  • request.json: 클라이언트에서 보내온 JSON 데이터를 받아옵니다. 데이터가 없으면 400 상태 코드로 오류를 반환합니다.
  • SQL INSERT: 사용자 이름과 이메일을 users 테이블에 삽입합니다.
  • JSON 응답: 유저가 추가되었다는 메시지를 클라이언트에게 반환합니다.

4. 유저 업데이트 (PUT)

기존 유저의 정보를 수정하는 API입니다. PUT 요청을 통해 특정 ID의 유저 정보를 업데이트합니다.

@user_blp.route('/<int:user_id>', methods=['PUT'])
def update_user(user_id):
    if not request.json:
        abort(400, message="No JSON data found in request")

    user_data = request.json
    cursor = mysql.connection.cursor()
    cursor.execute("UPDATE users SET name = %s, email = %s WHERE id = %s",
                   (user_data['name'], user_data['email'], user_id))
    mysql.connection.commit()
    cursor.close()

    return jsonify({'message': 'User updated successfully'})
  • URL 파라미터: user_id는 URL 경로에서 전달된 유저의 ID를 나타냅니다.
  • SQL UPDATE: 해당 ID에 맞는 유저의 이름과 이메일을 업데이트합니다.
  • JSON 응답: 성공적인 업데이트 후 메시지를 반환합니다.

5. 유저 삭제 (DELETE)

특정 유저를 삭제하는 API입니다. DELETE 요청을 사용하여 특정 ID의 유저를 데이터베이스에서 삭제합니다.

@user_blp.route('/<int:user_id>', methods=['DELETE'])
def delete_user(user_id):
    cursor = mysql.connection.cursor()
    cursor.execute("DELETE FROM users WHERE id = %s", (user_id,))
    mysql.connection.commit()
    cursor.close()
    return jsonify({'message': 'User deleted successfully'})
  • URL 파라미터: user_id는 삭제할 유저의 ID입니다.
  • SQL DELETE: 해당 ID의 유저를 users 테이블에서 삭제합니다.
  • JSON 응답: 삭제 성공 메시지를 반환합니다.

users.html:

  • 브라우저에서 사용자의 목록을 조회하고, 새로운 사용자를 추가, 기존 사용자를 업데이트하거나 삭제할 수 있는 HTML 페이지입니다.
  • JavaScript를 사용하여 API에 요청을 보내고, 받은 응답을 HTML로 표시합니다.
<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Users</title>
    <script>
      function fetchUsers() {
        fetch("/users")
          .then((response) => response.json())
          .then((users) => {
            const usersList = document.getElementById("users-list");
            usersList.innerHTML = "";
            users.forEach((user) => {
              const userItem = document.createElement("li");
              userItem.textContent = `ID: ${user.id}, Name: ${user.name}, Email: ${user.email}`;
              usersList.appendChild(userItem);
            });
          })
          .catch((error) => console.error("Error:", error));
      }

      function addUser() {
        const name = document.getElementById("name").value;
        const email = document.getElementById("email").value;
        fetch("/users", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ name: name, email: email }),
        })
          .then((response) => response.json())
          .then((data) => {
            console.log(data);
            fetchUsers();
          })
          .catch((error) => console.error("Error:", error));
      }

      window.onload = fetchUsers;

      function updateUser() {
        const userId = document.getElementById("update-user-id").value;
        const name = document.getElementById("update-name").value;
        const email = document.getElementById("update-email").value;
        fetch(`/users/${userId}`, {
          method: "PUT",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ name: name, email: email }),
        })
          .then((response) => response.json())
          .then((data) => {
            console.log(data);
            fetchUsers();
          })
          .catch((error) => console.error("Error:", error));
      }

      function deleteUser() {
        const userId = document.getElementById("update-user-id").value;
        fetch(`/users/${userId}`, {
          method: "DELETE",
        })
          .then((response) => response.json())
          .then((data) => {
            console.log(data);
            fetchUsers();
          })
          .catch((error) => console.error("Error:", error));
      }
    </script>
  </head>

  <body>
    <h1>Users</h1>
    <ul id="users-list">
      <!-- 사용자 목록이 여기에 표시됩니다. -->
    </ul>

    <h2>Add User</h2>
    <input type="text" id="name" placeholder="Name" />
    <input type="email" id="email" placeholder="Email" />
    <button onclick="addUser()">Add User</button>

    <h2>Update/Delete User</h2>
    <input type="number" id="update-user-id" placeholder="User ID" />
    <input type="text" id="update-name" placeholder="New Name" />
    <input type="email" id="update-email" placeholder="New Email" />
    <button onclick="updateUser()">Update User</button>
    <button onclick="deleteUser()">Delete User</button>
  </body>

</html>

Flask 사용자 관리 웹 페이지 (HTML + JavaScript)

이 HTML 페이지는 Flask로 구현된 사용자 API와 연동하여, 사용자 목록을 조회하고, 새로운 사용자 추가, 기존 사용자 수정, 삭제 기능을 제공하는 웹 인터페이스입니다. 각 기능은 JavaScript fetch() 메서드를 사용하여 API와 비동기적으로 통신합니다. 이제 각 부분을 세부적으로 설명하겠습니다.


1. 사용자 목록 조회

fetchUsers() 함수는 Flask에서 제공하는 /users 엔드포인트를 호출하여 사용자 목록을 가져옵니다. API 응답을 JSON 형태로 처리하고, 이를 HTML로 표시하는 기능을 합니다.

function fetchUsers() {
  fetch("/users")
    .then((response) => response.json())
    .then((users) => {
      const usersList = document.getElementById("users-list");
      usersList.innerHTML = "";
      users.forEach((user) => {
        const userItem = document.createElement("li");
        userItem.textContent = `ID: ${user.id}, Name: ${user.name}, Email: ${user.email}`;
        usersList.appendChild(userItem);
      });
    })
    .catch((error) => console.error("Error:", error));
}
  • fetch("/users"): /users API 엔드포인트에 GET 요청을 보내고, 반환된 JSON 데이터를 처리합니다.
  • users.forEach(): 받은 사용자 데이터 배열을 순회하며 각 사용자의 정보를 <li> 태그로 화면에 추가합니다.

2. 사용자 추가 (POST)

addUser() 함수는 사용자 이름과 이메일을 입력받아 /users API 엔드포인트로 POST 요청을 보내고, 새로운 사용자를 데이터베이스에 추가합니다.

function addUser() {
  const name = document.getElementById("name").value;
  const email = document.getElementById("email").value;
  fetch("/users", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ name: name, email: email }),
  })
    .then((response) => response.json())
    .then((data) => {
      console.log(data);
      fetchUsers();
    })
    .catch((error) => console.error("Error:", error));
}
  • fetch("/users", { method: "POST", body: JSON.stringify({ name, email }) }): POST 메서드를 사용하여 JSON 데이터를 서버로 전송합니다.
  • fetchUsers(): 사용자가 추가된 후, fetchUsers()를 호출하여 새로운 사용자 목록을 갱신합니다.

3. 사용자 업데이트 (PUT)

updateUser() 함수는 사용자 ID와 새로운 이름, 이메일을 입력받아 /users/:userId API 엔드포인트로 PUT 요청을 보내고, 기존 사용자의 정보를 업데이트합니다.

function updateUser() {
  const userId = document.getElementById("update-user-id").value;
  const name = document.getElementById("update-name").value;
  const email = document.getElementById("update-email").value;
  fetch(`/users/${userId}`, {
    method: "PUT",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ name: name, email: email }),
  })
    .then((response) => response.json())
    .then((data) => {
      console.log(data);
      fetchUsers();
    })
    .catch((error) => console.error("Error:", error));
}
  • fetch(/users/${userId}, { method: "PUT", body: JSON.stringify({ name, email }) }): 사용자의 ID에 해당하는 경로로 PUT 요청을 보냅니다. 새로운 이름과 이메일을 요청 본문에 포함하여 전달합니다.

4. 사용자 삭제 (DELETE)

deleteUser() 함수는 삭제할 사용자 ID를 입력받아 /users/:userId API 엔드포인트로 DELETE 요청을 보내고, 해당 사용자를 삭제합니다.

function deleteUser() {
  const userId = document.getElementById("update-user-id").value;
  fetch(`/users/${userId}`, {
    method: "DELETE",
  })
    .then((response) => response.json())
    .then((data) => {
      console.log(data);
      fetchUsers();
    })
    .catch((error) => console.error("Error:", error));
}
  • fetch(/users/${userId}, { method: "DELETE" }): DELETE 요청을 사용하여 해당 ID의 사용자를 삭제합니다.

5. 페이지 로드 시 사용자 목록 자동 조회

window.onload = fetchUsers; 코드가 페이지가 로드될 때 자동으로 사용자 목록을 가져오는 기능을 합니다. 페이지가 처음 로드될 때 fetchUsers()가 호출되어 사용자 목록이 표시됩니다.


6. HTML 구조

HTML 페이지는 사용자의 목록을 표시하는 <ul id="users-list">와 사용자를 추가, 수정, 삭제하는 폼을 포함하고 있습니다.

 
<h1>Users</h1>
<ul id="users-list">
  <!-- 사용자 목록이 여기에 표시됩니다. -->
</ul>

<h2>Add User</h2>
<input type="text" id="name" placeholder="Name" />
<input type="email" id="email" placeholder="Email" />
<button onclick="addUser()">Add User</button>

<h2>Update/Delete User</h2>
<input type="number" id="update-user-id" placeholder="User ID" />
<input type="text" id="update-name" placeholder="New Name" />
<input type="email" id="update-email" placeholder="New Email" />
<button onclick="updateUser()">Update User</button>
<button onclick="deleteUser()">Delete User</button>
  • <ul id="users-list">: 사용자의 목록을 동적으로 추가할 곳입니다. fetchUsers() 함수가 호출되면 여기에 각 사용자가 <li> 태그로 추가됩니다.
  • 사용자 추가, 수정, 삭제 폼: 사용자 이름, 이메일을 입력하고, 버튼을 클릭하여 추가, 수정, 삭제할 수 있는 입력 폼이 있습니다.

 

3. 학습 포인트

  • Flask 애플리케이션을 설정하고, MySQL을 연동하여 데이터베이스와 상호작용하는 방법.
  • Flask-Smorest를 사용하여 API 문서화 및 Blueprint 구조로 API를 관리하는 방법.
  • 클라이언트 측에서는 JavaScript를 사용하여 API와 상호작용하고, 실시간으로 데이터를 업데이트하는 방법.

4. 결론

이 예제는 Flask를 이용하여 MySQL 데이터베이스와 연동하고, Flask-Smorest로 API 문서화를 진행하며, HTML과 JavaScript로 사용자 인터페이스를 만드는 방법을 보여줍니다. 각 기술을 유기적으로 연결하여 RESTful API 및 클라이언트-서버 간의 실시간 데이터 통신을 구현할 수 있습니다.