[프로그래머스] 웹 서비스의 이해(4)

Lina Hongbi Ko·2024년 8월 25일
0

Programmers_BootCamp

목록 보기
9/76
post-thumbnail

2024년 8월 23일

✏️ 데이터베이스 DB

: DataBase(DB), 데이터들의 캠프(데이터들이 살고 있는 곳)

  • 데이터를 통합해(한 군데 모여서) 효율적으로 관리하기 위한 데이터 집합체 -> 데이터가 모여 있어서 효율적으로 관리가능
  • 데이터를 구조화해 관리함으로써 데이터 중복을 방지하고, 효율적인 빠른 데이터 연산을 가능하게 함

✏️ DBMS

: DataBase Management System, 데이터베이스를 운영하고 관리하기 위한 시스템

  • 우리는 결국 DBMS와 대화하는 것임

  • DBMS의 종류 : 운영회사는 다르지만, DB에 연산을 요청하기 위해 사용하는 주요 명령어는 같음
    ex) oracle, mysql, mariadb(mysql이 모체가 되는 시스템)

    ✏️ SQL

: Structured Query Language, 구조화된 질의언어, Query 라고도 부름

  • DB에 연산을 요청하기 위해 질문과 응답을 통해 사용 되는 언어
  • 데이터 생성, 조회, 수정, 삭제 등을 수행
  • 대표적인 SQL
    • 데이터 삽입 : INSERT
    • 데이터 조회 : SELECT
    • 데이터 수정 : UPDATE
    • 데이터 삭제 : DELETE
    • 데이터 생성 : CREATE

✏️ Docker

: 응용프로그램을 격리하는 기술

  • OS(Operating System)에 바로 프로그램을 설치하지 않고, Docker를 통해 설치

    • 도커는 컨테이너(Container) 여러 개를 들고 다니면서, 그 공간 안에 프로그램을 설치한다. 그리고 우리가 필요할 때(=프로그램을 사용할때) 그 컨테이너를 우리에게 주고, 우리는 그 컨테이너 안에서 작업을 한다. -> 그러면 우리 OS는 빠르고 가벼워질 것이고, 어플리케이션도 독립적으로 잘 움직일 것이다.
  • Docker 설치

    • Docker 사이트에서 다운로드(운영체제에 맞게 설치)
      • 내 노트북은 맥북 Inter버전이라 찾아서 설치 해야 했음,,

✏️ MariaDB 설치

: Docker을 설치 했으면, 이제 Docker 위에서 데이터베이스인 Mariadb를 설치해보자.

  1. (Docker가 on인 상태에서 시작) mariadb 설치

    • 터미널 : docker pull mariadb
    • mariadb를 당겨오는 것임(기존에 docker가 mairadb를 가지고 있기 때문에 당겨올 수 있음)
  2. 당겨온 mariaDB를 실행시키고 mariadb 라는 컨테이너 만들기

    • 터미널 : docker run --name mariadb -d -p 3306:3306 --restart=always -e MYSQL_ROOT_PASSWORD=root mariadb
    • mariadb 컨테이너를 만들고, 포트번호를 적어주고, root라는 비밀번호를 생성함
    • 데이터베이스도 하나의 서버이기 때문에, DB와 통신하고 싶으면 포트번호를 맞춰 소통해야함(3306은 default값)
  3. mariadb 컨테이너 접속

    • 터미널 : docker exec -it mariadb /bin/bash
    • docker에게 mariadb 컨테이너를 실행시켜달라고 요청
    • mariadb 컨테이너 안에는 이미 mariadb 관련된 설치를 다 해놓았음(= 환경을 다 구축해놓고 사용할 준비가 되어있다는 말)
  4. mariadb 실행

    • 터미널창의 입력부분이 ~# 으로 끝나는 것을 확인할 수 있음 -> 컨테이너 안에 들어 오게 됨
    • 이제 mariadb를 실행
    • 터미널 : mariadb -u root -p
      *(-u:user)
    • password 입력 -> 위에서 설정한 root 입력
  5. 설치 및 접속 완료됨

✏️ SQL : CREATE

: 이제 mariaDB을 이용해서 데이터를 모아서 관리해보려 한다. 그렇게 하기 위해서 일단, 저장소를 만들어야 한다.

