2026/02/17 Blog - 3

김기훈·2026년 2월 17일

TIL

목록 보기
143/194
post-thumbnail

  • 지금 로그인 / 회원가입 / 포스팅 기능 구련을 완료했는데
    • 전체 기능구현이 끝나고 디자인을 씌울까 아니면 기능구현이 되는대로 디자인을 씌울까
    • 기능별로 디자인도 같이 씌우기로 결정 BootStrap 사용 예정

디자인

로그인


회원가입


기본 페이지


기능연결

로그인

로그인 요약도

graph LR
    User[사용자] -->|클릭| Browser[브라우저 JS]
    Browser -->|1. fetch 요청 (JSON)| URL[/api/v1/user/login/]
    URL -->|2. 연결| View[Django View]
    View -->|3. 검증| Serializer[Serializer]
    Serializer -->|4. 조회| DB[(Database)]
    DB --> View
    View -->|5. 응답 (Token)| Browser
    Browser -->|6. 저장 및 이동| LocalStorage[브라우저 저장소]

1단계: 이벤트 감지 및 가로채기

  • HTML 폼(Form)은 원래 submit 버튼을 누르면 무조건 페이지를 새로고침하며 어딘가로 이동하려고 함
  • 그리하여 이걸 막고 "내가 알아서 데이터를 보낼게"라고 해야 함
