⚡️ API 개발 with Flask - 8

codeamor·2020년 7월 8일
0

API Development

목록 보기
8/9

✔️ 데이터베이스 설치

관계형 데이터베이스를 사용하기 위해서 먼저 데이터베이스를 설치한다.

우분투에서 MySQL 설치하기

apt 혹은 apt-get 패키지 매니저를 사용해서 MySQL 데이터베이스를 간단하게 설치할 수 있다.

sudo apt update
sudo apt install mysql-server

이제부터 root user 라는 개념이 계속 나올 것이다.
root 사용자는 관계형 데이터베이스에서 master 사용자를 뜻한다.
관리자 사용자이므로 해당 데이터베이스 시스템의 모든 권한을 가지고 있다.
리눅스의 root 사용자와 동일한 개념이라고 생각하면 된다.

아래 명령어를 실행한다.

mysql_secure_installation

여기서부터 ㄹㅇ 중요하다.

설치 과정 중에 root 사용자의 비밀번호를 설정하라고 나오면 설정하도록 하는데 아마 그런 말은 안나올 것이고 필자의 경우는 현재 root 비밀번호를 입력하라고 해서 입력했더니
ERROR 1045 (28000): Access denied for user 'root'@'localhost'
위 에러만 계속 떴었다.
아래에서 원인을 해결해 보자.

MySQL 5.7 이상의 버전 설치 시 주의할 점

현재 글을 쓰는 시점에서는 mysql 버전이 8.0.20 이다. 대부분 이 과정을 따라가야 할 것이다.

  1. mysql -u root 명령어로 MySQL 데이터베이스에 접속한다.
  • 위 명령어는 최고권리(root)를 가진 사용자(-u)로 mysql을 실행하라는 의미이다.

  • sudo mysql 과 같은 의미이다.

    • sudo는 Substitute User DO(다른 사용자의 권한으로 실행) 의 준말인데,
      명령어들의 앞에 sudo를 붙이면 root(최고권리자) 권한으로 실행된다고 생각하면 된다.
    • sudo를 안붙인 명령어를 실행하다가 종종 실행이 안되고 메시지 마지막에 Are you root? 라는
      되물음이 온다면 그냥 sudo 붙이고 명령어 쓰라는 말로 이해하면 된다.

  1. 위 사진처럼 MySQL에 접속했으면 다음 SQL 구문을 실행하여 어떤 인증 모드가 사용되고 있는지 확인한다.

SELECT user, plugin, host FROM mysql.user;

위 구문을 입력하면 user가 여러명 뜰텐데 root 사용자만 보면 된다.

아래 처럼 나오면 root 사용자는 auth_socket 인증 모드를 사용하고 있는 것이다.

+-----------+-----------------------+-----------+
| user      | plugin                | host      |
+-----------+-----------------------+-----------+
| root      | auth_socket           | localhost |
+-----------+-----------------------+-----------+
  1. 다음 SQL 명령어를 사용하여 root 사용자의 비밀번호를 사용해서 인증 모드로 변경하도록 하자.
    따옴표 안의 password 부분은 원하는 비밀번호를 사용하면 된다.

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_passwrod BY 'password';

대문자는 SQL 구문과 값을 구분하기 위해 사용한 것이므로 소문자로 써도 무방하다.

  1. 다음 SQL 구문을 실행하여 변경된 설정이 곧바로 반영되도록 하자.

FLUSH PRIVILEGES

  1. root 사용자의 인증 모드를 확인하여 변경사항이 잘 반영되었는지 확인하자.

SELECT user, authentication_string, plugin, host FROM mysql.user;

+-----------+-----------------------+-----------+
| user      | plugin                | host      |
+-----------+-----------------------+-----------+
| root      | mysql_native_password | localhost |
+-----------+-----------------------+-----------+

위와 같이 root 사용자의 plugin 칼럼 값이 mysql_native_password로 바뀌었다면
이제 root 사용자의 비밀번호를 사용하여 MySQL 데이터베이스에 접속할 수 있을 것이다.

  • 비밀번호를 설정한 지금부터는 위에서 사용했던 mysql -u root 명령어를 쓰면 에러가 뜨고
    비밀번호를 직접 입력하겠다고 알려주는 -p 옵션을 추가시켜서 사용해야 한다.
    mysql -u root -p


✔️ API에 데이터베이스 연결하기

이제부터 API에 MySQL 데이터베이스 시스템을 연결하여 데이터를 저장하도록 한다.

앞서 말한 것처럼 관계형 데이터베이스 시스템은 데이터를 저장하기 전에 미리 테이블 구조와 관계를 구현해 놓아야 한다.

그러므로 먼저 미니터 API를 위한 테이블 구조와 관계, 즉 스키마(schema)를 구현하도록 한다.

