자바스크립트 입문

7. 자바스크립트 Fetch API로 실시간 중복 확인 구현(feat.Django)

수달1234 2025. 5. 1. 10:13

시작

웹페이지에서 사용자 경험을 상승시키는데 중요한 방법 중 하나로 실시간으로 피드백을 제공하는 것입니다. 대표적으로 회원가입이나 정보 입력시 내가 입력한 값이 웹사이트에 저장된 값과 중복된 지 여부를 확인할 때 새로고침을 하지 않고 즉시 결과를 보여주면 사용자의 만족도가 크게 향상될것입니다. 직접 경험해보면 아시겠지만 새로고침을 하면서 생기는 1~2초의 딜레이도 사용성이 크게 떨어지는 경험들이 다들 있으니까요. 이번에는 자바스크립트의 Fetch를 사용하여 Django와 통신하고, 실시간으로 회원가입시 이메일과 닉네임 중복을 확인하는 방법을 알아보겠습니다.

 

 

AJAX와 Fetch API 소개

AJAX(Asynchronous JavaScript and XML)는 웹 페이지가 서버와 비동기적으로 데이터를 교환할 수 있게 해주는 기술입니다. 이 기술을 사용하면 전체 페이지를 새로고침하지 않고도 서버에서 데이터를 가져와 화면의 일부만 업데이트할 수 있습니다.

Fetch API는 네트워크 통신을 위한 JavaScript의 현대적인 인터페이스로, 기존의 XMLHttpRequest를 대체하는 보다 강력하고 유연한 방식입니다. Promise 기반으로 작동하여 더 깔끔한 비동기 코드 작성이 가능합니다

 

Django 백엔드 API 구현

Django에서 이메일과 닉네임 중복 확인을 위한 API 엔드포인트를 만들어 보겠습니다. 보통 views.py를 이용합니다.

 
 

 

    # 이메일 형식 검증
from django.core.validators import validate_email
from django.core.exceptions import ValidationError

# 중복 검증증
from django.contrib.auth import get_user_model


def check_email(request):
    """이메일 중복 확인 API"""
    email = request.GET.get('email', '')
    if not email:
        return JsonResponse({'valid': False, 'message': '이메일을 입력해주세요.'})
    

    try:
        validate_email(email)
    except ValidationError:
        return JsonResponse({'valid': False, 'message': '올바른 이메일 형식이 아닙니다.'})
    
    # 중복 검증
    User = get_user_model()
    exists = User.objects.filter(email=email).exists()
    if exists:
        return JsonResponse({'valid': False, 'message': '이미 사용 중인 이메일입니다.'})
    
    return JsonResponse({'valid': True, 'message': '사용 가능한 이메일입니다.'})

def check_nickname(request):
    """닉네임 중복 확인 API"""
    nickname = request.GET.get('nickname', '')
    if not nickname:
        return JsonResponse({'valid': False, 'message': '닉네임을 입력해주세요.'})
    
    # 중복 검증
    User = get_user_model()
    exists = User.objects.filter(nickname=nickname).exists()
    if exists:
        return JsonResponse({'valid': False, 'message': '이미 사용 중인 닉네임입니다.'})
    
    return JsonResponse({'valid': True, 'message': '사용 가능한 닉네임입니다.'})

그리고 이 뷰 함수들을 URL 패턴에 연결합니다:

 

from django.urls import path
from . import views

urlpatterns = [
    ## 기존 url값들
    path('check-email/', views.check_email, name='check_email'),
    path('check-nickname/', views.check_nickname, name='check_nickname'),
]

이제 Django 백엔드에서 /users/check-email/?email=a@a.com과 같은 URL 요청을 받으면 해당 이메일이 사용 가능한지 응답을 반환합니다.

 

JavaScript Fetch API 이해하기

Fetch API는 네트워크 요청을 더 쉽게 만들기 위해 제공되는 JavaScript 인터페이스입니다. 기본 사용법은 다음과 같습니다:

 
javascript
fetch(url)
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error('Error:', error));

fetch() 함수는 첫 번째 인자로 URL을 받고, 선택적으로 두 번째 인자로 옵션 객체를 받을 수 있습니다. 이 함수는 Promise를 반환하며, 이 Promise는 Response 객체로 해결(resolve)됩니다.

Fetch API의 주요 특징

  1. Promise 기반: 비동기 작업을 더 깔끔하게 처리할 수 있습니다.
  2. JSON 처리 간소화: response.json() 메서드를 통해 JSON 응답을 쉽게 파싱할 수 있습니다.
  3. 다양한 요청 옵션: HTTP 메서드, 헤더, 본문 등을 쉽게 설정할 수 있습니다.
  4. 강력한 에러 처리: catch()를 통해 네트워크 오류를 잡을 수 있습니다.

 

실시간 이메일 중복 확인 구현하기

