본문 바로가기

블록체인 기반 핀테크 및 응용 SW개발자 양성과정 일기

[41일차 복습 및 정리 1] JavaScript 로그인 실패 시 alert, 회원가입 이미지 업로드, image upload, 이미지 nunjucks html 뿌리기, 이미지 예외조건처리

반응형

 

 

오늘 수업 : ajax(axios)를 사용해서 로그인, 회원가입 server html에 reloading없이 alert 등을 바로 띄우는 기술 (?) 을 공부함. 

 

 

1. 로그인 시 DB에 있는 Data와 비교해서 로그인 실패(alert) 구현하기 

 

routers - user - user.controller.js

login_check 기존 코드

let login_check = async (req,res)=>{
    let userid = req.body.userid;
    let userpw = req.body.userpw;

    let result = await User.findOne({
        where:{userid, userpw}
    })
  
    req.session.uid = userid;
    req.session.isLogin = true;

    req.session.save(()=>{
        res.redirect('/');
    })
}

 

- > 비동기식으로 client가 login.html (input type="post") 에서  입력한 userid, userpw 과 같은 row 를 DB에서 찾아서 result 라는 변수에 넣음 -> DB에 있는 id, pw와 DB에 없는 id, pw로 console.log(result) 를 찍어 나오는 결과를 비교 

 

DB에 존재하는 id, pw으로 로그인 - result 값 ↓↓↓

User {
  dataValues: {
    id: 3,
    userid: '아이노유',
    userpw: '1234',
    username: '이힛',
    gender: false,
    userimage: null,
    userdt: 2021-05-10T13:39:41.000Z
  },
  _previousDataValues: {
    id: 3,
    userid: '아이노유',
    userpw: '1234',
    username: '이힛',
    gender: false,
    userimage: null,
    userdt: 2021-05-10T13:39:41.000Z
  },
  _changed: Set(0) {},
  _options: {
    isNewRecord: false,
    _schema: null,
    _schemaDelimiter: '',
    raw: true,
    attributes: [
      'id',
      'userid',
      'userpw',
      'username',
      'gender',
      'userimage',
      'userdt'
    ]
  },
  isNewRecord: false
}

 

DB에 존재하지않는 id, pw로 로그인한 경우 result값 ↓↓↓

 

 

 

 

 NULL 

 

 

 

 

 

 

 

 

 

 

 

 

 

1-1. result의 나오는 다른 결과값들을 이용해서 if 문으로 만들기 

 

let login_check = async (req,res)=>{
    let userid = req.body.userid;
    let userpw = req.body.userpw;

    let result = await User.findOne({
        where:{userid, userpw}
    })
    if(result == null){    ///  result의 값이 null 이면 = DB에 없다면 = id, pw가 틀리다면
        res.redirect('/user/login');  //login 하는 page로 돌아가 ! 
    }else{
        req.session.uid = userid;
        req.session.isLogin = true;
    
        req.session.save(()=>{
            res.redirect('/');
        })
    }
}

 

이제 로그인 실패로 다시 login.html로 돌아갔을 때 alert로 '입력 오류' 창을 뜨게 만들기 

그 기준(?)을 만들기 위해 res.redirect('/user/login/flag=0') flag라는 속성에 0을 넣고 url 보내기 

- > user.controller.js 의 login 부분에 받은 req.query.flag 값을 받고 넘기기 

 

1-2. user.controller.js - login_check 부분 

let login_check = async (req,res)=>{
    let userid = req.body.userid;
    let userpw = req.body.userpw;

    let result = await User.findOne({
        where:{userid, userpw}
    })
    if(result == null){    ///  result의 값이 null 이면 = DB에 없다면 = id, pw가 틀리다면
        res.redirect('/user/login?flag=0');  //login 하는 page로 돌아가 ! 
    }else{
        req.session.uid = userid;
        req.session.isLogin = true;
    
        req.session.save(()=>{
            res.redirect('/');
        })
    }
}

1-3. user.controller.js - let login 부분 

let login = (req,res)=>{
    let flag = req.query.flag;
    res.render('./user/login.html',{flag});
}

flag 값을 login.html 로 보냄 

 

1-4. login.html

