💋 더미 데이터란?
더미 데이터란, 프로그래밍에서 특정 데이터를 테스트나 데모 용도로 사용하기 위해 임의로 만든 데이터이다.
실제 운영 환경에서 사용되는 데이터가 아니며, 개발자나 테스터 등이 특정 기능이나 모듈을 테스트할 때 사용된다.
더미 데이터는 데이터베이스나 파일 등에 저장되며, 프로그램에서 이를 불러와 사용한다.
예를 들어, 상품 관리 시스템을 개발할 때 특정 상품 데이터를 더미 데이터로 만들어서 테스트할 수 있으며, 이를 통해 실제 데이터를 사용하지 않고도 프로그램이 예상한 대로 동작하는지 확인할 수 있다.
나는 작은 미션을 진행하면서, 아래 사진과 상품들을 보여주는 화면에 함께 치킨, 샐러드, 피자에 대한 더미 데이터를 추가하고 싶었다.
💋 더미 데이터를 추가하는 방법
크게 세 가지가 있다.
1.data.sql 스크립트 파일에 더미 데이터 추가하는 쿼리문 작성
2. Spring의 @PostConstruct를 사용해 초기화
3. Spring의 @ApplicationRunner를 사용해 초기화
하나씩 차례대로 살펴보자!
✔ 1. data.sql 스크립트 파일에 더미 데이터 추가하는 쿼리문 작성
data.sql은 스프링에서 제공하는 데이터베이스 초기화를 위한 스크립트 파일이다.
스크립트 파일 안에는 SQL 쿼리를 작성하여 데이터베이스 초기화 작업을 수행할 수 있으며, 스프링 부트에서는 data.sql 파일을 클래스패스 경로(src/main/resources)에 위치시키면, 애플리케이션이 실행될 때 자동으로 실행된다.
DROP TABLE IF EXISTS product;
CREATE TABLE PRODUCT
(
id BIGINT NOT NULL AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
img_url VARCHAR(255),
price INT NOT NULL,
PRIMARY KEY (id)
);
INSERT INTO PRODUCT (name, img_url, price)
values ('피자',
'https://cdn.dominos.co.kr/admin/upload/goods/20200311_x8StB1t3.jpg',
13000);
INSERT INTO PRODUCT (name, img_url, price)
values ('샐러드',
'https://m.subway.co.kr/upload/menu/K-%EB%B0%94%EB%B9%84%ED%81%90-%EC%83%90%EB%9F%AC%EB%93%9C-%EB%8B%A8%ED%92%88_20220413025007802.png',
20000);
INSERT INTO PRODUCT (name, img_url, price)
values ('치킨',
'https://cdn.thescoop.co.kr/news/photo/202010/41306_58347_1055.jpg',
10000);
✔ 2. Spring의 @PostConstruct를 사용해 초기화
PostInitializer는 애플리케이션이 실행될 때 초기화 작업을 수행하기 위한 빈이며, @PostConstruct를 붙인 메서드는 이 메서드가 속한 ProductInitializer 빈 생성 이후에 실행된다. 따라서 빈의 초기화 로직을 구현하는 데 사용된다.
@Component
public class ProductInitializer {
private final ProductDao productDao;
public ProductInitializer(ProductDao productDao) {
this.productDao = productDao;
}
@PostConstruct
public void init() {
// 더미 데이터 작성
Product pizza = new Product(
"피자",
"https://cdn.dominos.co.kr/admin/upload/goods/20200311_x8StB1t3.jpg",
13000);
Product salad = new Product(
"샐러드",
"https://m.subway.co.kr/upload/menu/K-%EB%B0%94%EB%B9%84%ED%81%90-%EC%83%90%EB%9F%AC%EB%93%9C-%EB%8B%A8%ED%92%88_20220413025007802.png",
20000);
Product chicken = new Product(
"치킨",
"https://cdn.thescoop.co.kr/news/photo/202010/41306_58347_1055.jpg",
10000);
// 더미 데이터 저장
productDao.save(pizza);
productDao.save(salad);
productDao.save(chicken);
}
}
위 코드에서 ProductDao는 상품 관련 데이터를 저장하는 DB에 접근하는 메서드를 작성한 빈이다.
위 코드를 작성하면, 애플리케이션 실행 시 PostConstruct가 실행되며 더미 데이터가 추가된다.
(심화)
하지만, 이 방법은 트랜잭션을 적용할 수 없다는 문제점이 있다.
@Component
public class ProductInitializer {
private final ProductDao productDao;
public ProductInitializer(ProductDao productDao) {
this.productDao = productDao;
}
@Transactional
@PostConstruct
public void init() {
// 더미데이터 저장 로직
}
}
저장 로직에 트랜잭션을 적용하기 위해 위의 코드와 같이 어노테이션을 설정했다고 하더라도, 트랜잭션이 적용되지 않는다.
스프링부트에서 초기화 코드를 먼저 호출하고, 그 다음에 트랜잭션 AOP가 적용하기 때문이다.
따라서 초기화 시점에는 해당 메서드에서 트랜잭션을 획득할 수 없다.
✔ 3. Spring의 @EventListener(ApplicationReadyEvent.class) 사용
2번 방법보다 이 방법을 통해 더미데이터를 추가하는 것을 권장한다.
@EventListener(ApplicationReadyEvent.class)
@Transactional
public void init() {
// 더미 데이터 저장 로직
}
(이유는 조금 심화)
잘 이해하지 못하겠다면, 일단 이렇게 설정해도 된다 정도로 넘어가자!
위와 같이 설정하는 경우에 트랜잭션 또한 적용할 수 있다.
ApplicationReadyEvent는 스프링 컨테이너가 모두 띄워졌을 때 발생하는 이벤트다.
스프링 컨테이너가 모두 완전히 떴다는 의미는 스프링 AOP, 트랜잭션 등등 모든 것을 완성한 Applicaiton Context가 완성되었다는 의미이다. 따라서 init() 메서드를 호출하면, 프록시를 통해 만들어진 스프링 빈을 통해서 해당 메서드가 호출되기 때문에 트랜잭션이 적용된다.
✔ 4. Spring의 @ApplicationRunner를 사용해 초기화
Spring Boot 애플리케이션은 내장형 톰캣과 같은 웹 컨테이너를 내장하고 있어서, 애플리케이션을 실행하면 내장형 톰캣이 시작되며, 이때 ApplicationRunner를 구현한 빈이 존재하면 자동으로 실행됩니다.
ApplicationRunner는 Spring Boot 애플리케이션의 생명주기 중에서 애플리케이션 시작 시점에 실행된다.
따라서 더미 데이터 추가나 초기화 작업 등을 수행하는 등의 초기화 작업을 수행하기 좋다.
@Component
public class ProductInitializer implements ApplicationRunner {
private final ProductDao productDao;
@Autowired
public ProductInitializer(ProductDao productDao) {
this.productDao = productDao;
}
@Override
public void run(ApplicationArguments args) {
// 더미 데이터 작성
Product pizza = new Product("피자", "https://cdn.dominos.co.kr/admin/upload/goods/20200311_x8StB1t3.jpg", 13000);
Product salad = new Product("샐러드", "https://m.subway.co.kr/upload/menu/K-%EB%B0%94%EB%B9%84%ED%81%90-%EC%83%90%EB%9F%AC%EB%93%9C-%EB%8B%A8%ED%92%88_20220413025007802.png", 20000);
Product chicken = new Product("치킨", "https://cdn.thescoop.co.kr/news/photo/202010/41306_58347_1055.jpg", 10000);
// 더미 데이터 저장
productDao.saveProduct(pizza);
productDao.saveProduct(salad);
productDao.saveProduct(chicken);
}
}
[개인적 궁금증] 위에서 등장한 두 종류의 ProductInitializer 클래스는 어떤 패키지에 들어가야 할까?
Spring Boot 프로젝트에서는 패키지를 구조화하여 관리하기 때문에 더미데이터 추가를 위한 ApplicationRunner나 PostConstruct 메서드는 해당하는 레이어의 패키지에 위치시켜야 한다. 예를 들어, Repository 레이어에 더미데이터 추가를 위한 코드를 작성한다면 Repository 인터페이스와 구현체가 위치한 패키지 내부에 작성하는 것이 좋다.
하지만 더미데이터 추가가 여러 레이어에서 이루어져야 한다면, 보통 config 패키지 내부에 DataLoader와 같은 이름의 클래스를 생성하여, 이곳에서 각 레이어별로 필요한 데이터를 추가합니다. 이 경우, ApplicationRunner나 PostConstruct 메서드를 사용하여 초기화를 수행합니다.
도움이 되었다면, 공감/댓글을 달아주면 깃짱에게 큰 힘이 됩니다!🌟
비밀댓글과 메일을 통해 오는 개인적인 질문은 받지 않고 있습니다. 꼭 공개댓글로 남겨주세요!