티스토리 뷰
갑작스런 사정이 생겨 밖에서 노트북으로 마저 처리하려 했으나 mysql이랑 env파일을 안 가져와서..
그래서 글을 먼저 작성하기로 했다!
이번 글은 리액트에서 formData를 서버로 건네주는 것에 대해 정리할 생각이다.
실시간 비밀번호에 이어 코드를 좀 깔끔하게 다진 후, 대망의 회원가입 폼데이터를 서버에 전달하는 작업에 거의 다 왔다.
아직 손 보아야 할 거 때문에 끝마치지는 못했는데 mysql에서 nickname의 not null 설정 때문이다.
회원가입을 할 때 이름은 입력받지만, 닉네임은 사용자가 선택할 수 있도록 회원가입 페이지에 포함하지 않은 것이 원인이었다.
닉네임의 not null 속성과 맞물렸기 때문에 default 값을 주거나 null 허용을 하는 둥의 조치를 취해야 한다.
🟡 에러
Field 'nickname' doesn't have a default value
이 에러가 닉네임의 낫 널 설정으로 인해 insert하는 서버가 제대로 완료되지 않아 뜬 에러이다.
닉네임 필드에 관해
ㅎㅎ 사용자 입장으로서 주변 지인한테 닉네임 필수/선택, 디폴트값을 줄까 말까에 대해 가볍게 물어보았는데 나도 공감하게 되는 내용들이어서 아래로 추려졌다.
- 누구는 이름, 누구는 닉네임을 사용하게 되는 상황도 불편할 것이고
- 닉네임은 선택인 게 더 좋을 거 같은데, 지정을 안 한 사용자는 디폴트값닉네임에 난수를 부여하는 게 좋지 않을까?
처음에 사전 검토 단계?에서 닉네임=이름이라 정의를 하고 시작을 했는데, 회원가입 페이지를 만들며 그래도 이름과 닉네임을 구분짓는 것이 진짜 서비스를 만들어 가는 과정이 아닐까? 라고 생각이 변화했다. 그래서 닉네임이라는 필드에 대한 고민이 깊었는데 대화가 도움이 되었다.
좀 더 깊이 있게 생각을 할 수 있었다면 좋았을 텐데.. 아쉬움이 들었지만 그래도 다음 프로젝트에서는 이 고민을 할 수 있게 되었으니 긍정적으로 헤쳐나가보려 한다.
그래서 나는 default값을 줄 예정으로 개선하려 한다!
핵심
프론트
onSubmit 이벤트로 사전에 만들어 둔 formData 상태를 보내주는 방식으로 서버에 데이터를 전달했다.
axios 사용: 객체(formData) -> json
서버
axios로 인해 json이 된 데이터를 다시 객체로 파싱해주는 작업이 필요해서 서버를 통괄하는 파일에 express.json을 기입한다.
1. 프론트에서 formData 상태를 만들어주고 값을 임시 변수에 저장하여 1차 유통한 후, 2차에 formData로 전해준다.
const [formData, setFormData] = useState({
form_id: "", form_pwd1: "", form_name: "",
form_tel: "", form_birthday: today, form_email: ""
});
폼데이터를 저장할 상태를 만들어준다. 나는 object 형식으로 만들었다.
객체 형식으로 만들면 key와 value를 빠르게 매치하고 값을 넣을 수 있다.
const onChangeInput = (e) => {
const { name:formName, value:formValue } = e.target;
setFormData(임시폼데이터저장소명 => ({
...임시폼데이터저장소명,
[formName] : formValue
}))
};
1차 유통에서는 formData 상태에 바로 값을 저장하지 않는다.
리액트의 불변성? 때문이라는데 값을 상태에 바로 저장을 해버리면 리액트에서 값의 변화를 감지해야 하는데 할 수 없게 되어버린단다.
그래서 formData 객체를 그대로 복제를 한 새로운 객체에 임시로 저장을 한 후, formData 상태에 저장을 해주어야 한다.
임시폼데이터저장소명: 자신이 원하는 변수명을 기재한다.
데이터 디스트럭쳐링을 하고 새 이름을 부여한 formName을 통해 각각의 키에 formValue를 매치하여 저장한다.
이 모든 코드를 setFormData로 감싸고 있으니 formData 상태에도 제대로 업데이트가 되었겠지!
date 타입은 e.target으로 정보를 얻을 수 없어 따로 처리를 해준다. onChangeInput과 같은 형태로 만들어주는 대신 키 값을 form_date, 또는 form_birthday 로 콕 찝어서 이 키에다 받은 date 값을 넣어주면 된다.
정말 로직이 똑같은데 반복 부분을 fucntion으로 정의할 수는 없었다. function을 외치면 모든 변수, 상태들의 값이 선언은 되어있는데 사용하지 않은 상태입니다 라는 문구가 뜨는 에러가 발생했고, onChangeInput에 매개변수 e, date로 넣었는데도 데이터 디스트럭쳐 때문에 에러가 발생한다. < 근데 지금 생각하니 조건문을 걸어서 만약 e면 디스트럭쳐를 하고, 아니면서 date면 복제를 다 하고 ["form_birthday"] : date < 이 부분에서만 이렇게 처리 가능하게 할 수도 있지 않을까? 대신 순서가 중요하겠다.
💬 화살표 함수를 이용한 복제 방식은 formData 객체 양식을 가장 간단하고 보기 좋게 복제하며, 키 밸류 값을 넣을 수 있는 가장 간단한 방법이다.
다른 방법으로도 시도를 해 보았는데 자꾸 에러랑 부딪히더라.ㅠ 내 기억에 에러는 상태 선언은 되어있는데 값이 사용이 되지 않았다는 문구도 있었고, 변수나 상태 로직이 전부 무시가 돼 버리는? 경우였다.
...을 통해서 간단하게 복제를 하고, [키 이름] : 밸류 이름 을 통해서 빠르게 매치하고 값을 넣을 수 있다. 해보니 이게 제일 낫더라!!!
2. form태그에 onSubmit을 걸어 서브밋 함수를 만든다. 거기서 axios로 서버에 폼데이터를 보낸다.
try {
const 회원가입결과명response = await axios.post('서버주소/자기가 지정한 api주소~~~/signup/register', formData);
if(회원가입결과명response.data.success) alert(회원가입결과명response.data.message);
else alert("회원가입에 실패하였습니다😔 \n 다시 시도 해 주세요.");
}
catch {
console.error("🟡 Signup.jsx 오류: 다시시도 해 주세요.");
}
회원가입결과명response: 서버에서 보내는 결과값을 받아서 사용하지 않을거라면 변수에 할당할 필요가 없는데, 나는 서버에서 res.json의 message를 통해서 회원가입 성공실패결과를 보내서 프론트 alert으로 띄어줄 거라서 변수값을 할당받았다.
주로 response라는 변수명을 많이 사용하는 것 같다. 나는 지난 글에서 좀 더 명확한 이름으로 짓는 게 좋다는 이야기를 들었고 나도 언제 다시봐도 이게 무슨 요청결과인지 바로 알고 싶어서 적절하게 변수명을 지었다.
여기서는 덜 헷갈리도록 뒤에 response라는 말까지 덧붙였다!
프론트 작업은 다 했다.
여기서 typeof formData를 하면 객체 형식이라는 것을 알 수 있는데 axios, fetch를 이용하면 json으로 자동 파싱이 된다.
서버에서는 json데이터를 객체로 바꾸는 작업을 해 주어야 한다.
3. 전체를 총괄하는 서버 파일에 두 문장을 추가한다.
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
express.json(): json -> 객체 변환
express.urlencoded({extended: true}): HTML form에서 데이터를 받을 때 변환에 필요한 코드라 한다.
나는 formData를 리액트의 상태로 받아서 굳이 필요하지 않을 수 있는데 확실하게 파싱을 하고플 때 같이 사용한다고 한다.
4. 회원가입 처리 서버 페이지에 폼데이터 값을 디스트럭쳐로 저장하고, 쿼리문을 이용하여 insert 하며 마무리한다.
router
.route('/signup/register')
.post((req, res) => {
const { form_id, form_pwd1, form_name, form_tel, form_birthday, form_email } = req.body;
const 사용자등록쿼리문 = 'INSERT INTO users(users_id, users_pwd, users_name, email, birthday, tel) VALUES(?,?,?,?,?,?)';
db.query(사용자등록쿼리문, [form_id, form_pwd1, form_name, form_email, form_birthday, form_tel], (err, results) => {
if(err) {
console.error(필요한 에러문구);
} else {
return res.json({
success: true,
message: "회원가입이 완료되었습니다😄" // < 이 문구를 프론트에서 사용하기 위해 변수로 등록함!
});
}
router .route .post 이 체이닝 기법은 자신이 구축해둔 라우터 방식에 따라 다르기 때문에 자신이 사용하던 방법을 참고하여 짜준다.
나는 최근에 do it node?? 라는 이지스퍼블리싱 유튜브를 보고 저 방법이 괜찮아보여서 최근 라우터를 재정비해서 저런 방식으로 짰다!
덕분에 server.js 길이도 줄이고 서버의 용도에 따라 각자 파일에서 관리하니 보기도 무지 편리하다! 강추!
사용자등록쿼리문 역시 변수로 지정하면 저게 무슨 작업을 하는 코드였는지 한눈에 파악이 가능하다.
마지막으로 res.json message로 성공 결과를 안내해주며
if(회원가입결과명response.data.success) alert(회원가입결과명response.data.message); 에서 결과를 연결지을 수 있게 해준다. ^^
만약 내가 처음에 올려둔 에러가 뜬다면 자신의 유저 테이블에 not null 설정이 남아있어서 에러가 뜰 수 있으니 적절하게 대처하면 해결이 가능하다.
'리액트로 웹 개발 A to Z' 카테고리의 다른 글
| 정처기 실기 준비, 데이터베이스 파트 (0) | 2025.10.14 |
|---|---|
| 리서치 페이지 : tailwind 사용하기 (with. CRA 5.0.1, postcss, 버전 충돌 해결) (0) | 2025.09.16 |
| 코드리뷰 하는 법 (0) | 2025.08.24 |
| 회원가입 폼 만들기 : 실시간 비밀번호 확인하기 (with. 데이터 디스트럭쳐🔥링, 비동기) (0) | 2025.08.21 |
| 정처기 필기 합격 : 공부 방법 (0) | 2025.08.13 |