React - fly.io로 pg 생성후 todo 만들기
npm i express 로 백엔드 부분 생성
app.js를 만들어주고
cors 미들웨어 설치
- npm i cors
// 모든 도메인에 대해서 CORS 허용해주도록 설정
import express from "express";
import cors from "cors";
const app = express();
app.use(cors());
// cdpn.io에서 들어오는 요청은 특별히 허용해주도록 설정
import express from "express";
import cors from "cors";
const app = express();
const corsOptions = {
origin: "*",
};
app.use(cors(corsOptions));
fly.io
Windows 에서 설치
윈도우는 새로운 버전의 powershell 을 통하여 설치 가능합니다. 우선 powershell 을 관리자 권한 으로 실행한 후, 하기의 명령어를 실행하여 봅시다.
iwr https://fly.io/install.ps1 -useb | iex
또는
pwsh -Command "iwr https://fly.io/install.ps1 -useb | iex"
flyctl 설치 확인
flyctl 이 정상적으로 설치되었는지 확인하기 위하여, 운영체제의 터미널을 실행하여 아래의 명령어를 입력하여 동작하는지 확인합니다.
flyctl
만일 정상적으로 설치되었다면, fly 와 관련된 내용이 출력될 것입니다.
flyctl 을 이용하여 fly.io 에 로그인
flyctl 을 이용하여 fly 서비스와 연동하기 위해서는 계정을 연동하여야 합니다.
flyctl auth login
명령어를 입력하면 fly 서비스 페이지와 함께 로그인을 할 수 있게 됩니다.
flyctl 을 이용한 docker 어플리케이션 배포
이번 절에서는 flyctl 을 통해서 docker 어플리케이션을 빌드하고 배포하는 방법에 대해서 간략히 서술했습니다.
Dockerfile 이 있는 프로젝트의 경로에서 터미널을 실행합니다. 그 후, 하기의 명령어를 입력합니다.
fly launch
DB 연결
fly.io 로 pg 생성
flyctl pg create
- 여기서 생성되는 정보는 영구저장소에 기록
- 외부에서는 fly.io 안쪽의 db에 바로접근이 불가능하기 때문에, 접근이 필요할 때 마다 flyctl proxy 명령으로 개구멍을 open
flyctl proxy 5432 -a [DB 서버명]
EX : flyctl proxy 5432 -a appName
- ctrl + c 로 프록시 닫기
- 디비버로 해당 DB에 접속되는지 테스트
- 디비 접급 정보에 에 새 db 정보 저장
- DB 비번을 노출한 이유 : 외부에서 접근이 불가능하기 때문에
잘 적어둔 정보를 잘 입력한다.
-- Drop the database if it exists and create a new one
DROP DATABASE IF EXISTS todo202401;
CREATE DATABASE todo202401;
-- Connect to the new database
-- In pgSQL, you usually switch databases using a client or connection string
-- Create the 'todo' table
CREATE TABLE todo (
id SERIAL PRIMARY KEY,
created_date TIMESTAMP NOT NULL,
modified_date TIMESTAMP NOT NULL,
content VARCHAR(200) NOT NULL,
is_checked BOOLEAN DEFAULT false NOT NULL
);
DROP TABLE IF EXISTS todo;
SELECT * FROM todo;
INSERT INTO todo (created_date, modified_date, content, is_checked) VALUES
(NOW(), NOW(), '첫 번째 할 일', false),
(NOW(), NOW(), '두 번째 할 일', true),
(NOW(), NOW(), '세 번째 할 일', false);
-- Add unique constraint to user_code and no
ALTER TABLE todo ADD CONSTRAINT unique_user_code_no UNIQUE (user_code, "no");
-- Insert test data
PG 설치
- npm install pg PG 연결 app.js
# 테이블 생성 CREATE TABLE todo ( id SERIAL PRIMARY KEY, created_date TIMESTAMP NOT NULL, modified_date TIMESTAMP NOT NULL, content VARCHAR(200) NOT NULL, is_checked BOOLEAN DEFAULT FALSE NOT NULL ); # 테이블 전체 조회 SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';
-
import express from "express"; import pkg from 'pg'; const { Pool } = pkg; const pool = new Pool({ user: 'postgres', password: '[비밀번호]', host: '127.0.0.1', database: 'postgres', port: 5432, }); const app = express(); app.use(express.json()); const port = 3000; app.get("/", (req, res) => { res.send("Hello World!"); }); // get 다건 app.get("/api/v1/todos", async (req, res) => { try { const { rows } = await pool.query( ` SELECT * FROM todo ORDER BY id DESC ` ); res.json({ resultCode: "S-1", msg: "성공", data: rows, }); } catch (error) { console.error(error); res.status(500).json({ resultCode: "F-1", msg: "에러 발생", }); } }); // get 단건 app.get("/api/v1/todos/:id", async (req, res) => { try { const { id } = req.params; const { rows } = await pool.query( ` SELECT * FROM todo WHERE id = $1 ORDER BY id DESC `, [id] ); if (rows.length === 0) { res.status(404).json({ resultCode: "F-1", msg: "not found", }); return; } res.json({ resultCode: "S-1", msg: "성공", data: rows[0], }); } catch (error) { console.error(error); res.status(500).json({ resultCode: "F-1", msg: "에러 발생", }); } }); // post 등록 app.post("/api/v1/todos", async (req, res) => { try { const { content } = req.body; const { rows } = await pool.query( ` INSERT INTO todo (created_date, modified_date, content, is_checked) VALUES (NOW(), NOW(), $1, false) RETURNING * `, [content] ); res.json({ resultCode: "S-3", msg: "성공", data: rows[0], }); } catch (error) { console.error(error); res.status(500).json({ resultCode: "F-1", msg: "에러 발생", }); } }); // patch 수정 app.patch("/api/v1/todos/:id", async (req, res) => { try { const { id } = req.params; const { rows } = await pool.query( ` SELECT * FROM todo WHERE id = $1 ORDER BY id DESC `, [id] ); if (rows.length === 0) { res.status(404).json({ resultCode: "F-1", msg: "not found", }); return; } const { is_checked } = req.body; await pool.query( ` UPDATE todo SET modified_date = NOW(), is_checked = $1 WHERE id = $2 `, [is_checked, id] ); res.json({ resultCode: "S-3", msg: "수정성공", data: rows[0], }); } catch (error) { console.error(error); res.status(500).json({ resultCode: "F-1", msg: "에러 발생", }); } }); // delete 삭제 app.delete("/api/v1/todos/:id", async (req, res) => { try { const { id } = req.params; const { rows } = await pool.query( ` SELECT * FROM todo WHERE id = $1 ORDER BY id DESC `, [id] ); if (rows.length === 0) { res.status(404).json({ resultCode: "F-1", msg: "not found", }); return; } await pool.query( ` DELETE FROM todo WHERE id = $1 `, [id] ); res.json({ resultCode: "S-4", msg: "삭제성공", data: rows[0], }); } catch (error) { console.error(error); res.status(500).json({ resultCode: "F-1", msg: "에러 발생", }); } }); app.listen(port, () => { console.log(`Example app listening on port ${port}`); });
프론트 부분은 저번 시간에 만든 코드를 참고한다.
https://codingbasics.tistory.com/224
React로 Todo 만들기
빈 폴더를 하나 만들고 터미널을 열고 npm create vite@latest √ Project name: . or 생성할 폴더명(본인이름) √ Package name: movie-app √ Select a framework: » React √ Select a variant: » JavaScript npm install npm run dev #
codingbasics.tistory.com