지난 과정까지 나만의 백엔드 서버 생성해 배포까지 완료하였고, 이제 서버에 기능을 붙이는 작업을 진행한다. 그 중에서도 이번에는 서버에 데이터베이스를 생성하고, 이 데이터를 조회하는 API를 구현해보려 한다.
최근에는 여러 데이터베이스 엔진이 많이 생겨 PostgreSQL, MongoDB 등 다양한 선택지가 존재하지만, 나는 다뤄본 경험이 있어 익숙하기도 하고, 참고 자료가 많은 MySQL을 선택했다.
가장 먼저 EC2 인스턴스에서만 접근 가능한 RDS를 생성한다. AWS의 Aurora and RDS 메뉴에서 데이터베이스를 생성할 수 있다.
| 엔진 옵션 | 자격 증명 설정 |
|---|---|
![]() | ![]() |
| 연결 설정 | 추가 구성 |
|---|---|
![]() | ![]() |
[엔진 옵션]
MySQL 엔진을 선택하고, 템플릿은 프리 티어 템플릿을 선택한다.
[자격 증명 설정]
⚠️ 추후 DB 접속 시 이 암호를 사용해야 하므로 잘 기억하도록 한다!
[연결 설정]
[추가 설정]
RDS 생성 전에 내부에 데이터베이스를 생성해보고 싶다면 초기 데이터베이스를 추가하면 된다. 추후 RDS에 접속해서 얼마든지 데이터베이스를 생성할 수 있기 때문에 이 과정은 패스해도 아무 문제 없다.
RDS 생성을 완료했고, 이제 EC2에서 접속이 잘 되는지 확인할 차례이다. EC2에서 MySQL RDS에 접속하기 위해서 mysql-server 라는 프로그램을 설치해야 한다.
$ sudo apt install mysql-server
mysql-server 설치가 완료되었다면, 본격적으로 RDS 접속을 시도한다. mysql이라는 키워드를 이용하며, 아래 명령어의 [키워드] 자리에 적절한 값을 넣어주면 된다.
$ mysql -h [RDS의 엔드포인트] -P 3306 -u [사용자 이름] -p
Enter password: [비밀번호]
[키워드]
-P는 포트 번호를 의미하며, MySQL은 3306번 포트를 사용하므로 3306을 입력한다.
[RDS의 엔드포인트]: -h는 RDS의 호스트를 의미하며, AWS RDS의 엔드포인트를 입력한다.[사용자 이름]: -u는 RDS의 사용자 이름을 의미하며, RDS 생성 시 지정한 사용자 이름을 입력한다.[비밀번호]: -p는 RDS의 비밀번호를 의미하며, RDS 생성 시 지정한 비밀번호를 입력한다.올바른 비밀번호를 입력한다면 MySQL에 성공적으로 접속할 수 있을 것이다. 접속하고 나면 기존 $ 형태가 아니라 mysql> 형태로 명령어 입력 창이 바뀌어 있는 것을 볼 수 있을 것이다. 이 mysql> 키워드 뒤에 SQL문을 입력하여 RDS를 조작할 수 있다.
mysql> show databases;
가장 먼저 show databeses; 명령어를 이용해 RDS에 존재하는 데이터베이스를 확인해본다. 만약 위 과정에서 데이터베이스 추가 설정을 진행했다면, 그 때 추가한 데이터베이스가 존재하는 것을 볼 수 있을 것이다. (나의 경우 db_test)

