사용자 프로필·팔로우·뱃지·이미지 관리를 담당하는 독서 게이미피케이션 플랫폼 Frolog의 프로필 도메인 서비스입니다.
닉네임·자기소개·프로필 이미지 CRUD, 팔로우/팔로워 시스템, 개구리(뱃지) 수집, 프로필 이미지 WebP 변환 및 S3 업로드, 개인 정보 암호화 저장, 사용자 활동 피드 집계를 처리합니다.
- 프로필 생성·수정·삭제
- 닉네임 중복 체크 및 자동 생성 ("형용사+명사+숫자" 패턴)
- 독서 취향 설정 (reading_preference)
- 자기소개 설정 (기본값 랜덤 할당)
- 프로필 이미지 업로드 (JPEG/PNG → WebP 200x200px, 최대 10MB)
- 이미지 저장소 마이그레이션 (DB → S3)
- 이미지 중복 제거 (SHA256 해시)
- 개인정보 암호화 저장 (PII_SECRET, 공개/비공개 설정)
- 팔로우/언팔로우 (양방향 관계)
- 팔로워/팔로잉 목록 조회 (페이지네이션)
- 개구리(뱃지) 부여·조회·소유 확인
- 사용자 활동 피드 (메모/리뷰 통계, ISBN별 집계)
- 계정 삭제 및 도서 콘텐츠 일괄 삭제
- Node.js (ESM), Express 기반
@frolog/express-api-server - ORM: Sequelize (
@frolog/models) - 공통 유틸:
@frolog/common-utils(로거, HashId, 암호화 등) - API 계약:
@frolog/frolog-api - 이미지 처리:
sharpv0.33.5 (WebP 변환),image-typev5.2.0 (MIME 타입 감지) - 스토리지: AWS S3 (
aws-sdkv2.1692.0) - Lint/Format: ESLint, Prettier
npm install
npm run dev # 개발 (nodemon)
npm start # 프로덕션
npm run lint # 코드 규칙 검사
npm run doc # JSDoc 생성src/
index.js # API 서버 부트스트랩 및 라우팅
common/
constants.js # PII 암호화 상수
utils.js # 닉네임 검증 유틸
s3.js # AWS S3 클라이언트 (파일 업로드/존재 확인)
services/
postProfile.js # 프로필 생성 (닉네임 자동 생성, 기본 개구리 부여)
getProfile.js # 프로필 조회 (공개 정보)
getProfileDetail.js # 프로필 상세 조회 (개인정보 포함)
editProfile.js # 프로필 수정 (닉네임, 자 기소개, 이미지 등)
deleteProfile.js # 프로필 삭제
deleteUserBookContent.js # 사용자 도서 콘텐츠 삭제 (리뷰/메모/우물 아이템)
getUsernameAvailability.js # 닉네임 중복 체크
uploadProfileImage.js # 이미지 업로드 (WebP 변환, DB 저장)
uploadProfileImageToS3.js # 이미지 S3 마이그레이션 (DB → S3)
deleteProfileImage.js # 이미지 삭제 (DB)
checkProfileImageExists.js # 이미지 위치 확인 (S3 우 선, DB 폴백)
followUser.js # 팔로우/언팔로우 (upsert)
getUserFollowers.js # 팔로워 목록 조회
getUserFollowings.js # 팔로잉 목록 조회
grantFrog.js # 개구리(뱃지) 부여 (관리 자)
getFrogs.js # 개구리 목록 조회
getFrogAvailability.js # 개구리 소유 확인
getProfileFeed.js # 사용자 활동 피드 (메모/ 리뷰 집계)src/index.js에서 @frolog/frolog-api 스펙과 서비스 로직을 매핑합니다.
- GET: GetUsernameAvailability (공개), GetProfile (공개), GetProfileDetail (공개), GetUserFollowings (공개), GetUserFollowers (공개), GetFrogs (login), GetProfileFeed (login)
- POST: PostProfile (admin), UploadProfileImage (login), FollowUser (login), GetFrogAvailability (login), GrantFrog (admin)
- PUT: EditProfile (login)
- DELETE: DeleteProfile (admin), DeleteUserBookContent (login)
없음. 이미지 S3 마이그레이션은 프로필 수정 시 온디맨드로 실행됩니다.
- GetUsernameAvailability, GetProfile, GetProfileDetail, GetUserFollowings, GetUserFollowers: 공개 API (인증 불필요)
- 개인정보는 공개 설정 및 소유자/관리자 권한에 따라 필터링
- GetFrogs, GetFrogAvailability, GetProfileFeed, UploadProfileImage, EditProfile, FollowUser: 로그인 필수
- PostProfile, DeleteProfile, GrantFrog: 관리자 전용 (is_admin=true)
- 소유자 검증: 프로필 수정·삭제 시 user_id 일치 확인
- HashId 인코딩: 모든 ID는 해시 형식으로 처리
닉네임 자동 생성
- 사용자가 닉네임 제공 시: 중복 체크 후 사용
- 닉네임 미제공 시:
- Adjective 테이블에서 랜덤 형용사 선택
- Noun 테이블에서 랜덤 명사 선택
- 숫자 3자리 생성 (기존 최대값 + 1)
- 패턴: "{형용사}{명사}{숫자}" (예: "ShinyFrog123")
초기 설정
- DefaultSelfIntro 테이블에서 랜덤 자기소개 할당
- 기본 개구리(뱃지) 자동 부여
- reading_preference 선택적 설정
업로드 플로우
- 사용자 이미지 업로드 (JPEG/PNG 등)
- MIME 타입 감지 및 검증 (최대 10MB)
- SHA256 해시 계산 (중복 제거용)
- DB 조회: 기존 해시 존재 시 재사용
- 신규 이미지: WebP 변환 (sharp, 200x200px, lossless)
- ProfileImage 테이블에 저장 (hash, data, mime_type)
- 프로필 수정 시: S3로 마이그레이션
- S3 업로드 후 DB에서 삭제
저장소 위치
- S3 경로: profile/{hash}.webp
- 우선순위: S3 확인 → DB 폴백
- 중복 방지: SHA256 해시 기반 deduplication
WebP 변환
- sharp 라이브러리 사용
- 200x200px 리사이징
- lossless 압축
- 원본 MIME 타입 보존 (메타데이터)
구조
- UserFollow: 양방향 팔로우 관계 테이블
- follower_id: 팔로우하는 사용자
- following_id: 팔로우되는 사용자
기능
- 팔로우/언팔로우 (upsert 패턴)
- 팔로워 수·팔로잉 수 집계
- 프로필 조회 시 팔로우 상태 포함
조회
- 페이지네이션 지원 (limit: 1-100, 기본값 10)
- 팔로워/팔로잉 목록 반환
구조
- UserFrog: 사용자별 획득 뱃지 테이블
- frog_key: 뱃지 고유 키
- granted_at: 획득 시각
기능
- 관리자가 뱃지 부여 (GrantFrog)
- 사용자 뱃지 목록 조회 (GetFrogs)
- 특정 뱃지 소유 확인 (GetFrogAvailability)
- 프로필 생성 시 기본 뱃지 자동 부여
구조
- Memo, Review, Well, WellItem 테이블 집계
- ISBN별 그룹화
- 메모 수·리뷰 수·마지막 활동 시각 포함
기능
- 페이지네이션 지원 (limit: 1-100, 기본값 10)
- 도서 정보 연동 (book-service)
- 우물 정보 연동 (well-service)
주요 모델
Profile
- user_id (PK, FK), username (unique), self_intro
- reading_preference, max_height
- profile_image_hash, created_at, updated_at
UserFollow
- follower_id (FK), following_id (FK) - 복합 PK
- created_at
UserFrog
- user_id (FK), frog_key (FK) - 복합 PK
- granted_at
ProfileImage
- hash (SHA256, PK), data (WebP 바이너리), mime_type (원본 MIME)
PersonalInfo
- user_id (FK), type, encrypted_data, is_public
- created_at, updated_at
- Book Service: ISBN으로 도서 정보 조회
- Well Service: 사용자 우물 정보 조회
- Memo/Review Service: 사용자 활동 데이터 조회
- SSC_TOKEN: 서비스 간 인증 토큰
아래 별표(*)를 제외한 환경변수는 선택적 필드입니다.
NODE_ENV: Node 동작 환경.SERVICE_NAME: 서비스 ID.NODE_PORT또는PORT: HTTP 서버 포트.
-
@frolog/models 참고.
-
(*)
S3_ACCESS_KEY_ID: S3 버킷 액세스 키 ID. -
(*)
S3_SECRET_ACCESS_KEY: S3 버킷 액세스 키. -
(*)
S3_REGION: S3 AWS 지역. -
(*)
S3_IMAGES_BUCKET: S3 이미지 버킷명.
JWT_PUBLIC_KEY: JWT 액세스 토큰 공개 키.SSC_TOKEN: 사전에 발급받은 서비스 간 통신 액세스 토큰.HASHIDS_SALT: Hashids 솔트.PII_SECRET: PII 암호화 대칭 키.