[PYTHON] 파이썬 Flask를 활용한 간단한 질문 답변 웹사이트 만들기

2024. 1. 2. 18:04DATA PROGRAMMING/PYTHON

이 글에서는 파이썬의 Flask라는 라이브러리와 Html을 활용해 간단한 질문 답변 웹사이트를 만들어보려고 한다. Flask는 파이썬을 통해 간단한 app을 만들 수 있게 해주는 라이브러리라고 생각하면 된다.

 

사전 준비

 

내가 사용한 환경인 파이참을 기준으로 설명하자면 사용할 html파일과 파이썬 파일이 함께 있어야 작동한다.

 

위와같이 설정이 되어있으면 된다.

 

 

위 사진처럼 애초에 하나의 폴더 안에 templates를 만들어 html파일을 저장하면 편하게 작업이 가능하다.

 

기본 원리

Flask를 활용하여 웹사이트를 만드는 원리를 간단하게 설명하자면 웹사이트의 페이지 등을 구성할 html 코드 및 파일을 만들고 Flask를 활용해 해당 웹페이지들이 연결되고 적절하게 기능하도록 파이썬 코드를 만들어주면 된다. 

 

우선 웹사이트의 기본 구조에 대해서 설명해 보려고 한다. 사용자는 제일 먼저 로그인 페이지를 만난다. 이 로그인 페이지에서는 회원가입이 되어있다면 바로 Q&A 게시판의 웹페이지로 이동할 수 있으며, 회원가입이 되어있지 않다면 게시판을 이용할 수 없다. 회원가입 페이지로 들어가 히원가입을 진행한 이후에 게시판을 이용할 수 있다.

 

 

각 웹페이지

 

해당 화면은 로그인 페이지의 실제 이미지이다. 네이버의 로그인 화면을 벤치마킹 하였으며 직접 로고를 만들어 html 코드를 통해 이미지를 불러왔다.

 

<!DOCTYPE html>
<html>
<head>
    <title>로그인</title>
    <style>
        body {
            font-family: 'Arial', sans-serif;
            background-color: #f5f5dc; /* 배경색 지정 */
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
        }

        .login-container {
            background-color: rgba(255, 255, 255, 0.8);
            padding: 30px 40px; /* 위아래 여백을 20px로 조절 */
            border-radius: 8px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
            width: 300px;
            text-align: center;
        }

        h1 {
            color: #333;
        }

        input[type="text"],
        input[type="password"],
        input[type="submit"] {
            width: calc(100% - 20px);
            padding: 10px;
            margin-bottom: 10px;
            border: 1px solid #ccc;
            border-radius: 4px;
        }

        input[type="submit"] {
            background-color: #4cc18f;
            color: white;
            border: none;
            cursor: pointer;
        }

        input[type="submit"]:hover {
            background-color: #ff905a;
        }

        p {
            margin-top: 15px;
        }

        a {
            color: #ff6f61;
            text-decoration: none;
        }

        a:hover {
            text-decoration: underline;
        }

        /* 로고 이미지 스타일 */
        img.logo {
            width: 40%; /* 이미지의 너비를 조정 */
            height: auto; /* 비율을 유지하면서 높이 조절 */
            margin-bottom: 55px; /* 이미지 아래 여백 조절 */
            display: block; /* 인라인 요소를 블록 요소로 변경하여 너비 설정 적용 */
            margin-left: auto; /* 가운데 정렬을 위한 왼쪽 여백 자동 설정 */
            margin-right: auto; /* 가운데 정렬을 위한 오른쪽 여백 자동 설정 */
        }
    </style>
</head>
<body>
    <div class="login-container">
        <img src="img/logo.png" alt="로고" class="logo">
        <h1>로그인</h1>
        <form method="POST" action="/login">
            <input type="text" name="username" placeholder="사용자명" required><br>
            <input type="password" name="password" placeholder="비밀번호" required><br>
            <input type="submit" value="로그인">
        </form>
        <p>아직 계정이 없으신가요? <a href="{{ url_for('register') }}">회원가입</a></p>
    </div>
</body>
</html>

 

위는 로그인 페이지의 html 코드이다. 위에서

<img src="img/logo.png" alt="로고" class="logo">

코드를 통해 logo.png 파일을 불러온 것을 확인할 수 있다. 이는 html만으로 만들기 힘든 이미지를 외부 프로그램으로 생성후 웹페이지에 삽입할 수 있음을 보여준다.

 

 

 

 

다음은 로그인 페이지에서 넘어갈 수 있는 회원가입 페이지이다. 웹사이트에서 사용할 아이디를 만들 수 있으며, 이 페이지 역시 네이버의 회원가입 페이지를 벤치마킹하였다. 회원가입시 입력하는 주소에 대한 정보는 다음 사이트에서 무료로 제공하는 Daum API 서비스를 활용하였다.

 

 

회원가입 페이지의 html 파일이다.

 

 

 