💡 데이터 저장소 만들기

  1. Docker로 MariaDB 실행

    • Docker Desktop 프로그램 실행
    • 터미널 실행
    • mariadb컨테이너 접속 : docker exec -it mariadb /bin/bash
    • mariadb 실행 : mariadb -u -root -p
  2. 데이터를 저장할 방(=database) 만들기

    • 데이터베이스의 방 만들기 : 데이터들이 들어갈 각 방을 역할에 맞게 만들어줘야한다. (여러 사이트를 운영해도 하나의 데이터베이스 안에서 여러 방들을 따로 만들면 충분히 관리 가능-> 각각의 사이트에서 필요한 데이터들을 방을 만들어서 분류하면 쉬움)

    • 우리는 터미널에서 쿼리를 사용해 mariadb 컨테이너에서 방을 만들고 관리할 것임
      ex) 'Tennis'라는 방을 만들어서 관리할 예정

      • 방 확인 : SHOW DATABASES;
      • 방 만들기 : CREATE DATABASE Tennis;
      • 방 들어가기 : USE Tennis;
// terminal

MariaDB [ (none) ]> SHOW DATABASE;
// 이 말은 아직 아무 방에 들어가지 않았다는 뜻
// information_schema, performance_schema, mysql, sys
// 이렇게 기본 방들만 있는 테이블표가 만들어져 있음

MariaDB [ (none) ]> CREATE DATABASE Tennis;
// 테니스 방을 만들어보자

// 다시 방을 보면 Tennis가 있는 것을 확인 할수 있다

MariaDB [ (none) ]> USE Tennis; 
// 방에 들어가보자

// Database changed

MariaDB [Tennis]>
// Tennis 방에 들어감

결과화면

  1. 방 안에서 저장소(=구역) 만들기

    • Tennis라는 방을 만들었고, 이제 이 방을 각각의 구역으로 다시 나눠 관리
    • 저장소(=구역)는 테이블로 만들 것임

    ex) 'member' 라는 테이블 생성 예정

    • 테이블 생성(=열(column)을 만듦) : CREATE TABLE member();

      ex)
      
      CREATE TABLE member(
          id VARCHAR(30),
          name VARCHAR(30),
          pwd VARCHAR(30) 
      );
    • 테이블 보기 : SHOW TABLES;

// terminal

// 테이블을 확인하자

MariaDB [Tennis]> SHOW TABLES;
// Empty set : 테이블이 비어있음

//테이블을 만들면
MariaDB [Tennis]> CREATE TABLES member
	(
		  id VARCHAR(30),
		  name VARCHAR(30),
		  pwd VARCHAR(30)
	);
// Query OK
// 테이블(컬럼)만 만들었고 아직 데이터는 넣지 않았음

결과화면

✏️ SQL : SELECT, INSERT

: 이렇게 방을 만들고 테이블의 프레임만 만들어둔 상태이다. 이제 데이터들을 넣고 조회하려면

💡 테이블 데이터 조회

: SELECT 컬럼명 FROM 테이블명;

ex)
SELECT id FROM member;
SELECT id, name, pwd FROM member;

  • 테이블의 모든 데이터들을 조회 하고 싶을 때
    : SELECT * FROM member;
  • 특정 데이터 조회
    : SELECT 컬럼명 FROM 테이블명 WHERE 조건;
    ex) id가 person1인 행만 조회 하고 싶을 때: SELECT * FROM member WHERE id='person1';

💡 테이블 데이터 삽입

: INSERT 컬럼명1, 컬럼명2, ... INTO 테이블명 VALUES (컬럼1 데이터, 컬럼2 데이터)

ex)
INSERT INTO member VALUES ('a','b','c');

*데이터를 삽입할 때는 한 행을 데이터라고 생각해 입력하면 됨

✏️ SQL : UPDATE, DELETE

: 테이블의 데이터를 업데이트 및 삭제하려면

💡 테이블 데이터 수정

: UPDATE 테이블명 SET 컬럼명 =수정할값 WHERE 조건;

ex)
UPDATE member SET pwd='zzzzz' WEHRE id = 'person1';

*WHERE 조건을 걸지 않으면 테이블 전체의 데이터에 영향이 가서 그 행의 데이터 모두 바뀌므로 주의!

💡 테이블 데이터 삭제

: DELETE FROM 테이블명 WHERE 조건;

ex)
DELETE FROM member WEHRE name = 'hongbi';

*WHERE 조건을 걸지 않으면 테이블 전체 데이터가 삭제됨(Empty set)

✏️ Node.js에 DB 연동

