#31 [서버 프로그래밍] (06.19)

sookyoung.k·2023년 6월 19일
2
post-thumbnail

🐨 지난 수업 복습

📍 구조체

// 구조체 선언 
struct user_info {
	string password;
	string name;
	uint8 age;
}

➡️ 데이터를 저장하는 형태! 변수 아님.
: 얘만 가지고 할 수 있는 건 없음... 어딘가에 담겨야 함! (키 값만 지정해 준 것... value는 아직 없음, 제약조건 - 데이터 타입 지정)

📍 생성자 함수

// 생성자 함수 
constructor() {
	// msg.sender는 deploy를 하는 지갑의 주소 
	owner = msg.sender;
	count = 0;
}

만들어둔 통(구조체)을 배포할 때 실행
➡️ 초기값 설정

📍 mapping

// mapping 데이터를 생성 
mapping (string => user_info) internal users;

➡️ mapping = json 이라고 생각하기~
: 괄호를 통해 데이터의 구조를 만들어주는 것이라고 생각하면 된다
: 키 값을 데이터의 형태로 넣어줄 것이다~ 하는 내용?

➡️ 얘는 변수입니다. (그래서 변수명을 지정해줌! 데이터를 찾기 쉽게 만들어준다!)

📍 배열

* 배열과 json

공통점) 여러가지의 데이터를 하나의 변수에 넣을 수 있다

차이점) key값!
배열에 key가 아예 없는 것은 아님. json의 key값 = 배열의 인덱스 (유사)
➡️ key의 이름으로 데이터를 찾는 것이 더 쉽고 편하다! (순서가 변해도 원하는 데이터를 추출할 수 있음) 그래서 아마도... 배열이 먼저 나오고 json이 나왔을 것

📍 modifier

➡️ 함수의 행동을 변경해준다
➡️ require()을 잘 사용하는 것이 중요하다~ (=if문)
➡️ _;: 함수의 원래 코드가 들어갈 자리

* 솔리디티에서는 for문을 잘 사용하지 않는다

➡️ 가스비 때문이다... for문은 행동이 많기 때문에! (무한반복... 가스비... 끝장...)
: for문은 반복을 하니까 만일 매개변수에 인자값이 잘못 들어오면 매우 큰일남 ㅋㅋ 백엔드 서버에서 작업을 끝낸 후 컨트랙트에 올려준다

📍 함수

  • 매개변수의 데이터 타입까지 지정해주어야 합니다 → returns에도 순서 맞춰줘야 한다
  • string타입은 memory로 지정해줘야 한다 (휘발성으로 줘야 함... 데이터 크기가 커서! 안 쓰면 에러)
  • public: 어디서든 사용 가능~
  • view: 변경x 데이터의 변화x 그냥 보여주는 함수

여기까지만 해도... 기능구현은 충분하다~,,, 이벤트는 나중에 차차,,,

🐨 SQL

  • cmd창에서 sql 접속

    명령어 > mysql -u root -p

패스워드... 까먹으면 안됩니다...

  • 데이터베이스 목록 보기

    명령어 > show databases;

* ;: 명령어 종료~,,, 세미콜론 잘 붙여줘야 한다... 세미콜론을 사용하지 않으면 절대 종료가 되지 않아...

  • 데이터베이스 생성

    명령어 > CREATE DATABASE [데이터베이스명];

다시 데이터보기 명령어(show databases;)를 입력하면 생성한 이름으로 잘 생성되었다는 것을 알 수 있당!

  • 사용할 데이터베이스 선택

    명령어 > USE [테이블명];

➡️ 유일하게 ;을 사용하지 않아도 되는 명령어이지만... 걍 쓰세요! 습관을 들이자!

  • 테이블 만들기
    ➡️ 각 필드별로 조건 지정 (필드의 이름, 타입, 제약조건 등)

CREATE TABLE [테이블명] (컬럼명 데이터타입 조건, 컬럼명 데이터타입 조건, ...);

