React 회원가입 구현
회원가입 폼
<main className={css.registerpage}>
<h2>회원가입 페이지</h2>
<form onSubmit={register} className={css.container}>
<input
type="text"
placeholder="사용자명"
value={userName}
onChange={handleChangeUserName}
/>
<strong>{errUserName}</strong>
<input
type="password"
placeholder="패스워드"
value={password}
onChange={handleChangePassword}
/>
<strong>{errPassword}</strong>
<input
type="password"
placeholder="패스워드 확인"
value={passwordConfirm}
onChange={handleChangePasswordConfirm}
/>
<strong>{errPasswordConfirm}</strong>
<button type="submit">가입하기</button>
</form>
</main>
상태 관리
const [userName, setUserName] = useState('')
const [password, setPassWord] = useState('')
const [passwordConfirm, setPasswordConfirm] = useState('')
const [errUserName, setErrUserName] = useState('')
const [errPassword, setErrPassword] = useState('')
const [errPasswordConfirm, setErrPasswordConfirm] = useState('')
const handleChangeUserName = e => {
const value = e.target.value
setUserName(value)
vaildateUserName(value)
}
const handleChangePassword = e => {
const value = e.target.value
setPassWord(value)
validatePassword(value)
}
const handleChangePasswordConfirm = e => {
const value = e.target.value
setPasswordConfirm(value)
validatePasswordConfirm(value)
}
입력 유효성 검사
const vaildateUserName = value => {
if (!value) {
setErrUserName('')
return
}
if (!/^[a-zA-Z][a-zA-Z0-9]{3,}$/.test(value)) {
setErrUserName('사용자명은 영문자로 시작하는 4자 이상의 영문자 또는 숫자여야 합니다.')
} else {
setErrUserName('')
}
}
const validatePassword = value => {
if (!value) {
setErrPassword('')
return
}
if (value.length < 4) {
setErrPassword('패스워드는 4자 이상이어야 합니다.')
} else {
setErrPassword('')
}
}
const validatePasswordConfirm = (value, current = password) => {
if (!value) {
setErrPasswordConfirm('')
return
}
if (value !== current) {
setErrPasswordConfirm('패스워드가 일치하지 않습니다.')
} else {
setErrPasswordConfirm('')
}
}
API 통신
const [registerState, setRegisterState] = useState('')
const register = async e => {
e.preventDefault() // form 전송 실행 방지
vaildateUserName(userName)
validatePassword(password)
validatePasswordConfirm(passwordConfirm)
if (
errUserName ||
errPassword ||
errPasswordConfirm ||
!userName ||
!password ||
!passwordConfirm
) {
return
}
try {
setRegisterState('등록 중')
// 회원가입 API 호출
const res = await axios.post('http://localhost:3000/register', {
userName,
password,
})
console.log(res)
setRegisterState('등록 완료')
} catch (err) {
console.log('회원가입 실패', err)
if (err.response) {
console.log('[error message] ' + err.response.data.error)
console.log('[status code] ' + err.response.status)
}
}
}
Express 서버 구축
Express
Node.js에서 웹 애플리케이션을 구축하기 위한 경량화된 웹 프레임워크
설치
npm install express
ES 모듈(ESM) 방식의 import / export 사용 설정
// package.json
{
"type": "module", <-- 추가
"dependencies": {
"express": "^5.1.0"
}
}
express 사용 준비
// index.js
import express from "express";
const app = express();
const port = 3000;
app.get("/", (req, res) => {
res.send("Hello World!");
});
app.listen(port, () => {
console.log(`${port}번 포트에서 실행 중`);
});
서버 실행
nodemon index.js
🚨 CORS 에러
서로 다른 출처(origin) 간의 자원 요청이 브라우저 보안 정책에 의해 차단될 때 발생
- 클라이언트: http://localhost:5173
- 서버(API): http://localhost:3000
같은 도메인이 아니므로, 브라우저는 보안상 CORS 정책을 적용
💡 해결 방법: cors 미들웨어 적용
npm install cors
import express from "express";
const app = express();
const port = 3000;
import cors from "cors";
app.use(cors()); // 모든 요청에 대해 허용
app.use(express.json()); // JSON 요청 본문 파싱을 위한 미들웨어
MongoDB 설정
MongoDB
NoSQL 데이터베이스
- 데이터는 컬렉션(Collection)에 도큐먼트(Document) 형태로 저장
- JSON과 비슷한 구조 (BSON)로 데이터를 저장
- 스키마가 자유로워 유연한 데이터 구조를 가짐
사용법
- 로그인
MongoDB: The World’s Leading Modern Database
Get your ideas to market faster with a flexible, AI-ready database. MongoDB makes working with data easy.
www.mongodb.com
- 프로젝트 생성
- 클러스터 생성
- username, password 입력 후, 연결 문자열 잘 가지고 있기
Mongoose
MongoDB를 Node.js에서 사용할 수 있도록 도와주는 ODM (Object Data Modeling) 라이브러리
- SQL의 ORM과 비슷한 개념
- 스키마 정의, 데이터 검증, 쿼리 작성 등을 쉽게 해줌
설치
npm i mongoose
User 스키마 생성
// model/user.js
import mongoose from "mongoose";
const { Schema, model } = mongoose;
const userSchema = new Schema({
userName: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
});
export const userModel = model("User", userSchema);
MongoDB 연결
// index.js
import mongoose from "mongoose";
mongoose
.connect( // 연결 문자열 적용
`mongodb+srv://{username}:{password}@cluster0.~~~.mongodb.net/{blog}?retryWrites=true&w=majority&appName=Cluster0`
) // blog는 DB 이름, 추가 안하면 자동으로 test라는 이름의 DB 생성
.then(() => console.log("MongoDB 연결됨"))
.catch((err) => console.log("MongoDB 연결 안됨"));
회원가입 User 정보 저장
// index.js
import { userModel } from "./model/user.js";
app.post("/register", async (req, res) => {
const { userName, password } = req.body;
// userModel 에서 이미 존재하는 사용자인지 확인
const existingUser = await userModel.findOne({ userName });
if (existingUser)
return res.status(409).json({ error: "이미 존재하는 사용자입니다." });
// 새 사용자 생성
const userDoc = new userModel({ userName, password });
// DB에 저장
const savedUser = await userDoc.save();
// 저장 성공 시, 응답 메시지 전송
res
.status(200)
.json({ user: { userName: savedUser.userName, _id: savedUser._id } });
});
- 이미 존재하는 사용자일 때
728x90
반응형
'LG 유플러스 유레카 SW > React' 카테고리의 다른 글
[#67] Multer 파일 업로드 + 게시글 작성/조회 (0) | 2025.05.02 |
---|---|
[#66] 비밀번호 암호화 + JWT 토큰 발급 (feat. 로그인) (2) | 2025.05.01 |
[#64] TanStack Query(React Query) 사용해보기 (0) | 2025.04.29 |
[#63] 날씨 오픈 API 연동 (1) | 2025.04.28 |
[#62] 용돈 기입장 프로젝트 (feat. React) (0) | 2025.04.28 |