: 데이터베이스를 만들고, 저장소를 만드는 것까지 훑어봤으므로 이제 Node.js와 연동해서 DB를 사용해보자.

  1. 테이블 만들기

    • Tennis 방의 Product 테이블 만들기

      • MariaDB 실행
      • 테이블 생성
      CREATE TABLE product(
        id ITN,
        name VARCHAR(30),
        description VARCHAR(30),
        price INT
      )
      • 데이터 입력
      INSERT INTO product VALUES(1, 'Red Racket', 'Hot Red', 300000);
      INSERT INTO product VALUES(2, 'Blue Racket', 'Cool Blue', 350000);
      INSERT INTO product VALUES(3, 'Black Racket', 'Chic Black', 500000);
      • 데이터 조회 (모든 데이터가 들어간 테이블 확인)
      SELECT * FROM product

      결과화면

  2. 테이블과 Node.js와 연동시키기

    • 데이터베이스 연결
      - node.js에 mysql 모듈을 설치해야함

      1. npm init

      2. npm install mysql --save

      3. 필요한 파일들이 다운 받아짐

      4. 연결시켜줘야함
        : 새 폴더 생성 -> database 폴더 -> connect 폴더 -> mariadb.js 파일 생성

      5. mariadb.js에 연결할 셋팅값 넣음(mysql 모듈 불러오고, mariadb 연결)

        // database / connect / mariadb.js
        
        const mariadb = require('mysql');
        // mysql 모듈 불러옴
        
        const conn = mariadb.createConnection(
          {
              host: 'localhost',
              port: 3306,
              user: 'root',
              password: 'root',
              database: 'Tennis' // 방이름
          }
        )
        // mariadb 연결시킴
        // 연결 통로 뚫음
        
        module.exports = conn;
        // 연결 통로를 밖에서 이용가능하게 만듦
      6. index.js에 mariadb 모듈로 연결시켜주기

        // index.js
        
        let server = require('./server');
        let router = require('./router');
        let requestHandler = require('./requestHandler');
        
        const mariadb = require('./database/connect/mariadb');
        
        mariadb.connect();
        // 연결을 시켜줌
        
        server.start(router.route, requestHandler.handle);
      7. product 테이블 값을 콘솔창에 보이게 하기

        // requestHandler.js
        	
        const mariadb = require('./database/connect/mariadb');
        
        function main(response) {
        	console.log('main');
            mariadb.query("SELECT * FROM product", function(err, rows) {
            	// 에러는 없다는 가정하고
                console.log(rows);
                
                // query() : query(sql)을 던짐
                // rows: 결과값
            })
            response.writeHead(200, {'Content-Type' : 'text/html'});
            response.write('Main Page');
            response.end();
        }
        
        function log(response) {
        	console.log('log');
            response.writeHead(200, {'Content-Type' : 'text/html'});
            response.write('Main Page');
            response.end();
        }
        
        let handle = {};
        
        handle['/'] = main;
        handle['/login'] = login;
        
        exports.handle = handle;
      8. 저장 후, 서버 on하면 터미널 콘솔창에서 데이터베이스에 넣어놓은 데이터가 찍히는 것을 확인 할 수 있음

        결과 화면

✏️ 메인 페이지 연동하기 -1

: 우리가 만든 main.html이 메인페이지가 되게 만들어야함

  1. main.html 파일 가져오기
// requestHandler.js

const fs = require('fs');
// node에서 제공하는 모듈 불러오기(fs : file sink)
// 이 모듈로 우리가 만든 html 가져올 수 있음

const main_view = fs.readFileSync('./main.html', 'utf-8');

const mariadb = require('./database/connect/mariadb');

function main(response) {
	console.log('main');
    mariadb.query("SELECT * FROM product", function(err, rows) {
        console.log(rows);
    })
    response.writeHead(200, {'Content-Type' : 'text/html'});
    response.write(main_view);
    response.end();
}

... 생략 ...
  1. 페이지는 연결되었으나 이미지가 뜨지 않음
    : 이미지를 값으로 인식하고 있기 때문
// requestHandler.js

const fs = require('fs');
const main_view = fs.readFileSync('./main.html', 'utf-8');
const mariadb = require('./database/connect/mariadb');

function main(response) {
	console.log('main');
	mariadb.query("SELECT * FROM product", function(err, rows){
		console.log(rows);
	})
	
	response.writeHead(200, {'Content-Type' : 'text/html'});
	response.write(main_view);
	response.end();
}

function redRacket(response) {
	fs.readFile('./img/redRacket.png', function(err, data){
		response.writeHead(200, {'Content-Type' : 'text/html'});
		response.write(data);
		response.end();
	})
}

function blueRacket(response) {
	fs.readFile('./img/blueRacket.png', function(err, data){
		response.writeHead(200, {'Content-Type' : 'text/html'});
		response.write(data);
		response.end();
	})
}

function blackRacket(response) {
	fs.readFile('./img/blackRacket.png', function(err, data){
		response.writeHead(200, {'Content-Type' : 'text/html'});
		response.write(data);
		response.end();
	})
}

function mainCss(response) {
	fs.readFile('./main.css', function(err, data){
    	response.writeHead(200, {'Content-Type' : 'text/css'});
        response.write(data);
        response.end();
    })
}

let handle = {};

handle['/'] = main;
handle['/main.css'] = mainCss;

/* image directory */

handle['/img/redRacket.png'] = redRacket;
handle['/img/blueRacket.png'] = blueRacket;
handle['/img/blackRacket.png'] = blackRacket;

