AWS S3

자동화 된 배포를 위해서는 배포 파일을 저장할 수 있는 저장소가 필요한데, 이 저장소를 S3로 선택했다.

이전 글에서 이미지 저장소를 만들 때도 썼던 그 S3인데, CI/CD 용 버킷을 새로 만들어서 사용한다.

S3를 선택한 이유는 자동 배포를 위해 AWS CodeDeploy를 사용할 예정이라 같은 AWS 서비스라서 연동하기 편하기 때문이다.


1. EC2에 적용할 IAM 역할 설정

CI/CD 과정에서 EC2 인스턴스에서 실행 중인 CodeDeploy를 통해 S3 버킷의 배포용 파일들에 접근한다.

따라서 EC2의 IAM 역할을 설정해줘야 문제 없이 동작한다.

1-1. IAM 역할 생성 페이지로 이동

1-2. 신뢰할 수 있는 엔티티 선택

1-3. 권한 추가

1-4. 역할 이름 지정

역할 이름 지정 후 생성을 완료한다.

1-5. EC2 인스턴스에 IAM 역할 연결

EC2 인스턴스로 이동해서 IAM을 연결한다.


2. S3 버킷 생성

CI/CD 용으로 버킷을 새로 만들것이다.

깃헙 액션에서 IAM 사용자 정보로 이 S3 버킷에 저장한다.

따라서 퍼블릭 엑세스가 필요 없으므로 최대한 private 하게 생성한다.

2-1. S3 버킷 생성 페이지로 이동

2-2. 버킷 만들기

아래처럼 리전과 이름만 설정하면 나머지는 기본값으로 생성하면 된다.

2-3. 버킷 생성 확인

 

CodeDeploy

CodeDeploy는 EC2, ECS 등의 서비스로의 애플리케이션 배포를 자동화하 해주는 배포 서비스이다.

S3에 저장된 배포 파일들을 이 CodeDeploy가 자동으로 배포하도록 설정할 수 있다.


1. CodeDeploy에 적용할 IAM 역할 설정

CodeDeploy 애플리케이션을 생성하고 이를 이용해 EC2에 배포할 것이다.

이 때, CodeDeploy가 EC2에 접근하여 배포 과정을 실행하기 위해 IAM 역할을 설정해줘야 한다.

1-1. IAM 역할 생성 페이지로 이동

1-2. 신뢰할 수 있는 엔티티 선택

CodeDeploy로 선택해주면 권한은 자동으로 추가되므로 이후는 기본값으로 설정한다.

1-3. 역할 이름 지정

역할 이름 지정 후 생성을 완료한다.


2. CodeDeploy 애플리케이션 생성

2-1. 애플리케이션 생성 페이지로 이동

2-2. 애플리케이션 생성

아래 사진처럼 앱 이름과 컴퓨팅 플랫폼을 설정해준다.

컴퓨팅 플랫폼은 EC2/온프레미스로 선택하고 애플리케이션을 생성한다.


3. CodeDeploy 배포 그룹 설정

3-1. 배포 그룹 생성 페이지로 이동

3-2. 배포 그룹 설정

배포 그룹 설정을 해준다.

역할은 위 1 에서 생성한 역할을 선택해준다.

3-3. 환경 구성

3-2에서 아래로 내려오면 환경 구성이 나온다.

EC2 인스턴스를 선택하고, 태그 그룹을 선택해준다.

이 글에서 생성한대로 EC2를 생성했다면 아래처럼 선택할 수 있다.

EC2 설정에서 태그를 따로 생성할 수도 있다.

태그를 선택하면 맨 아래 박스처럼 일치하는 인스턴스를 확인할 수 있다.

3-3. 설정 완료

AWS Systems Manager 설정은 적당히 넘기고

배포 설정을 확인하면 아래처럼 돼 있으면 넘어간다.

로드 밸런서는 사용하지 않으니 설정을 완료하고 배포 그룹을 생성한다.

CI/CD

지금까지 EC2 인스턴스를 만들고 서버를 띄워서 배포도 했고, RDS 인스턴스를 만들어서 DB도 연동했다.

