Files
Aislo/.agent/complete_and_old/auth_setup_guide.md
T

11 KiB

개발 환경 설정 가이드 (Setup Guide)

🚀 개발 시작 전 필수 설정

이 가이드는 로그인/보안 시스템 개발을 시작하기 전에 필요한 모든 설정을 다룹니다.


1️⃣ Google Gmail SMTP 설정 (개발용)

Step 1: Google 계정 2단계 인증 활성화

1. Google 계정으로 로그인
   → https://myaccount.google.com

2. 왼쪽 메뉴: "보안" (Security)

3. "2단계 인증" → 활성화
   (이미 활성화되어 있으면 스킵)

Step 2: 앱 비밀번호 생성

1. Google 계정 관리 페이지
   → https://myaccount.google.com/apppasswords

2. 앱 선택: "메일(Mail)"

3. 기기 선택: "Windows" (또는 개발 환경)

4. [생성] 버튼 클릭

5. 16자리 비밀번호 생성됨
   예: "abcd efgh ijkl mnop"
   
6. 이 비밀번호를 안전히 보관

⚠️ 주의: 이 비밀번호는 .env 파일에만 저장하고, Git에 절대 커밋하지 마세요!

Step 3: .env 파일 작성

프로젝트 루트에 config/.env 파일 생성:

# config/.env

# ===== Email Infrastructure (Phase 1) =====
SMTP_PROVIDER=google
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=umsangdon@gmail.com
SMTP_PASSWORD=abcd efgh ijkl mnop  # 위에서 생성한 앱 비밀번호
SMTP_USE_TLS=true

# 발송 이메일 주소
EMAIL_FROM_ADDRESS=umsangdon@gmail.com
EMAIL_FROM_NAME=Aislo Support
EMAIL_NOREPLY_ADDRESS=umsangdon+noreply@gmail.com

# 이메일 발송 설정
EMAIL_RETRY_COUNT=3
EMAIL_RETRY_DELAY_SECONDS=2
EMAIL_OTP_VALID_MINUTES=5
EMAIL_NOTIFICATION_ENABLED=true

# 관리자 이메일
ADMIN_EMAIL=umsangdon@gmail.com

# ===== Database =====
DB_HOST=localhost
DB_PORT=3306
DB_USER=root
DB_PASSWORD=your_password
DB_NAME=aislo_db
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_unicode_ci

Step 4: .gitignore 확인

프로젝트 루트의 .gitignore에 다음 추가:

# 환경 변수 (절대 Git에 커밋하지 않음)
config/.env
config/.env.local
.env
.env.local
.env.*.local

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

2️⃣ Python 환경 설정

필요한 라이브러리 설치

# 프로젝트 루트에서 실행

# FastAPI + 비동기 ASGI
pip install fastapi uvicorn

# 데이터베이스
pip install aiomysql

# 유효성 검사
pip install pydantic email-validator

# 비밀번호 암호화
pip install bcrypt

# 환경 변수 관리
pip install python-dotenv

# 이메일 발송 (기본 내장, 추가 설치 불필요)
# smtplib, email (Python 표준 라이브러리)

requirements.txt 생성 (권장)

pip freeze > requirements.txt

그 다음, 팀원이 환경 구축할 때:

pip install -r requirements.txt

3️⃣ 데이터베이스 초기화

MariaDB 서버 확인

# MariaDB 실행 중 확인
mysql -u root -p -e "SELECT VERSION();"

DB 및 테이블 생성

# MySQL 클라이언트 실행
mysql -u root -p

# 다음 SQL 실행:
-- 데이터베이스 생성
CREATE DATABASE IF NOT EXISTS aislo_db
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;

USE aislo_db;

-- 회사 테이블
CREATE TABLE IF NOT EXISTS companies (
  id INT AUTO_INCREMENT PRIMARY KEY,
  company_name VARCHAR(255) NOT NULL,
  company_code VARCHAR(20) UNIQUE NOT NULL,
  business_number VARCHAR(20),
  phone_number VARCHAR(20),
  address VARCHAR(500),
  representative_name VARCHAR(100),
  master_user_id INT NOT NULL,
  status ENUM('ACTIVE', 'INACTIVE', 'SUSPENDED') DEFAULT 'ACTIVE',
  subscription_status ENUM('FREE', 'TRIAL', 'PAID', 'EXPIRED') DEFAULT 'FREE',
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (master_user_id) REFERENCES users(id)
);

