# 개발 환경 설정 가이드 (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` 파일 생성: ```bash # 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`에 다음 추가: ```bash # 환경 변수 (절대 Git에 커밋하지 않음) config/.env config/.env.local .env .env.local .env.*.local # IDE .vscode/ .idea/ *.swp *.swo *~ ``` --- ## 2️⃣ Python 환경 설정 ### 필요한 라이브러리 설치 ```bash # 프로젝트 루트에서 실행 # 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 생성 (권장) ```bash pip freeze > requirements.txt ``` 그 다음, 팀원이 환경 구축할 때: ```bash pip install -r requirements.txt ``` --- ## 3️⃣ 데이터베이스 초기화 ### MariaDB 서버 확인 ```bash # MariaDB 실행 중 확인 mysql -u root -p -e "SELECT VERSION();" ``` ### DB 및 테이블 생성 ```bash # MySQL 클라이언트 실행 mysql -u root -p # 다음 SQL 실행: ``` ```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) ); ``` 확인: ```sql -- 테이블 목록 확인 SHOW TABLES; -- 사용자 테이블 구조 확인 DESCRIBE users; ``` --- ## 4️⃣ 프로젝트 폴더 구조 확인 ```bash # 필요한 폴더 생성 mkdir -p common_util mkdir -p config mkdir -p logs mkdir -p storage # .env 파일 위치 확인 ls -la config/.env ``` --- ## 5️⃣ 개발 서버 실행 ### FastAPI 서버 시작 ```bash # 프로젝트 루트에서 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] ``` ### 테스트 엔드포인트 확인 ```bash # 다른 터미널에서 curl http://127.0.0.1:8000/api/auth/health ``` --- ## 6️⃣ 이메일 발송 테스트 ### Python 테스트 스크립트 작성 ```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()) ``` 실행: ```bash python test_email.py ``` 결과: ``` ✅ 이메일 발송 성공! ``` Google 계정에서 수신 확인: ``` - 받는사람: umsangdon@gmail.com - 발신: "Aislo Support " - 제목: "[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)