버전 업데이트 시 일일이 테스트 및 빌드 하던 것도 Github Actions로 자동화했으니 CI 까지는 진행하였다.

이제 배포의 틀은 어느정도 갖춰지긴 했지만, 아직까지 수작업으로 매번 scp 커맨드를 써서 최신 버전으로 배포하고 있다.

결국 이런 단순 반복 작업은 사람이 하다보면 언젠가 꼭 실수가 나오기 마련이고, 이는 곧 장애로 이어질 수 있다.

따라서 이번엔 GitHub에 PR을 올리고 머지 시 배포되는것 까지 자동화(CD) 해보려 한다.

 

보통 이 두가지를 합쳐서 CI/CD라고 한다.

자동 빌드 및 테스트(CI, Continuous Integration)

업데이트 한 버전을 자동으로 빌드 및 테스트 하는 것

배포 자동화(CD, Continuous Deploy)

빌드 및 테스트를 마치고 성공적으로 업데이트 한 버전의 애플리케이션을 자동으로 배포 하는 것


CI/CD & 무중단 배포

애플리케이션의 버전을 업데이트하면 자동으로 빌드 및 테스트하고, 자동으로 배포까지 해보려 한다.

하지만 현재 배포 중인 서비스를 종료하고, 새로운 버전의 서비스를 띄우면 서버가 죽어있는 시간이 존재하지 않을까?

만약 별 다른 공지 없이 이렇게 서버가 내려가 있으면 사용자에게 나쁜 경험을 줄 수 있다.

따라서 새로운 버전을 배포해도 서버가 죽어있는 시간이 거의 없는 자동화 과정을 만들어보려 한다.

그림으로 나타내자면 아래와 같다.

 

 

참고자료

 

Github Actions CD: AWS EC2 에 Spring Boot 배포하기

Overview 애플리케이션을 개발하면 외부에서도 접근 가능하도록 클라우드 환경에 배포합니다. 이전에 포스팅 했던 AWS 1편에서는 마지막에 scp 명령어로 로컬에 존재하는 빌드 파일을 EC2 인스턴스

bcp0109.tistory.com

 

 

인덱스

지금껏 DB를 Jpa로 접하고, 공부도 부족해서 DB에 대해 너무 모르고 있었다.

인덱스도 이름만 들어보고 사용하면 읽기 성능이 좋아진다 라고만 알고 있었지 직접 써보질 않았기 때문에 잘 와닿지는 않았다.

이번 기회에 MySQL을 공부하면서 인덱스를 사용해서 성능 비교도 해보면서 DB에 대한 이해를 넓혀보고자 한다.


사용 기술

  • MySQL 8.4
  • DBeaver

사전 작업

아래처럼 DB에 400만 건의 데이터를 넣어뒀다.

 

데이터 형식은 아래 사진과 같다.

memberId = 1에 해당하는 데이터는 300만건, memberId = 2에 해당하는 데이터는 100만건이다.

  • 날짜는 5월 26~ 27일 사이의 랜덤 값
  • memberId = 1 또는 2이다.
  • content는 랜덤한 값

 

이 데이터들을 이용하여 인덱스 사용 전/후의 성능을 비교해볼 것이다.


1. 인덱스 사용 전 

인덱스를 사용했을때와 비교해보기 위해 대조군으로 측정한다.

1-1. 실행 계획 분석

MySQL의 EXPLAIN 을 이용하여 실행 계획을 분석한 결과는 아래와 같다.

인덱스 없이 탐색한 rows가 거의 400만 개로 풀 스캔한 결과인듯 하다.

1-2. 쿼리 시간

400만 건의 데이터를 조회하는데 18초가 걸렸다.

1-3. CPU 점유율

400만건의 데이터를 조회하기 위해 CPU 점유율이 27%까지 올라갔다.


2. 인덱스 추가

이제 인덱스를 추가해보자.

SQL로 생성해도 되고, DBeaver 같은 GUI를 써서 추가해줘도 된다.

본인은 아래처럼 GUI로 3개의 인덱스를 추가해줬다.

  • createdDate 인덱스
  • memberId 인덱스
  • createdDate, memberId 복합 인덱스

 