딱히 넣을 조건 없으면 조건 부분은 생략 가능

✔️primary key (기본키) : 제약조건 - 데이터 중복 x (unique, not null)
→ 하나의 데이터를 수정/삭제하기 위해서 필요함

  • 데이터 넣기

    명령어 > INSERT INTO [테이블명] VALUES (필드값, 필드값, ...);

* 가독성을 위해서 한 줄에 잘 사용하지 않고 나눠서 쓴다 (지 맘이긴 함)

특정 컬럼에만 데이터 넣기는 테이블명 뒤에 컬렴 명을 지정해준 후 values 뒤에 순서에 맞게 넣고 싶은 데이터만 넣어주면 된다.


키보드 잘못 눌러서 뭔가 잘못 쓴 것 같은데... id 중복인데 왜 PK가 안 먹을까... 일단 Query OK가 뜨긴 뜸...

  • 데이터 확인 (READ)

명령어 > SELECT * FROM [테이블명];

✔️* - 전체선택

두 번째로 넣은 데이터 id값이 ㅋㅋㅋㅋ 개 길다... 이래서 중복데이터로 안 잡혔구나 ㅋㅋㅋㅋ 이러면 안됩니다...

  • 데이터 수정

명령어 > UPDATE [테이블명] SET (컬럼명) = (변경할데이터 값) WHERE [조건];

where을 생략한다면?

이러면... 전부 바뀝니다...(password를 전부 '1111'로 바꾸는 것임... 이런 불상사가 일어나지 않기 위해서는 꼭 where 조건을 써주어야 함)

이렇게 조건을 걸어줘야 한다 (이상했던 id값을 name 컬럼 조건을 통해 변경)
➡️ UPDATE user_info SET id = 'test2' WHRER name = 'test2';

  • 해당 데이터만 보기

명령어 > SELECT * FROM [테이블명];

✔️ * 대신 컬럼명을 적으면 위와 같이 특정 데이터만 조회할 수 있다.

  • 데이터 삭제

명령어 > DELETE FROM [테이블명] WHERE [조건];

✔️ 마찬가지로 WHERE 조건을 걸지 않으면... 데이터값을 전체 삭제해버릴 수도 있으니 주의해야 함...

  • 테이블 구조 변경

명령어 > ALTER TABLE [테이블명] ADD [컬럼명] [데이터타입(크기)];


* 컬럼 추가! (not null 사용 x 기존의 데이터가 있기 때문에 추가할 때 잘못 추가하면 에러남)

명령어 > ALTER TABLE [테이블명] MODIFY COLUMN [컬럼명] [데이터타입] [제약조건];


* 컬럼에 제약조건 추가

  • 컬럼의 정보 확인 (데이터가 아니라 테이블 정보 보기)

명령어 > DESC [테이블명];

  • cmd에서 mysql 나가기

명령어 > EXIT


ㅋㅋㅋㅋ 인사해줌 bye~

🐨 mysql, 서버 연동

📍 express 서버 오픈 - mysql과 연동시키기

  • npm init -y - package.json 만들기

  • 필요한 패키지 설치 - npm install express ejs mysql2 dotenv

express 웹서버 만들어줌
ejs html을 화면에 보여주는 엔진
mysql2 sql과 연결해주는 엔진
dotenv (env-환경설정) 환경변수 설정! 해당하는 프로젝트 내에서 공통적으로 사용할 수 있는 변수

* 환경변수를 왜 쓰는지?
외부에 노출되지 않아야 하는 정보가 있기 때문에 (보안) + 여러 개의 자바스크립트 파일을 만들건데... 환경변수 설정하지 않으면 해당하는 파일마다 변수 설정을 따로 해줘야 함 (환경변수 설정 해두면 파일이 여러개여도 같은 변수 사용 가능)

  • index.js 파일 생성, 웹 서버 열기
