포스코X코딩온 웹 풀스택 과정을 수강하며 확실히 듣기 전보다 코딩능력이 증가했지만, 웹개발 공부가 거의 처음인 나에게 교육 진도가 정말 빨랐다. 그래서 지금까지 진행하며 배운 node.js와 mysql 그리고 리액트까지 살짝 다룰 수만 있을 정도이고, 어떤 작업이나 원하는 기능을 구현하고 싶을 때, 바로바로 구현하는 것에 어려움이 있다. 그래서 고민해본 결과 현재 진도를 나가고 있는 스프링부트를 배우는 것은 보류하고 node.js와 mysql 그리고 리액트를 원하는대로 능숙하게 다룰 수 있도록 강의와 개인 프로젝트를 진행하며 개인 실력을 기르기로 결심했다. 지금까지 정리하지 못한 블로그도 하루 1블로깅을 하며, 다시 정리하고자 한다. 일단 지금은 이전에 진행하던 리액트 개인 프로젝트를 완성하며, React와 Node.js를 능숙하게 다룰 수 있도록 노력할 예정이다. 블로그도 새로 팔까 고민중이다. 

 

[앞으로 하루동안 해야하는 것들]

default : 3시간 이상 집중(공부시간)

아침 운동,

1일 1블로깅

1일 1커밋

2일 1 백준/프로그래머스 문제풀기(번갈아가면서)

리액트 개인 프로젝트 (마무리 후 >> 포스코X코딩온 kdt에서 진행한 두 번째 프로젝트 완성 후 배포하여 마지막 프로젝트를 할 때 사용할 수 있도록 개발하기 >> 포트폴리오 작성)


 

[11월 6일 해야하는 것]

개인 프로젝트 로그인/회원가입 백엔드 구현

Node.js 강의 했던 부분 처음부터 실습 위주로 복습

1일 1블로깅

1일 1커밋