인덱스 생성 결과는 아래처럼 확인할 수 있다.

이 인덱스


3. memberId 인덱스 사용

3-1. 실행 계획 분석

3-2. 쿼리 시간

24초로 인덱스를 타지 않은 쿼리보다 느린 결과를 얻었다.

3-3. CPU 점유율

인덱스를 타지 않은 쿼리보다 더 높은 CPU 점유율을 기록했다.

3-4. 결과 분석

인덱스를 걸었음에도 불구하고 쿼리 시간이 더 느려졌다.

이유를 찾아보자면 인덱스를 탔음에도 탐색 범위를 많이 줄이지 못했기 때문에 인덱스 테이블도 확인하고,

Post 테이블의 데이터까지 확인해야 했기 때문에 인덱스 없이 테이블 풀 스캔을 한 결과보다 느리게 나왔다고 볼 수 있다.

 

참고로 memberId = 2로 쿼리를 날려보면 아래처럼 쿼리 속도가 8초로 개선됐음을 확인할 수 있다.

이를 통해 쿼리에 해당하는 데이터 분포도에 따라서 쿼리 속도가 더 느려질 수 있다는걸 알았다.


4. createdDate 인덱스 사용

4-1. 실행 계획 분석

rows 만 보면 인덱스를 사용하지 않았을 때와 큰 차이가 없다.

하지만 type이 all 이냐, index에 따라 효율이 달라지는듯 하다.

4-2. 쿼리 시간

인덱스를 타지 않은 쿼리보다 훨씬 빠른 조회 결과를 얻었다.

4-3. CPU 점유율

쿼리가 너무 빠르게 실행돼서 CPU 점유율 변동이 없었다.

거의 0.1% 정도라고 생각하면 될것 같다.

4-4. 결과 분석

createdDate는 데이터 분포가 골고루 되어 있어서 그런지 인덱스를 타면 조회 성능이 훨씬 개선됨을 알 수 있었다.

rows가 커서 조회 속도가 느리지 않을까 생각했는데 데이터 분포가 엄청 큰 영향을 미치는가 보다.


5. createdDate, memberId 복합 인덱스 사용

5-1. 실행 계획 분석

rows가 createdDate 단일 인덱스보다 더 적어졌다.

5-2. 쿼리 시간

createdDate 단일 인덱스 보다 더 빠른 조회 결과를 얻었다.

5-3. CPU 점유율

쿼리가 너무 빠르게 실행돼서 CPU 점유율 변동이 없었다.

여기서도 거의 0.1% 정도라고 생각하면 될것 같다.

5-4. 결과 분석

18초 걸리던 쿼리가 0.002초로 엄청난 조회 속도 개선이 되었다.

복합 인덱스를 잘 이용하면 단일 인덱스를 이용하는것 보다 더 좋은 조회 결과를 얻을 수 있는걸 알 수 있었다.

복합 인덱스는 인덱스 순서에도 영향을 받는다고 하니 잘 이용하기 위한 조건을 확인해서 잘 쓸 수 있도록 해야겠다.


6. 정리

특정 인덱스에 따라 성능이 좌우 되는건 아니고 데이터의 분포도에 따라 성능이 달라질 수 있음을 알았다.

인덱스를 사용하면 항상 성능이 좋아지는건 아니고 오히려 나빠질 수 있다는것도 알 수 있었다.

인덱스를 사용하기 위해 주의해야할 점과 더 효율적으로 쓸 수 있는 방법을 더 공부해봐야 할것 같다.

 

참고로 위에서 실험할때는 use index로 인덱스를 설정했다.

use index를 제거하면 아래처럼 MySQL 내부에서 최적화하여 인덱스를 타서 쿼리를 실행한다.

하지만 최적화 결과가 항상 최선은 아니기 때문에 EXPLAIN으로 자주 확인하는게 좋을듯 하다.

'데이터베이스' 카테고리의 다른 글

Redis 써보기  (0) 2024.04.17
[DB] DML, DDL, DCL 이란?  (0) 2023.10.01

100만 건 데이터 삽입

MySQL에 인덱스를 추가하고 성능 비교를 해보기 위해 DB에 데이터를 많이 넣어야 할 필요가 생겼다.