// express 로드
const express = require('express');
const app = express();
const port = 3000;

// view 파일의 기본 경로 설정
// 하위 폴더인 views 내에 뷰 파일들을 두겠다는 의미
app.set('views', __dirname + '/views');
// view engine 지정
app.set('view engine', 'ejs');

// post 데이터를 받는 경우에 json 형태로 데이터 변환
// true/false 뭘 써도 상관 x
app.use(express.urlencoded({ extended: false }));

// mysql과 접속시켜보자!
// mysql2 라이브러리 로드 (언제나 라이브러리를 불러올 때는 require)
const mysql = require('mysql2');
// mysql server 정보를 입력하여 연결
const connection = mysql.createConnection({
   host: 'localhost',
   port: 3306,
   user: 'root',
   password: '1234',
   // 사용할 데이터베이스 이름
   database: 'new_deal2',
});

// server 실행
const server = app.listen(port, function () {
   console.log('Server Start!');
});

➡️ node.js서버와 mysql 연동
* mysql.createConnection(): 설치해둔 mysql 라이브러리를 불러오고 createConnection() 메소드를 통해 DB와 연결해준다.
host: 연결할 hostIP주소
port: 포트 번호
user: DB사용자 이름
password: 사용자의 패스워드
database: 사용할 DB 이름

* 웹 소켓을 왜 두 개로 따로 나눠놨을까?
→ 서버의 과부화를 덜기 위해서!
근데 웹소켓이 뭐임...이따 검색...아니 다음에 질문...

  • 서버 실행 (nodemon index.js)

콘솔에 Server Start! 잘 찍힘 성공~

→ sql 서버와 백엔드(express 서버) 연결 완료!

📍 환경변수 설정

➡️ dotenv 라이브러리 - 환경 변수를 파일에 저장해놓고 접근할 수 있게 도와준다.

→ 아무 설정하지 않으면 현재 디렉토리에 위치한 .env 파일에서 환경 변수를 읽어온다.

  • .env 파일 생성

키 = 값 포멧으로 환경변수 설정한 것!

* 참고... 세미콜론 쓰면 에러뜹니다 ^^... 손이 자동으로 움직여버렸음... JAVA쓰던 버릇

→ 'localhost'라고 쓸 때 에러나면 '127.0.0.1'로 바꿔보세요
왜 에러나지?

  • index.js
// dotenv를 이용하여 환경변수 설정
require('dotenv').config();

➡️ require() 메소드를 통해서 라이브러리를 임포트한 후 config() 함수를 같이 호출
= 해당하는 환경변수를 사용하겠다 (.env 파일에 정의된 환경변수 값들이 process.env 객체에 저장된다.)

* config() 함수 - dotenv 패키지의 config()함수는 .env 파일을 읽어와서 해당 파일 안에 정의된 환경 변수를 읽어와서 node.js의 process.env 객체에 할당하는 역할을 한다. 이후 다른 라이브러리나 프로그램에서 process.env 객체를 사용해 해당 환경 변수를 사용할 수 있다. (바로 아래와 같이! connection 부분 수정!)
뤼튼한테 물어봄... 어떤 역할을 하는지 너무 궁금했다.


➡️ index.js에 sql연결하는 부분 환경변수 사용해서 고쳐주기!

* 보안상 민감한 내용이 담기기 때문에 git에 업로드 할 때는 .gitignore.env 파일을 추가해서 업로드되지 않도록 해야 한다.

* 참고 링크
https://www.daleseo.com/js-dotenv/

🐨 로그인/회원가입을 만들자!

📍 로그인

  • index.js에 로그인 페이지 주소를 만들어준다.
// localhost:3000 요청이 들어오는 경우
app.get('/', function(req, res) {
    // 'login.ejs' 파일 렌더링
    res.render('login')
})
  • 뷰 폴더에 login.ejs 파일 생성해서 화면을 만들어준다.
