회원관리(MariaDB) - Part1 회원가입
ㆍProject Diary/React + MariaDB (PicShare WebApp)
사용자 정보를 입력받아 데이터베이스에 저장하고, 중복된 이메일과 닉네임을 체크하며, 프로필 사진을 업로드하는 기능 기록
프론트엔드
- JoinSection.tsx
1. 입력 필드 변경 핸들러
// 입력 필드 변경 핸들러
const handleChange = async (e) => {
const { value, name } = e.target;
// 입력된 값을 상태에 저장
setUserInfo((userInfo) => ({ ...userInfo, [name]: value }));
// 이메일 중복 체크
if (name === "email" && value) {
try {
await axios.post(`${serverUrl}/auth/check-email`, { email: value });
setSuccess((success) => ({ ...success, email: "사용 가능한 이메일입니다." }));
} catch (err) {
if (err.response && err.response.data) {
setError((error) => ({ ...error, email: err.response.data.message }));
}
}
}
// 닉네임 중복 체크
if (name === "userNickname" && value) {
try {
await axios.post(`${serverUrl}/auth/check-nickname`, { userNickname: value });
setSuccess((success) => ({ ...success, userNickname: "사용 가능한 닉네임입니다." }));
} catch (err) {
if (err.response && err.response.data) {
setError((error) => ({ ...error, userNickname: err.response.data.message }));
}
}
}
};
- 입력된 값을 상태에 저장
- setUserInfo를 사용하여 입력된 값을 userInfo 상태에 저장합니다. - 이메일 중복 체크
- 이메일 입력 필드가 변경될 때마다 서버에 중복 체크 요청을 보냅니다.
- 중복되지 않은 경우 성공 메시지를, 중복된 경우 오류 메시지를 설정합니다. - 닉네임 중복 체크
- 닉네임 입력 필드가 변경될 때마다 서버에 중복 체크 요청을 보냅니다.
- 중복되지 않은 경우 성공 메시지를, 중복된 경우 오류 메시지를 설정합니다.
2. 회원가입 요청 핸들러
// 회원가입 요청 핸들러
const register = async (e) => {
e.preventDefault();
const formData = new FormData();
// 폼 데이터에 사용자 정보 추가
formData.append("email", userInfo.email);
formData.append("userName", userInfo.userName);
formData.append("userNickname", userInfo.userNickname);
formData.append("password", userInfo.password);
formData.append("photo", useDefaultProfile || !userInfo.photo ? "defaultProfile.jpg" : userInfo.photo);
try {
const res = await axios.post(`${serverUrl}/auth/join`, formData, {
headers: { "Content-Type": "multipart/form-data" },
});
if (res.data.affectedRows === 1) {
alert("회원가입이 성공했습니다.");
navigate("/login");
} else {
alert("회원가입에 실패했습니다.");
}
} catch (err) {
if (err.response && err.response.data) {
const { field, message } = err.response.data;
setError((error) => ({ ...error, [field]: message }));
} else {
console.error(err);
}
}
};
- 폼 데이터 생성
- FormData 객체를 사용하여 폼 데이터를 생성합니다.
- 사용자 정보를 formData에 추가합니다. - 회원가입 요청 전송
- axios.post를 사용하여 서버에 회원가입 요청을 보냅니다.
- 성공 시 알림을 표시하고 로그인 페이지로 이동합니다.
- 실패 시 오류 메시지를 설정합니다.
3. 프로필 사진 설정
3-1 상태 및 기본프로필 설정
const [useDefaultProfile, setUseDefaultProfile] = useState(true); // 기본 프로필 사용 여부
const [profilePreview, setProfilePreview] = useState(
`${serverUrl}/uploads/defaultProfile.jpg`
); // 프로필 사진 미리보기
<체크박스 변경 핸들러>
// 체크박스 변경 핸들러
const handleCheckboxChange = () => {
setUseDefaultProfile((prevUseDefaultProfile) => {
const newUseDefaultProfile = !prevUseDefaultProfile;
setProfilePreview(
newUseDefaultProfile
? `${serverUrl}/uploads/defaultProfile.jpg`
: profilePreview
);
return newUseDefaultProfile;
});
};
- 기본 프로필 사용 여부
-useState를 사용하여 기본 프로필 사용 여부와 프로필 사진 미리보기를 설정합니다. - 체크박스 변경 시
- handleCheckboxChange를 사용하여 체크박스 변경 시 기본 프로필 사용 여부를 토글합니다.
- 기본 프로필 사용 시 기본 프로필 사진을, 사용하지 않을 시 업로드한 사진을 미리보기로 설정합니다.
3-2 파일 입력 변경 핸들러
// 파일 입력 변경 핸들러
const handleFileChange = (e) => {
const file = e.target.files[0];
setUserInfo((prevUserInfo) => ({ ...prevUserInfo, photo: file }));
setProfilePreview(URL.createObjectURL(file));
};
파일 입력 시:
handleFileChange를 사용하여 파일 입력 시 선택한 파일을 userInfo 상태에 저장하고, 프로필 사진 미리보기를 업데이트합니다.
<프로필 사진 설정 UI>
{/* 프로필 이미지 */}
<tr>
<td>
<img src={profilePreview} alt="프로필사진" />
</td>
</tr>
{/* 프로필 이미지 설정 */}
<tr>
<td>
<div className="checkbox-label">
<p>나만의 프로필사진을 추가할까요?</p>
<label>
<input
type="checkbox"
checked={!useDefaultProfile}
onChange={handleCheckboxChange}
/>
{useDefaultProfile ? (
<span style={{ color: "#09fc52", fontWeight: "bold" }}>사진 추가하기</span>
) : (
<span style={{ color: "#09fc52", fontWeight: "bold" }}>기본 이미지로 변경</span>
)}
</label>
</div>
{!useDefaultProfile && (
<input
type="file"
name="photo"
id="photo"
onChange={handleFileChange}
placeholder="Profile Image"
/>
)}
</td>
</tr>
백앤드
- authRouter.js
1. 파일 업로드
Multer란?
- Multer는 Node.js의 미들웨어로, 파일 업로드를 처리하는 데 사용됩니다. 주로 사용자가 업로드한 파일을 서버에 저장할 때 사용됩니다.
왜 사용하는가?
- 파일 업로드는 단순한 텍스트 데이터 전송과는 다르기 때문입니다. 파일은 바이너리 데이터로 다뤄야 하며, 이를 처리하기 위해 특별한 미들웨어가 필요합니다. Multer는 이렇나 파일 업로드는 처리할 수 있도록 도와주는 미들웨어입니다.
어떻게 사용하는가?
- Multer를 사용하려면, 먼저 이를 설치하고 설정해야 합니다. 설정을 통해 업로드된 파일이 저장될 위치와 파일명을 정의합니다.
import multer from "multer";
// Multer 설정
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "uploads/"); // 파일이 저장될 폴더 경로
},
filename: (req, file, cb) => {
cb(null, Date.now() + "-" + file.originalname); // 파일명 설정
},
});
const upload = multer({ storage: storage });
파일 업로드 처리
// JOIN 기능
authRouter.post("/join", upload.single("photo"), (req, res) => {
const { email, userName, userNickname, password } = req.body;
let photo = req.file ? req.file.filename : "defaultProfile.jpg"; // 기본 프로필 사진 설정
// 회원 정보를 데이터베이스에 삽입
db.query(
`INSERT INTO users (email, userName, userNickname, password, profilePicture) VALUES (?, ?, ?, ?, ?)`,
[email, userName, userNickname, password, photo],
(err, result) => {
if (err) {
if (err.code === "ER_DUP_ENTRY") {
return res.status(400).json({ field: "email", message: "이미 존재하는 이메일입니다." });
} else {
return res.status(500).json({ message: "서버 오류가 발생했습니다. 다시 시도해주세요." });
}
} else {
res.status(200).json({ affectedRows: result.affectedRows });
}
}
);
});
upload.single("photo") 는 Multer가 파일 업로드를 처리하도록 하는 미들웨어입니다.
이 미들웨어는 요청 객체(req)에 file 속성을 추가하여 업로드된 파일에 접근할 수 있게 합니다
- req.file.filename은 저장된 파일명을 나타내며, 이를 통해 데이터베이스에 파일 정보를 저장합니다.
- 파일이 업로드되지 않은 경우, 기본 프로필 사진("defaultProfile.jpg")을 사용하도록 설정합니다.
2. API 엔드포인트 쿼리문 설명
2-1 이메일 중복 체크
// 이메일 중복 체크
authRouter.post("/check-email", (req, res) => {
const { email } = req.body;
// 이메일을 데이터베이스에서 조회
db.query(`SELECT email FROM users WHERE email = ?`, [email], (err, results) => {
if (err) {
// 서버 오류가 발생했을 경우
return res.status(500).json({ message: "서버 오류가 발생했습니다. 다시 시도해주세요." });
}
if (results.length > 0) {
// 이미 존재하는 이메일일 경우
return res.status(400).json({ field: "email", message: "이미 존재하는 이메일입니다." });
}
// 사용 가능한 이메일일 경우
res.status(200).json({ message: "사용 가능한 이메일입니다." });
});
});
- SELECT email FROM users WHERE email = ?
users 테이블에서 입력된 이메일이 존재하는지 확인하는 쿼리입니다.
2-2 닉네임 중복 체크
// 닉네임 중복 체크
authRouter.post("/check-nickname", (req, res) => {
const { userNickname } = req.body;
// 닉네임을 데이터베이스에서 조회
db.query(`SELECT userNickname FROM users WHERE userNickname = ?`, [userNickname], (err, results) => {
if (err) {
// 서버 오류가 발생했을 경우
return res.status(500).json({ message: "서버 오류가 발생했습니다. 다시 시도해주세요." });
}
if (results.length > 0) {
// 이미 존재하는 닉네임일 경우
return res.status(400).json({ field: "userNickname", message: "이미 존재하는 닉네임입니다." });
}
// 사용 가능한 닉네임일 경우
res.status(200).json({ message: "사용 가능한 닉네임입니다." });
});
});
- SELECT userNickname FROM users WHERE userNickname = ?
users 테이블에서 입력된 닉네임이 존재하는지 확인하는 쿼리입니다.