web3

pansy·2026년 8월 16일

백엔드(back-End)

웹사이트나 앱에서 사용자의 눈에 보이지 않는 곳에서 데이터를 처리하고 시스템을 작동시키는 서버, 데이터 베이스 등 프로그램 뒤를 관리하는 영역이다.

프론트엔드와 백엔드 구조를 가진다.

Flask

백엔드 개발에 많이 쓰이는 파이썬 프레임 워크이다.
간단한 문법과 가벼운 실행이 특징이다.
파이썬으로 작성되어 가볍고 유연하다.

UV

초고속 파이썬 패키지 및 프로젝트 관리자이다.
rust로 만들어서 굉장히 빠르다.
pip 설치 기능을 가지고 있다.
버전 관리가 쉽게 되있어 가상 환경을 만들 때 프로젝트마다 환경 부담이 줄어든다.

rust란
메모리 안전성과 뛰어난 성능을 동시에 제공하는 시스템 프로그래밍 언어이다.

Flask, 기본 라우팅 문법

@app.route("/경로", methods=["..."]
def xx():

/ 경로에 methods 안에 있는 메서드로 들어왔을 때 xx 함수를 실행한다.

request, 감시자

웹 브라우저(클라이언트)가 서버로 보낸 모든 요쳥 정보를 담고 있는 전역 객체이다.
클라이언트가 어떻게 요청을 보냈고 뭘 보냈는지 다 알 수 있다.

name = request.args.get("name","pca")

render_template

render_template("이름.html")

현재 경로에 있는 templates/이름.html을 반환한다.

Jinja Template

html 안에 flask에 변수, 조건문, 반복문 등을 사용할 수 있게 하는 도구

{{변수}}
{{% 로직 $}}

flask에서 session 만들기 및 할당하기

session["key"] = "value" (value에 딕셔너리, 문자열 사용가능)

flask를 이용하여 로그인 페이지 만들기

from flask import Flask, render_template, request, session

app = Flask(__name__)
app.secret_key = '1234'  # Replace with a secure secret key

users = {}

@app.route("/register", methods={"GET", "POST"})
def register():
   if request.method == 'post':
      username = request.form['username']
      password = request.form['password']
      if username in users:
         return "user already exisists"
      users[username] = password
      return "register sucessfull"
   return render_template('register.html')

@app.route("/login", methods=['GET', 'POST'])
def login():
   if request.method == 'post':
    username = request.form['username']
    password = request.form['password']
    if username in users[username] == password:
       return "login succsessfull"
    session['username'] = username

    
   else:
      return "fail"
   return render_template('login.html')
   
if __name__ == "__main__":
    app.run(port=5555, debug=True)
    ```

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Register</title>
</head>
<body>
    <form action="/register" method="post">
        <input type="text" name="username" placeholder="Username">
        <input type="password" name="password" placeholder="Password">
        <button type="submit">Register</button>
    </form> 
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>web</title>
</head>
<body>
    <form action="/login" method="post">
        <input type="text" name="username" placeholder="Username">
        <input type="password" name="password" placeholder="Password">
        <button type="submit">Login</button>
    </form> 
</body>
</html>

DB란 - Data Base

여러 사람에 의해 공유되어 사용될 목적으로 통합하여 관리되는 데이터의 집합을 말한다. - 데이터 집합소
데이터 베이스를 사용하는 이유는 서버를 끄면 데이터가 다 날라가기 때문에 데이터 베이스를 사용한다.
데이터 베이스는 서버를 꺼도 데이터가 데이터 베이스에 남아있기 때문에 데이터가 날라가지 않는다.

행과 열
회원의 이름(열), 나이(열), 성별(열)을 저장할 때 하나의 결과 (행)로 저장하는 과정
즉, 행은 가로방향의 개별 데이터 단위로, 하나의 객체나 사람에 대한 모든 정보를 담는다.
열은 세로 방향의 속성 단위로 이름, 나이, 성별 등 공통된 데이터 종류를 나타낸다.

sqlite3

경량화된 데이터베이스이다.
서버가 없기 때문에 따로 db서버를 열어둘 필요가 없다.
단일 파일로 로컬에 파일로 저장할 수 있다.
문법이 쉽고 간편하다.
flask와 잘 어울린다.

즉, 별도의 서버 없잉 파일 하나로 가볍게 작동하는 초경량 관계형 데이터 베이스(RDBMS)이다.
스마트폰, 앱, 웹 등에서 널리 사용된다.

TABLE 생성 명령어

CREATE TABLE 테이블 이름 ( 열이름1 데이터 타입, 열이름2 데이터 타입);

이미 이름이 같은 테이블이 있으면 오류 대신 무시한다.

예시코드

CREATE TABLE my_table (
    pansy TEXT,
    "17" INTEGER
);

데이터 조회 명령어

  • SELECT(데이터 전체 조회) : 데이터의 특정 열을 선택하거나, 모든 열을 한번에 조회할 수 있다.

    모든 열 조회
    SELECT * FROM my_table;

특정 열만 조회
SELECT pansy FROM my_table;

  • WHERE(조건 데이터 조회) : 원하는 데이터의 조건을 저장하여 필터링한다.
    문자열 데이터는 (' ')로 감싸야 한다.

문자열 조건 검색(pansy 열의 값이 'flower인 데이터) SELECT * FROM my_table WHERE pansy = 'flower`;

이 외에도 숫자 조건 (<,>, <=, >=, ==), 다중 조건(AND,OR) 등을 사용할 수 있다.

데이터 삽입 명령어

모든 열에 값을 순서대로 넣을 때 사용한다.
문자열 데이터는 (' ')로 감싸야 한다.

INSERT INTO my_table VALUES ('pansy', 17)

이 외에도 열 이름을 지정하여 삽입하거나 특정 열에만 데이터 삽입도 가능하다.

데이터 업데이트 명령어

원하는 데이터만 골라서 수정하려면 WHERE을 함께 사용해야한다.
WHERE를 생략하면 테이블의 모든 행이 변경되므로 주의해야 한다.

  • pansy열의 값이 'violet`인 행을 찾아, "17"열의 값을 30으로 수정
    UPDATE my_table 
    SET "17" = 30 
    WHERE pansy = 'violet';
이 외에도 여러 열을 동시에 업데이트 할 수도 있고 전체 데이터를 수정할 수도 있다.

### 데이터 삭제 명령어
데이터를 수정할 때와 마찬 가지로, 특정 데이터만 삭제하려면 `WHERE`을 함께 사용해야 한다.

- pansy 열의 값이 `rose`인 행만 골라서 삭제

``` py
DELETE FROM my_table 
WHERE pansy = 'rose';

이 외에도 여러 조건을 만족하는 데이터 삭제, 테이블의 모든 데이터 삭제가 가능하다.

Flask 문법과 sqlite3를 이용한 게시판 만들기

main 코드

import sqlite3
from flask import Flask, render_template, request, session
app = Flask(__name__)
app.secret_key = '1234'
users = {}

@app.route("/register", methods={"GET", "POST"})
def register():
   if request.method == 'POST':
      username = request.form['username']
      password = request.form['password']
      if username in users:
         return "user already exisists"
      users[username] = password
      return "register sucessfull"
   return render_template('register.html')

@app.route("/login", methods=['GET', 'POST'])
def login():
   if request.method == 'POST':
    username = request.form['username']
    password = request.form['password']
    if username in users and users[username] == password:
       session['username'] = username
       return "로그인 성공"

    return "fail"
   return render_template('login.html')

@app.route("/write", methods=["GET", "POST"])
def write():
    if request.method == "POST":
        title = request.form["title"]
        content = request.form["content"]

        db = sqlite3.connect("write.db")   
        db. execute(
            "INSERT INTO posts (title, content) VALUES (?, ?)",
            (title, content)
        )

        db.commit()
        db.close()
        return "작성 완료" 
    return render_template("write.html")

@app.route("/posts")
def posts():
    db = sqlite3.connect("write.db")

    posts = db.execute(
        "SELECT * FROM posts"
    
    ).fetchall()

    db.close()
    return render_template("posts.html", posts=posts)

@app.route("/edit/<int:id>", methods=["GET", "POST"])
def edit(id):
   db = sqlite3.connect("write.db")

   if request.method == "POST":
       title = request.form["title"]
       content = request.form["content"]

       db.execute(
           "UPDATE posts SET title = ?, content = ? WHERE id = ?",
           (title, content, id)
       )

       db.commit()
       db.close()
       return "수정 완료"

   post = db.execute(
       "SELECT * FROM posts WHERE id = ?",
       (id,)
   ).fetchone()

   db.close()
   return render_template("edit.html", post=post)


@app.route("/delete/<int:id>", methods = ["POST"])
def delete(id):
    db = sqlite3.connect("write.db")
    db.execute(
        "DELETE FROM posts WHERE id = ?",
        (id,)

    )
    db.commit()
    db.close()
    return "삭제 완료"

@app.route("/search")
def search():
    keyword = request.args.get("keyword", "")
    db = sqlite3.connect("write.db")

    posts = db.execute(
    "SELECT * FROM posts WHERE title LIKE ?",
    ('%' + keyword + '%',)
    ).fetchall()
    db.close()

    return render_template("search.html", posts=posts)


@app.route("/")
def index():
    db = sqlite3.connect("write.db")

    posts = db.execute(
        "SELECT * FROM posts"
    ).fetchall()

    db.close()
    return render_template("index.html", posts=posts)

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

CREATE TABLE IF NOT EXISTS  posts(
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  title TEXT,
  content TEXT
);

사이트

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Board</title>
</head>
<body>

    <h2>회원가입</h2>
    <form action="/register" method="post">
        <input type="text" name="username" placeholder="Username" required>
        <input type="password" name="password" placeholder="Password" required>
        <button type="submit">회원가입</button>
    </form>

    <h2>로그인</h2>
    <form action="/login" method="post">
        <input type="text" name="username" placeholder="Username" required>
        <input type="password" name="password" placeholder="Password" required>
        <button type="submit">로그인</button>
    </form>

    <h1>게시판</h1>

    <a href="/write">글쓰기</a>

    <form action="/search" method="get">
        <input type="text" name="keyword" placeholder="검색어" required>
        <button type="submit">검색</button>
    </form>

    {% for post in posts %}
        <p>번호: {{ post[0] }}</p>
        <p>제목: {{ post[1] }}</p>
        <p>내용: {{ post[2] }}</p>

        <a href="/edit/{{ post[0] }}">수정</a>

        <form action="/delete/{{ post[0] }}" method="post">
            <button type="submit">삭제</button>
        </form>

        <hr>
    {% endfor %}

</body>
</html>

로그인 및 회원가입

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>web</title>
</head>
<body>
    <form action="/login" method="post">
        <input type="text" name="username" placeholder="Username">
        <input type="password" name="password" placeholder="Password">
        <button type="submit">Login</button>
    </form> 
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Register</title>
</head>
<body>
    <form action="/register" method="post">
        <input type="text" name="username" placeholder="Username">
        <input type="password" name="password" placeholder="Password">
        <button type="submit">Register</button>
    </form> 
</body>
</html>

글 작성

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Write</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
   
</head>
<body>
    <form action="/write" method="post">
       <input type="text" name="title" placeholder="Title">
        <input type="text" name="content" placeholder="Content" required>
<button type="submit">게시글 작성</button>
        

    </form>
    
</body>
</html>

글 조회 및 삭제

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>글 조회</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
   
</head>
<body>

    {% for post in posts %}
        <p>{{ post [0] }}</p>
        <p>{{ post [1] }}</p>
        <p>{{ post [2] }}</p>
        
    <a href="/edit/{{ post[0] }}">수정</a>

    <form action="/delete/{{ post[0] }}" method="post">
        <button type="submit">삭제</button>
    </form>

<hr>
        {% endfor %}

    
</body>
</html>

글 수정

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Edit</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
</head>
<body>
      <form action="/edit/{{ post[0] }}" method="post">
    <input type="text" name="title" value="{{ post[1] }}" required>
    <textarea name="content" required>{{ post[2] }}</textarea>
    <button type="submit">게시글 수정</button>
</body>
</html>

글 검색

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Search</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
</head>
<body>
    <form action="/search" method="get">
    <input type="text" name="keyword" placeholder="검색어" required>
    <button type="submit">검색</button>
</form>
    {% for post in posts %}
        <P>{{ post[0] }}</P>
        <P>{{ post[1] }}</P>
        <P>{{ post[2] }}</P>
        <hr>
        {% endfor %}

</body>
</html>

0개의 댓글