<!DOCTYPE html>
<html lang="ko">
   <head>
      <meta charset="UTF-8" />
      <meta http-equiv="X-UA-Compatible" content="IE=edge" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <title>Document</title>
      <script>
         function signup() {
            location.href = '/signup';
         }
      </script>
   </head>
   <body>
      <!-- 유저가 입력할 수 있는 공간 -->
      <form action="/login" method="post">
         <label>ID</label>
         <input type="text" name="_id" /><br />
         <label>PASSWORD</label>
         <input type="password" name="_pass" /><br />
         <input type="submit" value="로그인" />
      </form>
      <button onclick="signup()">회원가입</button>
   </body>
</html>

* post를 사용하는 이유

  • 보안
  • get 방식으로는 255자 이상 데이터를 보내줄 수 없다 (보내줄 수 있는 데이터의 길이 문제 )
  • 다시 index.js로 돌아와서 login, signup API 만들어주기
// localhost:3000/signup [get]
app.get('/signup', function (req, rse) {
   res.render('signup');
});

// localhost:3000/login [post]
app.post('/login', function (req, res) {
   // 유저가 보낸 데이터를 변수에 대입 & 확인
   const input_id = req.body._id;
   const input_pass = req.body._pass;
   console.log(input_id, input_pass);

   // mysql의 user_info table에서 유저가 입력한 데이터가 존재하는가?
   const sql = `
   SELECT * 
   FROM user_info
   WHERE 
   id = ?
   and 
   password = ?
   ;
   `;
   const values = [input_id, input_pass];
   connection.query(sql, values, function (err, result) {
      if (err) {
         console.log(err);
         res.send(err);
      } else {
         // mysql에서 express 서버에 결과물의 데이터 형태가
         // 존재하는 경우
         /* [
                {
                    'id' : xxxx, 
                    'password' : xxxx, 
                    'name' : xxxx, 
                    'age' : xxxx, 
                    'loc' : xxxx
                }, 
                ... 
                
            ]
        */
         // 존재하지 않는 경우
         // []
         if(result.length == 0) {
            res.send('로그인 실패');
         } else {
            res.send('로그인 성공');
         }
      }
   });
});

➡️ 회원가입 페이지는 get 방식으로 불러온다.

➡️ 로그인 시 유저가 보내는 데이터는 post 방식으로 받는다.
→ 로그인을 하기 위해서는! 내 아이디와 비밀번호가 존재하는지 확인을 해야 한다. = select 구문으로 아이디와 비밀번호 조회!
→ 쿼리문을 아예 sql 변수에 할당, 입력받은 데이터를 values 변수에 할당
query(): connection 객체가 가지고 있는 메소드로 쿼리문을 실행시켜주는 역할을 한다.
connection.query() 함수를 통해서 쿼리문 실행!

  • 첫 번째 인자: 쿼리문 (sql 객체)
  • 두 번째 인자: 입력받은 데이터 (values 객체)
  • 세 번째 인자 - 콜백함수: input 데이터를 쿼리문에 넣었을 때 오류가 났을 경우 첫 번째 매개변수 err 실행, 오류가 나지 않을 경우 함수의 실행 결과에 따라 여러 결과를 받고, 그 결과값이 result에 저장된다.

* 백틱을 쓰면 쿼리문 나눠쓰기 편함~
* ? ➡️ 첫 번째 물음표에는 배열에 있는 첫 번째 값을 넣어주고, 두 번째 물음표에는 배열에 있는 두 번째 값을 넣어준다 (순서 맞춰서 넣어주기)

로그인 성공!

* 참고 링크
https://velog.io/@nayonsoso/Node.js-%EB%A1%9C-MySQL-%EC%A0%9C%EC%96%B4%ED%95%98%EA%B8%B0
https://t-anb.tistory.com/53

