2.1 전체 아키텍처
이 단계에서는 작업을 관리할 애플리케이션의 아키텍처를 설계할 거야. 프론트엔드, 백엔드, 데이터베이스가 어떻게 상호작용할지 그리고 각각에 어떤 컴포넌트가 포함될지 결정할 거야.
애플리케이션은 세 가지 주요 컴포넌트로 구성될 거야:
- Frontend (ReactJS): 시스템과 사용자 간 상호작용을 제공하는 클라이언트 부분.
- Backend (Flask): 프론트엔드에서 오는 요청을 처리하고 데이터베이스와 상호작용하는 서버 부분.
- Database (PostgreSQL): 사용자와 작업 데이터를 저장하는 저장소.
아키텍처는 다음과 같은 모습이 될 거야:
Terminal
+-------------+ +-------------+ +--------------+
| | | | | |
| Frontend +------->+ Backend +------->+ Database |
| (ReactJS) | | (Flask) | | (PostgreSQL) |
| | | | | |
+-------------+ +-------------+ +--------------+
컴포넌트 간 상호작용
- Frontend: CRUD 작업(작업 생성, 읽기, 업데이트, 삭제)을 수행하기 위해 백엔드로 HTTP 요청을 보냄.
- Backend: 프론트엔드에서 오는 HTTP 요청을 처리하고 비즈니스 로직을 수행하며 데이터베이스와 상호작용함.
- Database: 백엔드 요청에 따라 데이터를 저장 및 제공.
2.2 각 컴포넌트 설명
1. Frontend (ReactJS):
- 인터페이스 컴포넌트: 사용자 등록 및 인증, 작업 생성 및 편집, 작업 목록 보기용 컴포넌트.
- API와의 상호작용: Axios 라이브러리를 사용하여 백엔드에 HTTP 요청을 보냄.
2. Backend (Flask):
- REST API: 사용자 및 작업 관리를 위한 엔드포인트 구현.
- 데이터 모델: SQLAlchemy를 사용하여 사용자와 작업용 데이터 모델 정의.
- 비즈니스 로직: 데이터 유효성 검사 및 사용자 세션 관리를 포함한 애플리케이션 로직 처리.
3. Database (PostgreSQL):
- 테이블: 사용자 및 작업 정보 저장용 테이블.
- 테이블 간 관계: 사용자와 작업 테이블 간 관계 정의(예: 한 사용자가 여러 작업을 가질 수 있음).
4. 네트워크 상호작용
모든 컴포넌트 간 통신은 HTTP 프로토콜을 통해 이루어질 예정이야. 프론트엔드는 REST API를 통해 백엔드와 상호작용하고, 백엔드는 SQL 쿼리를 통해 데이터베이스와 상호작용할 거야.
- Frontend: 개발 및 테스트용 포트 3000.
- Backend: 프론트엔드와의 상호작용을 위한 포트 5000.
- Database: 백엔드와의 상호작용을 위한 포트 5432.
2.3 각 구성 요소의 상세 설명
1. 기본 데이터 구조
PostgreSQL 데이터베이스에 사용자와 작업 데이터를 저장하기 위해 두 개의 테이블을 만듭니다: users
와 tasks
.
users
테이블:
-
id (int, primary key)
: 사용자의 고유 식별자. username (varchar, unique)
: 사용자 이름.password (varchar)
: 사용자의 비밀번호 해시.
tasks
테이블:
-
id (int, primary key)
: 작업의 고유 식별자. title (varchar)
: 작업 제목.description (text)
: 작업 설명.-
owner_id (int, foreign key)
: 작업이 할당된 사용자의 식별자. -
status (varchar)
: 작업 상태 (예: 완료/미완료).
2. API 디자인
백엔드는 프론트엔드와 상호작용하기 위해 RESTful API를 제공합니다. 예상 엔드포인트 목록:
- 사용자:
- POST /users: 새 사용자 생성.
- GET /users: 모든 사용자 목록 가져오기.
- GET /users/:id: 특정 사용자 정보 가져오기.
- PUT /users/:id: 사용자 정보 업데이트.
- DELETE /users/:id: 사용자 삭제.
- 작업:
- POST /tasks: 새 작업 생성.
- GET /tasks: 모든 작업 목록 가져오기.
- GET /tasks/:id: 특정 작업 정보 가져오기.
- PUT /tasks/:id: 작업 정보 업데이트.
- DELETE /tasks/:id: 작업 삭제.
2.4 데이터 모델
다음은 Python 코드로 데이터베이스 테이블을 작업하는 방법이야:
User Model:
Python
from app import db
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
password = db.Column(db.String(120), nullable=False)
tasks = db.relationship('Task', backref='owner', lazy=True)
def to_dict(self):
return {
"id": self.id,
"username": self.username
}
Task Model:
Python
from app import db
class Task(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(120), nullable=False)
description = db.Column(db.Text, nullable=True)
owner_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
status = db.Column(db.String(20), nullable=False, default="미완료")
def to_dict(self):
return {
"id": self.id,
"title": self.title,
"description": self.description,
"owner_id": self.owner_id,
"status": self.status
}
2.5 라우트와 컨트롤러
서버 측에서 API 구현 예제:
Python
from app import app, db
from app.models import Task, User
from flask import request, jsonify
@app.route('/tasks', methods=['GET'])
def get_tasks():
tasks = Task.query.all()
return jsonify([task.to_dict() for task in tasks])
@app.route('/tasks', methods=['POST'])
def create_task():
data = request.get_json()
new_task = Task(
title=data['title'],
description=data.get('description'),
owner_id=data['owner_id'],
status=data.get('status', "완료되지 않음")
)
db.session.add(new_task)
db.session.commit()
return jsonify(new_task.to_dict()), 201
@app.route('/tasks/<int:id>', methods=['GET'])
def get_task(id):
task = Task.query.get_or_404(id)
return jsonify(task.to_dict())
@app.route('/tasks/<int:id>', methods=['PUT'])
def update_task(id):
data = request.get_json()
task = Task.query.get_or_404(id)
task.title = data['title']
task.description = data.get('description')
task.status = data.get('status', task.status)
task.owner_id = data['owner_id']
db.session.commit()
return jsonify(task.to_dict())
@app.route('/tasks/<int:id>', methods=['DELETE'])
def delete_task(id):
task = Task.query.get_or_404(id)
db.session.delete(task)
db.session.commit()
return '', 204
2.6 프론트엔드에서 서버로 요청하는 예제
작업 목록을 표시하는 React 컴포넌트의 예:
Javascript
import React, { useEffect, useState } from 'react';
import axios from 'axios';
const TaskList = () => {
const [tasks, setTasks] = useState([]);
useEffect(() => {
axios.get('http://localhost:5000/tasks')
.then(response => {
setTasks(response.data);
})
.catch(error => {
console.error('작업을 가져오는 중 오류가 발생하였습니다!', error);
});
}, []);
return (
<div>
<h1>작업 목록</h1>
<ul>
{tasks.map(task => (
<li key={task.id}>{task.title} - {task.status}</li>
))}
</ul>
</div>
);
};
export default TaskList;
GO TO FULL VERSION