프로젝트를 진행하면서, 실제 서비스를 위한 데이터가 아직 준비되지 않았거나 테스트 목적으로 대량의 데이터가 필요한 경우가 종종 있다.
이럴 때 사용하는 것이 바로 더미 데이터이다.
더미 데이터는 실제 데이터와 비슷한 형태로 만들어진 가짜 데이터로, 개발을 진행하면서 다양한 시나리오를 시험하거나 성능을 체크하는데 사용된다.
이번 글에서는 이런 더미 데이터의 생성 방법에 대해 자세히 알아보도록 하겠다.
ddl-auto
먼저 ddl-auto에 대해 알아야 한다.
ddl-auto는 Spring Boot의 JPA 설정에서 사용되는 속성 중 하나이다.
이 속성은 데이터베이스 스키마 생성 전략을 설정하는 데 사용되며, 다음과 같은 옵션들을 제공한다.
none : 기본 설정값으로, Hibernate가 데이터베이스 스키마를 생성하지 않는다.
validate : Hibernate가 애플리케이션을 실행할 때 Entity와 데이터베이스 테이블이 일치하는지 확인한다.
update : 데이터베이스 스키마를 애플리케이션 실행 시 자동으로 수정하도록 한다. 만약 Entity에 새로운 필드가 추가되면, 이에 대한 새로운 컬럼이 데이터베이스 테이블에 추가된다.
create : 애플리케이션 실행 시마다 데이터베이스 스키마를 생성하고, 종료 시에는 스키마를 삭제한다.
create-drop : create 옵션과 비슷하지만, 애플리케이션 종료 시에 데이터베이스 스키마를 삭제한다.
application.yml 설정
jpa:
hibernate:
ddl-auto: create-drop
defer-datasource-initialization: true
sql:
init:
data-locations: classpath*:db/data.sql
mode: always
platform: h2
ddl-auto: create-drop: 이 옵션은 Hibernate가 자동으로 테이블을 생성하고, 애플리케이션 종료시 테이블을 삭제하게 한다.
defer-datasource-initialization: true: 이 설정은 Spring Boot가 데이터 소스 초기화를 지연시키도록 한다. 이는 JPA 엔티티를 데이터베이스 스키마에 매핑하기 전에 SQL 스크립트를 실행할 수 있게 한다.
sql.init.data-locations: classpath*:db/data.sql: 이 설정은 더미 데이터를 삽입하기 위한 SQL 스크립트의 위치를 지정한다. 이 파일은 애플리케이션 시작 시 자동으로 실행된다.
위치를 지정해주지 않는다면 hibernate에서 resources 폴더에 import.sql을 알아서 찾아 실행시킨다.
sql.init.mode: always: 이 설정은 애플리케이션 재시작마다 SQL 스크립트를 실행하게 한다.
sql.init.platform: h2: 이 설정은 SQL 스크립트가 실행될 데이터베이스 플랫폼을 지정한다. 여기서는 H2 데이터베이스가 선택되었다.
이렇게 설정 해주면 더미데이터를 사용하기 위한 준비는 끝났다.
data.sql 파일 생성
다음과 같은 review 테이블이 있다면
@NoArgsConstructor
@Getter
@Setter
@Entity
public class Review extends Auditable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long reviewId;
private String title;
private String content;
private double rating;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "MEMBER_ID")
private Member member;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ITEM_ID")
private Item item;
@OneToMany(mappedBy = "review",cascade = CascadeType.ALL)
private List<ReviewImage> reviewImages = new ArrayList<>();
public void addImage(List<ReviewImage> images){
for (ReviewImage image : images) {
reviewImages.add(image);
if(image.getReview() != this){
image.setReview(this);
}
}
}
public void addMember(Member member){
this.member = member;
if(!member.getReviews().contains(this)){
member.getReviews().add(this);
}
}
public void addItem(Item item){
this.item = item;
if(!item.getReviews().contains(this)) {
item.getReviews().add(this);
}
}
// 기존에 연결된 이미지 모두 제거 하고 연결 정보 업데이트
public void clearImages() {
reviewImages.forEach(image -> image.setReview(null));
reviewImages.clear();
}
}
INSERT INTO review (CREATED_AT, LAST_MODIFIED_AT, CONTENT, RATING, TITLE, ITEM_ID, MEMBER_ID)
('2023-05-16 15:48:57.450179', '2023-05-16 15:48:57.450179', '꿀!', 5.0, '와 맛있당!', 2, 1),
('2023-05-16 15:49:30.000000', '2023-05-16 15:49:30.000000', '맛있어요!', 4.0, '맛있어요!', 1, 1),
('2023-05-16 15:50:00.000000', '2023-05-16 15:50:00.000000', '별로에요!', 2.5, '별로에요!', 1, 2),
('2023-05-16 15:50:30.000000', '2023-05-16 15:50:30.000000', '좋아요!', 4.5, '좋아요!', 1, 2),
('2023-05-16 15:51:00.000000', '2023-05-16 15:51:00.000000', '괜찮아요!', 3.0, '괜찮아요!', 1, 2);