Skip to content

대용량 랜덤 데이터는 어떻게 삽입되나요?

mintaek edited this page Jan 31, 2025 · 1 revision

유저의 편의성을 위해

유저가 넣고 싶은 데이터를 컬럼별로 하나씩 입력하는 것은 상당히 번거롭습니다. 편의를 위해 랜덤한 데이터를 삽입해 줍니다.

랜덤 데이터를 추가할 때, 의미없는 값보다는 사용자가 활용할 수 있는 값을 넣어주는 것이 활용하기 좋습니다.

사용자는 랜덤 값의 Domain 을 설정하고, 선택한 Domain 에 해당하는 랜덤 값을 추가합니다.

빠른 대용량 데이터 삽입을 위해

랜덤하게 생성된 데이터를 어떻게 추가할 지 고민하였습니다.
처음에 떠올린 방법은 프로시저를 생성하고, 반복문을 활용해 INSERT 문으로 데이터를 추가하는 것이었습니다.
그러나 반복된 INSERT 문을 활용한 데이터 추가는 성능이 좋지 않고, 쿼리 DB 에 불필요하게 많은 부하를 발생시키게 됩니다.

'bulk INSERT' VS 'Load Data'

Insert 명령문의 경우 데이터 삽입 시 마다 Validation 을 수행하기 때문에 대량의 데이터를 추가하기에는 좋은 방법이 아님을 확인하였습니다.
따라서 MySQL에서 대용량 데이터를 빠르게 삽입할 수 있는 LOAD DATA INFILE 쿼리를 활용하였습니다.
최종적으로 요청에 따라 .csv 파일을 생성하고, LOAD DATA 명령으로 데이터를 삽입하는 방안을 선택하였습니다.

불필요한 서버 부하를 줄이기 위해

랜덤한 데이터를 사용자의 요청만큼 생성해야 합니다.
사용자로부터 10만건을 요청받으면 10만건을, 100만건을 요청받으면 100만건을 생성해야 합니다.
이 많은 데이터들은 메모리에 상주하게 됩니다. 그러나 다량의 데이터를 생성함에 있어서 메모리에 전부 들고 있는 것은 좋은 방법이 아닙니다.

이 문제를 해결하기 위해 랜덤 데이터 생성을 일정 크기로 잘라 특정 배치 단위로 처리하도록 하였습니다.
csv 파일을 생성 시 요청 개수가 10000개를 넘는다면 10000개씩의 배치크기로 csv 파일을 생성하고, DB 에 파일을 넘겨줄 때에는 스트림으로 넘겨줍니다.
랜덤 생성된 데이터를 전부 읽어서 메모리에 상주하는 일이 없도록 처리해주었습니다. 최종적으로 약 10만건의 데이터를 생성하는데 3~4 초 정도의 수행시간을 확인하였습니다.

최종 Sequence Diagram

sequenceDiagram
    participant Client as 클라이언트
    participant RecordService as RecordService
    participant Domain as 도메인 데이터
    participant FileSystem as 파일 시스템
    participant Database as 데이터베이스

    Client->>RecordService: 랜덤 데이터 삽입 요청 (커스텀 or 도메인)
    alt 커스텀 데이터
        RecordService->>RecordService: 사용자 정의 데이터 반환 
    else 도메인 데이터
        RecordService->>Domain: 도메인 데이터 매핑
        Domain-->>RecordService: 매핑된 데이터 반환
    end

    RecordService->>RecordService: 랜덤 데이터 CSV 생성
    loop 데이터 생성 (배치 처리)
        RecordService->>FileSystem: CSV 파일 데이터 쓰기
        FileSystem-->>RecordService: 쓰기 완료
    end

    RecordService->>Database: LOAD DATA INFILE로 데이터 삽입
    alt 데이터 삽입 성공
        Database-->>RecordService: 삽입된 행 수 반환
    else 데이터 삽입 실패
        Database-->>RecordService: 에러 반환
        RecordService-->>Client: 에러 응답

    end

    RecordService->>FileSystem: CSV 파일 삭제
    FileSystem-->>RecordService: 삭제 성공
    RecordService-->>Client: 삽입 성공 응답
Loading