login.html  <br/>
<form method = "post" action ="/user/login_check">
    <table>
        <tr>
            <td>아이디</td>
            <td>
                <input type ="text" id ="userid" name = "userid">
            </td>
        </tr>
        <tr>
            <td>비밀번호 </td>
            <td>
                <input type ="text" id ="userpw" name = "userpw">
            </td>
        </tr>
    </table>
    <input type ="submit" value = "로그인하기">
</form>
{% if flag=="0" %}
    <script type="text/javascript" >
        alert('아이디, 패스워드 오류입니다.')
    </script>    
{% endif %}

{% if %} 절, flag 값을 활용해서 alert창 띄우기 

 

1-5.  alert 창 띄워진 이후의 id, pw text 창의 색 바꾸고 focus = 마우스 커서를 그 안으로 옮기면 , 클릭하면 색이 다시 하얘지도록 만들기 

{% if flag=="0" %}
    <script type="text/javascript" >
        alert('아이디, 패스워드 오류입니다.')

        let userid = document.querySelector('#userid');
        let userpw = document.querySelector('#userpw');
        userid.setAttribute('style', 'background:lightsalmon');
        userpw.setAttribute('style', 'background:lightsalmon');

        userid.addEventListener('focus', ()=>{
            userid.setAttribute('style', 'background:#fff')
        })
        userpw.addEventListener('focus', ()=>{
            userpw.setAttribute('style', 'background:#fff')
        })
    </script>    
{% endif %}

 

 

 

 

 

 

 

2. 로그인 성공 시 회원정보 볼 수 있는 info page 구현 

 

routers-user-user.controller.js

let info = async (req,res)=>{
    let result = await User.findAll({});

    res.render('./user/info.html',{result})
    // console.log(result)
}

2-1. 원래 설정해놓았던 res.json({result}) -> render('./user/info.html')로 변경 

 

 

2-2. 로그인한 userid 만 나오도록 설정

let info = async (req,res)=>{
    let userid = req.query.userid;
    let result = await User.findAll({
        where:{userid,}
    });
    console.log(result);
    res.render('./user/info.html',{
        result:result[0]
    })
    // console.log(result)
}

2-3. views - user - info.html 도 변경 (result가 1개가 나와서 for 구문이 필요없음) 

<table>
    <tr>
        <td>번호</td>
        <td>아이디</td>
        <td>비번</td>
        <td>이름</td>
        <td>성별</td>
        <td>사진</td>
        <td>등록일</td>
    </tr>

    <tr>
        <td>{{result.dataValues.id}}</td>
        <td>{{result.dataValues.userid}}</td>
        <td>{{result.dataValues.userpw}}</td>
        <td>{{result.dataValues.username}}</td>
        <td>{{result.dataValues.gender}}</td>
        <td>{{result.dataValues.userimage}}</td>
        <td>{{result.dataValues.userdt}}</td>
    </tr>

</table>

결과

여기서 시간을 오래 잡아먹은 부분 ! --> User.findAll 인 경우 userid 1가지만 값을 찾아와서 result:result[0] 이렇게 값을 넘겨줘야 했고 User.findOne()을 쓴다면 result:result 이렇게 써야 가능했다. 

 

findAll 전부를 찾아오는 개념 (비록 1개를가져와도) 변수에 넣을 때는 [0] 배열의 첫번째라고 사용

findOn 한개를 찾아오는 개념 -> 변수에 넣을 때 가져온 result 값을 그대로 넣어도 됨. 

 

즉, 아래와 같이도 가능 ! 

routers - user - user.controller

let info = async (req,res)=>{
    let userid = req.query.userid;

    let result = await User.findOne({
        where:{userid}
    });

    res.render('./user/info.html', {
        result,   //  result:result 
    }) 
}

 

 

 

 

 

 

 

 

 

3. 날짜 Dateformat 바꾸기

models - user.js 에서 애초에 table을 만들 때 날짜를 변환해서 table을 만들기 

 

3-1. userdt 부분 코드 추가 

            userdt:{
                type:Sequelize.DATEONLY,
                allowNull:false,
                defaultValue:Sequelize.NOW,
                get:function(){
                    return moment(this.getDataValue('userdt')).format('YYYY-MM-DD')
                }
            }

