일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- OSI7계층
- 호이스팅
- 자바스크립트
- TypeError: this.boardRepository.createBoard is not a function
- status code
- 트랜잭션
- 프로미스
- typescript
- CORS
- async/await
- rebase
- Jest
- JWT
- javascript
- on_delete
- manytomanyfield
- django westagram
- Django
- 실행 컨텍스트
- 노드
- nodeJS
- wecode
- pm2
- bcrypt
- 장고초기세팅
- westagram
- crud2
- 스코프
- docker
- node
- Today
- Total
될때까지
((TIL)) Node.js express로 인스타그램 구현하기2 본문
🌸 intro
오늘은 회원가입을 구현했다.
- 이메일 양식 검증
- 비밀번호 양식 검증
- 이메일 중복 => 409 에러
- 비밀번호 암호화 => bcrypt사용
- 관심사 분리 원칙 + mvc패턴 적용
- router -> controller -> service -> model 순으로 간다.
- router : url을 기능과 연결해주는 부분
- controller : 사용자의 요청을 받아 서비스로 전달하고 응답을 받아 프론트로 전달한다.
프론트와 백을 연결하는 어댑터역할 - service : 컨트롤러에서 넘어온 데이터를 검증하는 비즈니스 로직을 작성하고 모델로 넘겨준다.
- model : DB와 연결해서 CRUD하기 위한 로직을 구현하고 컨트롤러에게 전달한다.
- 맡은 기능만 구현해야한다. 모델에서 요청을 처리하거나 컨트롤러에서 비즈니스 로직 작성 노노.
스파게티 코드가 될 우려가 있다.
🧚🏻♀️ 클라이언트로부터 데이터 받는 방법
1. query parameter
const {userId, password} = req.query;
2. path parameter
router.get("/:userId", (req, res, next) => {
const {userId} = req.params;
console.log(userId); // {userId : 3}
// 3을 사용하고 싶다면 req.params.userId해야함.
})
3. body
const {userId, password} = req.body;
🧚🏻♀️ 노드에서 정규식 사용하기
정규표현식은 문자열에 포함된 특정 문자열을 조작하기 위해 사용하는 패턴으로, 사용자가 입력한 데이터값을 검증하고 싶을 때 사용할 수 있다. 예를 들어 회원가입 시 이메일양식/비밀번호 양식처럼.
노드에서는 RegExp 객체의 생성자를 호출해서 사용할 수 있다.
const re = new RegExp('ab+c')
문자열에 일치하는 부분이 있는지 여부는 test()라는 메소드를 사용해 확인 가능하며, true 또는 false값을 반환한다. 이를 코드에 적용시켜보면 아래와 같다.
const validateEmail = (email) => {
const emailValidation = new RegExp(
/^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/
);
console.log('emailValidation.test(email)', emailValidation.test(email)) // 일치하면 true , 틀리면 false 리턴
if (!emailValidation.test(email)) {
throw {status:400, message:"이메일 양식 탈락"}
}
};
🧚🏻♀️ DAO ? DTO ?
노드로 프로젝트를 할 때, models 폴더 안에 userDao.js를 만들고 그 안에서 데이터를 CRUD하는 쿼리문을 작성했다.
인턴쉽 때 controllers폴더 안에 userController.js를 만들고 body에 데이터를 담아 요청할 때, req.body에 담긴 데이터를 userDto라는 변수에 저장했다. DAO와 DTO가 뭐길래 구분해서 사용하는 걸까 궁금해서 공부해봤다.
- DTO : Data Transfer Object의 약자로 데이터를 서비스나 컨트롤러로 보낼 때 사용하는 객체다. 로직이 없는 순수한 데이터 객체 그 자체라고 생각하자.
- DAO : Data Access Object의 약자로 서비스와 DB를 연결해주는 객체다.
그래서 req.body에 담긴 데이터를 저장할때 DTO이름을 사용해 컨트롤러에서 서비스로 넘겨줬고, 모델단에서 데이터를 CRUD하는 쿼리문을 작성할때 해당 파일의 이름을 DAO로 작성했었던 것이군🤓
🧚🏻♀️ 자바스크립트에서 [ ] 빈 배열은 truthy값이다.
const signUp = async (email, password) => {
validateEmail(email)
validatePassword(password)
const user = await userDao.getUserByEmail(email);
// console.log('서비스에서 유저', user)
// => 여기서 DB에 존재하지 않는 이메일,비밀번호를 입력한 뒤에
// user를 찍어보면 []이 찍힌다. 자바스크립트에서 []는 truthy이므로 아래 코드가 계속 실행돼서 오류를 뱉어냈다.
if (user) {
throw {status:409, message:"이메일 중복"}
}
const hashedPassword = await bcrypt.hash(password, 10);
await userDao.createUser(email, hashedPassword);
}
해당 코드를 그래서 아래와 같이 변경했다. 그랬더니 잘 동작하는 코드👍
if (user.length === 0) {
throw {status:409, message:"이메일 중복"}
}
🧚🏻♀️ 비밀번호 암호화(Bcrypt)
대표적인 해시함수(해시함수=복호화 할 수 없는 알고리즘)인 SHA256은 원래 빠른 시간안에 데이터를 검색하기 위한 자료구조로 설계가 됐다. 그렇다 보니 빠른 게 오히려 단점이라지 이 빠름을 이용해 Rainbow table attack(해시함수를 사용해서 변환 가능한 모든 해시값을 테이블로 만든 것)을 해서 비밀번호를 알아낼 수 있기 때문이다.
이러한 취약점을 보완하기 위해 bcrypt가 나왔다.
bcrypt는 솔트(salt)와 키 스트레칭(key-stretching) 방식을 도입한 비밀번호 암호화 함수다.
- salt : 입력한 비밀번호 평문에 무작위 데이터를 소금치듯 더한다.
똑같은 비밀번호여도 솔트값에 따라 해시값이 달라지기 때문에 rainbow table attack 방어 성공! - key-stretching : 단방향 해시값을 몇번이고 반복해서 계속 해싱하는 방법이다.
이로 인해 빠른 속도의 취약점을 보완할 수 있다.
그렇다면 로그인할 때 비밀번호 검증은 어떻게 할까?
- 사용자가 입력한 비밀번호를 salt + key-stretcing한 뒤에 DB에 저장된 문자열과 비교한다.
사용 방법
npm install bcrypt
const bcrypt = requrie("bcrypt");
const saltRounds = 10;
// salt가 몇글자인지 지정할 수 있다. => 10자리의 salt를 사용하겠다는 뜻
// 높아질수록 보안이 높아지지만 속도 느려짐
// 암호화
bcrypt.hash(입력된비밀번호, saltRounds)
// 비교
bcrypt.compare(입력된비밀번호, DB에 저장된 비밀번호);
비밀번호 암호화는 hashSync or hash가 있고 비밀번호 검증에는 compareSync or compare가 있다.
둘의 차이점을 아래 블로그에서 참고했는데 전혀 이해가 되지 않았다... 동기/비동기 다시 공부해야겠다. 일단 첨부해놓기
🧚🏻♀️ Rebase 왜 안돼?
분명히 squah를 진행해서 작업했는데 왜 merge commit이 남았을까...!!! 아잇 안예뻐
실습해보자 => 실습 내용은 해당 포스팅 참고
'학습 > Node.js' 카테고리의 다른 글
((TIL)) Node.js express로 인스타그램 구현하기4 (0) | 2022.09.16 |
---|---|
((TIL)) Node.js express로 인스타그램 구현하기3 (1) | 2022.09.15 |
((TIL)) Node.js express로 인스타그램 구현하기1 (0) | 2022.09.13 |
예외 처리하기 (0) | 2022.08.22 |
버퍼와 스트림 (1) | 2022.08.22 |