챗봇 공부 노트

[8편] OAuth vs 자체 회원가입 — 서비스에 맞는 인증 전략

frontend-diary-log 2026. 1. 23. 19:37

 

📘 Aura_AI Day 8

자체 회원가입 / 로그인 기능 완성 + MySQL 연동 정리

안녕하세요.
오늘은 Google OAuth에 더해 자체 회원가입 / 로그인 기능을 완성하고,
이를 MySQL DB 저장 구조와 함께 안정적으로 연결했습니다.

UI 구현보다는
👉 **“인증 시스템을 실제 서비스 수준으로 완성하는 것”**에 초점을 둔 하루였습니다.


🎯 Day 8 목표

  • 회원가입 정보를 MySQL DB에 저장
  • 이메일 / 비밀번호 기반 로그인 구현
  • 입력값 유효성 검사(Regex) 적용
  • 이메일 / 닉네임 중복 체크
  • 회원가입 후 자동 로그인 → /chat 이동

✅ 오늘 추가된 기능 요약

  • 회원가입 데이터 MySQL 저장
  • Credentials 기반 로그인(Auth.js)
  • 회원가입 후 자동 로그인 처리
  • 클라이언트 + 서버 이중 Regex 검증
  • 이메일 / 닉네임 중복 체크
  • 로그인 실패 UX 개선

1️⃣ 오늘 설치한 패키지

npm install mysql2 bcryptjs

왜 이 패키지들인가?

  • mysql2
    • Promise 기반 API 지원
    • Connection Pool 제공 → 실무 표준
  • bcryptjs
    • 비밀번호 단방향 해시
    • 평문 저장 ❌, 복호화 ❌ → 보안 필수

2️⃣ DB 설계 (MySQL)

2-1. 데이터베이스 생성

CREATE DATABASE aura_ai
CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;

이모지, 한글까지 안전하게 저장하기 위해 utf8mb4 사용


2-2. users 테이블 구조

CREATE TABLE users (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  name VARCHAR(50) NOT NULL,
  email VARCHAR(255) NOT NULL,
  phone VARCHAR(30) NOT NULL,
  region VARCHAR(50) NOT NULL,
  nickname VARCHAR(50) NOT NULL,
  password_hash VARCHAR(255) NOT NULL,
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (id),
  UNIQUE KEY uniq_email (email),
  UNIQUE KEY uniq_nickname (nickname)
);

📌 설계 포인트

  • password ❌ → password_hash만 저장
  • 이메일 / 닉네임은 DB 레벨에서 UNIQUE
  • 코드 + DB 2중 방어

3️⃣ 기능 코드 핵심 설명


✅ 3-1. MySQL 연결 풀 생성 (db.ts)

import mysql from "mysql2/promise";

const pool = mysql.createPool({
  host: process.env.MYSQL_HOST,
  user: process.env.MYSQL_USER,
  password: process.env.MYSQL_PASSWORD,
  database: process.env.MYSQL_DATABASE,
  port: process.env.MYSQL_PORT ? Number(process.env.MYSQL_PORT) : 3306,
  connectionLimit: 10,
});

export default pool;

왜 Connection Pool인가?

  • 요청마다 연결 생성 ❌ (비효율)
  • 풀에서 재사용 → 성능 & 안정성
  • 실무에서 가장 일반적인 DB 접근 방식

✅ 3-2. 회원가입 API (route.ts)

전체 흐름

  1. 입력값 추출
  2. Regex 유효성 검사
  3. DB 중복 체크
  4. 비밀번호 해시
  5. 회원 저장

① Regex 유효성 검사

const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const phoneRegex = /^01[016789]-?\d{3,4}-?\d{4}$/;
const passwordRegex = /^(?=.*[A-Za-z])(?=.*\d).{8,}$/;

if (!emailRegex.test(email)) return Response.json({}, { status: 400 });
if (!phoneRegex.test(phone)) return Response.json({}, { status: 400 });
if (!passwordRegex.test(password)) return Response.json({}, { status: 400 });

📌 왜 서버에서도 검사할까?

  • 클라이언트 검증은 우회 가능
  • 서버 검증은 신뢰 가능한 최종 방어선

② 이메일 / 닉네임 중복 체크

SELECT id FROM users WHERE email = ? OR nickname = ?
  • 중복 시 409 Conflict
  • UX + API 의미 모두 명확

③ 비밀번호 해시 후 저장

const hashedPassword = await bcrypt.hash(password, 12);
  • 원본 비밀번호는 절대 저장하지 않음
  • 12 rounds → 보안과 성능 균형

✅ 3-3. Credentials 로그인 추가 (auth.ts)

Credentials({
  async authorize(credentials) {
    const identifier = credentials.identifier;
    const password = credentials.password;

    const [rows] = await pool.execute(
      "SELECT id, name, email, password_hash FROM users WHERE email = ? LIMIT 1",
      [identifier]
    );

    const isValid = await bcrypt.compare(password, user.password_hash);
    if (!isValid) return null;

    return { id, name, email };
  },
});

📌 핵심 개념

  • Credentials Provider는 직접 인증 로직을 구현
  • DB 조회 → bcrypt 비교
  • 성공 시 유저 객체 반환
  • 실패 시 null → Auth.js가 로그인 실패 처리

✅ 3-4. 회원가입 후 자동 로그인

const signInResult = await signIn("credentials", {
  identifier: payload.email,
  password,
  callbackUrl: "/chat",
  redirect: false,
});

if (signInResult?.url) {
  window.location.href = signInResult.url;
}

왜 자동 로그인?

  • 회원가입 → 로그인 재입력 ❌
  • UX 개선 + 이탈률 감소
  • 실제 서비스에서 매우 일반적인 패턴

✅ 3-5. 로그인 UX 개선

if (!email || !password) {
  alert("이메일과 비밀번호를 입력해주세요.");
}

if (result?.error) {
  alert("이메일 또는 비밀번호를 확인해주세요.");
}
  • 실패 원인을 명확하게 안내
  • 단순 alert이지만 UX 의도는 분명

4️⃣ 오늘 변경된 파일 정리

📂 신규 파일

  • db.ts — MySQL 연결 풀
  • route.ts — 회원가입 API

✏️ 수정 파일

  • auth.ts — Credentials Provider 추가
  • page.tsx
    • Regex 검증
    • 회원가입 후 자동 로그인
    • 로그인 실패 UX 개선

5️⃣ 오늘의 실무 포인트 정리

  • ✅ 비밀번호는 반드시 해시 저장
  • ✅ 검증은 프론트 + 서버 이중 처리
  • ✅ 중복 체크는 DB UNIQUE로 마무리
  • ✅ 회원가입 후 자동 로그인으로 UX 개선
  • ✅ OAuth + Credentials 공존 구조 완성

✅ Day 8 결과 체크리스트

  • 회원가입 정보 DB 저장
  • 이메일 / 비밀번호 로그인 가능
  • Regex 유효성 검사
  • 이메일 / 닉네임 중복 체크
  • 회원가입 후 /chat 이동