DATE --> DATEONLY 

get:function(){~} 추가 

this.getDataValue('userd') - class 활용 

 

 

3-2. npm install moment  다운

 

 

3-3. server.js 덮어쓰기 true로 변경 

sequelize.sync({force:true})

 

3-4. server on

table이 새로 덮여쓰였으니 data가 없다. 회원가입 추가 하기 

추가할 때는 false로 변경해주기 (true 상태면 계속 전체 덮여쓰기가 되어 회원은 1명뿐임 ) 

sequelize.sync({force:false})

 

3-5. login -> 나의 정보 보기 (info.html) 가서 날짜 잘 나오는지 확인 

 

 

 

 

 

 

 

 

 

 

 

 

 

4. 회원가입 시 image upload 가능하게 만들기 

( HTMl form ----post(image)---> SERVER ) 

 

4-1. image를 받을 수 있는 공간 만들기 

views  = join.html

        <tr>
            <td>이미지</td>
            <td>
                <input type ="file" name ="img" >
            </td>
        </tr>

* 받을 확장자도 정할 수 있음 (지금은 사용x ) 

<input type ="file" name ="userimage" accept="image/png, image/jpg">

 

 

4-2. form 부분 enctype 추가 ( ≒ body 영역 확장)

 

<input type ="file" method="post"> 있으면 enctype 추가 하자 

<form method = "post" action = "/user/join_success" enctype="multipart/form-data">

enctype = encoding type 

multipart/form-data = 모든 문자를 인코딩하지 않겠다. (form으로 server에 이미지, 파일을 전송할 때 주로 사용) 

 

http통신에 header/ body 있는데 post - body에 담아서 보내는.. 

이미지가 보내질 수 있게 form을 준비? 하는 개념 

 

enctype 속성 알기 

 

blckchainetc.tistory.com/104

 

enctype란? enctype의 속성 / nunjucks post로 서버에 이미지 보내기

enctype = encoding type 말 그대로 인코딩의 형태를 지정해주는 것 태그와 함께 쓰이며 form 안의 data 가 server로 제출될 때 해당 데이터를 어떻게 인코딩할지 인코딩되는 방법을 명시 한다. ** method가 pos

blckchainetc.tistory.com

 

 

4-3. npm install multer 다운 

 

내용을 가공해서 우리가 원하는 위치에 파일을 생성, 옮겨 확장자를 붙여 줌 

multer ----> app.use('/', ____ another middle ware___, router) 이렇ㄱ ㅔ 미들웨어를 계속 추가할 수 있음

대신 next(); 가 붙어서 다음 것도 모두 실행되게 만들기 

즉, 하나의 url 값에 두 가지의 callback함수가 들어갈 수 있다. 

 

ex) 콜백함수 많구나 ~ next(); 가 있겠구나 ~ 생각하기 

 

 

 

 

 

4-4. routers - user - index.js 에 multer 가져오기 / 환경설정 추가 

