MongoDB란?
MongoDB는 문서 기반(Document-based) NoSQL 데이터베이스이다. 관계형 데이터베이스(RDBMS)와 달리 테이블과 행 대신 컬렉션과 문서 형태로 데이터를 저장한다.
MongoDB의 주요 특징
- 문서 지향적: JSON과 유사한 BSON(Binary JSON) 형식으로 데이터 저장
- 스키마 자유: 미리 정의된 스키마 없이 문서마다 다른 구조 가능
- 분산 확장성: 수평적 확장(Sharding)을 통해 대용량 데이터 처리
- 유연한 쿼리: 강력한 쿼리 기능과 인덱싱 지원
- 높은 가용성: 복제(Replication)을 통한 데이터 백업 및 고가용성
몽구스를 이용해 개발을 해보겠다.
https://mongoosejs.com/docs/guide.html
Mongoose v8.13.3: Schemas
If you haven't yet done so, please take a minute to read the quickstart to get an idea of how Mongoose works. If you are migrating from 7.x to 8.x please take a moment to read the migration guide. Everything in Mongoose starts with a Schema. Each schema ma
mongoosejs.com
🔵 Front
📃 RegisterPage.jsx
import { useState } from 'react'
import css from './registerpage.module.css'
import axios from 'axios'
import axios from 'axios' ← 사용하기 위해서는 npm install axios 명령어를 입력해야한다.
axios
프론트엔드에서 백엔드로 데이터를 주고받을 때 사용하는 HTTP 통신 도구
리액트 함수 컴포넌트 단축어를 입력한다.
export const RegisterPage = () => {}
이전에 useState()를 react에서 import했었다. 이 훅(Hook)을 사용하는 이유는 바로, 사용자가 입력하는 값들을 실시간으로 추적하고, 그 값을 저장하기 위해서이다.
그러면 이제 뭘 해야 할까요?
맞아요~! 상태를 직접 정의해서 저장해줘야한다. ✅ 상태 선언 완료 check
const [username, setUsername] = useState('') // 이름
const [password, setPassword] = useState('') // 비밀번호
const [passwordOk, setPasswordOk] = useState('') // 비밀번호 확인
const [errUsername, setErrUsername] = useState('') // 이름에러
const [errPassword, setErrPassword] = useState('') // 비밀번호 에러
const [errPasswordOk, setErrPasswordOk] = useState('') // 비밀번호확인 에러
const [registerState, setRegisterState] = useState('') // 회원가입
이제는 로직을 구현해야한다. ✅ 유효성 검사 로직 check
const validateUsername = 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 validatePasswordCheck = (value, current = password) => {
if (!value) {
setErrPasswordOk(' ')
return
}
if (value !== current) {
setErrPasswordOk('패스워드가 일치하지 않습니다.')
} else {
setErrPasswordOk('')
}
}
validate~~함수들은 입력된 값들이 유효한지 확인하는 함수이다. 즉, 정해진 규칙에 맞는지 검사하는 로직인것!
✅ 사용자가 조작할때 발생하는 이벤트 로직 구현
const handleUsernameChange = e => {
const value = e.target.value
setUsername(value)
validateUsername(value)
}
const handlePasswordChange = e => {
const value = e.target.value
setPassword(value)
validatePassword(value)
}
const handlePasswordOkChange = e => {
const value = e.target.value
setPasswordOk(value)
validatePasswordCheck(value)
}
- 입력창에 글자를 입력할때마다 onChange가 호출된다.
- value: 사용자가 입력한 실시간 값
- set~~: 로 상태 저장
setPassword(value) → 입력한 패스워드 저장 👉🏻 validatePassword(value) → 유효성 검사
✅ register 함수 → 회원가입 버튼을 눌렀을 때 실행되는 핵심 로직
const register = async e => {
// 폼 제출 시 페이지 새로고침되는 기본 동작을 막아줌
e.preventDefault()
console.log('회원가입', username, password, passwordOk)
// 입력값 유효성 검사 (빈 값, 형식 오류 등)
validateUsername(username)
validatePassword(password)
validatePasswordCheck(passwordOk, password)
// 에러 메시지 있거나 빈 값이면 회원가입 막고 함수 종료
if (errUsername || errPassword || errPasswordOk || !username || !password || !passwordOk) {
return
}
// 상태를 ‘등록중’으로 표시 (로딩 메시지 출력 등)
try {
setRegisterState('등록중')
const response = await axios.post('http://localhost:3000/register', {
username,
password,
})
// 입력값을 서버에 전송 (POST /register)
console.log('회원가입 성공', response.data)
console.log('회원가입 성공', response.status)
setRegisterState('등록완료')
} catch (err) {
console.log('회원가입 실패', err)
if (err.response) {
// 서버가 응답을 반환한 경우
console.log('오류 응답 데이터 --', err.response.data)
console.log('오류 상태 코드 ---', err.response.status)
}
}
}
- 폼 제출 막기 (e.preventDefault())
- 입력값 콘솔 확인
- 유효성 검사 실행 (validateUsername, validatePassword, ...)
- 에러나 값 없음 → 조기 종료
- 서버로 POST 요청 전송 (axios.post)
- 성공 시 상태 변경 (등록완료)
- 실패 시 에러 로그 출력
return (
<main className={css.registerpage}>
<h2>회원가입 페이지</h2>
<form className={css.container} onSubmit={register}>
<input
type="text"
placeholder="사용자명"
value={username}
onChange={handleUsernameChange}
/>
<strong>{errUsername}</strong>
<input
type="password"
placeholder="패스워드"
value={password}
onChange={handlePasswordChange}
/>
<strong>{errPassword}</strong>
<input
type="password"
placeholder="패스워드 확인"
value={passwordOk}
onChange={handlePasswordOkChange}
/>
<strong>{errPasswordOk}</strong>
<button type="submit">가입하기</button>
</form>
</main>
👉🏻위에서 입력한 값을 상태에 저장해두고, 그 상태값을 필요한 곳에 작성해서 사용하면 된다.
🟢 MogoDB 실습 & Backend 연결
1️⃣ 클러스터 구축 → Free 선택 → 필요한 input 값 입력
터미널에 설치해야할 파일들
npm install mongodb
Node.js에서 MongoDB에 직접 접속할 수 있게 해주는 공식 드라이버를 설치하는 명령어
즉, mongoose 없이도 순수하게 MongoDB에 연결하고 데이터를 넣고 빼려면 이걸 써야 한다.
npm install nodemon
nodemon: 서버 코드 수정 시 자동 재시작해주는 도구
nodemon index.js
nodemon index.js로 실행하면, 코드를 저장할 때마다 자동으로 서버가 재시작된다.
📃 user.js - MogoDB에서 실제 데이터 저장/조회할 수 있게 도와주는 도구
import mongoose from 'mongoose';
const { Schema, model } = mongoose;
const userSchema = new Schema(
{
username: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
},
{
timestamps: true,
}
);
export const userModel = model('User', userSchema);
import mongoose from 'mongoose';
- MongoDB와 연결하고 데이터를 다룰 수 있는 라이브러리를 가져오는 코드
- mongoose는 MongoDB를 더 쉽게 쓰게 해주는 도구 (ODM)
const { Schema, model } = mongoose
- mongoose.Schema는 데이터의 구조(설계도)를 만드는 데 사용
- mongoose.model은 그 구조를 기반으로 실제로 DB에 저장하고 불러오는 도구(모델)를 만드는 함수
const userSchema = new Schema({ ... })
- 사용자 정보를 어떻게 저장할지를 정의하는 설계도
- username, password 각각 어떤 타입인지, 필수인지 등을 설정할 수 있다.
username: {
type: String, // 값의 자료형: 문자열
required: true, // 반드시 있어야 함
unique: true // 중복되면 안 됨
}
timestamps: true
- 자동으로 createdAt(생성 시각), updatedAt(수정 시각) 필드를 만들어준다.
- 언제 만들었고, 언제 수정됐는지 기록이 남는다.
export const userModel = model('User', userSchema)
- 'User'라는 이름의 MongoDB 컬렉션(테이블처럼 생각해도 좋아)을 만들고,
- 그 안에서 userSchema 설계에 따라 데이터를 저장/조회/삭제할 수 있게 해주는 모델을 만든다.
index.js에서 불러와서 이렇게 쓴다.
const user = new userModel({ username, password }); await user.save();
📃 index.js
import express from 'express';
const app = express();
const port = 3000;
import mongoose from 'mongoose';
import { userModel } from './model/user.js';
import cors from 'cors';
app.use(cors());
app.use(express.json());
// connect에 연결되어야한다.
mongoose
.connect(
'mongodb+srv://sh:1234@sh.hn6eyzo.mongodb.net/blog?retryWrites=true&w=majority&appName=sh'
)
.then(() => {
console.log('MongoDB 연결됨');
})
.catch((err) => {
console.log('MongoDB 연결 안됨', err);
});
//-----------------
// app.get('/', (req, res) => {
// res.send('Hello World!');
// });
app.post('/register', async (req, res) => {
try {
console.log('------', req.body);
const { username, password } = req.body;
// userModel 에서 이미 존재하는 사용자인지 확인
// 새 사용자를 생성
// mongoDB 에 저장
// 저장 성공 하면 프론트엔드로 응답 메시지(사용자의 username, _id) 전송
const existingUser = await userModel.findOne({ username });
if (existingUser) {
// 이미 존재하는 사용자
return res.status(409).json({ error: '이미 존재하는 아이디입니다.' });
}
const userDoc = new userModel({ username, password });
const savedUser = await userDoc.save();
res.status(201).json({
username: savedUser.username,
_id: savedUser._id,
});
} catch (err) {
console.log('에러', err);
res.status(500).json({ error: '서버 에러' });
}
});
app.listen(port, () => {
console.log(`${port} 포트에서 돌고있음`);
});
import express from 'express';
- express는 Node.js에서 웹 서버를 만들기 위한 프레임워크
const app = express();
const port = 3000;
- app은 서버 인스턴스를 생성한 것이며, port는 이 서버가 사용할 포트 번호를 지정한 것
import mongoose from 'mongoose';
import { userModel } from './model/user.js';
- mongoose는 MongoDB와 연결하고 데이터를 다룰 수 있게 해주는 라이브러리이다.
- userModel은 사용자 정보를 저장할 MongoDB 모델로, 별도의 파일에서 정의된 것을 불러온 것이다.
import cors from 'cors';
app.use(cors());
app.use(express.json());
- cors는 다른 도메인에서 요청을 허용하도록 도와주는 미들웨어이다.
- express.json()은 요청 본문을 JSON 형태로 해석할 수 있게 해주는 미들웨어이다.
✅ MongoDB 연결 설정
mongoose
.connect('...')
.then(() => { console.log('MongoDB 연결됨'); })
.catch((err) => { console.log('MongoDB 연결 안됨', err); });
- mongoose.connect()는 MongoDB Atlas와 연결하기 위한 메서드이다.
- 연결에 성공하면 'MongoDB 연결됨'을 출력하고, 실패 시 에러 메시지를 출력한다.
✅ 회원가입 라우터
app.post('/register', async (req, res) => {
...
});
- 이 라우터는 /register 경로로 POST 요청이 들어올 때 실행되는 코드이다.
- 요청으로 전달된 사용자 정보를 검증하고, MongoDB에 새 유저를 저장하는 기능을 한다.
내부 로직 😃
- req.body에서 username과 password를 추출한다.
- 해당 username이 이미 존재하는지 userModel.findOne()으로 확인한다.
- 이미 존재하면 409 Conflict 상태 코드를 응답한다.
- 존재하지 않으면 새 userModel 인스턴스를 생성하고, save() 메서드로 MongoDB에 저장한다.
- 저장이 성공하면 201 Created 상태 코드와 함께 username, _id를 프론트엔드로 반환한다.
- 에러 발생 시 500 Internal Server Error를 반환한다.
✅ 서버 실행
app.listen(port, () => {
console.log(`${port} 포트에서 돌고있음`);
});
- 이 코드는 Express 서버를 지정한 포트(3000번)에서 실행시키는 역할을 한다.
회원 가입 성공시 큰솔창에 위에와 같이 나온다.
DB에 저장도 잘된다.
🐛 실습 중 겪은 문제 - mongoose is not defined 에러 발생
model/user.js 파일에서 mongoose를 사용했는데, 실행 시 ReferenceError: mongoose is not defined라는 에러가 발생했다.
mongoose를 import하지 않고 사용했기 때문이다. 하하..
⚙️ 해결과정
model/user.js 상단에 다음 코드를 추가하여 문제를 해결했다.
import mongoose from 'mongoose';
🐛 실습 중 겪은 문제 - axios is not defined 에러로 회원가입 실패
React에서 axios.post()를 사용해 회원가입 요청을 보내려 했지만, ReferenceError: axios is not defined라는 에러가 발생.. 이것도 역시 import를 안했다.
⚙️ 해결과정
컴포넌트 상단에 axios를 import하고, 필요한 경우 패키지를 설치하여 문제를 해결했다.
import axios from 'axios';
npm install axios
🎠회고

점심때 나갔다왔는데 날씨가 너~~~~~무 좋아. 방구석에서 수업 듣는 나는 점심시간이 그렇게 더운지 이제야 알았당

새라이브러리를 배운다는 기쁨과 동시 빠른 수업을 따라가기 위한 나의 노력.. 다들 잘따라간다.. 넘흐 느린 나..🐢 워..후...
몽고 DB를 망고 DB로 부르는 나..
망고 DB가 이름 더 귀여우니까 그걸로 바꿔줘~ 🥭
망고 DB이면 로고까지 너무 큐티하지 않을까? (망고 먹고 싶네요.. 애플 망고도)
몽고 DB의 의미는 매우 큰 DB 이다. humongous ← mongo로 줄인것! 별다줄 ㅇㅈ? ㅇㅈ

홈플러스에서 미스터비스트 초콜릿이 원플원이래요~
https://www.youtube.com/watch?v=6ZXzn1jwtM4
" 잃어버린 것들은 잃어버린 그 자리에
가끔 뒤 돌아 보면은
슬픔 아는 빛으로 피어 "
'💡 URECA > 🗒️ 스터디 노트' 카테고리의 다른 글
[URECA] Day 65 ReactQuill 사용법과 bcrypt, JWT, cookie-parser 보안 내용 정리 (2) | 2025.05.01 |
---|---|
[URECA] Day64 React API 공공데이터 (0) | 2025.04.29 |
[URECA] Day63 React Weather API (0) | 2025.04.28 |
[URECA] Day 62 React Proj WalletWatcher (2) | 2025.04.25 |
[URECA] Day 60 React Redux (0) | 2025.04.24 |