-- 사용자 테이블
CREATE TABLE IF NOT EXISTS users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  email VARCHAR(255) UNIQUE NOT NULL,
  password_hash VARCHAR(255) NOT NULL,
  company_id INT,
  is_master BOOLEAN DEFAULT FALSE,
  status ENUM('PENDING', 'ACTIVE', 'INACTIVE', 'REJECTED') DEFAULT 'PENDING',
  last_email_verified_at TIMESTAMP,
  login_failures INT DEFAULT 0,
  last_failed_at TIMESTAMP,
  account_locked_until TIMESTAMP,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (company_id) REFERENCES companies(id),
  INDEX (email),
  INDEX (company_id)
);

-- OTP 저장 (선택사항, users 테이블에 컬럼 추가 가능)
ALTER TABLE users ADD COLUMN IF NOT EXISTS otp_hash VARCHAR(255);
ALTER TABLE users ADD COLUMN IF NOT EXISTS otp_expires_at TIMESTAMP;

-- 가입 요청 테이블
CREATE TABLE IF NOT EXISTS join_requests (
  id INT AUTO_INCREMENT PRIMARY KEY,
  user_id INT NOT NULL,
  company_id INT NOT NULL,
  status ENUM('PENDING', 'APPROVED', 'REJECTED') DEFAULT 'PENDING',
  requested_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  reviewed_at TIMESTAMP,
  reviewed_by INT,
  review_comment TEXT,
  FOREIGN KEY (user_id) REFERENCES users(id),
  FOREIGN KEY (company_id) REFERENCES companies(id),
  FOREIGN KEY (reviewed_by) REFERENCES users(id),
  INDEX (status),
  INDEX (company_id)
);

-- 로그인 이력 테이블
CREATE TABLE IF NOT EXISTS login_logs (
  id INT AUTO_INCREMENT PRIMARY KEY,
  user_id INT,
  email VARCHAR(255),
  status ENUM('SUCCESS', 'FAILURE') NOT NULL,
  failure_reason VARCHAR(100),
  user_agent TEXT,
  login_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (user_id) REFERENCES users(id),
  INDEX (user_id),
  INDEX (login_at)
);

-- 활동 로그 테이블
CREATE TABLE IF NOT EXISTS activity_logs (
  id INT AUTO_INCREMENT PRIMARY KEY,
  user_id INT NOT NULL,
  action_type ENUM('FILE_UPLOAD', 'FILE_DOWNLOAD', 'PROJECT_SAVE', 'DATA_PROCESS', 'PAGE_VIEW'),
  action_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  resource_id VARCHAR(255),
  status ENUM('SUCCESS', 'FAILURE') DEFAULT 'SUCCESS',
  details JSON,
  FOREIGN KEY (user_id) REFERENCES users(id),
  INDEX (user_id),
  INDEX (action_at)
);

-- 시스템 관리자 로그
CREATE TABLE IF NOT EXISTS system_admin_logs (
  id INT AUTO_INCREMENT PRIMARY KEY,
  admin_user_id INT NOT NULL,
  action_type ENUM('USER_DELETE', 'COMPANY_DELETE', 'QA_MODIFY', 'QA_DELETE', 'RESET_PASSWORD'),
  target_id INT,
  action_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  details JSON,
  FOREIGN KEY (admin_user_id) REFERENCES users(id),
  INDEX (admin_user_id),
  INDEX (action_at)
);

-- Q&A 요청 테이블
CREATE TABLE IF NOT EXISTS support_requests (
  id INT AUTO_INCREMENT PRIMARY KEY,
  company_id INT,
  user_email VARCHAR(255),
  subject VARCHAR(255) NOT NULL,
  message TEXT NOT NULL,
  status ENUM('NEW', 'REVIEWED', 'RESOLVED', 'DELETED') DEFAULT 'NEW',
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  reviewed_at TIMESTAMP,
  reviewed_by INT,
  review_notes TEXT,
  FOREIGN KEY (company_id) REFERENCES companies(id),
  FOREIGN KEY (reviewed_by) REFERENCES users(id),
  INDEX (status),
  INDEX (created_at)
);