그래서 아래처럼 한번에 100만 건의 데이터를 삽입하는 Bulk Insert를 해보려고 한다.

 

기본적인 과정은 이전 글에서와 똑같다.

하지만 100만 건의 데이터를 생성하기 위해서는 메모리를 꽤 잡아먹는다.

만약 VM에 충분한 힙 메모리가 설정되어 있지 않다면 OutOfMemory 에러가 발생할 것이다.

그래서 이것과 관련해서 설정을 정리해보려 한다.


사용 기술

  • Spring Boot 3.2.4 / gradle-kotlin
  • Java 17, IntelliJ
  • MySQL 8.4
  • EasyRandom, SpringDataJpa, JDBC

1. 인텔리제이 설정

1-1. 메모리 표시기 활성화

윈도우에서는 Ctrl + Shift + A 를 입력하고 메모리를 검색하면 아래와 같은 창을 볼 수 있다.

맥에서는 Cmd + Shift + A

여기서 메모리 표시기를 켜고, 우측 하단에 추가된 메모리 표시기를 확인한다.

1-2. VM 설정 편집

마찬가지로 Ctrl + Shift + A 로 VM을 검색한 후 아래 사진처럼 설정한다.

여기서 -Xmx 설정이 힙 메모리 상한 설정이다.

 

여기서 해준 설정은 인텔리제이 VM 설정이기 때문에 아래 1-3 처럼 테스트 환경을 인텔리제이 빌드로 변경해야 한다.

만약 Gradle 환경에서 하고 싶을 경우 Gradle 힙 메모리 상한을 설정해주면 된다.

1-3. 테스트 환경 설정 변경

아래처럼 인텔리제이 설정 창에 들어가서 테스트 설정을 변경해준다.


2. 결과

OutOfMemory 에러 없이 DB에 100만 건의 데이터가 잘 들어간걸 확인할 수 있다.

 

Bulk Insert

최근 MySQL을 만져보면서 이런저런 DB 관련 공부를 하고 있다.

그러던 중 인덱스와 관련 해서 성능 테스트를 할 겸 DB에 여러 건의 데이터를 넣는 방법을 생각해보았다.

지금껏 여러 건의 데이터를 넣을 때는 대부분 SpringDataJpa의 saveAll()을 사용하였다.

애초에 아직까지는 해봐야 2자리 수나 100건 정도의 데이터 정도만 넣어보고 있었기에 별 불편함을 느끼지 않았다.

하지만 1만건 이상의 데이터를 넣어야 하는 일이 생길 수있으니 이번 기회에 여러 건의 데이터를 넣는 방법들에 대해 정리해보려 한다.


사용 기술

  • Spring Boot 3.2.4 / gradle-kotlin
  • Java 17
  • MySQL 8.4
  • EasyRandom, SpringDataJpa, JDBC

 


DB에 여러 건의 데이터를 넣는 방법

DB에 여러 건의 데이터를 넣는 방법은 이 글에 정리해두었다.

이 글에서는 위 글에서 정리한 방법들을 실습한다.

  1. JPA의 save() 사용 ->  데이터 수 만큼 for 문으로 Insert
  2. JPA의 saveAll() 사용
  3. JPA의 Bulk Insert 사용
  4. JDBC Bulk Insert 사용

공통적으로 이지랜덤이라는 라이브러리를 이용하여 1000개의 랜덤 객체를 만들어서 DB에 Insert 해보려 한다.

이제 각 방법들로 DB에 여러 건의 데이터를 넣어보고 비교 해보자.


1. JPA - save()

우선 Jpa의 save() 메서드를 이용한 테스트부터 해보자.

1-1. 코드

예시 코드는 아래와 같다.

SpringDataJpa를 사용하면 자주 썼을 JpaRepository의 save() 메서드를 for문으로 루프를 돌려보았다.

스프링 프레임워크 유틸에서 제공하는 StopWatch를 이용하여 객체 생성 시간과 DB Insert 시간을 측정하였다.

이지 랜덤을 이용하여 PostFixtureFactory를 만드는건 이전 글에서 사용한 방식을 이용한다.