mysql> use db_test;
이번에는 여러 데이터베이스 중 직접 사용할 데이터베이스(db_test)로 이동한다.
CREATE TABLE notes (
uuid BINARY(16) DEFAULT (UUID_TO_BIN(UUID(), 1)) PRIMARY KEY,
title VARCHAR(255) NOT NULL,
contents TEXT NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
간단한 SQL문을 이용해 db_test 데이터베이스 내에 notes라는 테이블을 생성한다. 각 줄(line)이 테이블의 컬럼(column)을 의미하며, 각각의 데이터는 고유 ID, 제목, 내용, 생성 일시, 업데이트 일시 정보를 갖게 될 것이다.
mysql> show tables;
show tables 명령어를 이용해 테이블이 잘 생성되었는지 확인한다.

다음으로 테이블에 샘플 데이터를 추가한다.
INSERT INTO notes (title, contents)
VALUES
('My First Note', 'A note about something'),
('My Second Note', 'A note about something else');
제목, 내용을 값으로 가지는 데이터 두 개를 추가해본다. 고유 ID, 생성 일시, 업데이트 일시는 값을 따로 입력하지 않아도 자동으로 생성될 것이다.
mysql> select * from notes;
SELECT 문을 이용해 notes 테이블에 있는 데이터를 조회한다.

위와 같이 데이터가 잘 추가된 것을 볼 수 있다.
위의 과정을 통해 EC2에서 MySQL RDS에 접근할 수 있는 것을 확인하였다. 다음은 EC2 콘솔을 이용해 데이터베이스에 접속하는 것이 아니라 Express 서버를 이용해 데이터베이스에 접근해 데이터를 가져올 수 있는 환경을 구현한다. 이제 본인이 사용하는 코드 에디터를 활용해 Express 서버의 코드를 수정하면 된다.
프로젝트에 MySQL2 라이브러리를 설치한다. MySQL2는 Node.js 환경에서 MySQL에 접근하기 쉽도록 도와주는 라이브러리이다.
$ npm install mysql2
보다 자세한 내용은 MySQL2 공식문서를 참고하는 것을 추천한다.
참고
공식문서 MySQL2
프로젝트의 src 폴더 내부에 db 폴더를 생성하고, 내부에 database.js라는 파일을 생성해 데이터베이스 관련 로직을 관리한다.
MySQL의 createPool을 사용해 데이터베이스에 연결한다. database.js 파일 내부에 공식문서에서 제공하는 pool 객체 생성 방식을 복사한 후 다음과 같이 설정을 추가한다.
import mysql from 'mysql2/promise';
import 'dotenv/config';
// Create the connection pool. The pool-specific settings are the defaults
const pool = mysql.createPool({
host: process.env.MYSQL_RDS_ENDPOINT,
user: process.env.MYSQL_RDS_USERNAME,
password: process.env.MYSQL_RDS_PASSWORD,
port: 3306,
database: 'db_test',
});
host: AWS RDS의 엔드포인트를 입력한다.user: AWS RDS에 설정한 username을 입력한다.password: AWS RDS에 설정한 password를 입력한다.port: AWS RDS에 설정한 포트 번호를 입력한다. MySQL은 대체로 3306번 포트를 사용한다.database: 사용할 데이터베이스를 선택한다. 위에서 사용한 db_test를 지정한다.⚠️ 보안을 위해 AWS RDS의 엔드포인트, username, password를 절대로 GitHub 레포지토리에 노출해서는 안 된다. GitHub에서 경고를 보낼 뿐만 아니라, 추후 이 때문에 AWS에서 요금 폭탄을 마주할 수도 있다.
나는 RDS의 엔드포인트, username, password를 모두 .env 파일 내부에 저장한 후 이를 불러와서 사용했다. 하지만 .env 파일 역시 GitHub에 업로드하면 절대 안 되기 때문에 .gitignore 파일에 .env 형식을 추가한 상태이다. 따라서 .env 파일은 GitHub에 커밋을 올려 자동 배포가 되더라도 EC2에 추가가 되지 않을 것이고, 이 .env 파일은 EC2의 프로젝트 디렉토리 내부에 직접 저장해야만 한다.
EC2에 .env 파일을 추가하기 위해 잠시 다시 EC2로 돌아가본다.
➁-1 프로젝트 디렉토리로 이동
$ cd ~ # 홈 디렉토리로 이동
$ cd <프로젝트 이름> # 프로젝트 디렉토리로 이동
EC2에 접속해 프로젝트가 위치한 디렉토리로 이동한다.
➁-2 .env 파일 생성
$ touch .env
.env 파일을 생성한다.
➁-3 .env 파일 작성
$ nano .env
nano 에디터를 이용해 .env 파일 내부에 정보를 작성한다.
MYSQL_RDS_ENDPOINT=[RDS엔드포인트]
MYSQL_RDS_USERNAME=[RDS username]
MYSQL_RDS_PASSWORD=[RDS password]
Ctrl+O 키를 이용해 저장하고, Ctrl+X를 이용해 에디터에서 빠져나오면 작성이 완료된다.
다음으로 Express 프로젝트로 돌아와 데이터베이스의 테이블에서 데이터를 조회하는 함수를 한 번 작성해본다. 데이터를 조회할 때마다 새로 SQL문을 작성하는 것은 굉장히 비효율적이므로 데이터를 조회하는 함수를 작성한 후 이 함수를 호출하는 방법을 사용할 것이다.
데이터베이스에 SQL문으로 요청이 들어오면 테이블을 조회해 결과값을 반환하는 데까지 시간이 필요하므로 async / await 키워드를 이용해 비동기 함수를 생성한다.
/**
* 전체 note 목록을 가져오는 getNotes 함수
* @returns {Array<{ uuid: string, title: string, contents: string, created: string }>}
*/
export async function getNotes() {
const [rows] = await pool.query(
`SELECT BIN_TO_UUID(uuid, true) AS uuid, title, contents, created FROM notes`
);
return rows;
}
위의 getNotes 함수를 database.js 파일에 추가한다.
pool의 query 메서드의 인수로 SQL 문을 전달해 데이터를 조회(SELECT), 삽입(INSERT), 수정(UPDATE), 삭제(DELETE)할 수 있는데, 이번에는 간단히 데이터를 조회하는 함수를 만들어보는 것이므로 SELECT 문을 이용해 데이터베이스에 저장된 notes 테이블을 조회한다.
Express의 라우터에서 함수를 사용할 수 있도록 함수를 내보낸다(export 한다).
이제 Express의 라우팅을 이용해 /notes라는 주소로 접근하면 데이터를 조회할 수 있는 GET 메서드를 작성한다. src 폴더 내부에 있는 index.js 파일에 다음 코드를 추가한다.
import { getNotes } from './db/database.js';
...
// GET notes
app.get('/notes', async (req, res) => {
const notes = await getNotes();
if (notes.length === 0)
res.send({
ok: 1,
item: [],
});
res.send({ ok: 1, item: notes });
});
배열 형태의 데이터베이스 조회 결과를 notes 변수에 저장하고, notes 배열에 아무 요소가 없다면 빈 배열을 반환하며 요소가 있다면 해당 요소를 반환하는 HTTP GET 메서드이다.
이제 변경 사항을 GitHub 레포지토리에 푸시하면 배포가 완료될 것이다. 브라우저에서 지정한 엔드포인트(https://api.jinwook.site/notes)로 접속하여 데이터를 요청하면 다음과 같이 notes 테이블에 저장된 데이터를 잘 불러오는 것을 확인할 수 있을 것이다.

추가적으로 note 상세를 조회하는 GET 메서드, note를 저장하는 POST 메서드, note를 수정하는 PUT 메서드, note를 삭제하는 DELETE 메서드를 구현하였지만 우선 이번 포스트에서는 생략한다.
다음 포스트에서는 생성한 API를 기반으로 Swagger를 이용해 API 명세서를 작성하는 과정을 소개할 예정이다. Front-end 개발을 하며 Swagger가 언제 나오는지 기다린 적도 많고... 도대체 어떻게 해야 Swagger를 만들 수 있는지 궁금했는데, 이 궁금증을 해결할 수 있는 시간이 될 수 있을 것이다.