-- 세션 테이블 (Secure HttpOnly 쿠키 저장소)
CREATE TABLE IF NOT EXISTS sessions (
  id VARCHAR(255) PRIMARY KEY,
  user_id INT NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  expires_at TIMESTAMP NOT NULL,
  last_activity_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (user_id) REFERENCES users(id),
  INDEX (user_id),
  INDEX (expires_at)
);

확인:

-- 테이블 목록 확인
SHOW TABLES;

-- 사용자 테이블 구조 확인
DESCRIBE users;

4️⃣ 프로젝트 폴더 구조 확인

# 필요한 폴더 생성
mkdir -p common_util
mkdir -p config
mkdir -p logs
mkdir -p storage

# .env 파일 위치 확인
ls -la config/.env

5️⃣ 개발 서버 실행

FastAPI 서버 시작

# 프로젝트 루트에서
cd your-project

# Uvicorn 서버 실행
uvicorn main:app --reload --host 127.0.0.1 --port 8000

확인:

INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started server process [12345]

테스트 엔드포인트 확인

# 다른 터미널에서
curl http://127.0.0.1:8000/api/auth/health

6️⃣ 이메일 발송 테스트

Python 테스트 스크립트 작성

# test_email.py

import asyncio
from common_util.common_util_email import EmailService
from common_util.common_util_email_templates import get_otp_email_html

async def test_send_otp():
    """OTP 이메일 발송 테스트"""
    html_body, text_body = get_otp_email_html("123456")
    
    result = await EmailService.send_email(
        to_email="umsangdon@gmail.com",  # 수신 테스트 이메일
        subject="[Aislo] 테스트 - 이메일 인증 코드",
        body_html=html_body,
        body_text=text_body
    )
    
    if result:
        print("✅ 이메일 발송 성공!")
    else:
        print("❌ 이메일 발송 실패")

if __name__ == "__main__":
    asyncio.run(test_send_otp())

실행:

python test_email.py

결과:

✅ 이메일 발송 성공!

Google 계정에서 수신 확인:

- 받는사람: umsangdon@gmail.com
- 발신: "Aislo Support <umsangdon@gmail.com>"
- 제목: "[Aislo] 테스트 - 이메일 인증 코드"
- 본문: HTML 템플릿 + OTP 코드 "123456"

7️⃣ 문제 해결 (Troubleshooting)

문제 1: "SMTP 연결 실패"

Error: [Errno 11001] getaddrinfo failed

해결:

  1. 인터넷 연결 확인
  2. .env 파일의 SMTP_HOST, SMTP_PORT 확인
  3. 방화벽에서 포트 587 허용 확인

문제 2: "앱 비밀번호 인증 실패"

Error: b'5.7.8 Username and password not accepted'

해결:

  1. Google 계정 2단계 인증 활성화 확인
  2. 앱 비밀번호 정확히 입력 (띄어쓰기 포함)
  3. .env 파일에서 SMTP_PASSWORD 재확인

문제 3: "메일이 스팸 폴더로 들어감"

해결:

  1. 발신자 이름 명확히 하기: EMAIL_FROM_NAME=Aislo Support
  2. 이메일 템플릿에 스팸 키워드 제거
  3. Phase 2에서 AWS SES로 마이그레이션

체크리스트

  • Google 계정 2단계 인증 활성화
  • 앱 비밀번호 생성 (16자리)
  • config/.env 파일 작성
  • .gitignore.env 추가
  • Python 라이브러리 설치 (pip install -r requirements.txt)
  • MariaDB 데이터베이스 및 테이블 생성
  • 필요한 폴더 생성 (common_util, config, logs, storage)
  • FastAPI 서버 실행 확인
  • 이메일 발송 테스트 성공

📚 다음 단계

  1. 로그인 페이지 구현 (A06_Login, A07_Register, A09_Security)
  2. 회원가입 API 작성 (A07_Register_Router.py)
  3. 로그인 API 작성 (A06_Login_Router.py)
  4. 프론트엔드 연결 (A06_Login_Api_Fetch.ts, A07_Register_Api_Fetch.ts)
  5. 테스트 및 검증

자세한 내용은 다음 문서를 참고하세요:

  • .agent/login_security_plan.md — 전체 보안 계획
  • .agent/email_infrastructure_plan.md — 이메일 인프라 상세
  • .agent/backend.md — 백엔드 API 명세

작성일: 2026-07-07
상태: 초안 (v1.0)