📍 회원가입 시 아이디 중복체크

  • 뷰 폴더에 회원가입 창을 보여줄 화면을 먼저 만들어준다! - signup.ejs
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 유저가 아이디를 입력하는 공간 -->
    <form action="/check_id" method="get">
        <label>ID</label>
        <input type="text" name="_id"><br>
        <input type="submit" value="아이디 중복 체크">
    </form>
</body>
</html>
  • index.js/check_id 주소 만들러 갑시다!
// localhost:3000/check_id [get]
app.get('/check_id', function (req, res) {
   // 유저가 입력한 데이터를 변수에 대입 & 확인
   const input_id = req.query._id;
   console.log(input_id);

   const sql = `
        select 
        *
        from
        user_info
        where 
        id = ?;
    `;
   const values = [input_id];
   // connection을 이용하여 mysql server에 sql 쿼리문을 실행
   connection.query(sql, values, function (err, result) {
      if (err) {
         console.log(err);
         res.send(err);
      } else {
         if (!result.length) {
            //result.length == 0
            res.send('사용할 수 있는 아이디입니다.');
         } else {
            res.send('사용할 수 없는 아이디입니다.');
         }
      }
   });
});



결과 확인 (아까 아이디 'test'로 가입했으니까 '사용할 수 없는 아이디입니다' 라는 결과값이 result에 저장되어 값을 넘겨준다)

📍 회원가입

  • index.js 중복체크 잘 되는지 확인 후 check_id 부분 수정
// localhost:3000/check_id [get]
app.get('/check_id', function (req, res) {
   // 유저가 입력한 데이터를 변수에 대입 & 확인
   const input_id = req.query._id;
   console.log(input_id);

   const sql = `
        select 
        *
        from
        user_info
        where 
        id = ?;
    `;
   const values = [input_id];
   // connection을 이용하여 mysql server에 sql 쿼리문을 실행
   connection.query(sql, values, function (err, result) {
      if (err) {
         console.log(err);
         res.send(err);
      } else {
         if (!result.length) {
            //result.length == 0
            // res.send('사용할 수 있는 아이디입니다.');
            res.render('signup2', {
                data : input_id
            })
         } else {
            // res.send('사용할 수 없는 아이디입니다.');
            res.redirect('/signup?result=false');
         }
      }
   });
});

➡️ !result.length = result의 길이가 0일 때 = 이미 존재하는 아이디가 없으니까 사용 가능한 아이디라는 의미! → render()함수를 통해 signup2 페이지 보여주고 넘어온 result 값을 넘겨준다.
➡️ 사용가능한 아이디일 때 res.render() 함수를 통해 signup2 페이지로 data 값을 보내준다. (입력받은 json 데이터)

➡️ 그 외의 경우 = 사용할 수 없는 아이디라는 의미니까 리다이렉트 signup 페이지

  • 뷰 폴더에 회원가입 창을 만들어준다. signup2.ejs 파일 생성 (회원가입하는 창)
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 유저가 데이터를 입력하는 공간 생성 -->
    <form action="/signup2" method="post">
        <label>ID</label>
        <input type="text" name="_id" value="<%=data%>" readonly><br>
        <label>PASSWORD</label>
        <input type="password" name="_pass" required><br>
        <label>NAME</label>
        <input type="text" name="_name" required><br>
        <label>AGE</label>
        <input type="number" name="_age" required><br>
        <label>LOC</label>
        <input type="text" name="_loc"><br>
        <input type="submit" value="회원 가입">
    </form>
</body>
</html>

➡️ value="<%=data%>"중복체크 성공한 아이디 값(데이터)를 바로 가져와야 함
➡️ readonly: 수정하면 안 되니까 읽기 전용
➡️ required: 입력 안 하면 안 넘어간당

  • signup2.ejs에서 post 방식으로 받은 데이터를 처리하기 위한 signup2 주소 만들러 다시 갑시다~