이제 Fetch API를 사용하여 이메일 필드에서 포커스가 빠져나갈 때(blur 이벤트) 서버에 중복 확인 요청을 보내고 결과를 표시하는 기능을 구현해 보겠습니다.

 // 실시간 이메일 검증 
    emailField.addEventListener('blur', function() {
        const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        // 이메일 피드백
        const emailFeedback = document.getElementById('email-feedback') || createFeedbackElement(this, 'email-feedback');
        
       // 값이 비어있으면 피드백 제거
        if (!this.value) {
            emailFeedback.textContent = '';
            return;
        }

        // 이메일 형식 검증
        if (!emailPattern.test(this.value)) {
            emailFeedback.textContent = '올바른 이메일 형식이 아닙니다.';
            emailFeedback.style.color = 'red';
            return;
        }

        // 이메일 형식이 올바르면 중복 확인 AJAX 요청
        emailFeedback.textContent = '확인 중...';
        emailFeedback.style.color = 'blue';
        
        fetch(`/users/check-email/?email=${encodeURIComponent(this.value)}`)
            .then(response => response.json())
            .then(data => {
                if (data.valid) {
                    emailFeedback.textContent = data.message;
                    emailFeedback.style.color = 'green';
                } else {
                    emailFeedback.textContent = data.message;
                    emailFeedback.style.color = 'red';
                }
            })
            .catch(error => {
                emailFeedback.textContent = '서버 오류가 발생했습니다.';
                emailFeedback.style.color = 'red';
                console.error('Error:', error);
            });

    });
  • 이벤트 리스너 : 이메일 입력 필드에 blur를 사용했습니다. blur는 사용자가 필드에서 포커스를 빼면 실행됩니다.(예를들면 이메일 입력칸에 이메일 입력을 한 후 닉네임 입력칸으로 마우스를 클릭한 상황 같은)
  • emailFeedback : 피드백 요소가 있으면 가져오거나, 없다면 새로 생성하도록합니다.
  • if (!this.value) : 필드가 비어있으면 피드백을 지우고 함수를 종료합니다.
  • if (!emailPatter.test(this.value)) : 이메일 형식이 올바른지 확인합니다. "!"를 넣어서 올바르지 않으면 에러메세지를 출력합니다.
  • Fetch API : Get 요청을 사용해 url에 이메일값을 쿼리로 포함합니다. " encodeURIComponent" URL에 특수문자가 포함된경우 안전하게 인코딩합니다.
  • .then : 첫번째 응답에서 JsON 형태(response.json)으로 반환하고, 두번째를 통해 이 값이 타당(Django에서 정의한 응답 필드->views.py 에서 check_email함수) 확인하고 메세지를 표시합니다.
  • .catch : 그 외 오류 발생시 에러 메세지를 표시하고 콘솔에 기록합니다. 

닉네임 중복 확인도 추가하기

이메일 중복 확인과 같은 방식으로 닉네임 중복 확인도 구현할 수 있습니다

// 닉네임 필드 검증
    nicknameField.addEventListener('blur', function() {
        const nicknameFeedback = document.getElementById('nickname-feedback') || 
                               createFeedbackElement(this, 'nickname-feedback');
        
        // 값이 비어있으면 피드백 제거
        if (!this.value) {
            nicknameFeedback.textContent = '';
            return;
        }
        
        // 닉네임 중복 확인 AJAX 요청
        nicknameFeedback.textContent = '확인 중...';
        nicknameFeedback.style.color = 'blue';
        
        fetch(`/users/check-nickname/?nickname=${encodeURIComponent(this.value)}`)
            .then(response => response.json())
            .then(data => {
                if (data.valid) {
                    nicknameFeedback.textContent = data.message;
                    nicknameFeedback.style.color = 'green';
                } else {
                    nicknameFeedback.textContent = data.message;
                    nicknameFeedback.style.color = 'red';
                }
            })
            .catch(error => {
                nicknameFeedback.textContent = '서버 오류가 발생했습니다.';
                nicknameFeedback.style.color = 'red';
                console.error('Error:', error);
            });
    });

 

폼 제출 시 최종 검증

실시간 중복 확인 결과를 활용하여 폼 제출 시 최종 검증을 수행할 수도 있습니다.

    // 폼 제출 검증
    signupForm.addEventListener('submit', function(e) {
        // 이메일 피드백 확인
        const emailFeedback = document.getElementById('email-feedback');
        if (emailFeedback && emailFeedback.style.color === 'red') {
            e.preventDefault();
            alert('이메일을 확인해주세요.');
            emailField.focus();
            return;
        }
        
        // 닉네임 피드백 확인
        const nicknameFeedback = document.getElementById('nickname-feedback');
        if (nicknameFeedback && nicknameFeedback.style.color === 'red') {
            e.preventDefault();
            alert('닉네임을 확인해주세요.');
            nicknameField.focus();
            return;
        }
        
        // 비밀번호 길이 검증
        if (passwordField.value.length < 8) {
            e.preventDefault();
            alert('비밀번호는 최소 8자 이상이어야 합니다!');
            passwordField.focus();
            return;
        }
    });

폼이 제출될 때 이메일과 닉네임 피드백 요소의 색상을 확인합니다. 빨간색(오류)라면 폼 제출을 막고(e.preventDefault) 알람을 통해 이를 사용자에게 알려줍니다.

 

 

결론

JavaScript의 Fetch API를 활용하여 Django 백엔드와 통신하는 실시간 중복 확인 기능을 구현해보았습니다. 이 기능은 사용자가 폼을 제출하기 전에 즉각적인 피드백을 제공하여 사용자 경험을 크게 향상시킵니다.

주요 장점으로는

  1. 페이지 새로고침 없이 실시간으로 데이터 검증
  2. 서버 부하 감소 (유효하지 않은 폼 제출 방지)
  3. 즉각적인 사용자 피드백으로 사용성 향상

이제 후에는 Get요청이 아닌 보안이나 데이터 크기 제한으로 인해 POST방식을 사용하는 방식과 같은 방법으로 더 새롭게 배울수있습니다.

 

실제 실행 결과