백엔드 개발에서 초기 데이터를 설정할 , 하드코딩으로 값을 입력하는 경우가 많습니다. 하지만 데이터가 많아질수록 코드가 복잡해지고 관리가 어려워지죠. 이번 포스팅에서는 하드코딩 대신 CSV 파일 활용하여 데이터를 초기화하는 방법과, 과정에서 발생한 문제를 어떻게 해결했는지 소개합니다.

 

1. 하드코딩 방식의 문제점

처음에는 아래와 같이 데이터를 직접 코드에 하드코딩하여 초기화했습니다.

@Component
@Order(1)
public class TestDataRunner implements ApplicationRunner {

    @Autowired
    ProductRepository productRepository;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        Product product1 = createProduct((long) 768848, "[STANLEY] GO CERAMIVAC 진공 텀블러/보틀 3종", 21000, 45);
        Product product2 = createProduct((long) 748943, "디오디너리 데일리 세트 (Daily set)", 19000, 89);
        ...
        
        productRepository.save(product1);
        productRepository.save(product2);
        ...
    }

    public Product createProduct(Long productNumber, String productName, int productPrice, int productStock) {
        Product product = Product.builder()
                .productNumber(productNumber)
                .productName(productName)
                .productPrice(productPrice)
                .productStock(productStock)
                .build();
        return product;
    }
}

하드 코딩 방식에는 아래와 같은 문제점이 있었습니다.

  • 데이터 수정의 어려움: 데이터를 변경할 때마다 코드를 수정하고 재배포해야 했습니다.
  • 가독성 저하: 데이터가 많아질수록 코드가 복잡해지고 유지보수가 어려워졌습니다.

2. CSV 파일을 활용한 데이터 입력

문제를 해결하기 위해 데이터를 CSV 파일로 관리하고, 애플리케이션 실행 해당 파일을 읽어 데이터베이스에 저장하도록 변경했습니다.

CSV 파일

 

@Component
@Order(1)
public class TestDataRunner implements ApplicationRunner {

    @Autowired
    ProductRepository productRepository;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        File file = new File("/Users/kimkiyun/Downloads/items_.csv");
        BufferedReader br = null;
        String line = "";

        try {
            br = new BufferedReader(new FileReader(file));
            while ((line = br.readLine()) != null) {
                List<String> aLine = new ArrayList<>();
                String[] lineArr = line.split(",");
				
                Product product = Product.builder()
                    .productNumber((long) Integer.parseInt(lineArr[0]))
                    .productName(lineArr[1])
                    .productPrice(Integer.parseInt(lineArr[2]))
                    .productStock(Integer.parseInt(lineArr[3]))
                    .build();
	            productRepository.save(product);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (br == null) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

 

3. 문제 해결 과정

CSV 데이터를 읽어오면서 두 가지 문제가 발생했습니다.

문제 1. 첫 번째 행(컬럼명) 처리 문제

  • CSV 파일의 첫 번째 행은 데이터가 아니라 컬럼명이므로, 이를 무시해야 했습니다.
  • 해결 방법: 데이터를 저장하기 전에 번째 행을 건너뛰도록 for문을 수정했습니다.
for (int i = 1; i < csvList.size(); i++) { // 첫 번째 행 제외
    // 데이터 저장 로직
}

 

문제 2. 데이터 내 포함된 , 처리 문제

  • CSV 파일은 ","로 행을 구분하는데 CSV 데이터에서 ""로 감싸진 값 내부에 ','가 포함된 경우, split(",")으로 제대로 나뉘지 않아 오류가 발생했습니다.
  • 해결 방법: 정규식을 활용해 CSV 파일의 구조를 정확히 파싱했습니다.
String[] lineArr = line.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)", -1);

 

정규식은 큰따옴표 내부의 쉼표 무시하고 데이터를 분리할 있도록 합니다.

 

전체코드

애플리케이션을 실행하고 상품 데이터를 조회해오는 메서드를 실행하면 다음과 같이 잘 들어간걸 확인할 수 있습니다.

+ Recent posts