// localhost:3000/signup2 [post]
app.post('/signup2', function (req, res) {
   // 유저가 입력한 데이터를 변수에 대입 & 확인
   const input_id = req.body._id;
   const input_pass = req.body._pass;
   const input_name = req.body._name;
   const input_age = req.body._age;
   const input_loc = req.body._loc;
   console.log(input_id, input_pass, input_name, input_age, input_loc);

   const sql = `
        insert 
        into 
        user_info
        values 
        (?, ?, ?, ?, ?);
   `
   const values = [input_id, input_pass, input_name, input_age, input_loc];
   connection.query(
        sql,
        values,
        function(err, result) {
            if (err) {
                console.log(err);
                res.send(err);
            } else {
                console.log(result);
              // 이부분을 '/login'으로 쓰면 아래와같은 에러가 난다...
                res.redirect('/');
            }
        }
   )
});

결과를 확인하려고 했는데...

왜...?

데이터는 잘 들어온 것 같은데...?

➡️ 이유: login 주소값은 post라서 ^^... ejs 수정하면 잘 된다 (/login 에서 /로) 경로 문제였기 때문에 데이터는 잘 들어가져있음 ㅎㅎ 굿
아니 회원가입 성공하면 다시 로그인(메인)페이지로 돌아가야지 경로 설정 제정신 아니었음 ㅠ 머하는 것임 ㅠㅠ

워크벤치에도 데이터 잘 들어왔는지 확인~

