user-service 개발 요약
✅ 전체 흐름
- TekaPicker 프로젝트 내 user-service 개발 진행
- NestJS 기반의 gRPC 서비스로 회원가입/로그인 기능 구현 목표
- PostgreSQL + TypeORM + bcrypt + JWT 기반 인증 시스템 설계
- gRPC 클라이언트로는 BloomRPC 사용
- 개발 중 상태 유지 및 보안 고려 위해 .env 도입
✅ 초기 환경 설정
- NestJS 모노레포 구조 생성 실패 → 수동으로 apps/user 앱 생성
npx nest g app user 로 apps/user 생성
npx nest g lib database 로 libs/database 생성 → TypeORM 연동용
- PostgreSQL 컨테이너 띄움 (
teka-postgres)
- DBeaver로 DB 확인
typeorm + @nestjs/typeorm + pg 설치
✅ Database 연동
User 엔티티 생성 (id, email, password, createdAt)
@PrimaryGeneratedColumn('uuid') → UUID 기본 키 생성
@CreateDateColumn() → 자동 createdAt 처리
DatabaseModule에 TypeOrmModule.forRoot(...) 설정
UserModule에 TypeOrmModule.forFeature([User]) 설정 → 레포지토리 주입 가능
🔍 핵심 개념
forRoot() → 전체 커넥션 연결
forFeature() → 특정 모듈에서 레포지토리 주입 허용
@InjectRepository(User) → Repository 주입 요청
✅ 회원가입 기능 (SignUp)
- gRPC proto 작성 (
SignUpRequest, UserResponse)
apps/user/src/user.proto 정의 후 copy:proto 스크립트로 dist에 복사
bcrypt 설치 → 비밀번호 해싱 구현
- 중복 이메일 확인 (
findOne)
bcrypt.hash(password, 10) 사용
- 해싱된 비밀번호로 DB 저장
- JWT 토큰 발급 (
jwt.sign(payload, secret, { expiresIn: '1h' }))
- 응답으로
id, email, accessToken 반환
- 에러 처리 시
RpcException 사용 → gRPC 에러 코드 명시
✅ 로그인 기능 (Login)
LoginRequest, LoginResponse 추가
- DB에서 이메일로 유저 검색
bcrypt.compare()로 비밀번호 비교
- 일치 시 JWT 토큰 재발급
- 불일치 시
RpcException({ code: 16 }) → UNAUTHENTICATED
- 로그인 성공 시 동일한 형식으로 응답 반환
✅ .env 처리
apps/user/.env 생성 후 JWT_SECRET 저장
dotenv.config({ path: resolve(...) })로 경로 명시적 지정
- 실행 위치 따라
../../../../apps/user/.env 등 상대 경로 조정 필요
.env 로딩 확인 위해 console.log(process.env.JWT_SECRET) 사용
✅ BloomRPC 테스트
- proto 로딩 후 gRPC 메서드 노출 확인
- SignUp / Login 테스트 완료
- 토큰 반환 확인
- 오류 발생 시 RpcException 메시지 출력 확인
✅ 개발 스크립트
"scripts": {
"build:user": "nest build user",
"start:user": "node dist/apps/user/src/main.js",
"dev:user": "ts-node-dev --respawn --transpile-only apps/user/src/main.ts",
"copy:proto": "cp apps/user/src/proto/user.proto dist/apps/user/src/user.proto"
}
✅ 최종 상태
- 회원가입 기능 구현 완료
- 로그인 기능 구현 완료
- JWT 기반 인증 플로우 구축
- gRPC 기반 user-service 인증 기능 완성
- 프론트엔드 연동 전 단계까지 완료