198 lines
5.0 KiB
Markdown
198 lines
5.0 KiB
Markdown
# 🐛 로그인 버그 수정 완료
|
|
|
|
## 문제 상황
|
|
|
|
- ✅ 회원가입 후 바로 로그인 → **정상 작동**
|
|
- ❌ 로그아웃 후 다시 로그인 시도 → **"이메일 또는 비밀번호가 올바르지 않습니다" 에러**
|
|
- 입력한 정보는 모두 정확함
|
|
|
|
## 🔍 원인 분석
|
|
|
|
### 문제의 원인
|
|
Drizzle ORM 스키마와 코드 간 필드명 불일치
|
|
|
|
**Drizzle 스키마 (schema.ts):**
|
|
```typescript
|
|
export const users = sqliteTable('users', {
|
|
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
email: text('email').notNull().unique(),
|
|
passwordHash: text('password_hash').notNull(), // ← camelCase
|
|
nickname: text('nickname').notNull(),
|
|
createdAt: integer('created_at', { mode: 'timestamp' })
|
|
});
|
|
```
|
|
|
|
**로그인 코드 (login/+page.server.ts) - 수정 전:**
|
|
```typescript
|
|
const validPassword = await verifyPassword(password, user.password_hash);
|
|
// ^^^^^^^^^^^^^ snake_case 사용
|
|
```
|
|
|
|
### 왜 회원가입은 작동했나?
|
|
|
|
회원가입 시에는 **새로운 passwordHash 값을 직접 전달**하기 때문에 필드명 불일치가 문제가 되지 않았습니다:
|
|
|
|
```typescript
|
|
// register/+page.server.ts
|
|
const user = await createUser(platform.env.DB, email, passwordHash, nickname);
|
|
// passwordHash를 직접 전달하므로 문제 없음
|
|
```
|
|
|
|
하지만 로그인 시에는 **DB에서 조회한 user 객체의 필드에 접근**하므로:
|
|
|
|
```typescript
|
|
// login/+page.server.ts
|
|
const user = await getUserByEmail(platform.env.DB, email);
|
|
// user.passwordHash가 올바른 필드명인데
|
|
// user.password_hash로 접근 → undefined 반환
|
|
const validPassword = await verifyPassword(password, undefined);
|
|
// undefined와 비교하므로 항상 실패!
|
|
```
|
|
|
|
## ✅ 해결 방법
|
|
|
|
### 수정된 코드
|
|
|
|
```typescript
|
|
// src/routes/login/+page.server.ts (수정 후)
|
|
const validPassword = await verifyPassword(password, user.passwordHash);
|
|
// ^^^^^^^^^^^^ camelCase로 수정
|
|
```
|
|
|
|
## 🔧 수정 내역
|
|
|
|
**파일:** `src/routes/login/+page.server.ts`
|
|
|
|
**변경 사항:**
|
|
```diff
|
|
- const validPassword = await verifyPassword(password, user.password_hash);
|
|
+ const validPassword = await verifyPassword(password, user.passwordHash);
|
|
```
|
|
|
|
## ✅ 테스트 시나리오
|
|
|
|
이제 다음 시나리오가 모두 정상 작동합니다:
|
|
|
|
### 1. 회원가입 → 자동 로그인
|
|
```
|
|
1. /register 페이지 접속
|
|
2. 정보 입력 (예: test@test.com / 123456 / 테스터)
|
|
3. 회원가입 버튼 클릭
|
|
4. ✅ 자동으로 로그인되어 메인 페이지로 이동
|
|
```
|
|
|
|
### 2. 로그아웃 → 재로그인
|
|
```
|
|
1. 로그아웃 버튼 클릭
|
|
2. /login 페이지로 이동
|
|
3. 동일한 정보 입력 (test@test.com / 123456)
|
|
4. 로그인 버튼 클릭
|
|
5. ✅ 정상 로그인되어 메인 페이지로 이동
|
|
```
|
|
|
|
## 🎯 Drizzle ORM 필드명 규칙
|
|
|
|
Drizzle ORM은 다음과 같이 필드명을 처리합니다:
|
|
|
|
### 데이터베이스 컬럼 (snake_case)
|
|
```sql
|
|
CREATE TABLE users (
|
|
id INTEGER PRIMARY KEY,
|
|
password_hash TEXT NOT NULL -- DB는 snake_case
|
|
);
|
|
```
|
|
|
|
### TypeScript 타입 (camelCase)
|
|
```typescript
|
|
// Drizzle가 자동으로 camelCase로 변환
|
|
type User = {
|
|
id: number;
|
|
passwordHash: string; // TypeScript는 camelCase
|
|
}
|
|
```
|
|
|
|
### 올바른 사용법
|
|
|
|
```typescript
|
|
// ✅ 올바른 방법
|
|
const user = await getUserByEmail(db, email);
|
|
console.log(user.passwordHash); // camelCase
|
|
|
|
// ❌ 잘못된 방법
|
|
console.log(user.password_hash); // undefined!
|
|
```
|
|
|
|
## 📝 추가 확인 사항
|
|
|
|
다른 파일들도 확인했지만 모두 올바르게 작성되어 있습니다:
|
|
|
|
### ✅ hooks.server.ts
|
|
```typescript
|
|
event.locals.user = {
|
|
id: user.id, // ✅ 올바름
|
|
email: user.email, // ✅ 올바름
|
|
nickname: user.nickname // ✅ 올바름
|
|
};
|
|
```
|
|
|
|
### ✅ db.ts
|
|
```typescript
|
|
const newUser: NewUser = {
|
|
email,
|
|
passwordHash, // ✅ camelCase 사용
|
|
nickname
|
|
};
|
|
```
|
|
|
|
## 🚀 실행 방법
|
|
|
|
수정사항이 이미 빌드되었으므로 바로 실행 가능합니다:
|
|
|
|
```bash
|
|
pnpm cf:dev
|
|
```
|
|
|
|
그런 다음:
|
|
1. http://localhost:8787/register - 새 계정 생성
|
|
2. 로그아웃
|
|
3. http://localhost:8787/login - 재로그인
|
|
4. ✅ 정상 작동 확인!
|
|
|
|
## 🎓 교훈
|
|
|
|
### Drizzle ORM 사용 시 주의사항
|
|
|
|
1. **스키마 정의 시 camelCase 사용**
|
|
```typescript
|
|
passwordHash: text('password_hash') // TypeScript는 camelCase
|
|
```
|
|
|
|
2. **코드에서도 camelCase로 접근**
|
|
```typescript
|
|
user.passwordHash // ✅ 올바름
|
|
user.password_hash // ❌ undefined
|
|
```
|
|
|
|
3. **TypeScript 타입 활용**
|
|
```typescript
|
|
// 타입 추론을 사용하면 오타 방지
|
|
const hash: string = user.passwordHash;
|
|
```
|
|
|
|
## 🎉 완료!
|
|
|
|
로그인 버그가 수정되었습니다!
|
|
|
|
**수정 사항:**
|
|
- ✅ `user.password_hash` → `user.passwordHash`로 변경
|
|
- ✅ 빌드 성공
|
|
- ✅ 테스트 준비 완료
|
|
|
|
**이제 정상 작동합니다:**
|
|
- ✅ 회원가입 → 자동 로그인
|
|
- ✅ 로그아웃 → 재로그인
|
|
- ✅ 비밀번호 검증 정상 작동
|
|
|
|
즐거운 개발 되세요! 🚀
|
|
|