그 구조는 다음과 같다.

  • users 테이블은 이름, 이메일, 암호화된 비밀번호, 사용자 프로파일 등의 사용자 정보를 저장한다.
  • user_follow_list 테이블은 사용자들이 다른 사용자들을 팔로우하는 리스트를 저장한다.
    • many to many 관계이며 users 테이블에 id를 통한 외부 키로 연결되어 있다.
  • tweets 테이블은 사용자들의 트윗들을 저장한 테이블이며 users 테이블과 one to many 관계를 가지고 있다. (한 사용자가 여러 트윗들을 할 수 있다.)
    • 마찬가지로 users 테이블에 id를 통한 외부 키로 연결되어 있다.

이제 다음 명령어를 통해 MySQL 데이터베이스에 접속한다.

mysql -u root -p

그리고 'miniter'라는 이름의 데이터베이스를 생성한다.

CREATE DATABASE miniter;

📌️ MySQL은 데이터베이스 시스템이다. 데이터베이스 시스템 안에는 여러 데이터베이스가 존재할 수 있다. 그리고 각 데이터베이스에는 여러 테이블이 존재하는 구조가 된다.

데이터베이스를 생성했다면 해당 데이터베이스를 사용하겠다고 use 명령어를 사용해서 MySQL 데이터베이스 시스템에 알려 줘야 한다.
알려주지 않으면 MySQL은 어떠한 데이터베이스를 선택해야 할지 모르므로 오류가 난다.

USE miniter

miniter 데이터베이스를 선택했으면 이제 miniter 데이터베이스에 테이블들을 생성하도록 하자.
SQL에서 테이블 생성은 CREATE TABLE 구문을 사용해서 생성할 수 있다.

CREATE TABLE 구문의 기본적인 문법은 아래와 같다.

CREATE TABLE users(
    column 1 data_type,
    column2 data_type,
    ...
    PRIMARY KEY (column1), 
    CONSTRAIT 1,
    CONSTRAIT 2
)

위에 있는 미니터 API 데이터베이스 스키마에 있는 테이블들을 생성하려면 다음의 CREATE TABLE 구문들을 사용하면 된다.

CREATE TABLE users(
    id INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL,
    hashed_password VARCHAR(255) NOT NULL,
    profile VARCHAR(2000) NOT NULL,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, 
    PRIMARY KEY (id), 
    UNIQUE KEY email (email)
);

CREATE TABLE users_follow_list(
    user_id INT NOT NULL,
    follow_user_id INT NOT NULL,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (user_id, follow_user_id),
    CONSTRAINT users_follow_list_user_id_fkey FOREIGN KEY (user_id)
    REFERENCES users(id), 
    CONSTRAINT users_follow_list_follow_user_id_fkey FOREIGN KEY (follow_user_id)
    REFERENCES users(id)
);

CREATE TABLE tweets(
    id INT NOT NULL AUTO_INCREMENT,
    user_id INT NOT NULL,
    tweet VARCHAR(300) NOT NULL,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id),
    CONSTRAINT tweets_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id)
);
  1. id INT NOT NULL AUTO_INCREMENT,
  • NOT NULL은 해당 칼럼은 null 값이 될 수 없다는 뜻이다. 즉 해당 칼럼은 항상 값이 존재해야 한다는 뜻이다.
  • AUTO_INCREMENT을 명시해 주면 해당 칼럼의 값이 자동으로 1씩 증가된다는 뜻이다.
    주로 id 값을 자동 생성하기 위해 사용된다.

  1. created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    : DEFAULT CURRENT_TIMESTAMP의 뜻은 만일 해당 칼럼의 값이 없으면 디폴트 값으로 현재 시간(timestamp) 값을 사용하라는 뜻이다.
  • 이 방식은 주로 created_at처럼 해당 값이 생성된 시점을 기록하는 칼럼에 주로 사용된다.
    일일이 created_at 값을 지정해 주지 않아도 데이터베이스가 자동으로 생성해 주므로 편리하다.

  1. updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  • ON UPDATE CURRENT TIMESTAMP의 뜻은 만일 해당 로우(row)의 값이 업데이트, 즉 수정이 되면 해당 칼럼의 값을 수정이 이루어진 시간의 값으로 자동 생성해 준다는 뜻이다.
    로우가 언제 업데이트 되었는지 자동으로 기록되므로 편리하다.

  1. PRIMARY KEY (id),
    : PRIMARY KEY 구문을 통해 고유 키로 사용될 칼럼을 정해 준다.
  • 고유 키는 한 개의 칼럼으로 정할 수도 있지만 여러 칼럼을 정할 수도 있다.
  • 여러 칼럼을 고유 키로 정해 주면 해당 칼럼 값들을 합한 값이 고유 키가 된다.

  1. UNIQUE KEY email (email)
  • UNIQUE KEY의 뜻은 해당 칼럼의 값이 중복되는 로우가 없어야 한다는 뜻이다.
  • 이메일의 경우 이미 등록된 이메일로 중복된 등록이 되면 안 되기 때문에 UNIQUE KEY 구문을 사용해 시스템적으로 방지해 둘 수 있어서 편리하고 안전하다.

  1. CONSTRAINT users_follow_list_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id),
    : CONSTRAINT ... FOREIGN KEY .. REFERENCES ... 구문을 통해서 외부 키를 걸 수 있다.
  • users_follow_list 테이블과 tweets 테이블 둘 다 users 테이블에 외부 키를 통해 연결된다.

