BookLog 엔터티 구조 설계 및 구현 완료 보고서
작업 결과: 29개 엔터티 + 10개 Enum 생성 완료 (총 39개 파일)
1. 생성된 엔터티 목록
1. users 도메인 (4개 엔터티 + 2개 Enum)
| 엔터티 |
파일명 |
책임 |
주요 필드 |
| Users |
Users.java |
사용자 기본 정보 |
id, nickname, profileImageUrl, status |
| AuthAccounts |
AuthAccounts.java |
소셜 로그인 계정 |
id, userId, provider, providerId |
| UserSettings |
UserSettings.java |
사용자 설정 (1:1) |
userId, isShelfPublic, isPostPublic |
| UserFollows |
UserFollows.java |
팔로우 관계 (복합키) |
followerId, followeeId, followedAt |
Enum 타입:
UserStatus.java: ACTIVE / INACTIVE / DELETED
AuthProvider.java: GOOGLE / NAVER / KAKAO / LOCAL
2. library.books 도메인 (7개 엔터티 + 2개 Enum)
| 엔터티 |
파일명 |
책임 |
주요 필드 |
| Books |
Books.java |
도서 메타 정보 (외부 API 캐싱) |
id, title, isbn13, publisherId, source, rawData |
| Authors |
Authors.java |
작가 정보 |
id, name, biography, wikidataId |
| BookAuthors |
BookAuthors.java |
도서-작가 매핑 (복합키) |
bookId, authorId, role, displayOrder |
| AuthorAwards |
AuthorAwards.java |
작가 수상 이력 |
id, authorId, awardName, year |
| Genres |
Genres.java |
장르 마스터 |
id, name |
| BookGenres |
BookGenres.java |
도서-장르 매핑 (복합키) |
bookId, genreId |
| Publishers |
Publishers.java |
출판사 |
id, name |
Enum 타입:
BookSource.java: KAKAO / NAVER / ALADIN / MANUAL
AuthorRole.java: AUTHOR / TRANSLATOR
3. library.shelves 도메인 (4개 엔터티 + 2개 Enum)
| 엔터티 |
파일명 |
책임 |
주요 필드 |
| UserBooks |
UserBooks.java |
핵심! 사용자별 독서 기록 |
id, userId, bookId, status, progress |
| Shelves |
Shelves.java |
서재/폴더 |
id, userId, name, isPublic |
| ShelfBooks |
ShelfBooks.java |
서재-도서 매핑 (복합키) |
shelfId, userBookId, addedAt |
| ReadingLogs |
ReadingLogs.java |
일별 독서 기록 |
id, userBookId, logDate, pagesRead |
Enum 타입:
ReadingStatus.java: PLANNING / READING / COMPLETED / STOPPED
MediaType.java: PAPER / EBOOK / AUDIO
4. tags 도메인 (2개 엔터티 + 1개 Enum)
| 엔터티 |
파일명 |
책임 |
주요 필드 |
| Tags |
Tags.java |
태그 마스터 (분위기/문체/몰입도) |
id, category, name |
| BookTags |
BookTags.java |
도서-태그 매핑 (복합키) |
userBookId, tagId |
Enum 타입:
TagCategory.java: MOOD / STYLE / IMMERSION
5. posts 도메인 (6개 엔터티 + 1개 Enum)
| 엔터티 |
파일명 |
책임 |
주요 필드 |
| Posts |
Posts.java |
북로그 게시글 |
id, userId, userBookId, status, content |
| PostImages |
PostImages.java |
게시글 이미지 |
id, postId, imageUrl, displayOrder |
| Comments |
Comments.java |
댓글 (대댓글 지원) |
id, postId, userId, parentCommentId |
| PostLikes |
PostLikes.java |
좋아요 (복합키) |
postId, userId, likedAt |
| PostBookmarks |
PostBookmarks.java |
북마크 (복합키) |
postId, userId, bookmarkedAt |
| PostViews |
PostViews.java |
조회수 추적 |
id, postId, userId, sessionId |
Enum 타입:
PostStatus.java: DRAFT / PUBLISHED
6. onboarding 도메인 (4개 엔터티 + 1개 Enum)
| 엔터티 |
파일명 |
책임 |
주요 필드 |
| OnboardingQuestions |
OnboardingQuestions.java |
온보딩 질문 |
id, questionKey, questionType |
| OnboardingOptions |
OnboardingOptions.java |
온보딩 선택지 |
id, questionId, optionKey, label |
| UserOnboardingAnswers |
UserOnboardingAnswers.java |
사용자 답변 (복합키) |
userId, questionId, optionId |
| UserOnboardingStatus |
UserOnboardingStatus.java |
온보딩 완료 상태 (1:1) |
userId, isCompleted, isSkipped |
Enum 타입:
QuestionType.java: SINGLE / MULTI
7. ai 도메인 (1개 엔터티)
| 엔터티 |
파일명 |
책임 |
주요 필드 |
| AiBookInsights |
AiBookInsights.java |
AI 기반 도서 인사이트 |
id, userId, userBookId, insightType |
8. search 도메인 (1개 엔터티)
| 엔터티 |
파일명 |
책임 |
주요 필드 |
| SearchHistory |
SearchHistory.java |
최근 검색어 (선택적) |
id, userId, keyword, searchedAt |
참고: 프론트엔드 localStorage로 처리 검토 대상
2. 기존 디렉토리 구조 변경 사항
📁 변경 전 (기존 구조)
domain/library/books/entity/
├── common/
│ ├── Authors.java
│ ├── AuthorRole.java
│ ├── AuthorRewards.java
│ └── Genres.java
└── mapping/
└── BookAuthors.java
📁 변경 후 (신규 구조)
domain/library/books/entity/
├── Books.java
├── BookSource.java
├── Authors.java
├── AuthorRole.java
├── AuthorAwards.java ← AuthorRewards에서 이름 변경
├── BookAuthors.java ← mapping에서 이동
├── Genres.java
├── BookGenres.java
└── Publishers.java
변경 이유
-
패키지 구조 단순화
common/, mapping/ 서브 패키지 제거
- 모든 엔터티를
entity/ 직접 하위에 배치
- import 경로 단순화:
entity.common.Authors → entity.Authors
-
ERD 명명 규칙 통일
- ERD에서
author_awards → AuthorAwards (일관성)
- 기존
AuthorRewards에서 변경
-
도메인별 분리 명확화
library.books: 도서 메타데이터 관련
library.shelves: 사용자 독서 기록 관련
tags: 태그 관련 (별도 도메인)
3. 수정된 파일 목록 및 이유
🔧 신규 생성 엔터티 (29개)
모든 엔터티는 ERDCloud SQL을 기반으로 JPA 엔터티로 변환하여 새로 생성되었습니다.
🔧 기존 파일 수정 (7개)
1. Books.java
수정 이유: 기존 서비스와 호환성 유지
// 추가된 필드
@Column(name = "publisher_name", length = 255)
private String publisherName;
@OneToMany(mappedBy = "book", cascade = CascadeType.ALL, orphanRemoval = true)
private List<BookAuthors> bookAuthors = new ArrayList<>();
// 추가된 메서드
public LocalDateTime getPublishedAt() {
return this.publishedDate;
}
public void updateBasicInfo(...) // BookImportService 호환
public void replaceBookAuthors(...) // BookAuthors 관리
변경 내용:
publisherName 필드 추가 (BookSearchConverter 호환)
bookAuthors 양방향 관계 추가
getPublishedAt() getter 추가
updateBasicInfo(), replaceBookAuthors() 비즈니스 메서드 추가
2. Authors.java
수정 이유: Wikidata 연동 기능 지원
// 추가된 필드
@Column(name = "wikidata_id", length = 20)
private String wikidataId;
@Column(name = "wikidata_raw_json", columnDefinition = "TEXT")
private String wikidataRawJson;
// 추가된 메서드
public boolean hasWikidataId() { ... }
public void applyWikidataEnrichment(AuthorWikidataEnrichment enrichment) { ... }
public static Authors ofName(String name) { ... }
변경 내용:
- Wikidata 관련 필드 추가 (작가 정보 자동 보강)
- 정적 팩토리 메서드 추가
- 메타데이터 적용 메서드 추가
3. BookAuthors.java
수정 이유: 새로운 엔터티 구조로 재작성
// 위치 변경: entity/mapping/ → entity/
// 복합키 전략: @EmbeddedId → @IdClass
@IdClass(BookAuthors.BookAuthorId.class)
public class BookAuthors {
@Id private Long bookId;
@Id private Long authorId;
@Id private AuthorRole role;
// 양방향 관계 지원
public void setBook(Books book) { ... }
}
변경 내용:
- 복합키 구조 변경 (기존 단일 ID → 복합키)
- Books와 양방향 관계 설정
displayOrder 필드 추가 (정렬 순서)
4. BooksRepository.java
수정 이유: 필드명 변경 반영
// 변경 전
Optional<Books> findByKakaoUrl(String kakaoUrl);
// 변경 후
Optional<Books> findByDetailUrl(String detailUrl);
변경 내용:
- Books 엔터티 필드명에 맞게 수정 (
kakaoUrl → detailUrl)
5. AuthorsRepository.java
수정 이유: import 경로 수정
// 변경 전
import com.example.booklog.domain.library.books.entity.common.Authors;
// 변경 후
import com.example.booklog.domain.library.books.entity.Authors;
변경 내용:
- 패키지 구조 변경에 따른 import 경로 수정
6. GenresRepository.java
수정 이유: import 경로 수정
// 변경 전
import com.example.booklog.domain.library.books.entity.common.Genres;
// 변경 후
import com.example.booklog.domain.library.books.entity.Genres;
7. AuthorRewardRepository.java
수정 이유: 엔터티명 변경 및 메서드 수정
// 변경 전
import com.example.booklog.domain.library.books.entity.common.AuthorRewards;
public interface AuthorRewardRepository extends JpaRepository<AuthorRewards, Long> {
List<AuthorRewards> findAllByAuthor_AuthorId(Long authorId);
}
// 변경 후
import com.example.booklog.domain.library.books.entity.AuthorAwards;
public interface AuthorRewardRepository extends JpaRepository<AuthorAwards, Long> {
List<AuthorAwards> findAllByAuthor_Id(Long authorId);
}
변경 내용:
AuthorRewards → AuthorAwards (ERD 통일)
- 연관관계 메서드명 수정 (
Author_AuthorId → Author_Id)
8. BookImportService.java
수정 이유: 새 엔터티 구조 반영
// import 경로 수정
import com.example.booklog.domain.library.books.entity.BookSource;
import com.example.booklog.domain.library.books.entity.AuthorRole;
import com.example.booklog.domain.library.books.entity.Authors;
import com.example.booklog.domain.library.books.entity.BookAuthors;
// BookAuthors 생성 시 book 파라미터 추가
mappings.add(BookAuthors.builder()
.book(book) // ← 추가
.author(author)
.role(AuthorRole.AUTHOR)
.displayOrder(order++)
.build());
// Authors 생성
Authors.builder().name(normalized).build()
변경 내용:
- import 경로 전면 수정
- BookAuthors 빌더에
book 파라미터 추가
sortOrder → displayOrder 사용
9. AuthorEnrichmentService.java
수정 이유: import 경로 수정
// 변경 전
import com.example.booklog.domain.library.books.entity.common.Authors;
// 변경 후
import com.example.booklog.domain.library.books.entity.Authors;
🗑️ 삭제된 디렉토리 및 파일
✅ 삭제: domain/library/books/entity/common/
├── Authors.java (신규 entity/Authors.java로 대체)
├── AuthorRole.java (신규 entity/AuthorRole.java로 대체)
├── AuthorRewards.java (AuthorAwards로 이름 변경)
└── Genres.java (신규 entity/Genres.java로 대체)
✅ 삭제: domain/library/books/entity/mapping/
└── BookAuthors.java (신규 entity/BookAuthors.java로 대체)
삭제 이유:
- 패키지 구조 단순화
- 중복 파일 제거
- ERD 기반 신규 엔터티로 완전 대체
4. 핵심 설계 특징
JPA Best Practice 적용
-
BaseEntity 상속
public abstract class BaseEntity {
@CreatedDate
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;
}
-
복합키 패턴 통일
@IdClass(BookAuthors.BookAuthorId.class)
public class BookAuthors {
@Id private Long bookId;
@Id private Long authorId;
@Id private AuthorRole role;
public static class BookAuthorId implements Serializable {
// equals, hashCode 구현
}
}
-
1:1 관계 최적화
@OneToOne(fetch = FetchType.LAZY)
@MapsId
public class UserSettings {
@Id
private Long userId;
}
-
Enum 활용
- 10개 Enum으로 상태 관리 명확화
- DB에는
VARCHAR로 저장 (@Enumerated(EnumType.STRING))
연관관계 설계 원칙
| 관계 유형 |
매핑 방식 |
예시 |
| 1:N |
@ManyToOne 단방향 우선 |
UserBooks → Users |
| N:M |
중간 엔터티 + 복합키 |
BookAuthors (Books ↔ Authors) |
| 1:1 |
@OneToOne + @MapsId |
UserSettings ↔ Users |
기본 원칙:
FetchType.LAZY 기본값
- 단방향 관계 우선, 양방향은 필요시만
- FK 명시적 네이밍 (
fk_테이블_참조테이블)
5. 최종 통계
| 항목 |
개수 |
비고 |
| 총 엔터티 |
29개 |
BaseEntity 상속 |
| 총 Enum |
10개 |
상태 관리용 |
| 복합키 엔터티 |
9개 |
@IdClass 패턴 |
| 1:1 관계 |
2개 |
@mapsid 사용 |
| 새로 생성된 파일 |
39개 |
엔터티 + Enum |
| 수정된 파일 |
9개 |
Service, Repository |
| 삭제된 디렉토리 |
2개 |
common/, mapping/ |
📦 패키지 구조
domain/
├── users/entity/ (4 entities + 2 enums)
├── library/
│ ├── books/entity/ (7 entities + 2 enums)
│ └── shelves/entity/ (4 entities + 2 enums)
├── tags/
│ ├── entity/ (1 entity + 1 enum)
│ └── mapping/ (1 entity)
├── posts/entity/ (6 entities + 1 enum)
├── onboarding/entity/ (4 entities + 1 enum)
├── ai/entity/ (1 entity)
└── search/entity/ (1 entity)
해결된 이슈
- import 경로 불일치로 인한 컴파일 에러 해결
- 중복 엔터티 파일 제거
- ERD 명명 규칙 통일 (AuthorRewards → AuthorAwards)
BookLog 엔터티 구조 설계 및 구현 완료 보고서
작업 결과: 29개 엔터티 + 10개 Enum 생성 완료 (총 39개 파일)
1. 생성된 엔터티 목록
1. users 도메인 (4개 엔터티 + 2개 Enum)
Users.javaAuthAccounts.javaUserSettings.javaUserFollows.javaEnum 타입:
UserStatus.java: ACTIVE / INACTIVE / DELETEDAuthProvider.java: GOOGLE / NAVER / KAKAO / LOCAL2. library.books 도메인 (7개 엔터티 + 2개 Enum)
Books.javaAuthors.javaBookAuthors.javaAuthorAwards.javaGenres.javaBookGenres.javaPublishers.javaEnum 타입:
BookSource.java: KAKAO / NAVER / ALADIN / MANUALAuthorRole.java: AUTHOR / TRANSLATOR3. library.shelves 도메인 (4개 엔터티 + 2개 Enum)
UserBooks.javaShelves.javaShelfBooks.javaReadingLogs.javaEnum 타입:
ReadingStatus.java: PLANNING / READING / COMPLETED / STOPPEDMediaType.java: PAPER / EBOOK / AUDIO4. tags 도메인 (2개 엔터티 + 1개 Enum)
Tags.javaBookTags.javaEnum 타입:
TagCategory.java: MOOD / STYLE / IMMERSION5. posts 도메인 (6개 엔터티 + 1개 Enum)
Posts.javaPostImages.javaComments.javaPostLikes.javaPostBookmarks.javaPostViews.javaEnum 타입:
PostStatus.java: DRAFT / PUBLISHED6. onboarding 도메인 (4개 엔터티 + 1개 Enum)
OnboardingQuestions.javaOnboardingOptions.javaUserOnboardingAnswers.javaUserOnboardingStatus.javaEnum 타입:
QuestionType.java: SINGLE / MULTI7. ai 도메인 (1개 엔터티)
AiBookInsights.java8. search 도메인 (1개 엔터티)
SearchHistory.java2. 기존 디렉토리 구조 변경 사항
📁 변경 전 (기존 구조)
📁 변경 후 (신규 구조)
변경 이유
패키지 구조 단순화
common/,mapping/서브 패키지 제거entity/직접 하위에 배치entity.common.Authors→entity.AuthorsERD 명명 규칙 통일
author_awards→AuthorAwards(일관성)AuthorRewards에서 변경도메인별 분리 명확화
library.books: 도서 메타데이터 관련library.shelves: 사용자 독서 기록 관련tags: 태그 관련 (별도 도메인)3. 수정된 파일 목록 및 이유
🔧 신규 생성 엔터티 (29개)
모든 엔터티는 ERDCloud SQL을 기반으로 JPA 엔터티로 변환하여 새로 생성되었습니다.
🔧 기존 파일 수정 (7개)
1.
Books.java수정 이유: 기존 서비스와 호환성 유지
변경 내용:
publisherName필드 추가 (BookSearchConverter 호환)bookAuthors양방향 관계 추가getPublishedAt()getter 추가updateBasicInfo(),replaceBookAuthors()비즈니스 메서드 추가2.
Authors.java수정 이유: Wikidata 연동 기능 지원
변경 내용:
3.
BookAuthors.java수정 이유: 새로운 엔터티 구조로 재작성
변경 내용:
displayOrder필드 추가 (정렬 순서)4.
BooksRepository.java수정 이유: 필드명 변경 반영
변경 내용:
kakaoUrl→detailUrl)5.
AuthorsRepository.java수정 이유: import 경로 수정
변경 내용:
6.
GenresRepository.java수정 이유: import 경로 수정
7.
AuthorRewardRepository.java수정 이유: 엔터티명 변경 및 메서드 수정
변경 내용:
AuthorRewards→AuthorAwards(ERD 통일)Author_AuthorId→Author_Id)8.
BookImportService.java수정 이유: 새 엔터티 구조 반영
변경 내용:
book파라미터 추가sortOrder→displayOrder사용9.
AuthorEnrichmentService.java수정 이유: import 경로 수정
🗑️ 삭제된 디렉토리 및 파일
삭제 이유:
4. 핵심 설계 특징
JPA Best Practice 적용
BaseEntity 상속
복합키 패턴 통일
1:1 관계 최적화
Enum 활용
VARCHAR로 저장 (@Enumerated(EnumType.STRING))연관관계 설계 원칙
@ManyToOne단방향 우선@OneToOne+@MapsId기본 원칙:
FetchType.LAZY기본값fk_테이블_참조테이블)5. 최종 통계
📦 패키지 구조
해결된 이슈