* connection.query() 안에 있는 function은 콜백함수!! (매개변수로 err랑 result(우리가 설정한 변수명이지만)가 들어와야 함
이따 더 찾아보기

✔️ 사용할 수 없는 아이디일 때

// 코드 수정
// localhost:3000/signup [get]
app.get('/signup', function (req, res) {
   // res.render('signup');
   const data = req.query.result;
   console.log(data);
   let output = 0;
   if (data) {
      output = data;
   }
   res.render('signup', {
      data: output,
   });
});

➡️ data라는 변수에 쿼리문의 실행 결과인 result값을 할당 = 아까 콜백함수에서 저장된 result 값을 data에 할당하고 잘 받아오는지 콘솔에 찍어보기
근데 왜 이렇게 코드를 수정한거지...? 이해 안 감 질문하기
➡️ 알아냄! 사용할 수 없는 아이디면 else로 빠져야 하는데 어차피 아무런 행동이 일어나지 않게 해주면 되니까 signup페이지 렌더해주면 된다. (그리고 dataoutput (0으로 초기화되어있음) 들어감)

  • signup.ejs 수정 → 자바스크립트 코드 추가
<!DOCTYPE html>
<html lang="ko">
   <head>
      <meta charset="UTF-8" />
      <meta http-equiv="X-UA-Compatible" content="IE=edge" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <title>Document</title>
      <script>
         function check() {
            alert('사용할 수 없는 아이디입니다!');
         }
      </script>
   </head>
   <% if (data == 'false') {%>
   <body onload="check()">
   <%} else {%>
   <body>
      <%}%>
      <!-- 유저가 아이디를 입력하는 공간 -->
      <form action="/check_id" method="get">
         <label>ID</label>
         <input type="text" name="_id" /><br />
         <input type="submit" value="아이디 중복 체크" />
      </form>
   </body>
</html>

➡️ data 값이 false일 경우 check() 함수 실행되어 alert 창이 뜬다

✔️ 주소창: res.redirect('/signup?result=false');

🐨 간단한 게시판 기능 구현

  • 워크벤치에서 새 테이블 만들기



알아서 쿼리문 작성해줌 개꿀

  • index.js 수정 → 로그인 성공 시 /board로 리다이렉트 하게 수정해준다
// localhost:3000/login [post]에 아래 부분 수정 
         if (result.length == 0) {
            // res.send('로그인 실패');
            res.redirect('/');
         } else {
            // res.send('로그인 성공');
            res.redirect('/board');
         }
  • /board주소 만들기
// localhost:3000/board [get]
app.get('/board', function(req, res) {
    res.render('board')
})
  • 뷰 폴에 board.ejs 만들기
<!DOCTYPE html>
<html lang="ko">
   <head>
      <meta charset="UTF-8" />
      <meta http-equiv="X-UA-Compatible" content="IE=edge" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <title>Document</title>
      <script>
         function add_content() {
            location.href = '/add_content';
         }
      </script>
   </head>
   <body>
      <button onclick="add_content()">글 쓰기</button>
   </body>
</html>

일단 데이터 가져온 다음에 테이블을 만들 것임

  • index.js/add_content 경로를 만들어준다 (왜냐면... 위에서 만들었으니깐... 글쓰기 버튼을 누르면 이동할 경로)
// localhost:3000/add_content [get]
app.get('/add_content', function (req, res) {
   res.render('add_content');
});
  • 경로를 만들었으니 뷰 폴더에 화면 만들기 → add_content.ejs 생성
<!DOCTYPE html>
<html lang="ko">
   <head>
      <meta charset="UTF-8" />
      <meta http-equiv="X-UA-Compatible" content="IE=edge" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <title>Document</title>
   </head>
   <body>
      <form action="/add_content2" method="post">
         <label>Title</label>
         <input type="text" name="_title" /> <br />
         <label>Content</label>
         <textarea name="_content" width="500px" height="1000px"></textarea><br />
         <input type="submit" value="글 쓰기" />
      </form>
   </body>
</html>

✔️ post방식을 사용한 이유는 보안보다는 content의 크기 때문에! 그런걸듯.

→ 워크벤치에서 데이터 들어가는지 확인하기 (잠시 작성자랑 시간 not null 해제)

  • 다시 index.js/add_content2 주소 설정
// localhost:3000/add_content2 [post]
app.post('/add_content2', function(req, res) {
    // 유저가 입력한 데이터를 변수에 대입 & 확인
    const input_title = req.body._title;
    const input_content = req.body._content;
    console.log(input_title, input_content);

    const sql = `
        insert
        into
        board (
            title,
            content
        ) 
        values (
            ?, ?
        ) 
    `
    const values = [input_title, input_content];
    connection.query (
        sql,
        values,
        function(e, result) {
            if (e) {
                console.log(e);
                res.send(e);
            } else {
                console.log(result);
                res.redirect('/board');
            }
        }
    )
})


로그인 하면 이렇게 넘어가고

내용을 쓰면

데이터가 잘 넘어갔음을 확인할 수 있다!

📍 데이터를 테이블 형태로 보여주기

  • 보드 테이블에서 데이터를 가져와서 화면에 보여줘야 함 (index.js 수정)
// localhost:3000/board [get]
app.get('/board', function (req, res) {
   // sql server에 있는 board table의 정보를 로드
   const sql = `
        select 
        * 
        from 
        board;
    `;
   connection.query(sql, function (err, result) {
      if (err) {
         console.log(err);
         res.send(err);
      } else {
         res.render('board', {
            data: result,
         });
      }
   });
   //    res.render('board'); (하나만 실행되어야 함)
});
  • board.ejs에 테이블 생성
<!DOCTYPE html>
<html lang="ko">
   <head>
      <meta charset="UTF-8" />
      <meta http-equiv="X-UA-Compatible" content="IE=edge" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <title>Document</title>
      <script>
         function add_content() {
            location.href = '/add_content';
         }
      </script>
   </head>
   <body>
      <button onclick="add_content()">글 쓰기</button>
      <!-- 글의 목록  -->
      <table border="1">
         <tr>
            <th>글 번호</th>
            <th>글 제목</th>
         </tr>
         <tr>
            <td><%=data[0]['no']%></td>
            <td><%=data[0]['title']%></td>
         </tr>
         <tr>
            <td><%=data[1]['no']%></td>
            <td><%=data[1]['title']%></td>
         </tr>
      </table>
   </body>
</html>

<!-- 
    data 변수의 형태
        [
            {
                'no' : 1, 
                'title' : 'test',
                'content' : xxxxxx,
                'writer' : xxxxxx,
                'create_dt' : xxx
            },
            ...
        ]
-->

➡️ 일단 테이블 두 개만 만들기

결과물 출력 완료! 그런데... 2개니까 이러지... 여러개면? 쌉귀찮음
어떻게 해야 할까?

➡️ 인덱스 번호 말고 계속 반복이니까 <tr> 태그를 통해서 반복해줘야 한다

      <!-- 글의 목록  -->
      <table border="1">
         <tr>
            <th>글 번호</th>
            <th>글 제목</th>
         </tr>
         <%for (var i=0; i<data.length; i++) {%>
            <tr>
                <td><%=data[i]['no']%></td>
                <td><%=data[i]['title']%></td>
            </tr>
         <%}%>
      </table>

➡️ for문을 사용해서 코드 수정 (이러면 알아서 테이블에 추가가 된다)

📍 상세페이지

  • index.jsview_content 주소 추가
// localhost:3000/view_content [get]
app.get('/view_content/:_no', function (req, res) {
   const input_no = req.params._no;
   console.log(input_no);

   const sql = `
        select 
        * 
        from
        board
        where
        no = ?
    `;
   const values = [input_no];

   connection.query(sql, values, function (e, result) {
      if (e) {
         console.log(e);
         res.send(e);
      } else {
         // result 형태: [{}]
         res.render('view_content', {
            data: result[0],
         });
      }
   });
});
  • board.ejs에 컨텐츠 상세 정보로 이동할 수 있게 코드를 수정해준다.

✔️ 스크립트 코드 추가

         function view(no) {
            location.href = '/view_content/' + no;
         }

✔️ 테이블에 자바스크립트 코드 추가

 <!-- 글의 목록  -->
      <table border="1">
         <tr>
            <th>글 번호</th>
            <th>글 제목</th>
         </tr>
         <%for (var i=0; i<data.length; i++) {%>
            <tr>
                <td><%=data[i]['no']%></td>
                <td onclick="view('<%=data[i].no%>')"><%=data[i]['title']%></td>
            </tr>
         <%}%>
      </table>

➡️ 타이틀을 누르면 view()함수가 실행되도록 한다
➡️ view()함수는 경로 이동시켜준다

  • 뷰 폴더에 view_content.ejs를 만들어서 상세정보를 보여주는 페이지를 만든다.
<!DOCTYPE html>
<html lang="ko">
   <head>
      <meta charset="UTF-8" />
      <meta http-equiv="X-UA-Compatible" content="IE=edge" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <title>Document</title>
   </head>
   <body>
      <!-- 글의 상세 정보 -->
      <ul>
         <li>Title: <%=data['title']%></li>
         <li>Content: <%=data['content']%></li>
      </ul>
   </body>
</html>

코드 추가

  • index.js에 상세정보 페이지 주소를 다시 보면!
// localhost:3000/view_content [get]
app.get('/view_content/:_no', function(req, res) {
    const input_no = req.params._no;
    console.log(input_no);

    const sql = `
        select 
        * 
        from
        board
        where
        no = ?;
    `
    const values = [input_no];

    connection.query(
        sql,
        values,
        function(e, result) {
            if(e) {
                console.log(e);
                res.send(e);
            } else {
                // result 형태: [{}]
                res.render('view_content', {
                    data : result[0]
                })
            }
        }
    )
})

➡️ :_no: 해당하는 넘버의 키로 데리고 오겠다! params로 불러옴
이건 왜 params로 받는 것인가 찾아보기

아까 만든 테이블의 제목 클릭하면 잘 넘어갑니다~

🐨 Git 업로드

GitHub에 올릴 때 .env는 올리면 안 되고... node_modules는 안 올려도 된다.

profile
영차영차 😎

0개의 댓글