테이블들을 생성했다면 마지막으로 SHOW TABLES 명령어로 테이블들이 생성되었는지 확인해 보자.
그리고 EXPLAIN table_name 명령어로 테이블들의 칼럼과 칼럼 타입 등을 확인할 수 있다.

올바르게 입력하고 생성했다면 터미널 창에서 다음과 같은 결과를 확인할 수 있다.

(api)  ssm@asusumin ~/Projects/api mysql -u root -p                                             
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 15
Server version: 8.0.20-0ubuntu0.20.04.1 (Ubuntu)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> CREATE DATABASE miniter;
Query OK, 1 row affected (0.01 sec)

mysql> USE miniter;
Database changed
mysql>  
mysql> CREATE TABLE users(
    ->     id INT NOT NULL AUTO_INCREMENT,
    ->     name VARCHAR(255) NOT NULL,
    ->     email VARCHAR(255) NOT NULL,
    ->     hashed_password VARCHAR(255) NOT NULL,
    ->     profile VARCHAR(2000) NOT NULL,
    ->     created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    ->     updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, 
    ->     PRIMARY KEY (id), 
    ->     UNIQUE KEY email (email)
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> CREATE TABLE users_follow_list(
    ->     user_id INT NOT NULL,
    ->     follow_user_id INT NOT NULL,
    ->     created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    ->     PRIMARY KEY (user_id, follow_user_id),
    ->     CONSTRAINT users_follow_list_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id), 
    ->     CONSTRAINT users_follow_list_follow_user_id_fkey FOREIGN KEY (follow_user_id) REFERENCES users(id)
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> CREATE TABLE tweets(
    ->     id INT NOT NULL AUTO_INCREMENT,
    ->     user_id INT NOT NULL,
    ->     tweet VARCHAR(300) NOT NULL,
    ->     created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id),
    ->     CONSTRAINT tweets_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id)
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> show tables;
+-------------------+
| Tables_in_miniter |
+-------------------+
| tweets            |
| users             |
| users_follow_list |
+-------------------+
3 rows in set (0.00 sec)

mysql> explain users;
+-----------------+---------------+------+-----+-------------------+-----------------------------+
| Field           | Type          | Null | Key | Default           | Extra                       |
+-----------------+---------------+------+-----+-------------------+-----------------------------+
| id              | int           | NO   | PRI | NULL              | auto_increment              |
| name            | varchar(255)  | NO   |     | NULL              |                             |
| email           | varchar(255)  | NO   | UNI | NULL              |                             |
| hashed_password | varchar(255)  | NO   |     | NULL              |                             |
| profile         | varchar(2000) | NO   |     | NULL              |                             |
| created_at      | timestamp     | NO   |     | CURRENT_TIMESTAMP | DEFAULT_GENERATED           |
| updated_at      | timestamp     | YES  |     | NULL              | on update CURRENT_TIMESTAMP |
+-----------------+---------------+------+-----+-------------------+-----------------------------+
7 rows in set (0.00 sec)

mysql> explain users_follow_list;
+----------------+-----------+------+-----+-------------------+-------------------+
| Field          | Type      | Null | Key | Default           | Extra             |
+----------------+-----------+------+-----+-------------------+-------------------+
| user_id        | int       | NO   | PRI | NULL              |                   |
| follow_user_id | int       | NO   | PRI | NULL              |                   |
| created_at     | timestamp | NO   |     | CURRENT_TIMESTAMP | DEFAULT_GENERATED |
+----------------+-----------+------+-----+-------------------+-------------------+
3 rows in set (0.00 sec)

mysql> explain tweets;
+------------+--------------+------+-----+-------------------+-------------------+
| Field      | Type         | Null | Key | Default           | Extra             |
+------------+--------------+------+-----+-------------------+-------------------+
| id         | int          | NO   | PRI | NULL              | auto_increment    |
| user_id    | int          | NO   | MUL | NULL              |                   |
| tweet      | varchar(300) | NO   |     | NULL              |                   |
| created_at | timestamp    | NO   |     | CURRENT_TIMESTAMP | DEFAULT_GENERATED |
+------------+--------------+------+-----+-------------------+-------------------+
4 rows in set (0.00 sec)

mysql> exit

exit 명령어를 통해 MySQL 데이터베이스 시스템 접속을 종료할 수 있다.
이제 미니터 API에 데이터베이스를 연결시킬 것이다.

0개의 댓글