[First Project] 회원가입 구현하기(POST signup & checkUserId)

hailey·2020년 10월 20일
0

FirstProject

목록 보기
3/14
post-thumbnail

1. 회원가입 flow 정리

  1. 사용자가 회원가입 페이지에서 이메일을 입력하면, 글자가 입력될 때마다 checkUserId API가 서버로 해당 값을 보낸다.
  2. 서버는 데이터베이스에서 중복되는 값이 있는지 확인한다. 있으면 해당 데이터를, 없으면 null을 반환한다.
  3. 서버의 응답에 따라 클라이언트에서 '이미 가입된 회원입니다.'를 출력하거나 다음 단계(비밀번호 입력하기)로 통과시킨다.
  4. 통과된 사용자가 가입에 필요한 모든 정보를 입력하고 '제출하기' 버튼을 누른다.
  5. signup API가 데이터베이스에 새로운 데이터를 저장한다.

여기서 2~4번이 checkUserId API, 5번이 signup API에 구현되어야 한다.


2. 디렉토리 구조

/SERVER
index.js
 /controller
   index.js
   /users
    checkUserId.js
    index.js
    signup.js
 /routes
  users.js

3. API

1) checkUserId

if (res.useremail) {res.json(data)}
else {null}

500: Internal Server Error

err

2) signup

  • Method: POST

  • URI: http://localhost/users/signup

  • Request
    [Headers] Content-Type: application/json
    [Form Data Parameters] password, useremail, githubId

  • Response
    200: OK

201: Created

{
    "password": "password",
    "email": "email",
    "githublink": "githublink" 
}

500: Internal Server Error

err

4. 각 소스코드

SERVER/index.js
세팅된 서버의 index.js에서 각 API 경로를 설정해주었다.

const express = require('express');
const app = express();
const session = require('express-session');
const cors = require('cors');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');

const usersRouter = require('./routes/users');
const reviewsRouter = require('./routes/reviews');

const port = 4000;

app.use(cookieParser());
app.use(bodyParser.json());
app.use(express.urlencoded({ extended: false }));
// app.use(
//   cors({
//     origin: *,
//     methods: ["GET","POST", "OPTION", "PUT"],
//     credentials: true
//   })
// ) // client주소를 origin에 넣을 필요가 있다.

app.use(
  session({
    secret: 'safuproject',
    resave: false,
    saveUninitialized: true,
  }),
);

app.get('/', function (req, res) {
  res.send('success');
});

app.use('/users', usersRouter);

app.listen(port, () => {
  console.log(`server listening on ${port}`);
});

SERVER/routes/users.js

const express = require('express');
const router = express.Router();

const { usersController } = require('../controller');

//POST signup
router.post('/signup', usersController.signup.post);

//POST checkUserId
router.post('/signup/checkId', usersController.checkUserId.post);

module.exports = router;

SERVER/controller/index.js

module.exports = {
  usersController: require('./users'),
};

SERVER/controller/users/index.js

여기서부터 컨트롤러와의 여정이 험난해지겠다는 느낌을 살짝 받기 시작했다. SR 때 API를 잘게 쪼개어둔 덕이다. 더 나은 방식이 있을지, 아니면 이번이 첫 프로젝트라 복잡하게 느껴지는건지 모르겠다.

module.exports = {
  signup: require('./signup'),
  checkUserId: require('./checkUserId'),
};

SERVER/controller/users/checkUserId.js

const { users } = require('../../models');

module.exports = {
  post: (req, res) => {
    const { useremail } = req.body;
    users
      .findOne({
        where: {
          email: useremail,
        },
      })
      .then((data) => {
        if (data !== null) {
          res.status(201).json(data);
        } else {
          res.status(201).json(data);
        }
      })
      .catch((err) => {
        res.status(500).send('err');
      });
  },
};

SERVER/controller/users/signup.js

const { users } = require('../../models');

module.exports = {
  post: (req, res) => {
    const { useremail, password, githubId } = req.body;
    users
      .create({
        useremail: useremail,
        password: password,
        githubId: githubId,
        active: true,
      })
      .then((data) => {
        if (created) {
          res.status(201).json(data);
        }
      })
      .catch((err) => {
        res.status(500).send('err');
      });
  },
};

5. 회원가입 구현 회고

