CodeGym /행동 /Docker SELF /애플리케이션 아키텍처 설계

애플리케이션 아키텍처 설계

Docker SELF
레벨 23 , 레슨 1
사용 가능

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 데이터베이스에 사용자와 작업 데이터를 저장하기 위해 두 개의 테이블을 만듭니다: userstasks.

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;
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION