React-nodebird (9) - 시퀄라이즈를 통해 회원가입하기 (CORS 문제 해결)

장택진·2022년 11월 2일
0

React-nodebird

목록 보기
9/15

데이터의 흐름

우선 데이터의 흐름을 보면 포트번호가 같으면 같은 프로그램으로 본다.

CORS


서버와 연동을 해봤다면 한번쯤 보게되는 에러이다.
해석해보면 'Access-Control-Allow-Origin'가 요청헤더에 없다고 한다.

개발자 도구의 네트워크탭에서 확인해보자.
진짜 Request Headers에 'Access-Control-Allow-Origin'가 없다.

그게 뭔데...?

그림으로 보면 브라우저는 포트번호가 3060이고, 백엔드 서버는 포트번호가 3065이다.
다른 도메인으로 요청을 보내면 브라우저가 차단을 해버린다. 이게 CORS이다.
서버가 차단하는게 아니라 브라우저가 차단하는 것이기 때문에 브라우저를 변조시키면 해결 될 것 같다. 근데 그게 될까? 그건 해킹이나 다름없다. 그럼 어떻게 해야할까? 간단하게 생각해보면 3060에서 3065로 보내는 것을 허용시키면 된다.
여기서 알아둬야 할 점이 하나 있다. 서버에서 다른 서버로 보낼 때는 CORS에러가 생기지 않는다. (브라우저에서 도메인이 다른 서버에 보낼 때에만 CORS에러가 생긴다.)
이걸 활용해보면, 같은 도메인인 브라우저에서 프론트 서버로 보내고, 프론트 서버에서 백엔드 서버로 요청을 보내고, 응답을 백엔드 서버에서 프론트 서버로 넘겨주고, 다시 프론트 서버에서 브라우저로 넘겨주면 될 것 같다. 이게바로 Proxy 이다.

// app.js - 최상단

const cors = require("cors");
...

app.use(cors({
  origin: 'https://localhosthost:3060',
  credentials: false, // default
}));

CORS는 보안정책이다.
브라우저는 사용자들이 사용하는 것이기 때문에 해커들도 있을 수 있다. 그 해커들이 브라우저에서 백엔드 서버로 바로 요청보내면 위험할 수 있다. 그래서 브라우저에서 차단을 미리 해주는 것이고, 보낼 수 있도록 허용하게 된다면 보안상 위험이있다.
그래서 origin: 'https://localhosthost:3060'를 통해 이 사이트에서 온 요청만 허용받겠다라는 설정을 해놓는게 좋다. 주의할 점은 개발 할 때는 localhost에서 요청을 보내기 때문에 처음에는 모두허용('*') 으로 하다가 최종 배포할 때 바꾸는 것이 좋다.

dotenv를 통해 개인정보 안전하게 하기

npm i dotenv 로 설치를 한다.
.env파일을 만들고 그안에 상수로 안전하게 놓을 값을 쓴다.

COOKIE_SECRET = snssecret
DB_PASSWORD = 비밀번호
  1. json파일
    json 확장자를 js로 바꿔서 .env파일을 가져올 수 있게 해주고
const dotenv = require('dotenv');
dotenv.config();

module.exports = {
  development: {
    username: 'root',
    password: process.env.DB_PASSWORD,
    database: 'react-SNS',
    host: '127.0.0.1',
    dialect: 'mysql',
  },
  test: {
    username: 'root',
    password: process.env.DB_PASSWORD,
    database: 'react-SNS',
    host: '127.0.0.1',
    dialect: 'mysql',
  },
  production: {
    username: 'root',
    password: process.env.DB_PASSWORD,
    database: 'react-SNS',
    host: '127.0.0.1',
    dialect: 'mysql',
  },
};

민감한 정보를 process.env.DB_PASSWORD 이런식으로 .env파일에서 가져온다

회원가입 프론트엔드, 백엔드 완성하기

회원가입에 대한 백엔드 서버에 구성을 알아보겠습니다.
시퀄라이즈의 create 메소드를 통해 req.body에 들어있는 email, nickname, password 데이터를 받아옵니다.

또한, 데이터가 어떤 흐름으로 전송되는지를 먼저 알아야합니다.

  1. 회원가입 폼에서 email, nickname, password 객체 데이터를 가지고 submit

  2. saga의 signUpSIGN_UP_REQUEST가 실행되고, signUp의 action데이터(email, nickname, password의 데이터들이 객체로 들어있음)

  3. signUpAPIdata로 백엔드 서버로 데이터가 전송됩니다.

  4. 프론트서버에서 전송받은 데이터를 req.body로 백엔드서버에서 받게됩니다.

    비밀번호같은 데이터는 데이터를 그대로 전송하게되면 보안에 위협이 되므로 bcrypt라는 라이브러리를 이용합니다.
    hash메소드를 통해 감싸주고, 뒤에 숫자를 붙여줍니다. 보통 10~13의 숫자를 쓰게되는데, 숫자가 높을수록 보안이 강해집니다. 아래 공식문서를 통해 시퀄라이즈와 bcrypt의 더 많은 정보를 확인해볼 수 있습니다.

아이디(이메일)이 중복으로 가입이 되게 해줘서는 안되기 때문에 const { User } = require('../models)로 User를 사용할 수 있게 가져오고, 시퀄라이즈의 find함수중 findOne으로 email이 있는지 체크 후 있다면 에러코드가 나오게 코드를 작성해줍니다.

if문에서 return을 안해주게되면, 아래의 res.send와 2개가 전송이 되서 can't set header already sent 에러가 발생하게되므로 주의해야합니다.

요청(req)과 응답(res)은 아래와 같이 구성되어 있습니다.

  • 헤더 : 상태(status), 용량(storage), 타임, 쿠키
  • 바디 : 데이터

프론트엔드와 백엔드를 완성하고 CORS 문제를 해결해주면 회원가입기능이 완성됩니다.
(사진은 User테이블에 데이터가 성공적으로 들어간 것입니다.)

profile
필요한 것은 노력과 선택과 치킨

0개의 댓글