분명 SR 때 회원가입 flow를 정리했었는데도 막상 코드를 작성하려니 모든 과정이 헷갈리기 시작했다. 이전의 sprint들을 통해 회원가입 요청이 들어왔을 때 중복값을 검사하여 기존 회원인 경우 로그인 페이지로 리다이렉트 시키거나, 새로운 회원이면 가입을 시키는 방식에만 익숙했었기 때문이다.
심지어 github 이슈에는 checkUserId를 만들지 않았기에 그런 API가 있었다는 사실을 잊고(!!!) 회원가입만 구현하려니 머리가 좀 아픈 게 아니었다. 결국...
1) findOrCreate로 signup 로직을 짰다가
2) findOne을 이용한 CheckUserId를 추가했다가
3) 다시 두 API를 나누는 과정을 겪어야했다.

*에러와 수정
완성된 코드를 보면 그리 복잡하지 않음에도 잦은 실수가 반복되다보니 마음이 급해져 수정도 여러 차례에 걸쳤다.
1) 우리 팀의 API를 기록한 git book에 따르면 회원가입 시에는 201, 500 코드로만 응답하게 되어 있다. 이미 가입된 회원인 경우, 서버에서 에러가 난 경우 등 회원가입이 되지 않는 모든 응답을 500 에러로 주다 보니 res값이 중복되어 에러코드가 발생했었다.
2) 위의 에러에서도 이미 가입된 회원인 경우 뿐만 아니라 서버 에러가 아닌 모든 경우에는 null값을 클라이언트에 전달했어야 했는데 이 부분을 최초 코드 작성 시에 놓쳤다.
3) 구글링을 하던 중 .spread를 보고 회원가입 로직에 딱 좋겠다 싶어서 적용하였으나 에러가 발생했다. 그때 짠 코드는

.spread((data, created) => {
      if (created) {
        res.status(201).json(data);
      } else {
        res.status(500).send('err');
      }
    })

이렇다. 다시 .then으로 고치니 잘 돌아가서 수정했다. spread가 data를 받고 created를 boolean값으로 처리해준다고 이해했는데, 이 부분에 대한 추가 공부가 필요하다.
4) POSTMAN 사용법에 대해서도 잘 모르고 있었다. POST를 확인하려면 BODY탭에서 key와 value에 fake data라도 넣어줘야 한다. 데이터를 보내주지도 않고 GET마냥 확인하고 있었다.
5) 제일 중요한 부분이라고 할 수도 있는데 user와 users, useremail과 email을 헷갈리지 않고 쓰는 것이다. 사소하면서도 중요한 것들이 헷갈릴 때가 제일 힘들다. 혹시 내가 제대로 파악하지 못한 부분이 있는 건 아닐까 해서. 데이터베이스와 API는 늘 상기하자.
6)

      .then((data, created) => {
        if (created) {
          res.status(201).json(data);
        } else {
          res.status(500).send('err');
        }
      })

합쳐져있던 코드를 나누면서 메소드 사용법을 꼼꼼히 숙지하지 않았다. signup에서도 익숙한 findOrCreate를 무심코 쓰다가, create로 바꾼 후에도 문법에 맞도록 코드를 수정하지 않았다. 제발제발 공식문서와 함께 코드를 작성하자.
7)

    users
      .create({
        where: {
          useremail: useremail,
          }

또 무심코 쓴 부분. checkUserId에서는 회원정보가 최초로 입력되기 때문에 where를 데이터베이스에서 찾을 수 없다. create되어야 할 값만 주면 된다.

다음에는
1. 바로 코드 구현에 들어가지 말고 내가 해야 할 일을 순서대로 정리해본다. 이때 git workflow 명령어와 API(req, res), 연결되는 DB, 지켜야 할 팀 룰을 함께 적어본다.
2. 적어둔 목록이 하나씩 완료될 때마다 보완점 등을 기록한다.
3. 뭘하든 정신차리고 한다.
4. 조급해하지 말 것. 천천히해도 할까말까다.
5. 구글링, 공식문서 참고, 팀원들과의 소통은 아끼지 말자.




➤계속 공부하고 있습니다. 더 나은 의견과 질문이 있으시다면 언제든, 어떤 경로로든 이야기해주세요.

profile
옳고 그름을 고민합니다

0개의 댓글