BulkInsertTest

@DisplayName("")
@Test
void test() {
    Long memberId = 1L;
    EasyRandom easyRandom = PostFixtureFactory.get(
        memberId,
        LocalDate.of(2024, 5, 26),
        LocalDate.of(2024, 5, 27)
    );

    // #1 - JPA save()
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    List<Post> posts = IntStream.range(0, 1000)
        .mapToObj(i -> easyRandom.nextObject(Post.class))
        .toList();
    stopWatch.stop();
    System.out.println("객체 생성 시간: " + stopWatch.getTotalTimeSeconds());

    StopWatch queryStopWatch = new StopWatch();
    queryStopWatch.start();
    for (Post post : posts) {
        postRepository.save(post);
    }
    queryStopWatch.stop();
    System.out.println("DB Insert 시간: " + queryStopWatch.getTotalTimeSeconds());
}

1-2. 결과

1000개의 랜덤 객체를 생성하는데는 0.11초밖에 걸리지 않는다.

하지만 DB에 데이터를 넣는데 11.45초가 걸린다.

1000번의 트랜잭션과 1000번의 Insert 쿼리가 시간을 많이 잡아먹는듯 하다.

2. JPA - saveAll()

2-1. 코드

이지 랜덤을 이용한 객체 생성 로직은 똑같으므로 생략하도록 한다.

BulkInsertTest

// #2 JPA - saveAll()
StopWatch stopWatch = new StopWatch();
stopWatch.start();
List<Post> posts = IntStream.range(0, 1000)
    .mapToObj(i -> easyRandom.nextObject(Post.class))
    .toList();
stopWatch.stop();
System.out.println("객체 생성 시간: " + stopWatch.getTotalTimeSeconds());

StopWatch queryStopWatch = new StopWatch();
queryStopWatch.start();
postRepository.saveAll(posts);
queryStopWatch.stop();
System.out.println("DB Insert 시간: " + queryStopWatch.getTotalTimeSeconds());

2-2. 결과

생성 로직이 똑같기 때문에 객체 생성 시간은 모든 테스트에서 거의 똑같을 것이다.

그런데 DB Insert 시간에서 save()와 큰 차이가 난다.

아무래도 트랜잭션을 1000번 열고 닫는 save() 보다는 1번 열고 닫는 saveAll()이 효율이 더 좋다.

하지만 save()와 마찬가지로 DB에 Insert 쿼리를 1000번 날리고 있다는 문제가 있다.


3. JPA - Bulk Insert

위처럼 2초 정도면 그래도 괜찮지 않나..? 하는 생각도 들지만 좀 더 나아가보자.

이제 성능 개선을 위해서는 한번의 Insert 쿼리로 1000건의 데이터를 넣을 수 있는 Bulk Insert에 눈이 간다.

만약 ID 생성 전략이 Auto Increment가 아니고, Jpa의 Bulk Insert 기능을 사용하고자 한다면 아래처럼 yml 설정을 해주면 된다.

본인은 Auto Increment 전략을 사용하고 있으므로 Jpa의 Bulk Insert 테스트는 생략하도록 하겠다.

spring:
  jpa:
    properties:
      hibernate:
        jdbc:
          batch_size: 100
          order_inserts: true # 삽입 작업 최적화
          order_upates: true  # 업데이트 작업 최적화

4. JDBC - Bulk Insert

본인의 프로젝트의 ID 생성 전략이 Auto Increment이므로 하이버네이트의 Bulk Insert 기능을 사용할 수 없다.

그래서 Bulk Insert를 사용하기 위해 JDBC Template을 사용하는 Repository를 따로 만들었다.

4-1. 코드

PostJdbcRepository

NamedParameterJdbcTemplate 를 사용하였다.

@Repository
@RequiredArgsConstructor
public class PostJdbcRepository {

    private static final String TABLE = "post";
    private final NamedParameterJdbcTemplate jdbcTemplate;

    public void bulkInsert(List<Post> postList) {
        String sql = String.format("""
            INSERT INTO %s (member_id, content, created_date)
            VALUES (:memberId, :content, :createdDate)
            """, TABLE);

        SqlParameterSource[] params = postList.stream()
            .map(BeanPropertySqlParameterSource::new)
            .toArray(SqlParameterSource[]::new);

        jdbcTemplate.batchUpdate(sql, params);
    }
}

