본문 바로가기
Spring Boot

회원가입 기능 구현

by 녹녹1 2023. 7. 17.

진행하는 프로젝트는 React로 웹단을 만들고 Spring Boot로 서버를 하기로 했다

통신은 axios를 사용했다

 

먼저 스프링부트에서는

UserVO / UserController - UserService - UserMapper 이렇게 있고 마이바티스 형식으로 진행했다

 

UserVO.java

package com.josam.clink.user;

import lombok.Data;

@Data
public class UserVO {
	private int userNO;
	private String userId;
	private String userName;
	private String nickname;
	private String pwd;
	private String email;
	private String phoneNumber;
	private String photoUrl;
	private String userStatus;
	private String userSocial;
	private String userAccessToken;
	private String userUpdateToken;
}

 

userNO는 DB에서 자동으로 증가시키게 했고 회원가입할 때는 아이디, 이름, 닉네임, 비밀번호, 이메일만 입력받음! 

맨 밑에서 4개는 2차 프로젝트 때 사용할 토큰용인데 미리 만들어둠

 

UserController.java

package com.josam.clink.user;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@RequestMapping("/clink/user")
@Controller
public class UserController {
	@Autowired
	UserService userService;

	@PostMapping("/join.do")
	@ResponseBody
	public String join(@RequestBody UserVO userVO) {
		int r = userService.insert(userVO);
		if (r == 0) {
			return "no";
		} else {
			return "yes";
		}
	}
  }

컨트롤러 역할을 하고 UserService를 주입받아서 사용한다.

회원가입이 제대로 처리되면 "yes"를 처리되지 않으면 "no"를 반환하게 만들었다

 

UserService.java

package com.josam.clink.user;

import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
	@Autowired
	UserMapper userMapper;

	public int insert(UserVO vo) {
		// 비밀번호 암호화
		return userMapper.insert(vo);
	}

UserMapper를 주입받아서 사용함

비밀번호 암호화를 여기에서 걸려고 주석을 걸어놨다 

1차 끝나면 공부해서 걸어두려고 한다

 

UserMapper.java

package com.josam.clink.user;

import java.util.Map;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper {
	int insert(UserVO vo);
	int login(String userId, String pwd);
	int checkDuplicateId(String userId);
	 UserVO selectUserById(int userId);
}

UserMapper 인터페이스는 마이바티스랑 연결해서 데이터베이스랑 연동하는 것을 도와준다

 

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.josam.clink.user.UserMapper">

	<insert id="insert" parameterType="com.josam.clink.user.UserVO">
		INSERT INTO user (
			`userId`, `userName`, `nickname`, `pwd`, `email`, 
			`phoneNumber`, `photoUrl`, `userStatus`, `userSocial`, `userAccessToken`, `userUpdateToken`
		) VALUES (
			#{userId}, #{userName}, #{nickname}, MD5(#{pwd}), #{email}, #{phoneNumber},
			#{photoUrl}, #{userStatus}, #{userSocial}, #{userAccessToken}, #{userUpdateToken}
		)
	</insert>

</mapper>

DB에서 데이터 꺼내오는 쿼리문을 작성하는 파일이다.

패스워드 부분에 MD5라고만 적어두면 알아서 암호화가 된다고 한다. 신기..

하지만 뚫리기 쉽다고 하니 바꿔야 한다 (나중에..)

 

그리고 이제 VS Code의 Join.js

 

import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import axios from 'axios';
import Button from 'react-bootstrap/Button';
import Form from 'react-bootstrap/Form';
import InputGroup from 'react-bootstrap/InputGroup';
import 'bootstrap/dist/css/bootstrap.min.css';
import '../styles/Join.scss';
import { Link } from 'react-router-dom';