action = "/user/join_success" -> post('/join_success) 하는 routers - user - index.js 에 코드 추가 

 

routers - user - index.js

const express = require('express');
const router = express.Router();
const userController = require('./user.controller')
const multer=require('multer');                      //추가1

const upload = multer({                                    // 추가2
    storage:multer.diskStorage({                          //storage: 어디에 저장
        destination:function(req,file,callback){
            callback(null,'uploads/')
        },
        filename:function(req,file,callback){              //filename: 어떤 이름으로 저장
            callback(null,new Date().valueOf())
        }
    })
})

router.get('/join',userController.join);
router.post('/join_success', upload.single('img'),userController.join_success);   //추가3
router.get('/login', userController.login);
router.post('/login_check', userController.login_check);
router.get('/logout', userController.logout);
router.get('/info', userController.info);

module.exports=router;

 

 

img 에 담은 엄~ 청 긴 text(image 도 text로 이루어져있) 를 따로 빼서 처리한 것 ( 너무큼) 

 

 

4-5. npm install path 다운

 

4-6. routers - user - index.js 에 path 가져오기 

const path = require('path');                    //추가1

const upload = multer({
    storage:multer.diskStorage({
        destination:function(req,file,callback){
            callback(null,'uploads/')
        },
        filename:function(req,file,callback){
            callback(null,new Date().valueOf() + path.extname(file.originalname))  //추가2
        }
    })
})

추가 2 = 확장자 가져오는 코드 

 

*path.extname(filePath); 

파일 확장자 추출 후 출력 

- 경로의 마지막 부분의 문자열에서 마지막 '.' 에서부터 경로의 확장자를 반환 

- 경로의 마지막 부분에 '.'가 없어가 첫 글자가 '.'이라면 빈 문자열을 반환

 

4-7. uploads 폴더 (이미지 사진 저장되는 폴더) 만들기 

 

4-8. server on -> 회원가입 -> upload 폴더 확인 -> 사진이 들어와 있어야함 ! 

 

 

 

5. image DB에 저장하기 (SERVER ---img--> DB) 

DB에 img (엄청 큰 용량의 text)를 저장하지 않고 경로만 저장한다. 

DB에 파일 경로만 넣어주면 끝  ! 

 

5-1. 파일 경로 가져오기 

routers - user - user.controller.js

img 변수에 req.body.img 받은 거 넣고 insert, render에도 추가

let join_success = async(req,res)=>{
    let userid = req.body.userid;
    let userpw = req.body.userpw;
    let username = req.body.username;
    let gender = req.body.gender;
    let userimage = req.file.path;                //추가 

    await User.create({
        userid,userpw,username, gender, userimage        //추가 
    })

    res.render('./user/join_success.html',{
        userid, userpw, username, gender, userimage            //추가
    });
}

req.file.path -> 다른 변수들과 다른 이유 

 

router.post('/join_success', upload.single('img'), userController.join_success);

여기서 처리했기 때문에 바로 사용가능하다. 

 

 

5-2. server on -> 회원가입 -> mysql prompt check ! 

 

 

 

 

6. image html 화면에 뿌려보기 (DB---img--->SERVER---> HTML) 

 

6-1. server.js 아래 추가 

app.use(express.static('uploads'))

 

6-2. views-user - join_success.html

<!DOCTYPE html>
<html lang="en">
<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>
    join_success.html <br/>
    <div><img src = "http://localhost:3000/{{userimage}}"></div>
    
    {{username}}님 환영합니다. <br/>
    {{username}}님의 ID 는 {{userid}}입니다.     
</body>
</html>

 

6-3. routers-user-use.controller.js


let join_success = async(req,res)=>{
    let userid = req.body.userid;
    let userpw = req.body.userpw;
    let username = req.body.username;
    let gender = req.body.gender;
    let userimage = req.file.filename;         // req.file.path---> req.file.filename수정

    await User.create({
        userid,userpw,username, gender, userimage
    })

    res.render('./user/join_success.html',{
        userid, userpw, username, gender, userimage
    });
}

req.file console.log 해보면 요렇게 나옴. 

path, filename 을 내가 사용한 것 

{
  fieldname: 'img',
  originalname: 'KakaoTalk_20201220_141237197.jpg',
  encoding: '7bit',
  mimetype: 'image/jpeg',
  destination: 'uploads/',
  filename: '1620757206785.jpg',
  path: 'uploads\\1620757206785.jpg',
  size: 1619505
}

 

 

 

http://localhost:3000/~~~.jpg  <-uploads/ 가 없는이유 : uploads도 

app.use(express.static('uploads'))

server.js 에서 사용할거라고 해놔서 uploads 경로는 이미 있는 거라고 생각하기  !

 

 

 

 

7. image 안올린 경우, 예외처리 해주기 by 삼항 조건 연산자  

 

회원가입 시, image 안올린 경우 console.log(req.file) 값 = undefined 가 나온다. 

이걸 이용해서 삼항 조건 연산자 만들기 

 

7-1. routers - user - user.controller.js 변수 userimage 수정 

    let userimage = req.file ==undefined ? '' : req.file.filename; 

만약 req.file의 값이 undefined면 (이미지가 없으면) userimage의 값을 '' 아무것도 넣지 말고 이미지가 있으면 (undefined가 아니라면) req.file.filename을 넣어라

 

 

가장 마지막 eeeee image 안넣어서 userimage값이 ''

 

 

반응형