BulkInsertTest

// #3 JdbcTemplate - bulk insert
StopWatch stopWatch = new StopWatch();
stopWatch.start();
List<Post> posts = IntStream.range(0, 10000 * 10)
    .mapToObj(i -> easyRandom.nextObject(Post.class))
    .toList();
stopWatch.stop();
System.out.println("객체 생성 시간: " + stopWatch.getTotalTimeSeconds());

StopWatch queryStopWatch = new StopWatch();
queryStopWatch.start();
postJdbcRepository.bulkInsert(posts);
queryStopWatch.stop();
System.out.println("DB Insert 시간: " + queryStopWatch.getTotalTimeSeconds());

4-2. 결과

객체 생성 로직은 똑같으므로 위 테스트들과 거의 똑같은 시간이 걸린다.

하지만 DB Insert 시간이 극적으로 차이가 난다.

 

아래처럼 쿼리 단 한번으로 모든 데이터를 삽입하니 훨씬 적은 시간이 드는걸 알 수 있다.

또한 JPA는 엔티티를 영속화 하면 1차 캐시에 저장하고 관리하므로 오버헤드가 더 생길 것이다.

따라서 이렇게 큰 차이가 생긴다고 생각할 수 있다.


5. 정리

정리하자면 1000건의 데이터 Insert에 대한 결과는 아래와 같다.

5-1. JPA - save() 1000건

5-2. JPA - saveAll() 1000건

5-3. JDBC - Bulk Insert 1000건

 

save() vs saveAll() 에서는 트랜잭션 수 의 차이가 있었고

saveAll() vs Bulk Insert 에서는 Insert 쿼  의 차이가 있었다.

또한 JPA는 엔티티를 영속화 하면 1차 캐시에 저장하고 관리하므로 오버헤드가 더 생긴다.

이상이 DB Insert 시간에 차이가 생기는 원인이라고 생각할 수 있다.

 

위 결과는 1000건의 데이터에 대한 결과지만, 데이터 건수가 늘어날수록 차이는 훨씬 벌어진다.

Jpa가 DB를 굉장히 편하게 사용할 수 있게 해주지만, 어느 정도 한계는 있는듯 하다.

물론 하이버네이트가 지원하는 Bulk Insert를 사용할 수 있다면 괜찮겠지만 Auto Increment 일땐 사용할 수 없으니...

아무래도 은총알은 없다는 말처럼, Jpa에 국한되지 말고 필요할때 적절한 기술을 사용해야할것 같다.

EasyRandom

프로젝트를 진행하면 빈번하게 테스트를 위한 데이터를 만들어줘야하는 번거로움이 생긴다.

필요한 데이터 수가 적다면 큰 문제가 되지 않지만, 많은 양의 테스트 데이터를 필요로 하는 테스트가 여럿 있다면 굉장히 힘들어진다.

이미 선배 개발자들이 이런 번거로움을 겪고 만든 디자인 패턴인 Object Mother 라는 패턴도 있었다.

이러한 번거로움을 줄이고자 좋은 라이브러리들도 나왔다.

그 중 이지 랜덤이라는 라이브러리를 사용해보려한다.


EasyRandom 써보기

사용법은 이지랜덤 깃허브 링크에도 잘 나와있다.

의존성 추가를 위해 아래 코드를 build.gradle에 추가해준다.

// build.gradle.kts
// EasyRandom
implementation("org.jeasy:easy-random-core:5.0.0")

 

우선 내가 만들 데이터의 조건은 아래와 같았다.

  • 데이터의 ID 값은 DB Insert 시 Auto Increment로 만들어야 하므로 null 값이어야 한다.
  • 테이블 조인에 사용할 FK인 memberId는 특정 값으로 넣을 수 있어야 한다.
  • 데이터의 생성 일자는 특정 날짜 사이의 랜덤 값을 이용해야 한다.

원래라면 이런 조건을 생각하면서 테스트용 객체를 어떻게 생성할지 고려해야겠지만