// 'loginForm'이라는 ID를 가진 폼이 제출(submit)될 때를 기다림
document.getElementById('loginForm').addEventListener('submit', async function(e) {
    
    // 브라우저의 기본 동작(새로고침)을 막음, 이걸 안 하면 순식간에 페이지가 깜빡이고 데이터가 다 날아감
    e.preventDefault();

2단계: 데이터 포장 - JSON

  • 백엔드의 LoginSerializer는 JSON 데이터를 기다리고 있음
  • 그래서 사용자가 입력창(input)에 적은 내용을 가져와서 JSON 문자열로 포장해야 함
// 화면에 입력된 값을 변수에 담음
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;

// ... fetch 함수 내부 ...
body: JSON.stringify({  // 자바스크립트 객체를 JSON 문자열로 변환
    email: email,
    password: password
})
// 여기서 만든 JSON 키값(email, password)은 백엔드 LoginSerializer에 정의된 필드명과 반드시 철자가 똑같아야 함 

3단계: Fetch - 비동기 통신

  • (A) 주소
    • /api/v1/user/login/으로 요청을 쏘면
    • Django urls.py가 이를 낚아채서 LoginAPIView로 연결해 줌
  • (B) 메서드
    • POST로 쏘기 때문에 LoginAPIView의 def post(self, request): 함수가 실행
  • (C) 헤더
    • 백엔드가 request.data를 파싱 할 때 "아, 이거 JSON이구나"라고 알 수 있게 해 줌
const response = await fetch('/api/v1/user/login/', { # (A) 목적지 주소
    method: 'POST',                                   # (B) HTTP 메서드
    headers: {
        'Content-Type': 'application/json',           # (C) "나 지금 JSON 보낸다"라고 선언
    },
    body: JSON.stringify({ ... })                     # (D) 실제 데이터(Payload)
});
  

4단계: 응답 처리

  • 백엔드(LoginAPIView)가 로직을 다 처리하고 Response(...)를 반환하면
    • 자바스크립트는 그 결과를 받아서 행동을 결정
const data = await response.json(); // 응답 온 JSON을 다시 자바스크립트 객체로 풉니다.

if (response.ok) {
    // 성공 시 (HTTP 상태 코드 200~299)
    // 백엔드가 준 토큰(access, refresh)을 브라우저 창고(localStorage)에 저장합니다.
	// data.token.access라고 쓸 수 있는 이유는, 백엔드 LoginAPIView에서 Response({"token": {"access": ...}}) 형태로 데이터를 내려줬기 때문
    localStorage.setItem('access_token', data.token.access);
    
    // 메인 페이지로 이동시킵니다.
    window.location.href = "/"; 
} else {
    // 실패 시 (HTTP 상태 코드 400, 401, 500 등)
    // 백엔드가 보낸 에러 메시지(data.message)를 띄웁니다.
    alert("로그인 실패: " + ...);
}

회원가입

  • 프론트엔드(JS) -> 백엔드(Django) -> DB

회원가입 흐름도

graph LR
    User[사용자 입력] -->|비번 일치 확인| JS[프론트엔드 JS]
    JS -->|1. JSON 전송 (email, nickname, pw)| URL[/api/v1/user/signup/]
    URL --> View[SignupAPIView]
    View -->|2. 데이터 검증| Serializer[SignupSerializer]
    Serializer -->|3. 중복 체크| DB[(Database)]
    DB --> Serializer
    Serializer -->|4. 유저 생성| Service[SignupService]
    Service --> DB
    View -->|5. 성공 응답 (201)| JS
    JS -->|6. 로그인 페이지로 이동| Page[Login Page]

1단계: 이벤트 감지 및 1차 검문

  • 회원가입 버튼을 누르면 자바스크립트가 가장 먼저 작동
    • 여기서 중요한 건 서버로 보내기 전에 프론트에서 먼저 거르는 작업
document.getElementById('signupForm').addEventListener('submit', async function(e) {
    e.preventDefault(); // 1. 새로고침 막기

    // 2. 입력값 가져오기
    const email = document.getElementById('email').value;
    const nickname = document.getElementById('nickname').value;
    const password = document.getElementById('password').value;
    const passwordConfirm = document.getElementById('passwordConfirm').value; // 확인용 비밀번호

    // [핵심!] 프론트엔드 유효성 검사 (1차 검문)
    // 서버까지 갈 필요도 없이, 여기서 틀렸으면 바로 돌려보냅니다.
    if (password !== passwordConfirm) {
        alert("비밀번호가 일치하지 않습니다.");
        return; // 함수 종료 (서버로 요청 안 보냄)
    }

2단계: 데이터 선별 및 포장

  • SignupSerializer는 딱 3가지 정보만 원함: email, nickname, password
    • 프론트에서 passwordConfirm을 입력받았지만, 이건 검사만 하고 실제 JSON 포장 단계에서는 제거
    • 백엔드 SignupSerializer의 fields = ["email", "nickname", "password"]와 정확히 일치해야 함
// ... fetch 함수 내부 ...
    body: JSON.stringify({
        email: email,       // 백엔드가 원하는 필드명 1
        nickname: nickname, // 백엔드가 원하는 필드명 2
        password: password  // 백엔드가 원하는 필드명 3
        // passwordConfirm은 보내지 않습니다!
    })

3단계: Fetch - 비동기 통신

  • 포장된 데이터를 들고 백엔드 API 주소로 떠남
  • Django 처리 과정

    • 도착
      • /api/v1/user/signup/ 주소에 있는 SignupAPIView가 요청을 받습니다.
    • 2차 검문 (Serializer)
      • SignupSerializer가 "이메일 형식이 맞는지", "이미 가입된 이메일인지(validate_email)" 정밀 검사
    • 생성 (Service)
      • 문제가 없으면 SignupService.create_user가 DB에 유저를 저장합니다.
    • 응답
      • "잘 만들었어(201 Created)"라는 신호를 보냅니다.
const response = await fetch('/api/v1/user/signup/', { // (A) 목적지
    method: 'POST',                                    // (B) 생성 요청
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ ... })
});

4단계: 응답 처리 및 이동

  • 백엔드의 처리 결과를 보고 사용자에게 알림을 줌
const data = await response.json();

if (response.ok) {
    // 성공 시: 환영 메시지 띄우고 로그인 페이지로 보냄
    alert("회원가입 완료! 로그인 페이지로 이동합니다.");
    window.location.href = "/api/v1/user/login-page/";
} else {
    // 실패 시: 백엔드 검문소(Serializer)에서 걸린 이유를 알려줌
    // 예: "이미 존재하는 이메일입니다."
    // ... (에러 메시지 파싱 로직) ...
    alert(errorMessage);
}  

기능구현

포스트 작성 기능

  • 연휴중에 빠르게 처리하다보니 기록을 못했음

작성 글 조회


profile
안녕하세요.

0개의 댓글