[๋ฐ๋ธŒ์ฝ”์Šค] GUI ํ™œ์šฉ๊ณผ API ์—ฐ๋™์œผ๋กœ ๋ฐฐ์šฐ๋Š” DB ํ™œ์šฉ ์‹ฌํ™”

2025. 5. 1. 20:54ยท๐Ÿ•Š๏ธํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐ๋ธŒ์ฝ”์Šค/TIL

์ง€๊ธˆ๊นŒ์ง€๋Š” Terminal ๊ธฐ๋ฐ˜ CLI๋กœ MariaDB๋ฅผ ๋‹ค๋ค„์™”๊ณ , ๋Œ€๋ถ€๋ถ„์˜ ์ž‘์—…์— ํฐ ๋ถˆํŽธ์€ ์—†์—ˆ๋‹ค. ํ•˜์ง€๋งŒ ์Šคํ‚ค๋งˆ๋‚˜ ํ…Œ์ด๋ธ” ๊ตฌ์กฐ๋ฅผ ํ•œ๋ˆˆ์— ํ™•์ธํ•˜๊ฑฐ๋‚˜ ์‹œ๊ฐ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐ์ž‘ํ•˜๋Š” ๋ฐ์—๋Š” ํ•œ๊ณ„๊ฐ€ ์žˆ์—ˆ๋‹ค.

์˜ค๋Š˜์€ GUI ๊ธฐ๋ฐ˜ ๋„๊ตฌ์ธ MySQL Workbench๋ฅผ ํ™œ์šฉ์„ ๋ฐฐ์› ๋Š”๋ฐ, ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์˜ค๋ฅ˜๋ฅผ ๊ฒช์–ด์„œ ๋‹ค๋ฅธ ํ•ด๊ฒฐ์ฑ…๋„ ์ฐพ์•„๋ณด๊ฒŒ ๋˜์—ˆ๋‹ค. Workbench ์˜ค๋ฅ˜๋ฅผ ๋Œ€์ฒดํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ์•ˆ๊ณผ, ์ƒˆ๋กœ ๋ฐฐ์šด ๋‚ด์šฉ๋“ค(DB ์—ฐ๋™, ๋ฆฌํŒฉํ† ๋ง)์„ ์ •๋ฆฌํ•ด๋ณธ๋‹ค.


๐ŸฌMySQL GUI

MySQL Workbench

MySQL Workbench๋Š” SQL ๊ฐœ๋ฐœ๊ณผ ๊ด€๋ฆฌ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ค๊ณ„, ๊ทธ๋ฆฌ๊ณ  ์œ ์ง€๋ฅผ ์œ„ํ•œ ๋‹จ์ผ ๊ฐœ๋ฐœ ํ†ตํ•ฉ ํ™˜๊ฒฝ์„ ์ œ๊ณตํ•˜๋Š” ๋น„์ฃผ์–ผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ค๊ณ„ ๋„๊ตฌ

MySQL Workbench๋Š” ์ฒ˜์Œ ์จ๋ณด๋Š”๊ฒŒ ์•„๋‹ˆ๋‹ค. DB ์ „๊ณต ๊ณผ๋ชฉ์„ ๋“ค์„ ๋•Œ, ์‹ค์Šต์„ ์œ„ํ•ด MySQL๊ณผ Workbench๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์•˜๊ณ , ์ด๊ฒŒ ์˜ค๋Š˜์˜ ์‹ค์Šต์— ๋ฐœ๋ชฉ์„ ์žก๋Š” ์…ˆ์ด ๋˜์—ˆ๋‹ค...
 
์ด๋ฏธ Workbench๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ์–ด์„œ, ์„ค์น˜ ๊ณผ์ •์€ ๊ฑด๋„ˆ๋›ฐ๊ณ  ๋ฐ”๋กœ Database Connection์„ ์‹œ๋„ํ–ˆ๋‹ค. Docker Desktop์„ ์‹คํ–‰ํ•˜๊ณ , Hostname(127.0.0.1), Port(3306), Username(root), Password๊นŒ์ง€ ๋ชจ๋‘ ์ œ๋Œ€๋กœ ์„ค์ •ํ•˜๊ณ  connect๋ฅผ ๋ˆŒ๋Ÿฌ๋ณด์•˜๋‹ค.
์ ‘์† ์ž์ฒด์—๋Š” ๋ฌธ์ œ๊ฐ€ ์—†์—ˆ์ง€๋งŒ ์ ‘์† ํ›„ ๋ณด์ด๋Š” ํ™”๋ฉด์ด ๋ฌธ์ œ์˜€๋‹ค. ๋ฐ๋ธŒ์ฝ”์Šค ์‹ค์Šต์„ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” MariaDB ์ƒ์˜ ํ…Œ์ด๋ธ”์ด ์•„๋‹ˆ๋ผ MySQL ์‹ค์Šต ์‹œ ์‚ฌ์šฉํ–ˆ๋˜ ํ…Œ์ด๋ธ”๋“ค์ด ๋ณด์ด๊ณ  ์žˆ์—ˆ๋‹ค. ๋‚ด๊ฐ€ ์ ‘์†ํ•˜๋ ค๊ณ  ํ–ˆ๋˜ DB๋Š” Docker ์ปจํ…Œ์ด๋„ˆ์—์„œ ์‹คํ–‰๋˜๋Š” mariadb์˜€์ง€๋งŒ, ์–ด์งธ์„œ์ธ์ง€ ๋กœ์ปฌ๋กœ ์‹ค์Šตํ–ˆ์—ˆ๋˜ MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ๋ณด์ธ ๊ฒƒ์ด๋‹ค.
 