이지 랜덤을 사용하면 아래처럼 쉽게 사용할 수 있었다.

PostFixtureFactory

public class PostFixtureFactory {

    public static EasyRandom get(Long memberId, LocalDate firstDate, LocalDate lastDate) {
        Predicate<Field> idPredicate = named("id")
            .and(ofType(Long.class))
            .and(inClass(Post.class));

        Predicate<Field> memberIdPredicate = named("memberId")
            .and(ofType(Long.class))
            .and(inClass(Post.class));

        EasyRandomParameters param = new EasyRandomParameters()
            .excludeField(idPredicate)
            .dateRange(firstDate, lastDate)
            .randomize(memberIdPredicate, () -> memberId);

        return new EasyRandom(param);
    }
}

ㄴexcludeField

기본적으로 모든 필드를 랜덤화 해주지만, excludeField로 특정 필드를 랜덤화 하지 않을 수 있다.

본인은 Auto Increment를 위해 생성한 객체의 Id 값이 null 이여야 하므로 여기서 사용했다.

ㄴdateRange

LocalDateTime을 firstDate, lastDate 사이의 랜덤 값으로 사용하기 위해 사용했다.

ㄴrandomize

기본적으로 랜덤한 값을 넣지만 위처럼 콜백에 특정 값을 지정해주면 특정 값으로 삽입한다.

 

이 외에도 많은 기능을 제공한다.

공식 문서를 참고해서 사용해보면 굉장히 편하게 테스트 객체를 생성할 수 있을것 같다.

Test

테스트 클래스에서 아래처럼 사용할 수 있다.

@DisplayName("이지 랜덤으로 객체를 생성한다.")
@Test
void test() {
    Long memberId = 1L;
    EasyRandom easyRandom = PostFixtureFactory.get(
        memberId,
        LocalDate.of(2024, 5, 26),
        LocalDate.of(2024, 5, 27)
    );

    List<Post> posts = IntStream.range(0, 10)
        .mapToObj(i -> easyRandom.nextObject(Post.class))
        .toList();

    for (Post post : posts) {
        System.out.println(post);
    }
}

결과

내가 원한대로 Id는 null, memberId는 특정 값(1L), 생성 일자는 26~27일 사이의 객체를 만들 수 있었다.

 

참고자료

 

백엔드 개발자를 위한 한 번에 끝내는 대용량 데이터 & 트래픽 처리 | 패스트캠퍼스

데이터 처리 4대장 : MySQL, MongoDB, Kafka, Redis 외 31가지 기술스택 활용을 담은 초격차 강의! 실무 경험에 기반한 18가지 Use Case와 105개 실습 클립으로 대용량 테이터 & 처리를 완벽하게 경험해보세요!

fastcampus.co.kr

 

데이터가 필요해...!!(Object Mother와 EasyRandom)

예제 객체를 마구마구 생성해주는 EasyRanom 사용기입니다

velog.io

 

 

'백엔드 > 연습' 카테고리의 다른 글

Prometheus를 이용하여 메트릭 수집  (0) 2024.06.06
Spring Boot Actuator 써보기  (0) 2024.06.05
QueryDSL 적용하기: gradle-kotlin  (0) 2024.05.13
포트원 API 사용해보기  (0) 2024.04.04
plain-jar 파일 생성 방지  (0) 2024.01.16

DB 공부의 필요성

최근..은 아니고 꾸준히 느끼는게 나는 DB에 대해서 너무 모른다.

SQL도 부족하고, 데이터베이스 지식 자체가 부족해서 프로젝트 고도화를 할 때 걸림돌이 되고 있다.

면접때도 인덱스 관련해서 물어보면 써본적이 없어서 잘 대답하지 못하고 있고...

아무래도 DB를 JPA로 접하다보니 이런 문제가 생긴것 같다.

로컬에서 MySQL을 띄우는것부터 시작해서 이것저것 시도해보면서 공부해봐야지.

어느정도 공부를 해보고 EC2 + 도커 + MySQL로 RDS를 대체하는 작업도 겸하면서 DB에 대해서 알아가야겠다.

+ Recent posts