const Join = () => {
  // 모든 칸 입력했는지 체크(예정)

  const navigate = useNavigate();
  const [userName, setUserName] = useState('');
  const [userId, setuserId] = useState('');
  const [nickname, setNickname] = useState('');
  const [pwd, setPwd] = useState('');
  const [confirmPwd, setConfirmPwd] = useState('');
  const [email, setEmail] = useState('');

  // 아이디 중복체크
  function checkDuplicateId() {
    let id = { userId: userId };
    axios
      .post('http://localhost:80/clink/user/check-duplicate-id.do', id)
      .then((response) => {
        console.log(response.data);
        if (response.data === 'success') {
          alert('사용할 수 있는 아이디입니다.');
        } else if (response.data === 'fail') {
          alert('사용 중인 아이디입니다.');
          setuserId('');
        }
      })
      .catch((error) => {
        console.log(error);
        alert('다시 시도하세요');
      });
  }

  // 회원가입
  function handleSubmit(e) {
    // e.preventDefault();

    var param = {
      userName: userName,
      userId: userId,
      nickname: nickname,
      pwd: pwd,
      confirmPwd: confirmPwd,
      email: email,
    };

    axios
      .post('http://localhost:80/clink/user/join.do', param)
      .then((response) => {
        console.log(response.data);
        if (response.data === 'yes') {
          alert('회원가입 되었습니다. 로그인해주세요.');
          navigate('/');
        }
      })
      .catch((error) => {
        console.log(error);
        alert('다시 시도해세요');
      });
  }

  return (
    <div className="JoinContainer">
      <div id="backgroundCircle"></div>
      <form action="join.do" method="post">
        <div className="JoinTitle">
          <h1>회원가입</h1>
        </div>
        <div className="JoinInputBox">
          <Form.Control
            name="name"
            placeholder="이름"
            className="joinInput"
            onChange={(e) => {
              setUserName(e.target.value);
            }}
          />
          <InputGroup className="joinInput">
            <Form.Control
              name="userId"
              placeholder="아이디"
              variant="outline-secondary"
              onChange={(e) => {
                setuserId(e.target.value);
              }}
              value={userId}
            />
            <Button id="JoinIdentifyBtn" onClick={() => checkDuplicateId()}>
              중복확인
            </Button>
          </InputGroup>
          <Form.Control
            name="nickname"
            placeholder="닉네임"
            className="joinInput"
            onChange={(e) => {
              setNickname(e.target.value);
            }}
          />
          <Form.Control
            type="password"
            name="password"
            placeholder="비밀번호"
            className="joinInput"
            onChange={(e) => {
              setPwd(e.target.value);
            }}
          />
          <Form.Control
            type="password"
            name="confirmPassword"
            placeholder="비밀번호 확인"
            className="joinInput"
            onChange={(e) => {
              setConfirmPwd(e.target.value);
            }}
          />

          <InputGroup className="joinInput">
            <Form.Control
              placeholder="이메일"
              type="email"
              name="email"
              onChange={(e) => {
                setEmail(e.target.value);
              }}
            />
            <Button variant="outline-secondary" id="JoinIdentifyBtn">
              본인인증하기
            </Button>
          </InputGroup>
        </div>
      </form>
      <div className="JoinBtnBox">
        <Button
          variant="primary"
          className="LoginSubmitBtn"
          type="submit"
          onClick={() => handleSubmit()}
        >
          회원가입하기
        </Button>
      </div>
      <div className="JoinLoginBtn">로그인</div>
    </div>
  );
};

export default Join;

리액트 부트스트랩으로 Form이랑 Button을 가져다 썼다.

 

아 axios 사용해서 통신하면 CORS에러가 뜨는데 나는 WebConfig.java파일을 스프링 부트에 만들어뒀다.

어노테이션을 사용할 수도 있고 다양한 방법 중에 원하는 방법으로 하면 될 것 같다 

 

회원가입에서 해야 할 것들이 많은데 현재는 가장 기본적인 것만 구현했다

  • 입력한 값 서버로 보내서 DB에 저장하기
  • 아이디 중복체크하기

해야할 것 

  • 이메일 중복확인
  • 모든 칸 작성했는지 확인하기
  • 비밀번호 - 비밀번호 확인 동일하게 입력했는지 확인
  • 등등..

 

추가로 하고싶은 것 / 2차때 하기로 한 것

  • 아이디 저장 버튼 (쿠키 사용해서)
  • 핸드폰 번호 인증

 

댓글