프로젝트 작업일지 : 회원가입 (이메일 중복 검사)

작업일지에 들어가며

지난 글에서는 기본적인 회원가입 로직을 구현했다.

 

이번에는 회원가입 기능 중 이메일 중복 검사 기능을 만들어보겠다.

 

사용자가 입력한 필드의 값을 서버로 보내 중복되는 이메일이 있는 지 검사하고 응답을 받아 모달 내부에

 

사용 가능 및 사용 불가를 표시해주면 될 것 같다. 바로 시작해보자!


프론트 코드

1. Chakra UI | Dialog

응답 메세지를 띄울 모달로 차크라UI의 Dialog 컴포넌트를 사용

import { Button } from "../components/ui/button"
import {
  DialogActionTrigger,
  DialogBody,
  DialogCloseTrigger,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogRoot,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog"

const DuplicatedEmail = () => {
  return (
    <DialogRoot>
      <DialogTrigger asChild>
        <Button variant="outline" size="sm">
          중복 확인
        </Button>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>이메일 중복 확인</DialogTitle>
        </DialogHeader>
        <DialogBody>
          <p>
          </p>
        </DialogBody>
        <DialogFooter>
          <DialogActionTrigger asChild>
            <Button variant="outline">Cancel</Button>
          </DialogActionTrigger>
          <Button>사용하기</Button>
        </DialogFooter>
        <DialogCloseTrigger />
      </DialogContent>
    </DialogRoot>
  )
}

export default DuplicatedEmail;

기존 폼을 알맞게 수정해주자!

 

2. 이메일 중복 체크 핸들러 구현

const DuplicatedEmail = ({ email, setIsEmailAvailable }) => {
  const [message, setMessage] = useState("");
  const [isSuccess, setIsSuccess] = useState(false);

  const handleCheckEmail = async () => {
    try {
      const response = await axios.get("http://localhost:8080/auth/check-email", {
        params: { email },
      });
      if (response.status === 200) {
        setMessage("사용 가능한 이메일입니다.");
        setIsSuccess(true);
        setIsEmailAvailable(true);  // 이메일이 사용 가능하면 상태 변경
      }
    } catch (error) {
      if (error.response && error.response.status === 400) {
        setMessage("이미 사용 중인 이메일입니다.");
        setIsSuccess(false);
        setIsEmailAvailable(false);  // 이메일이 중복되면 상태 변경
      } else {
        setMessage("이메일 확인 중 오류가 발생했습니다.");
      }
    }
  };

서버로 axios 요청을 보내 이메일 중복 여부를 검사하고 응답 상태를 받아 각각 메세지를 작성하였고,

이메일 중복 검사 여부와, 성공 여부를 useState를 사용하여 저장한다.

 

3. 사용 가능 여부 메세지 출력

  return (
    <DialogRoot>
      <DialogTrigger asChild>
        <Button
          colorPalette="orange"
          width="full"
          size="lg"
          onClick={handleCheckEmail}
        >
          중복 확인
        </Button>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>이메일 중복 확인</DialogTitle>
        </DialogHeader>
        <DialogBody>
          <p>{message}</p>
        </DialogBody>
        {isSuccess && (
          <DialogFooter>
            <DialogActionTrigger asChild>
              <Button colorPalette="orange">사용하기</Button>
            </DialogActionTrigger>
          </DialogFooter>
        )}
        <DialogCloseTrigger />
      </DialogContent>
    </DialogRoot>
  );

버튼에 onClick 이벤트를 걸어주고 <DialogBody> 내부에 핸들러에서 설정한 메세지를 담고, 사용하기 버튼에도 성공 여부를 담아준다.

 

이렇게 리액트 코드는 마무리되었고 이제 요청을 받고 이메일 중복 검사를 처리할 백 코드를 작성해보자


백 코드

이전 시간에 만들어두었던 RegisterResponseDto와 MembersMainRepository를 활용할 예정이다.

1. Dto

@Getter
public class RegisterResponseDto extends ResponseDto {

	private RegisterResponseDto() {
		super(ResponseCode.SUCCESS, ResponseMessage.SUCCESS);
	}

	// 회원가입 성공 시 응답 메소드
	public static ResponseEntity<RegisterResponseDto> success() {
		RegisterResponseDto result = new RegisterResponseDto();
		return ResponseEntity.status(HttpStatus.OK).body(result);
	}

	// 닉네임 중복 시 응답 메소드
	public static ResponseEntity<ResponseDto> duplicateId() {
		ResponseDto result = new ResponseDto(ResponseCode.DUPLICATE_NICKNAME, ResponseMessage.DUPLICATE_NICKNAME);
		return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(result);
	}

	// 이메일 중복 시 응답 메소드
	public static ResponseEntity<ResponseDto> duplicateEmail() {
		ResponseDto result = new ResponseDto(ResponseCode.DUPLICATE_EMAIL, ResponseMessage.DUPLICATE_EMAIL);
		return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(result);
	}

	// 전화번호 중복 시 응답 메소드
	public static ResponseEntity<ResponseDto> duplicatePhone() {
		ResponseDto result = new ResponseDto(ResponseCode.DUPLICATE_PHONE, ResponseMessage.DUPLICATE_PHONE);
		return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(result);
	}
}

 

2. Repository

public interface MembersMainRepository extends JpaRepository<MembersMain, Integer> {
	
	MembersMain findByEmail(String email);
	
	// 이메일 중복 검사
	boolean existsByEmail(String email);
}

 

3. Service

AuthProcess

public interface AuthProcess {
	
	ResponseEntity<? super RegisterResponseDto> register(RegisterRequestDto dto);
	
	ResponseEntity<? super RegisterResponseDto> checkEmailDuplication(String email);
}

 

AuthProcessImpl

@Service
@RequiredArgsConstructor
public class AuthProcessImpl implements AuthProcess {

	private final MembersMainRepository membersMainRepository;
    
	... 생략

	// 이메일 중복 체크
	@Override
	public ResponseEntity<? super RegisterResponseDto> checkEmailDuplication(String email) {
		boolean existedEmail = membersMainRepository.existsByEmail(email);
		if (existedEmail) {
			return RegisterResponseDto.duplicateEmail(); // 중복된 이메일
		}
		return RegisterResponseDto.success(); // 사용 가능한 이메일
	}
}

 

컨트롤러를 통해 받아온 이메일 입력값을 검증하고 사용 가능 여부를 반환

 

4. Controller

AuthController

@RestController
@RequestMapping("/auth")
@RequiredArgsConstructor
public class AuthController {
	private final AuthProcess authProcess;
	
    ...생략

	// 이메일 중복검사
	@GetMapping("/check-email")
	public ResponseEntity<? super RegisterResponseDto> checkEmailDuplication(@RequestParam("email") String email) {
		return authProcess.checkEmailDuplication(email);
	}
}

@RequestParam을 통해 클라이언트로부터 이메일을 받고 서비스에 넘겨주고 서비스에서 검증 후 값을 반환

 

5. 이메일 중복 검사 테스트

이전 회원가입 구현 시 가입했던 이메일로 검증하자 사용 중인 이메일이라고 메세지를 출력

중복되지 않은 이메일 입력 시 사용 가능한 이메일 메세지 출력


작업일지를 마치며

✨ 나의 생각

회원가입 로직을 구현하면서 애초에 중복검사하는 로직을 구현해놨기 때문에

참고할만한 자료들은 많이 없었지만 이번 작업은 GPT의 도움을 조금만 받고 꽤나 수월하게 진행되었다. 

작은 기능들을 하나 둘씩 구현해가면서 점점 더 스프링, 리액트에 적응되어가고 있는 것 같다.

다음 작업은 아마 로그인 기능을 구현하지 않을 까 싶다.