[파이썬 Projects]/<파이썬 웹개발>

[FastAPI] FastAPI + Streamlit + PostgresSQL (1)

기록자_Recordian 2025. 4. 25. 18:20
728x90
반응형
이전 내용
 

[SQL] PostgreSQL: pg Admin 사용하기

이전 내용 [SQL] PostgresSQL 다운로드 하기PostgresSQL 란? PostgreSQL은 오픈 소스 객체-관계형 데이터베이스 관리 시스템(ORDBMS)으로, 많은 기능과 뛰어난 성능, 유연성을 제공하는 데이터베이스이다. [주

puppy-foot-it.tistory.com


FastAPI + Streamlit + PostgreSQL
조합으로 대시보드 페이지 만들기

 

FastAPI + Streamlit + PostgreSQL의 조합으로 대시보드 페이지를 만들어본다.

이 프로젝트는 MVC 패턴을 따르며, 각 개발도구는 다음의 역할을 한다.

 

- 모델 (Model): PostgreSQL

  • 데이터베이스는 애플리케이션의 데이터 모델을 정의하고, 데이터를 저장하며, 데이터를 처리하는 역할. 

- 뷰 (View): Streamlit

  • 사용자 인터페이스를 제공하는 컴포넌트들로 구성되어 있으며, 사용자가 데이터를 입력하고 결과를 시각화하는 부분 담당.

- 컨트롤러 (Controller): FastAPI

  • 클라이언트의 요청을 처리하고, 비즈니스 로직을 실행하며, 모델에서 데이터를 가져오고, 뷰에 데이터를 전달하는 역할.

대략적인 진행 순서

 

- PostgreSQL (pg Admin)을 통해 데이터베이스, 테이블 생성

- FastAPI (VS Code)를 통해

  • 가상 환경 만들기 (가상 환경명: my_shop)
  • 가상 환경에 필요한 라이브러리 설치하기
  • PostgreSQL 연결하기
  • 가상 데이터(Faker 라이브러리) 생성
  • 생성된 데이터 데이터베이스에 삽입하기 ▶ 1편
  • 고객 더미 데이터, 마케팅 더미 데이터 수정 및 추가
  • 데이터 분석 함수 만들기
  • FastAPI로 API 기능 구현하기
  • 포스트맨으로 테스트 하기

- Streamlit (VS Code) 을 통해

  • Streamlit과 FastAPI 연동하기
  • Streamlit 데이터분석 시각화 함수 구현하기
  • Streamlit 실행하여 확인하기

PostgreSQL 로 데이터베이스, 테이블 생성하기

 

  • 데이터베이스 이름: shop
  • 테이블: 총 6개 (customers, sales, reviews, payments, products, marketing)

테이블을 생성하고 나면 하단의 ERD 처럼 보여야 한다.

※ ERD: Entity Relationship Diagram의 약자로, 데이터베이스 구조를 시각적으로 표현하는 모델링 기법.

 

 

CREATE TABLE customers (
    customer_id SERIAL PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    email VARCHAR(150) NOT NULL UNIQUE,
    phone VARCHAR(20),
    gender VARCHAR(10),
    birth_date DATE,
    registration_date DATE DEFAULT CURRENT_TIMESTAMP,
    userid VARCHAR(20) UNIQUE,
    passwd VARCHAR(310)
)

CREATE TABLE products
(
	product_id SERIAL PRIMARY KEY,
	name VARCHAR(255) NOT NULL,
	category VARCHAR(100),
	price DECIMAL(10, 2) NOT NULL,
	stock_quantity INT NOT NULL,
	created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)

 

CREATE TABLE marketing
(
	marketing_id SERIAL PRIMARY KEY,
	campaign_name VARCHAR(255) NOT NULL,
	target_audience VARCHAR(255),
	budget DECIMAL(10,2),
	start_date DATE,
	end_date DATE
)

CREATE TABLE sales
(
	sale_id SERIAL PRIMARY KEY,
	customer_id INT REFERENCES customers(customer_id),
	product_id INT REFERENCES products(product_id),
	quantity INT NOT NULL,
	total_price DECIMAL(10,2) NOT NULL,
	sale_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
	marketing_id INT REFERENCES marketing(marketing_id)
)

CREATE TABLE payments
(
	payment_id SERIAL PRIMARY KEY,
	sale_id INT REFERENCES sales(sale_id),
	payment_method VARCHAR(50) NOT NULL,
	payment_status VARCHAR(50) NOT NULL,
	payment_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)

 

CREATE TABLE reviews
(
	review_id SERIAL PRIMARY KEY,
	customer_id INT REFERENCES customers(customer_id),
	product_id INT REFERENCES products(product_id),
	rating INT CHECK(rating BETWEEN 1 AND 5),
	review_text TEXT,
	review_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)

 


anaconda prompt 가상환경 만들기

 

새로운 프로젝트 폴더를 생성한 후, anaconda prompt를 켜고 가상환경을 생성한다.

# 설치할 경로로 이동 후
conda create -n my_shop

 

그리고 VS Code를 켜고 인터프리터에서 좀 전에 만든 가상환경을 선택해 주면 된다.

만약, VSCode 터미널에서 'conda'은(는) 내부 또는 외부 명령, 실행할 수 있는 프로그램, 또는 배치 파일이 아닙니다.
라는 에러가 발생하면 ctrl+shift+p 누르고 
Terminal: Select Default Profile를 선택한 뒤,
Command Prompt를 선택한 후 재시작을 하면 해결이 된다.

 

가상환경을 실행한 후,

conda activate my_shop

필요한 라이브러리 (FastAPI, Streamlit 등)를 다운 받는다.

근데, 코드를 여러 번 치는 것은 너무 불편하므로, 파일을 하나 만들어서 해당 파일에 필요한 라이브러리와 모듈을 적어놓고 올리는 방법도 있다.

pip freeze > requirements.txt
pip install -r requirements.txt

 

[설치한 주요 라이브러리]

  • FastAPI: 고성능의 웹 프레임워크로, 빠른 API 구축을 지원하며 비동기 프로그래밍 지원.
  • Streamlit: 데이터 애플리케이션을 쉽게 만들 수 있는 프레임워크로, Python 코드로 대화형 웹 앱 생성.
  • psycopg2: PostgreSQL 데이터베이스와 Python 애플리케이션 간의 상호 작용을 위한 PostgreSQL 드라이버.
  • SQLAlchemy: SQL 데이터베이스와의 상호작용을 위한 객체 관계 매핑(ORM) 라이브러리로, 데이터베이스 쿼리를 보다 직관적으로 작성할 수 있게 해준다.
  • scikit-learn: 머신러닝을 위한 라이브러리로, 다양한 알고리즘, 데이터 전처리 및 모델 평가 도구 제공.
  • matplotlib: 데이터 시각화를 위한 라이브러리로, 다양한 그래프와 차트를 만들 수 있게 해준다.
  • plotly: 대화형 시각화가 가능한 그래프를 생성할 수 있는 라이브러리로, 웹 기반 시각화에 강점을 갖고 있다.
  • pandas: 데이터 분석을 위한 라이브러리로, 데이터 조작 및 분석을 쉽게 할 수 있는 고성능 데이터 구조 제공.
  • numpy: 고성능의 수치 계산을 위한 라이브러리로, 다차원 배열 객체와 다양한 수학 함수가 포함되어 있다.
  • uvicorn: ASGI(Asynchronous Server Gateway Interface) 서버로, FastAPI와 같은 비동기 어플리케이션을 실행하기 위해 사용.

가상의 고객 데이터(더미 데이터) 생성하여
데이터베이스에 넣기

 

각 테이블별로 생성해야 하는 데이터 수는 다음과 같다.

  • 고객 30명 생성 (customers 테이블)
  • 상품 30개 생성 (products 테이블)
  • 판매 1000건 생성 (sales 테이블)
  • 결제 1000건 (판매와 연결) (payments 테이블)
  • 리뷰 900건 (일부 판매된 상품에 연결) (reviews 테이블)

◆ 데이터베이스 연결하기 (PostgreSQL)

import psycopg2
import random
from faker import Faker
from datetime import datetime, timedelta
import string

# PostgreSQL 연결 정보
DB_NAME = "shop"
DB_USER = "postgres"
DB_PASSWORD = "1234"
DB_HOST = "localhost"

# Faker 라이브러리 사용
faker = Faker('ko_KR')

def connectd_db():
    return psycopg2.connect(
        dbname=DB_NAME, user=DB_USER, password=DB_PASSWORD, host=DB_HOST
    )
  • psycopg2는 PostgreSQL과 Python을 연결하는 데 필수적인 도구

◆ customers 테이블에 더미 데이터 생성해서 삽입하기

def insert_customers(cursor):
    print("[1/5] 고객 데이터 생성 중...")
    for _ in range(30):
        # AUTO_INCREMENT (SERIAL) 생략 가능
        cursor.execute( 
            """
            INSERT INTO customers (name, email, phone, gender, birth_date, registration_date, userid, passwd)
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
            """,
            (faker.name()[:20], # 이름: 20자 제한
             faker.email()[:50], # 이메일: 50자 제한
             faker.phone_number()[:15], # 전화 번호 길이 제한
             random.choice(["Male", "Female"]),
             faker.date_of_birth(minimum_age=18, maximum_age=65),
             faker.date_time_between(start_date="-2y", end_date="now"), # 현재 시간으로부터 2년 전
             faker.user_name()[:10] + (str(random.randint(1,9999))), # userid : 이름과 임의의숫자 조합
             faker.password()) # 비밀번호
            )

 

◆ products 테이블에 더미 데이터 삽입하기

def insert_products(cursor):
    print("[2/5] 상품 데이터 생성 중...")
    for _ in range(30):
        cursor.execute(
            """
            INSERT INTO products (name, category, price, stock_quantity, created_at)
            VALUES (%s, %s, %s, %s, %s)
            """,
            (faker.word(),
            random.choice(["Electronics", "Clothing", "Books", "Furniture"]),
            round(random.uniform(10, 1000), 2), # 10 ~ 100 사이의 무작위 가격 (소수점 2자리 수)
            random.randint(10, 100),
            faker.date_time_between(start_date="-2y", end_date="now"))
        )

 

◆ sales 테이블에 더미 데이터 삽입하기

def insert_sales(cursor):
    print("[3/5] 판매 데이터 생성 중...")
    # customer_id만 조회하므로, 단일 컬럼 데이터 처리
    # 리스트 컴프리헨션을 사용
    cursor.execute("SELECT customer_id FROM customers")
    customers = [row[0] for row in cursor.fetchall()] # fetchall의 결과는 리스트에 튜플 형태로 담겨옴 [(1, ), (2, )] > 0번째 값만 추출

    cursor.execute("SELECT product_id, price FROM products")
    products = cursor.fetchall() # 튜플이 들어있는 리스트 (product_id, 가격)

    sales = []
    for _ in range(1000):
        customer_id = random.choice(customers)
        product_id, price = random.choice(products) # products 튜플에 들어있는 값
        quantity = random.randint(1, 5)
        total_price = price * quantity
        sale_date = faker.date_time_between(start_date="-2y", end_date="now")
        sales.append((customer_id, product_id, price, total_price, sale_date))

    cursor.executemany(
        """
        INSERT INTO sales (customer_id, product_id, quantity, total_price, sale_date)
        VALUES (%s, %s, %s, %s, %s)
        """,
        sales
    )
  • cursor.execute("SELECT customer_id FROM customers"): customers 테이블에서 customer_id 열의 모든 값을 선택.
    ※ cursor.execute(): SQL 쿼리를 실행하는 메서드. cursor는 데이터베이스의 명령을 실행하고 결과를 가져오는 객체
  • customers = [row[0] for row in cursor.fetchall()]: fetchall() 메서드를 사용하여 SELECT 쿼리의 결과를 가져옴. 결과는 리스트 형태의 튜플로 반환
  • products = cursor.fetchall(): 이 메서드는 이전 쿼리의 결과를 모두 가져와서 products라는 변수에 저장. 이 변수에는 각 제품의 product_id와 가격이 포함된 튜플이 들어있는 리스트가 저장 됨.

◆ payments 테이블에 더미 데이터 삽입하기

def insert_payment(cursor):
    print("[4/5] 결제 데이터 생성 중...")
    cursor.execute("SELECT sale_id FROM sales")
    sales_id = [row[0] for row in cursor.fetchall()]

    payments = []
    for sale_id in sales_id: # 실제 판매된 데이터에만 생성되도록
        payment_method = random.choice(["Credit Card", "PayPal", "Bank Transfer"])
        payment_status = random.choice(["Completed", "Pending", "Failed"])
        payment_date = faker.date_time_between(start_date="-1y", end_date="now") 
        payments.append((sale_id, payment_method, payment_status, payment_date))

    cursor.executemany(
        """
        INSERT INTO payments (sale_id, payment_method, payment_status, payment_date)
        VALUES (%s, %s, %s, %s)
        """,
        payments
    )

 

◆ reviews 테이블에 더미 데이터 삽입하기

def insert_reviews(cursor):
    print("[5/5] 리뷰 데이터 생성 중...")
    # 구매 건(sales)에 대한 리뷰가 아닌 구매 상품(products)에 대한 리뷰
    cursor.execute("SELECT customer_id, product_id FROM sales ORDER BY RANDOM() LIMIT 900")

    reviews = []
    for customer_id, product_id in cursor.fetchall():
        rating = random.randint(1,5)
        review_text = faker.paragraph(nb_sentences=3, variable_nb_sentences=True)[:200] if random.random() > 0.2 else None # 20% 확률로 텍스트 없음
        review_date = faker.date_time_between(start_date="-1y", end_date="now")
        reviews.append((customer_id, product_id, rating, review_text, review_date))
    
    cursor.executemany(
        """
        INSERT INTO reviews (customer_id, product_id, rating, review_text, review_date)
        VALUES (%s, %s, %s, %s, %s)
        """,
        reviews
    )

 

◆ main 함수

def main():
    conn = connectd_db()
    cursor = conn.cursor()

    insert_customers(cursor)
    insert_products(cursor)
    insert_sales(cursor)
    insert_payment(cursor)
    insert_reviews(cursor)

    conn.commit()
    cursor.close()
    conn.close()
    print("🤞🏻 더미 데이터 생성 완료!")

if __name__ == "__main__":
    main()

 

더미데이터 생성이 완료되어 데이터베이스에 잘 삽입되었다.

 

근데 리뷰는 한글로 설정해도 라틴어(?)로 밖에 생성이 안 되나 보다.


[참고]

https://shuka.tistory.com/55

https://zephyrus1111.tistory.com/405

https://wikidocs.net/226761


다음 내용

 

[FastAPI] FastAPI + Streamlit + PostgresSQL (2)

이전 내용 [FastAPI] FastAPI + Streamlit + PostgresSQL (1)이전 내용 [SQL] PostgreSQL: pg Admin 사용하기이전 내용 [SQL] PostgresSQL 다운로드 하기PostgresSQL 란? PostgreSQL은 오픈 소스 객체-관계형 데이터베이스 관리 시

puppy-foot-it.tistory.com

 

728x90
반응형