로그인을 구현하려는 목적?
우리가 네이버나 구글의 메일 서비스나 다른 서비스를 이용할 때,
거의 필수적으로 거치는 과정이 있다.
바로 로그인이다.
그만큼 대부분의 웹에 들어가는 기능인 로그인을 구현해보는 시간을 갖도록 하자.
이 계획은 여러 단계로 나누어 글을 작성할 것이다.
오늘은 기본적인 api 구성까지 해보도록 하자.
사용하는 주요 기술
Express : express를 이용해서 서버를 구현할 예정이다.
(koa로 하려 했지만 아직은 express가 부족하다 생각하기에 이번에는 express를 이용해 공부를 더 할 예정이다.)
Joi : 스키마 언어를 검토해주고, node용 validator보다 관계에 따른 정의가 가능하다.
(ex. 옵션 설정에서 a는 필수 요소로 지정하고 b는 필수가 아니라 지정하면 옵션대로 스키마를 검토한다.)
const schema = Joi.object().keys({
username: Joi.string().min(3).max(30).required(), // required()는 필수 요소에 사용
birthyear: Joi.number().integer().min(1900).max(2018),
});
기본적인 api 구현
api의 구조는 다음 사진을 보며 설명하겠다.
express.Router()를 이용해서 해당 라우터 마다
app.use('/api', auth) 처럼 사용해줘 라우터를 나누어 사용해주었다.
또한, 등록과 로그인, 로그아웃 등의 기능을 구현하기 위해
post와 get 메서드를 이용했다.
(정보 전달이 필요한 기능에서는 post, 정보를 받기위해서는 get)
data를 json으로 전달하기에 express.json()을 사용해 줘야한다.
bcrypt의 해싱을 통한 비밀번호 해싱
정보를 관리하는 차원에서 정보를 있는 그대로 저장하고 다룬다면 보안적으로 이슈가 있을 것이다.
이때 해싱을 통해 인간은 해독할 수 없는 문자열로 변형해주어 저장하게 된다.
Hash의 어원인 다진고기, 잘게 썰다 처럼 한번 손질하면 다시 원래의 모양을 갖을 수 없게 해주는 것이다.
즉, 단방향이라는 것이다.
위의 비밀번호는 hash 비동기 콜백으로 동작 하도록 했다.
나머지 정보는 아래의 링크에 잘 정리되어 있어서 가져왔다.
(링크)
코드
server.js 최상위 스크립트
import express from 'express';
import cors from 'cors';
import api from './api/index.js';
const app = express();
const port = 4000;
// 라우터 설정
// const router = express.Router();
app.use('/api', api); // api 라우트 적용
app.get('/', (req, res) => {
res.send('hello');
}
)
app.use(cors());
app.listen(port, () => {
console.log(`listening on 4000`);
});
api/index.js
import express from 'express';
import auth from './auth/index.js';
const api = express.Router();
api.use('/auth', auth);
export default api;
api/mudule/user.js
import db from './db.js';
import bcrypt from 'bcrypt';
// const findByUsername = (username) => {
// return
// }
// 비밀번호 생성
export const setPassword = async (password) => {
const hash = await bcrypt.hash(password, 10);
// .then(hash => console.log(hash));
// console.log(hash);
return hash;
}
export const checkPassword = async (password, hashedPassword) => {
const result = await bcrypt.compare(password, hashedPassword);
return result;
}
api/auth/index.js
import express from 'express'
import * as authCtrl from './auth.ctrl.js';
const auth = express.Router();
auth.use(express.json());
auth.post('/register', authCtrl.register);
auth.post('/login', authCtrl.login);
auth.get('/check', authCtrl.check);
auth.post('/logout', authCtrl.logout);
export default auth;
api/auth/auth.ctrl.js
import Joi from 'joi';
import db from '../models/db.js';
import { setPassword } from '../models/user.js';
// 여기서 각 동작을 위한 api 작성
export const register = async (req, res) => {
// 회원가입
const schema = Joi.object().keys({
// 객체가 다음 필드를 갖음을 검증
username: Joi.string().alphanum().min(3).max(20).required(),
// 문자열 타입, 알파벳과 0~9의 범위, 최소3 최대 20의 길이, 필수적인
password: Joi.string().required()
});
// validate() 현제 스키마와 옵션을 사용하여 값을 검증한다.
const result = schema.validate(req.body);
if (result.error) {
req.status = 400;
req.body = result.error;
return;
}
const { username, password } = req.body;
try {
// username이 이미 있는지 확인
// const exist = db.query("SELECT EXISTS(SELECT name FROM account_info) as isChk")
// if (exist) {
// req.status(409); // Conflict
// return;
// }
let hspw = await setPassword(password);
// db.query(`INSERT INTO account_info (name,password) VALUES (${username},${hsqw})`)
// console.log(username, hspw);
await res.send(`${username}, ${hspw}`)
hspw = "deleted";
} catch (e) {
throw e; // 에러
}
}
export const login = (req, res) => {
// 로그인
}
export const check = (req, res) => {
// 로그인 상태 확인
}
export const logout = (req, res) => {
// 로그아웃
}
오늘은 register 등록 api의 구현까지 해보았다.
이런 로그인 과정은 라우터를 이용해 api를 동작하게 하여 데이터 등록 및 가져오기를 통해
구현된다는 것을 알게되었다.
앞으로는 다른 동작들도 구현해보도록 하자.
'React' 카테고리의 다른 글
React 에서 쿼리스트링과 useSearchParams 사용하기 (0) | 2023.02.16 |
---|---|
React) 로그인 기능 구현 (완) (1) | 2022.12.13 |
React) 21장 백엔드 프로그래밍: koa-router 사용하기 (0) | 2022.07.07 |
React) 21장 백엔드 프로그래밍: nodemon 사용하기 (0) | 2022.07.07 |
React) 21장 백엔드 프로그래밍: Koa 1 (0) | 2022.07.06 |