(코테 준비는 내일부터

 


[리액트 개인 프로젝트 로그인/회원가입 기능 구현]

로그인과 회원가입 구현은 bcrypt 암호화를 사용하여 구현했다.

 

먼저 bycrypt를 설치해준다.

npm i bcrypt

 

 컨트롤러에 적용

// /Controller/Cstory.js

const bcrypt = require("bcrypt");

 

이렇게 위에서 불러주고, 회원가입할때 암호화하여 패스워드를 보내주고 로그인할때 비교하여 비교한 값이 true라면 로그인 성공, false라면 로그인 실패를 해주면된다. 

 

먼저 회원가입 기능을 구현해보자 패스워드 암호화 함수를 따로 만들어준다.

// /Controller/Cstory.js

const bcrypt = require("bcrypt");
//나머지 부분들은 생략한다.
 
 //Auth 기능
 
 //비밀번호 암호화
const bcryptP = (pw) => {
    return bcrypt.hashSync(pw, 10);
}

pw는 암호화하고자 하는 데이터이고, 10은 salt값이다. 여기서 salt란 입력한 값에 붙이는 특정 값으로 보안을 높여준다. 여기서 주의할 점은 bcrypt는 단방향 암호화이기 때문에 복호화가 불가능하다. 복호화가 가능한 암호를 만들고 싶다면, crypto의 createCipheriv를 사용하면 된다.

 

그 다음에 회원가입을 할 때, 암호화를 하여 데이터를 넣어준다.

// /Controller/Cstory.js

const bcrypt = require("bcrypt");
//나머지 부분들은 생략한다.
 
 //Auth 기능
 
 //비밀번호 암호화
const bcryptP = (pw) => {
    return bcrypt.hashSync(pw, 10);
}

// 회원가입
const signup = async(req, res) => {

    try {
        const {email, nickname, pw} = req.body;
        const hashPw = bcryptP(pw);//위에서 만들어준 암호화 사용
        const signUp = await models.user.create({
            email: email,
            nick_name: nickname,
            pw: hashPw,
        });
        if(signUp){
            res.json({result:true});
        }    
    } catch (error) {
        console.log(error);
    }

}

 

이후에 로그인을 할때 비교해줄 함수를 만들고 이 함수를 적용하여 로그인 기능을 구현하면된다.

 

간편하게 보기위해 이전에 만들었던 회원가입 부분은 생략하도록 하겠다.

// /Controller/Cstory.js

const bcrypt = require("bcrypt");
//나머지 부분들은 생략한다.
 
 //Auth 기능
 
 //비밀번호 암호화
const bcryptP = (pw) => {
    return bcrypt.hashSync(pw, 10);
}

//비밀번호 비교
const conpareBcryptP = async (pw, dbpw) => {
    return await bcrypt.compare(pw, dbpw);
}

여기서 비교한 값을 비동기로 처리한 이유를 설명하자면, 암호를 비교한 후 일치한다면 true를 리턴해주고, 일치하지 않는다면 false를 리턴해준다. 근데 이 값을 받기 위해선 비동기로 처리해야하기 때문에 async await을 사용해주었다.

 

로그인할려고 하는 사용자가 보낸 데이터(이메일과 패스워드)를 구조분해할당으로 받고, 시퀄라이즈의 쿼리문으로 해당 이메일을 가진 튜플을 가져온다. 튜플이 존재하지 않을 경우 "해당 유저가 존재하지 않습니다"라는 msg랑 false값을 보내준다.

// /Controller/Cstory.js

const bcrypt = require("bcrypt");
//나머지 부분들은 생략한다.
 
 //Auth 기능
 
 //비밀번호 암호화
const bcryptP = (pw) => {
    return bcrypt.hashSync(pw, 10);
}

//비밀번호 비교
const conpareBcryptP = async (pw, dbpw) => {
    return await bcrypt.compare(pw, dbpw);
}


//로그인 데이터 보냄
const login = async(req, res) => {

    try {
        const {email, pw} = req.body;
        console.log("로그인 데이터", email, pw);
        const result = await models.user.findOne({
            where: {email},
        });
        if(!result){
            res.json({
                result : false,
                msg : "해당 유저는 존재하지 않습니다.",
            });
        } 
        
        if (result) {
			//튜플이 존재할 때
        }
    } catch (error) {
        console.log(error);
    }

 

이제 튜플 즉, 유저가 존재할 때 비밀번호가 일치에 따라 일치한다면 true값을 일치하지 않는다면 false값을 보내준다. 

// /Controller/Cstory.js

const bcrypt = require("bcrypt");
//나머지 부분들은 생략한다.
 
 //Auth 기능
 
 //비밀번호 암호화
const bcryptP = (pw) => {
    return bcrypt.hashSync(pw, 10);
}

//비밀번호 비교
const conpareBcryptP = async (pw, dbpw) => {
    return await bcrypt.compare(pw, dbpw);
}

//로그인 데이터 보냄
const login = async(req, res) => {

    try {
        const {email, pw} = req.body;
        console.log("로그인 데이터", email, pw);
        const result = await models.user.findOne({
            where: {email},
        });
        if(!result){
            res.json({
                result : false,//프론트에서 로그인했을때 받은 값이 false라면 msg를 p태그로 띄워주기
                msg : "해당 유저는 존재하지 않습니다.",
            });
        } 
        
        if (result) {
            const compare = await conpareBcryptP(pw, result.pw);
            console.log("비교 후 리턴 값", compare);//비교한 후의 리턴값을 받을려면 비동기로 받아야한다.
            if(compare){//compare이 true일 때,
                res.json({
                    result : true,
                    msg: "로그인 성공!"
                });
            } else{//compare이 false일 때,
                res.json({
                    result : false,
                    msg : "비밀번호가 일치하지 않습니다."
                })
            }

        }
    } catch (error) {
        console.log(error);
    }

 

이를 모두 합친 코드는 다음과 같다.

// /Controller/Cstory.js

const bcrypt = require("bcrypt");
//나머지 부분들은 생략한다.
 
 //Auth 기능
 
 //비밀번호 암호화
const bcryptP = (pw) => {
    return bcrypt.hashSync(pw, 10);
}

//비밀번호 비교
const conpareBcryptP = async (pw, dbpw) => {
    return await bcrypt.compare(pw, dbpw);
}

// 회원가입
const signup = async(req, res) => {

    try {
        const {email, nickname, pw} = req.body;
        const hashPw = bcryptP(pw);//위에서 만들어준 암호화 사용
        const signUp = await models.user.create({
            email: email,
            nick_name: nickname,
            pw: hashPw,
        });
        if(signUp){
            res.json({result:true});
        }    
    } catch (error) {
        console.log(error);
    }

}

//로그인 데이터 보냄
const login = async(req, res) => {

    try {
        const {email, pw} = req.body;
        console.log("로그인 데이터", email, pw);
        const result = await models.user.findOne({
            where: {email},
        });
        if(!result){
            res.json({
                result : false,
                msg : "해당 유저는 존재하지 않습니다.",
            });
        } 
        
        if (result) {
            const compare = await conpareBcryptP(pw, result.pw);
            console.log("비교 후 리턴 값", compare);//비교한 후의 리턴값을 받을려면 비동기로 받아야한다.
            if(compare){
                res.json({
                    result : true,
                    msg: "로그인 성공!"
                });
            } else{
                res.json({
                    result : false,
                    msg : "비밀번호가 일치하지 않습니다."
                })
            }

        }
    } catch (error) {
        console.log(error);
    }

 


구현을 하면서 겪었던 에러와 알게된 점

 

- 에러 : data must be a string and salt must either be a salt string or a number of rounds

bcrypt가 받는 데이터는 반드시 string  값이거나 salt값으로 받아야 한다.

근데 나는 포스트맨으로 비밀번호를 int값으로 보냈기 때문에 에러가 발생했었다.

 

- try catch문을 사용하는 이유 :

try catch문을 사용하지 않은 상태에서 에러가 발생하면 서버가 꺼진다. 이를 방지하기 위해 try catch문으로 에러를 받는 것이다. 또한 에러가 발생했을때 어떤 작업을 할지도 정할 수 있기 때문에 매우 유용하다.


앞으로 구현해야하는 작업들

[백엔드 : Node.js]

[구현해야하는 기능]

  • 메인페이지 정보 보내기 11/6 (완)
  • 회원가입 : 데이터 베이스로 정보 보내기 11/6  (완)  
  • 로그인 : 비밀번호 암호화 하기 JWT로 구현 11/6 (완)
  • 이야기 상세 페이지에서 수정과 삭제가 가능
  • 마이페이지 들어가 내가 적은 이야기 확인가능 
  • 이야기 업로드 가능

 

  • 이야기 업로드 기능 11/7 - 8
  • 사진 업로드 서버로 올렸다가 다시 받으면서 주소 간소화 성공하기(코프런 참고) 
  • 에디터 가져와서 벨로그처럼 기능할 수 있도록 하기(코프런 참고)
  • 챗지피티 api 가져와 맞춤법 검사 해주기
  • 마이페이지 : 사용자 아이디가 있는 이야기와 세계 가지고 오기

[프론트엔드 : 리액트] : 백엔드 마무리 후 작업

  • 메인페이지
  • 회원가입 페이지
  • 로그인 모달
  • 사용자의 작업이 가능하도록 토큰 부여(로그인 했을때 백엔드에서 true값과 로그인 성공 메세지를 전달 받으면 토큰 받기 토큰이 있을경우 이용할 수 있는 기능 보여주기)
  •  
  • 마이페이지
  • 스토리 상세페이지
  • 스토리 업로드 페이지(챗지피티 적용(백엔드에서))

+ Recent posts