---
(ํ•ด๊ฒฐ๋ฐฉ๋ฒ• #1 ์ •๋ฆฌ์ค‘)
---

VSCode MySQL Extension

๋” ๊ฐ„๋‹จํ•œ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค. ๊ทธ๋ƒฅ ๋‹ค๋ฅธ GUI๋ฅผ ์“ฐ๋ฉด ๋˜๋Š” ๊ฒƒ. ๋‚˜๋Š” ๊ฐœ๋ฐœ ํŽธ์˜์„ฑ์„ ์œ„ํ•ด IDE ๋‚ด์—์„œ ํ•ด๊ฒฐํ•˜๊ณ  ์‹ถ์–ด VSCode์˜ Extension์„ ์‚ฌ์šฉํ•ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ๋‹ค.
 
ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ ๊ฒ€์ƒ‰์ฐฝ์—์„œ MySQL์„ ๊ฒ€์ƒ‰ํ–ˆ์„ ๋•Œ, ๋‘ ๋ฒˆ์งธ๋กœ ๋‚˜์˜จ Extension์„ ์„ค์น˜ํ–ˆ๋‹ค.

Extension์„ ์„ค์น˜ํ•œ ํ›„, ๋ฉ”๋‰ด ๋ชฉ๋ก์—์„œ Database๋ฅผ ํด๋ฆญํ•˜๋ฉด Connect to Server ํ™”๋ฉด์ด ๋‚˜์˜จ๋‹ค. ์ด ํ™”๋ฉด์—์„œ ํ˜ธ์ŠคํŠธ, ํฌํŠธ, ์œ ์ €, ํŒจ์Šค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•˜๊ณ  connect๋ฅผ ๋ˆŒ๋ €๋”๋‹ˆ mariadb์—์„œ ์ƒ์„ฑํ•œ ํ…Œ์ด๋ธ”์ด ์ •์ƒ์ ์œผ๋กœ ํ‘œ์‹œ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

์ •์„์ ์ธ ๋ฐฉ๋ฒ•์€ MySQL Workbench์ธ ๊ฒƒ ๊ฐ™๊ธด ํ•˜์ง€๋งŒ, ๋‚˜์ฒ˜๋Ÿผ ์ฐฝ์„ ์—ฌ๋Ÿฌ๊ฐœ ๋„์šฐ๋Š” ๊ฒƒ์ด ๋ถ€๋‹ด์Šค๋Ÿฝ๊ณ  IDE ๋‚ด์—์„œ ํ•œ ๋ฒˆ์— ํ•ด๊ฒฐํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด Extension ์‚ฌ์šฉ๋„ ์ข‹์€ ์„ ํƒ์ผ ๊ฒƒ ๊ฐ™๋‹ค.


๐Ÿงฉํ…Œ์ด๋ธ” ์ƒ์„ฑ

Youtube ์Šคํ‚ค๋งˆ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , users์™€ channels ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ–ˆ๋‹ค. workbench ์—์„œ๋Š” GUI ๊ธฐ๋ฐ˜์œผ๋กœ, ์ฒดํฌ๋ฐ•์Šค ํด๋ฆญํ•˜์—ฌ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ…Œ์ด๋ธ” ์ƒ์„ฑ์ด ๊ฐ€๋Šฅํ•œ๋ฐ vscode mysql์—์„œ๋Š” ์ง์ ‘ SQL์„ ์ž‘์„ฑํ•ด์ค˜์•ผ ํ•œ๋‹ค๋Š”๊ฒŒ ์กฐ๊ธˆ ๋ฒˆ๊ฑฐ๋กœ์šด ๊ฒƒ ๊ฐ™๊ธฐ๋„ ํ•˜๋‹ค. MySQL Workbench์—์„œ๋Š” GUI์—์„œ row ์ถ”๊ฐ€ ํ›„ ์‹คํ–‰ํ•˜๋ฉด, SQL ๋ช…๋ น์–ด๋„ ๋‚˜์˜ค๋Š”๋ฐ mysql Extension์€ SQL๋กœ Exportํ•˜๋Š”๊ฒŒ ์œ ๋ฃŒ ํ”Œ๋žœ์œผ๋กœ ์ œ๊ณต๋˜๊ณ  ์žˆ๊ธฐ๋„ ํ•˜๋‹ค. ๊ทธ๋ž˜๋„ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์€ ๋‹ค ์ œ๊ณตํ•˜๊ณ  IDE์—์„œ ํ•œ๋ฒˆ์—  ํ•ด๊ฒฐ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š”๊ฒŒ ๋„ˆ๋ฌด ํŽธํ•ด์„œ ์ถฉ๋ถ„ํžˆ ๋งŒ์กฑํ•˜๊ณ  ์‚ฌ์šฉ์ค‘

CREATE TABLE users(  
    id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    email VARCHAR(100) NOT NULL UNIQUE,
    name VARCHAR(45) NOT NULL,
    password VARCHAR(20) NOT NULL,
    contact VARCHAR(45),
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE channels (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    sub_num INT NOT NULL DEFAULT 0,
    video_count INT NOT NULL DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    user_id INT NOT NULL,
    FOREIGN KEY(user_id) REFERENCES users(id)
);

๐Ÿ—‚๏ธDB ์—ฐ๋™ํ•˜์—ฌ API ๋ฆฌํŒฉํ† ๋งํ•˜๊ธฐ

์šฐ์„  mysql2 ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ด์ค€๋‹ค

npm install --save mysql2

ํŒจํ‚ค์ง€ ์„ค์น˜ ํ›„, db ์—ฐ๊ฒฐ์„ ์ˆ˜ํ–‰ํ•  ์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ , ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์—ˆ๋‹ค.

const mysql = require("mysql2");

const connection = mysql.createConnection({
  host: "localhost",
  user: "root",
  password: "root",
  database: "Youtube",
});

connection.query("SELECT * FROM `users` ", function (err, results, fields) {
  console.log(results);
  console.log(fields);
});
  • ์„ค์ •ํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์—ฐ๊ฒฐ
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ” ์ค‘ users์ธ ํ…Œ์ด๋ธ”์„ ๋ฐ›์•„์™€, ๊ฒฐ๊ณผ๊ฐ’๊ณผ ํ•„๋“œ(๊ฒฐ๊ณผ์— ๋Œ€ํ•œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ)๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

 

Timezone ์„ค์ •

created_at ์ปฌ๋Ÿผ์˜ ์‹œ๊ฐ„์„ ํ™•์ธํ•ด๋ณด๋‹ˆ, ํ˜„์žฌ ์‹œ๊ฐ„๊ณผ ๋งž์ง€ ์•Š๋Š” ์ด์ƒํ•œ ๊ฐ’์ด ์ €์žฅ๋˜์–ด ์žˆ์—ˆ๋‹ค. ์ด๋Š” MariadDB์˜ ๊ธฐ๋ณธ ํƒ€์ž„์กด ์„ค์ •์ด UTC๋กœ ๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ํ•œ๊ตญ ์‹œ๊ฐ„(KST, UTC+9)์— ๋งž์ถฐ์„œ ๊ฐ’์„ ์ €์žฅํ•˜๊ฑฐ๋‚˜ ์กฐํšŒํ•˜๋ ค๋ฉด, time_zone ์„ค์ •์„ ๋”ฐ๋กœ ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

SET GLOBAL time_zone = 'Asia/Seoul';
SET time_zone = 'Asia/Seoul';
  • Global์€ ์ „์ฒด ์„œ๋ฒ„ ์„ค์ •์„ ๋ฐ”๊พธ๋Š” ๋ช…๋ น์–ด์ด๊ณ , SESSION์€ ํ˜„์žฌ ์„ธ์…˜(์ฟผ๋ฆฌ ์‹คํ–‰ ์ค‘์ธ ์—ฐ๊ฒฐ)์—๋งŒ ์ ์šฉ๋œ๋‹ค.

time_zone ์„ค์ •์ด ์ž˜ ์ ์šฉ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๋ ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์ฟผ๋ฆฌํ•œ๋‹ค.

SELECT @@global.time_zone, @@session.time_zone;

โญ Asia/seoul๋กœ ์ž˜ ์„ค์ •๋˜์—ˆ๋‹ค๋ฉด, ์ดํ›„๋ถ€ํ„ฐ๋Š” created_at ๊ฐ™์€ TIMESTAMP/DATETIME ์ปฌ๋Ÿผ์— ํ˜„์žฌ ํ•œ๊ตญ ์‹œ๊ฐ„์ด ์ €์žฅ๋œ๋‹ค.

 

โŒ์ด์Šˆ: ๊ธฐ์กด ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ์˜ ์‹œ๊ฐ„๋Œ€๋Š” UTC ๊ธฐ์ค€์œผ๋กœ ํ‘œ์‹œ๋˜๋Š” ๋ฌธ์ œ

time_zone์„ ์„ค์ •ํ–ˆ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ๊ธฐ์กด์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ์˜ ์‹œ๊ฐ„๋Œ€๋Š” ์—ฌ์ „ํžˆ ์ด์ „ ์„ค์ •(UTC ๊ธฐ์ค€)์œผ๋กœ ํ‘œ์‹œ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค.
๊ฐ•์‚ฌ๋‹˜ ํ™”๋ฉด์—์„œ๋Š” ๊ธฐ์กด ๋ฐ์ดํ„ฐ๋„ ์ •์ƒ์ ์œผ๋กœ KST๋กœ ๋ณ€ํ™˜๋˜์–ด ๋ณด์˜€์ง€๋งŒ, ๋‚ด ๋กœ์ปฌ์—์„œ๋Š” ์ด๋ฏธ ์‚ฝ์ž…๋œ ๋ฐ์ดํ„ฐ์˜ ์‹œ๊ฐ„์€ ๋ณ€ํ•˜์ง€ ์•Š์•˜๋‹ค.

 

โœ…์›์ธ ๋ถ„์„
MySQL DATETIME ํƒ€์ž…์€ timezone ์ •๋ณด ์—†์ด ๋ฌธ์ž์—ด๋กœ ์‹œ๊ฐ„๋งŒ ์ €์žฅํ•˜๋Š” ํƒ€์ž…์ด๋‹ค. ์ฆ‰,

  • DATETIME ์ปฌ๋Ÿผ์€ ์ž…๋ ฅ๋œ ์‹œ๊ฐ์ด ๊ทธ ์‹œ์ ์˜ ์‹œ์Šคํ…œ ์‹œ๊ฐ„ ๊ธฐ์ค€์œผ๋กœ ๊ทธ๋Œ€๋กœ ์ €์žฅ๋œ๋‹ค.
  • timezone์„ ๋ฐ”๊ฟ”๋„ ๊ธฐ์กด์— ์ €์žฅ๋œ DATETIME ๊ฐ’์—๋Š” ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋Š”๋‹ค.
  • ๋ฐ”๋€Œ๋Š” ๊ฑด timezone ์„ค์ • ๋ณ€๊ฒฝ ์ดํ›„์— INSERT ๋˜๋Š” ๋ฐ์ดํ„ฐ ๋ฟ์ด๋‹ค.

๐Ÿค”๊ทธ๋Ÿฐ๋ฐ ๊ฐ•์‚ฌ๋‹˜ ํ™”๋ฉด์—์„œ๋Š” ์™œ ๋ฐ”๊ผˆ์ง€??
๊ฐ•์‚ฌ๋‹˜๊ป˜์„œ๋Š” created_at ์ƒ์„ฑ ์‹œ, TIMESTAMP๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ƒ์„ฑํ•˜์…จ๊ธฐ์— ์ž๋™์œผ๋กœ ๋ณ€ํ™˜๋˜์–ด ๋ณด์ธ ๊ฒƒ์ด์—ˆ๋‹ค. DATETIME๊ณผ ๋‹ค๋ฅด๊ฒŒ, TIMESTAMP๋Š” timezone ์˜ํ–ฅ์„ ๋ฐ›๋Š” ํƒ€์ž…์ด๊ธฐ์— timezone ์„ค์ •์„ ๋ฐ”๊พธ๋ฉด ์ด์— ๋งž์ถฐ ์ž๋™ ๋ณ€ํ™˜๋˜์–ด ๋ณด์ธ๋‹ค.

๋‚˜๋Š” DATETIME์œผ๋กœ created_at์„ ์ƒ์„ฑํ–ˆ๊ณ , ๊ฐ•์‚ฌ๋‹˜์€ TIMESTAMP๋ฅผ ์“ฐ์…”์„œ ์ด๋Ÿฐ ์ฐจ์ด๊ฐ€ ๋ฐœ์ƒํ–ˆ๋˜ ๊ฒƒ!

 

๐Ÿ”จDATETIME์œผ๋กœ ์ €์žฅ๋œ ๊ฐ’์„ KST๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฐฉ๋ฒ•
CONVERT_TZ() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

UPDATE users
SET created_at = CONVERT_TZ(created_at, '+00:00', 'Asia/Seoul');
  • ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๊ธฐ์กด ๊ฐ’๋“ค์ด Asia/Seoul ์‹œ๊ฐ„๋Œ€๋กœ ์ž˜ ๋ณ€ํ™˜๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ฐ’ ์ž์ฒด๋ฅผ ๋ฐ”๊พธ๋Š” ์ฟผ๋ฆฌ์ด๋ฏ€๋กœ, ์‹ ์ค‘ํ•˜๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ๊ธฐ์กด๊ฐ’์ด UTC์ธ์ง€, ๊ทธ๋ฆฌ๊ณ  9์‹œ๊ฐ„ ์ฐจ์ด๊ฐ€ ๋‚˜๋Š”์ง€ ๊ผญ ํ™•์ธํ•˜๊ณ  ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

SELECT created_at,
       CONVERT_TZ(created_at, '+00:00', 'Asia/Seoul') AS kst_time
FROM users;

 
๐Ÿฅธ์‹ค๋ฌด์  ์ ์šฉ
๋‚˜๋Š” DB์— ์ €์žฅ๋œ ๊ฐ’์„ ์™„์ „ํžˆ ๋ณ€ํ™˜ํ–ˆ๋Š”๋ฐ, ์‹ค์ œ๋กœ๋Š” ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค๊ณ  ํ•œ๋‹ค.
๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ, DB์—๋Š” UTC์— ์ €์žฅํ•˜๊ณ , ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‹จ์ด๋‚˜ SELECT ์ฟผ๋ฆฌ์—์„œ๋งŒ KST๋กœ ๋ณ€ํ™˜ํ•ด์„œ ๋ณด์—ฌ์ฃผ๋Š” ๋ฐฉ์‹์„ ๋งŽ์ด ์“ด๋‹ค๊ณ  ํ•œ๋‹ค.

  • ์„œ๋ฒ„๋ฅผ ์—ฌ๋Ÿฌ ๋Œ€/๊ตญ๊ฐ€๋ฅผ ์šด์˜ํ•  ๋•Œ ํ˜ผ๋ž€์ด ์ค„๊ณ 
  • ์‹œ๊ฐ„ ๊ธฐ์ค€์œผ๋กœ ํ†ต์ผํ•ด๋‘๋ฉด ๋””๋ฒ„๊น…์ด ์‰ฝ๊ณ 
  • ํƒ€์ž„์กด ์ •์ฑ…์ด ๋ฐ”๋€” ๋•Œ๋„ ์œ ์—ฐํžˆ ๋Œ€์‘ ๊ฐ€๋Šฅํ•ด์„œ

ํƒ€์ž„์กด ๋ณ€๊ฒฝ์— ์œ ์—ฐํ•œ ๋Œ€์‘์„ ์œ„ํ•ด์„œ๋Š” DATETIME๋ณด๋‹ค๋Š” TIMESTAMP๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ create_at ๋“ฑ ์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๋Š”๊ฒŒ ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

 
โญ๊ฒฐ๋ก : DATETIME vs TIMESTAMP

์ €์žฅ ํ˜•ํƒœ๋ฌธ์ž์—ด๋กœ ๊ณ ์ • ์‹œ๊ฐ„ ์ €์žฅUTC๋กœ ์ €์žฅ + timezone ๋ณ€ํ™˜
timezone ์„ค์ • ์˜ํ–ฅ์—†์Œ์žˆ์Œ
์ถ”์ฒœ ์šฉ๋„๊ณ ์ •๋œ ์‹œ๊ฐ„ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์ƒ์„ฑ์ผ, ์ˆ˜์ •์ผ ๋“ฑ ์‹œ์Šคํ…œ ์‹œ๊ฐ„ ์ €์žฅ ์‹œ

 

dateStrings ์˜ต์…˜

Node.js์—์„œ DB๋ฅผ ์กฐํšŒํ•  ๋•Œ, created_at ๊ฐ’์— .000Z๊ฐ€ ๋ถ™์–ด์„œ ์ถœ๋ ฅ๋œ๋‹ค. ์ด ๊ฐ’์„ ์ง€์šฐ๊ณ  ์‹ถ๋‹ค๋ฉด Mysql2 ๋ชจ๋“ˆ ์„ค์ •์—์„œ dateStrings ์˜ต์…˜์„ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

const connection = mysql.createConnection({
  host: "localhost",
  user: "root",
  password: "root",
  database: "Youtube",
  dateStrings: true
});
  • dateStrings ์˜ต์…˜์„ ํ†ตํ•ด DATETIME์ด๋‚˜ TIMESTAMP ๊ฐ’์ด ๋ฌธ์ž์—ด ํ˜•ํƒœ๋กœ ๋ฐ˜ํ™˜๋˜๊ธฐ ๋•Œ๋ฌธ์—, ํŒŒ์‹ฑ์—†์ด ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

DB ๋ชจ๋“ˆํ™”

DB ์—ฐ๊ฒฐ ์ฝ”๋“œ๋ฅผ ๋ณ„๋„ ๋ชจ๋“ˆ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋„๋ก ๊ตฌ์„ฑํ–ˆ๋‹ค.

const mysql = require("mysql2");

const connection = mysql.createConnection({
  host: "localhost", // ECONNREFUSED ๋ฐฉ์ง€๋ฅผ ์œ„ํ•ด IP๋กœ ๋ณ€๊ฒฝ
  user: "root",
  password: "root",
  database: "Youtube",
  dateStrings: true,
});

module.exports = connection;

์ด์ œ API ์—์„œ๋Š” require('./mariadb')๋กœ ์‰ฝ๊ฒŒ DB ์ปค๋„ฅ์…˜์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

โŒ์˜ค๋ฅ˜: Error socket hang up

API๋ฅผ ํ…Œ์ŠคํŠธ ํ•˜๋Š” ๋„์ค‘, socket hang up ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์˜€๋‹ค.

conn.query(
     `SELECT * FROM users Where email = ${email}`,
    function(err, results, fields) {
        res.status(200).json(results)
    }
)

์œ„์˜ SELECT ๊ตฌ๋ฌธ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ์˜€๋‹ค.
 

ํ…œํ”Œ๋ฆฟ ๋ฆฌํ„ฐ๋Ÿด ๊ฐ’์„ ์ง์ ‘ ์ฃผ์ž…ํ•˜๋ฉด, SQL Injection ๊ฐ€๋Šฅ์„ฑ์ด ์ƒ๊ธฐ๊ณ , ๊ฐ’์ด null, string ๋“ฑ์˜ ํ˜•์‹์ผ ๋•Œ ์ฟผ๋ฆฌ ํŒŒ์‹ฑ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ ์„œ๋ฒ„๊ฐ€ ๊ฐ•์ œ๋กœ ์ข…๋ฃŒ๋œ๋‹ค.

`SELECT * FROM users WHERE email = ?`, email,

prepared statement ๋ฐฉ์‹์œผ๋กœ ์ˆ˜์ •ํ•˜์—ฌ, ์•ˆ์ „ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
 

โŒ์˜ค๋ฅ˜: connect ECONNREFUSED 127.0.0.1:7777

์ด๋Š” MySQL์ด 127.0.0.1 ๊ธฐ์ค€์œผ๋กœ๋งŒ ํฌํŠธ ์—ฐ๊ฒฐ์„ ๋ฐ›๋„๋ก ์„ค์ •๋˜์–ด ์žˆ๋Š”๋ฐ, Node.js์—์„œ๋Š” localhost๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ IPv6(::1)๋กœ ํ•ด์„๋˜๋ฉด์„œ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•˜์—ฌ ์ƒ๊ธฐ๋Š” ์˜ค๋ฅ˜์ด๋‹ค. host๋ฅผ ๋ช…ํ™•ํ•œ IP๋กœ ์ง€์ •ํ•˜๋ฉด ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.


๐Ÿšฉ๋ฆฌํŒฉํ† ๋ง ๊ฒฐ๊ณผ

๊ธฐ์กด์—๋Š” Map ๊ฐ์ฒด์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ–ˆ์ง€๋งŒ, ์ด์ œ๋Š” MariaDB์™€ ์—ฐ๋™ํ•˜์—ฌ ์‹ค์ œ DB์— ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋„๋ก ๋ฆฌํŒฉํ† ๋งํ–ˆ๋‹ค.
(์ฝ”๋“œ ์ผ๋ถ€๋งŒ ์ฒจ๋ถ€)

//ํšŒ์›๊ฐ€์ž…
router.post("/signup", function (req, res) {
  if (req.body !== undefined && req.body.email) {
    const { email, password, name, contact } = req.body;

    // ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ์ด๋ฉ”์ผ์ธ์ง€ ํ™•์ธ
    const checkQuery = "SELECT * FROM users WHERE email = ?";
    conn.query(checkQuery, [email], (err, results) => {
      if (err) {
        console.error("ํšŒ์›๊ฐ€์ž… ์ค‘๋ณต ํ™•์ธ ์˜ค๋ฅ˜:", err);
        return res.status(500).json({ message: "์„œ๋ฒ„ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค." });
      }

      if (results.length > 0) {
        return res.status(409).json({ message: "์ด๋ฏธ ์กด์žฌํ•˜๋Š” ์ด๋ฉ”์ผ์ž…๋‹ˆ๋‹ค." });
      }

      // ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž ์ถ”๊ฐ€
      const insertQuery =
        "INSERT INTO users (email, password, name, contact) VALUES (?, ?, ?, ?)";
      conn.query(
        insertQuery,
        [email, password, name, contact || null],
        (err, result) => {
          if (err) {
            console.error("ํšŒ์›๊ฐ€์ž… ์˜ค๋ฅ˜:", err);
            return res
              .status(500)
              .json({ message: "์„œ๋ฒ„ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค." });
          }

          res.status(201).json({
            message: `${name}๋‹˜ ํšŒ์›๊ฐ€์ž…์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค.`,
          });
        }
      );
    });
  } else {
    res.status(400).json({ message: "์š”์ฒญ๊ฐ’์„ ์ œ๋Œ€๋กœ ๋ณด๋‚ด์ฃผ์„ธ์š”" });
  }
});

๋ฆฌํŒฉํ† ๋ง ํ›„ Postman์œผ๋กœ API ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•œ ๊ฒฐ๊ณผ,

  • users ํ…Œ์ด๋ธ”์— ์ •์ƒ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ ์‚ฝ์ž…
  • ์ค‘๋ณต ์ด๋ฉ”์ผ์€ 409 conflict๋กœ ์‘๋‹ต
  • ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋„ ๋ช…ํ™•ํ•˜๊ฒŒ ๋ถ„๋ฆฌ๋˜์–ด, ์›์ธ์„ ํŒŒ์•…ํ•˜๊ธฐ ํŽธํ•ด์กŒ๋‹ค.

GUI๋ฅผ ํ™œ์šฉํ•ด๋ณด๋‹ˆ ์ƒ๊ฐ๋ณด๋‹ค ํ›จ์”ฌ ํŽธ๋ฆฌํ–ˆ๋‹ค. Workbench๊ฐ€ ์ž๊พธ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜์„œ CLI๋ฅผ ๊ณ„์† ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋‚˜ ๊ณ ๋ฏผํ–ˆ์—ˆ๋Š”๋ฐ, ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์„ ํ†ตํ•ด GUI๋ฅผ ์‚ฌ์šฉํ•ด๋ณด๋‹ˆ ํ›จ์”ฌ ์ง๊ด€์ ์ด๊ณ  ์ฟผ๋ฆฌ ์ž‘์„ฑ๋„ ์ˆ˜์›”ํ–ˆ๋‹ค. datetime๊ณผ timestamp์˜ ์ฐจ์ด๋ฅผ ์•Œ๊ฒŒ ๋œ ๊ฒƒ๋„ ํฐ ์ˆ˜ํ™•์ด์—ˆ๋‹ค. timezone ์„ค์ •์„ ์‹ค์Šตํ•˜๋˜ ์ค‘ ๋งˆ์ฃผ์นœ ์˜ค๋ฅ˜ ๋•Œ๋ฌธ์— ์ฒ˜์Œ์—” ๋‹นํ™ฉํ–ˆ์ง€๋งŒ, ์›์ธ์„ ์ฐพ๊ณ  ํ•ด๊ฒฐํ•˜๋Š” ๊ณผ์ •์„ ํ†ตํ•ด ๊ฐœ๋…์„ ๋ช…ํ™•ํžˆ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์–ด์„œ ์˜คํžˆ๋ ค ์ข‹์€ ๊ฒฝํ—˜์ด์—ˆ๋˜ ๊ฒƒ ๊ฐ™๋‹ค. ๋ณธ๊ฒฉ์ ์œผ๋กœ DB์™€ ์—ฐ๋™ํ•œ API๋ฅผ ๋งŒ๋“ค์–ด๋ณด๋ฉด์„œ ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์— ํ•œ ๊ฑธ์Œ ๋” ๋‹ค๊ฐ€๊ฐ€๋Š” ๊ธฐ๋ถ„์ด ๋“ค์–ด ๋งค์šฐ ๋ฟŒ๋“ฏํ•จ

'๐Ÿ•Š๏ธํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐ๋ธŒ์ฝ”์Šค > TIL' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[๋ฐ๋ธŒ์ฝ”์Šค] ์ธ์ฆ/์ธ๊ฐ€ ์‹œ์Šคํ…œ ์ดํ•ด: ์ฟ ํ‚ค, ์„ธ์…˜, JWT์™€ ๋ณด์•ˆ ํฌ์ธํŠธ  (0) 2025.05.04
[๋ฐ๋ธŒ์ฝ”์Šค] ๋ฐฑ์—”๋“œ ํŒŒํŠธ 5  (0) 2025.05.01
[๋ฐ๋ธŒ์ฝ”์Šค] ์‚ฌ์šฉ์ž-๊ฒŒ์‹œ๊ธ€ ์˜ˆ์ œ๋กœ ๋ฐฐ์šฐ๋Š” ํ…Œ์ด๋ธ” ์„ค๊ณ„์™€ ์ปฌ๋Ÿผ ์†์„ฑ, ์ œ์•ฝ์กฐ๊ฑด  (0) 2025.04.28
[๋ฐ๋ธŒ์ฝ”์Šค] RDBMS ํ•ต์‹ฌ ๊ฐœ๋…๊ณผ ์ •๊ทœํ™” ์ดํ•ด(RDBMS vs NoSQL, PK, FK)  (1) 2025.04.25
[๋ฐ๋ธŒ์ฝ”์Šค] Express ๋ผ์šฐํ„ฐ ๋ชจ๋“ˆํ™”์™€ userId๋ฅผ ํ™œ์šฉํ•œ API ๊ตฌ์กฐ ๊ฐœ์„   (0) 2025.04.23
'๐Ÿ•Š๏ธํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐ๋ธŒ์ฝ”์Šค/TIL' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
  • [๋ฐ๋ธŒ์ฝ”์Šค] ์ธ์ฆ/์ธ๊ฐ€ ์‹œ์Šคํ…œ ์ดํ•ด: ์ฟ ํ‚ค, ์„ธ์…˜, JWT์™€ ๋ณด์•ˆ ํฌ์ธํŠธ
  • [๋ฐ๋ธŒ์ฝ”์Šค] ๋ฐฑ์—”๋“œ ํŒŒํŠธ 5
  • [๋ฐ๋ธŒ์ฝ”์Šค] ์‚ฌ์šฉ์ž-๊ฒŒ์‹œ๊ธ€ ์˜ˆ์ œ๋กœ ๋ฐฐ์šฐ๋Š” ํ…Œ์ด๋ธ” ์„ค๊ณ„์™€ ์ปฌ๋Ÿผ ์†์„ฑ, ์ œ์•ฝ์กฐ๊ฑด
  • [๋ฐ๋ธŒ์ฝ”์Šค] RDBMS ํ•ต์‹ฌ ๊ฐœ๋…๊ณผ ์ •๊ทœํ™” ์ดํ•ด(RDBMS vs NoSQL, PK, FK)
ํ‚ํ‚์ž‰
ํ‚ํ‚์ž‰
๋ฟŒ๋ก ํŠธ ๊ฐœ๋ฐœ์ž(์ง€๋ง์ƒ)์˜ ํ’€์Šคํƒ ๊ฐœ๋ฐœ์ž ๋„์ „๊ธฐ
  • ํ‚ํ‚์ž‰
    monicx.dev
    ํ‚ํ‚์ž‰
  • ์ „์ฒด
    ์˜ค๋Š˜
    ์–ด์ œ
    • ๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ (86) N
      • ๐Ÿ–ฅ๏ธdevelop (11)
        • Github (2)
        • Frontend (4)
        • Backend (5)
        • Mobile (0)
        • CS (0)
        • Three.js (0)
        • Docker (0)
      • ๐Ÿ“•review (15)
        • ์ฑ… (10)
        • ํ–‰์‚ฌ (0)
        • ํšŒ๊ณ  (2)
      • โญproject (5)
        • petiary (2)
        • ๆšŽ่ฉ  (0)
        • ์ธํ„ด (2)
      • ๐Ÿ˜ถ‍๐ŸŒซ๏ธalgorithm (0)
      • ๐Ÿ’กtips (1)
      • ๐Ÿ˜Ždaily (10)
      • ๐Ÿ•น๏ธgame (0)
      • ๐Ÿ•Š๏ธํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐ๋ธŒ์ฝ”์Šค (44) N
        • TIL (26) N
        • ํ”„๋กœ์ ํŠธ (13) N
        • ํšŒ๊ณ  (5)
  • ๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

    • ํ™ˆ
    • ํƒœ๊ทธ
  • ๋งํฌ

    • ๋ฒจ๋กœ๊ทธ
  • ์ธ๊ธฐ ๊ธ€

  • ์ตœ๊ทผ ๊ธ€

  • hELLOยท Designed By์ •์ƒ์šฐ.v4.10.3
ํ‚ํ‚์ž‰
[๋ฐ๋ธŒ์ฝ”์Šค] GUI ํ™œ์šฉ๊ณผ API ์—ฐ๋™์œผ๋กœ ๋ฐฐ์šฐ๋Š” DB ํ™œ์šฉ ์‹ฌํ™”
์ƒ๋‹จ์œผ๋กœ

ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”