exports.handle = handle;
  1. 이미지가 모두 포함된 서버에서 main.html을 확인할 수 있음

결과화면

✏️ 메인 페이지 연동하기 -2

: oderlist 테이블을 만들고 데이터를 insert해볼 것이다.

ex) red racket의 order버튼을 누르면 id=1인 데이터묶음을 oderlist테이블에 insert 되게 만들 것임

  • 서버가 특정 행동을 하게 만들려면 requestHandle.js에서 url을 통해 url값을 넣어줘서 처리하게 하였다. 따라서, 요청을 url로 해야 한다.
  1. url에 localhost:8888/order 을 입력하면 oder page가 나오게 만들기
// requsetHandler.js

... 생략 ...

function order(response) {
	response.writeHead(200, {'Content-Type' : 'text/html'});
	response.write('order page');
	response.end();
}

let handle = {};

handle['/'] = main;

/* url 값 받아오기*/
handle['/oder'] = order;

/* image directory */

handle['/img/redRacket.png'] = redRacket;
handle['/img/blueRacket.png'] = blueRacket;
handle['/img/blackRacket.png'] = blackRacket;

exports.handle = handle;
  1. 데이터베이스 orderlist테이블에 insert하기
  • order버튼을 누르면, 상품의 id와 버튼을 누른 날짜를 orderlist 테이블에 추가하기
    • 현재날짜의 값을 넣기 위해 new Date()사용
    • id도 받아와서 사용 => requestHandler에서 productId를 전해주기 위해 handle을 사용해야 하기 때문에 라우터를 이용해야함, 그런데 라우터도 productId를 server.js에서 인수로 던져줘
//  requestHandler.js

... 생략 ...

function order(response, productId) {
	response.writeHead(200, {'Content-Type' : 'text/html'});
	response.write(main_view);
		
	mariadb.query("INSERT INTO orderlist VALUES (" + productId + ", '" + new Date().toLocaleDateString() + "');", function(err, rows){
		console.log(rows);
	});
	response.end();
}

let handle = {};

handle['/'] = main;

/* url 값 받아오기*/
handle['/oder'] = order;

/* image directory */

handle['/img/redRacket.png'] = redRacket;
handle['/img/blueRacket.png'] = blueRacket;
handle['/img/blackRacket.png'] = blackRacket;

exports.handle = handle;
// router.js

function route(pathname, handle, response, productId) {
	console.log('pathname : ' + pathname);
	
	if (typeof handle[pathname] == 'function') {
		handle[pathname](response, productId);
	} else {
		response.writeHead(404, { "Content-Type": "text/html" });
    	response.write("Not Found");
    	response.end();
	}
}

exports.rotue = route;
// server.js

let http = require("http");
let url = require("url");

function start(route, handle) {
  function onRequest(request, response) {
    let pathname = url.parse(request.url).pathname;
    let queryData = url.parse(request.url, true).query;
    
    route(pathname, handle, response, queryData.productId);
  }

  http.createServer(onRequest).listen(888);
}

exports.start = start;
// main.html

... 생략...

<input class="card_buttonn" type="button" value="order" onclick="location.href='/order?productId=1'">

✏️ 주문 내역 페이지 연동

  • oderlist 페이지에 연동된 데이터들 뿌리기
// orderlist.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Order List</title>
  <style>
    h1 {text-align: center;}
    div {text-align: center; margin-bottom: 50px;}
    table {margin: 0 auto;}
    td {text-align: center;}
  </style>
</head>
<body>
  <h1>Order List</h1>
  <div>
    <a href="./main.html">go home</a>
  </div>
  
  <table style="border: 1px solid black">
    <th>Product</th>
    <th>Order Date</th>
</body>
</html>
// requestHandler.js

const orderlist_view = fs.readFileSync("./orderlist.html", "utf-8");

... 생략 ...
function orderlist(response) {
	console.log('orderlist');
	
	response.writeHead(200, { "Content-Type": "text/html" });
	
	mariadb.query("SELECT * FROM orderlist", function(err, rows) {
		response.write(orderlist_view);
		
		rows.forEach((element) => {
			response.write("<tr>" + "<td"> + element.product_id + "</td>"
			+ "<td>" + element.order_date + "</td>" + "</tr>");
		});
		
		response.write("</table>");
		response.end();
	})
}

let handle = {};

handle['/'] = main;
handle['/oder'] = order;
handle['/orderlist'] = orderlist;

/* image directory */

handle['/img/redRacket.png'] = redRacket;
handle['/img/blueRacket.png'] = blueRacket;
handle['/img/blackRacket.png'] = blackRacket;

exports.handle = handle;

결과화면

profile
프론트엔드개발자가 되고 싶어서 열심히 땅굴 파는 자

0개의 댓글