다음으로 웹사이트의 핵심기능인 긴 글 용 게시판과 짧은 글 용 게시판이다.

 

웹사이트는 사용의 편의성과 목적에 맞게 게시판을 긴글용 게시판과 짧은 글 용 게시판으로 나누어서 구성하였다. 위의 이미지를 보면 알 수 있듯이 긴글용 게시판은 크게 추가, 검색, 수정, 삭제 네가지 기능이 있다. 각 기능을 작동시키는 것은 파이썬이 담당한다.

 

위는 파이썬 코드이다. 각 기능을 담당하는 메소드들을 만들어 주었다. 물론 각 기능의 웹페이지를 담당하는 html파일을 따로 만들어야하고 파이썬 코드를 통해 각 페이지를 엮고, 제대로 기능할 수 있게 만들어 줘야 한다. 이 과정이 생각보다 복잡해 에러가 많이 났기에 여러 차례의 수정을 해야만 했다. 

 

짧은글 게시판은 긴글 게시판에 비해 기능이 거의 없기 때문에 하나의 html 파일과 하나의 메소드를 연결해주기만 하면 되었다.

 

파이썬 Flask 원리와 총정리.

 

from flask import Flask, render_template, request, redirect, url_for, session, flash
import sqlite3
import hashlib

app = Flask(__name__)
app.secret_key = 'qwert'

db_path = "qa.db"

 

가장 먼저 flask 등 써야할 라이브러리들을 넣어 준다. 그리고 app.secrest_key를 통해 고유한 저장소를 얻을 수 있다. 이는 회원들의 정보(아이디, 비밀정보 등)을 저장할 수 있게 해준다.

 

# 데이터베이스 초기화
def init_db():
    with sqlite3.connect(db_path) as conn:
        cursor = conn.cursor()
        cursor.execute("""
            CREATE TABLE IF NOT EXISTS questions (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                question TEXT,
                answer TEXT,
                user_id INTEGER,
                answerer_id INTEGER
            )
        """)
        cursor.execute("""
            CREATE TABLE IF NOT EXISTS users (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                username TEXT NOT NULL,
                password TEXT NOT NULL,
                nickname TEXT 
            )
        """)
        conn.commit()

 

sql을 이용 할 수 있도록 해주는 sqlite3 라이브러리를 활용해 데이터베이스를 초기화해준다.

 

# 유저 정보 조회 함수
@app.template_global()
def get_user_by_id(user_id):
    if user_id is None:
        return "Unknown"

    with sqlite3.connect(db_path) as conn:
        cursor = conn.cursor()
        cursor.execute("SELECT nickname FROM users WHERE id = ?", (user_id,))
        user = cursor.fetchone()
        return user[0] if user else "Unknown"

# 초기화 함수 호출
init_db()

 

유저 정보를 조회하는 함수를 만들고, 초기화 함수를 호출한다.

@app.route('/')
def home():
    if 'logged_in' in session:
        return redirect(url_for('index'))
    else:
        return redirect(url_for('login'))

# 인덱스(질문 목록) 라우트
@app.route('/index', methods=['GET', 'POST'])
def index():
    if 'logged_in' in session:
        if request.method == 'GET':
            user_id = session.get('user_id', None)
            with sqlite3.connect(db_path) as conn:
                cursor = conn.cursor()
                cursor.execute("SELECT * FROM questions")
                questions = cursor.fetchall()
            return render_template('index.html', questions=questions, get_user_by_id=get_user_by_id, user_id=user_id)
        elif request.method == 'POST':
            # 여기에 POST 요청 처리 코드를 추가합니다.
            pass
    else:
        flash('로그인이 필요합니다.')
        return redirect(url_for('login'))

# 회원가입 라우트
@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        nickname = request.form['nickname']

        hashed_password = hashlib.sha256(password.encode()).hexdigest()

        with sqlite3.connect(db_path) as conn:
            cursor = conn.cursor()
            cursor.execute("INSERT INTO users (username, password, nickname) VALUES (?, ?, ?)", (username, hashed_password, nickname))
            conn.commit()

        flash('회원 가입이 완료되었습니다. 로그인 해주세요.')
        return redirect(url_for('login'))

    return render_template('register.html')

 

이후에 위 코드와 마찬가지로 질문 목록, 로그인, 로그아웃등 웹사이트에서 사용할 기능들을 함수로서 적용해 주면 된다. 웹페이지에서 사용할만한 웬만한 기능들은 flask 라이브러리에서 지원하는 경우가 많으니 잘 활용하면 된다.

 

이번 프로젝트를 진행하면서 파이썬의 Flask를 만드는 기본적인 원리에 대해서 이해하게 되었다. 만들고 싶은 웹페이지를 각각의 html파일을 통해 만들고, 웹페이지를 연결하고 각 페이지들이 원하는대로 작동할 수 있게 하는 역할은 파이썬이 담당하는 것이다