저는 커피를 매우 좋아합니다. 커피의 맛을 따지는 것보다는 그저 즐기는 것을 좋아하는 사람입니다. 최근 진행 중인 프로젝트에서 소상공인 상가 정보 공공 데이터를 활용하는 기능을 추가하고자 했습니다. 이 블로그 포스트에서는 데이터 처리 과정과 개선 방안을 공유하고자 합니다.

implementation 'com.opencsv:opencsv:5.9' 라이브러리 사용@EventListener(ApplicationReadyEvent.class) 를 통해 애플리케이션 실행시 애노테이션이 적용된 메서드를 실행CSVReader 객체 생성‘,’ 로 구분된 파일 형식List<String[]> , List<Cafe>의 반환용 리스트 생성convertCsvToCafe() 메서드 실행onvertCsvToCafe() 을 통해 row에 있는 데이터를 조작해 Cafe 객체를 생성cafeList를 saveAll(); 로 저장"상가업소번호","상호명","지점명","상권업종대분류코드","상권업종대분류명","상권업종중분류코드","상권업종중분류명","상권업종소분류코드","상권업종소분류명","표준산업분류코드","표준산업분류명","시도코드","시도명","시군구코드","시군구명","행정동코드","행정동명","법정동코드","법정동명","지번코드","대지구분코드","대지구분명","지번본번지","지번부번지","지번주소","도로명코드","도로명","건물본번지","건물부번지","건물관리번호","건물명","도로명주소","구우편번호","신우편번호","동정보","층정보","호정보","경도","위도"
"MA0101202210A0093845","이상한스냅","","M1","과학·기술","M113","사진 촬영","M11301","사진촬영업","M73303","사진 처리업","11","서울특별시","11470","양천구","11470600","신월5동","1147010300","신월동","1147010300100090004","1","대지",9,4,"서울특별시 양천구 신월동 9-4","114703005067","서울특별시 양천구 월정로",283,,"1147010300100090004000001","백송주택","서울특별시 양천구 월정로 283","158822","07902","","","",126.828831598706,37.5421174398055
@Transactional
@EventListener(ApplicationReadyEvent.class)
public void readCsv() {
log.info("데이터 저장 시작");
CSVReader reader = null;
long startTime = System.currentTimeMillis();
try {
reader = new CSVReader(new FileReader(PATH));
List<String[]> rows = reader.readAll();
List<Cafe> cafeList = new ArrayList<>();
for (int i = 0; i < rows.size(); i++) {
if ("카페".equals(rows.get(i)[8])) {
Cafe cafe = convertCsvToCafe(rows.get(i));
cafeList.add(cafe);
}
}
long elapsedTime = System.currentTimeMillis() - startTime; // 소요 시간 계산
log.info("총 데이터 수 : {}, 데이터 수: {}, 소요 시간: {} ms", rows.size(), cafeList.size(),
elapsedTime);
cafeRepository.saveAll(cafeList);
} catch (FileNotFoundException | CsvValidationException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (CsvException e) {
throw new RuntimeException(e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
public Cafe convertCsvToCafe(String[] row) {
String name = ""; // [1] + [2]
String roadNamedAddress = ""; //[31] + [30] + [35] + [36]
String zipCode = ""; // [33]
double longitude = 0; // [37]
double latitude = 0; // [38]
for (int i = 1; i < row.length; i++) {
name = row[1] + " " + row[2];
roadNamedAddress = row[31] + " " + row[30];
zipCode = row[33];
longitude = Double.valueOf(row[37]);
latitude = Double.valueOf(row[38]);
}
return Cafe.builder()
.name(name)
.roadNamedAddress(roadNamedAddress)
.zipCode(zipCode)
.longitude(longitude)
.latitude(latitude)
.build();
}
관련해서 질문이 있습니다.
1. saveAll() 은 BulkInsert 용으로 쓰신걸까요 ?
그렇다면 DB에 Insert 할 때, SaveAll()할 때, 채번 방식에 따라서 insert 쿼리가 1개씩 나갈 수 있어요.
그 부분 확인해보세요.
-> 굳이 Spring Boot를 띄울 필요가 없는데, 느낌상 스프링을 띄운거 같아요.
-> 이 부분에 대해서 고민해봐도 좋을거 같아요.
-> CSV파일이 있다면 DBeaver WorkBench를 통해서 그냥 밀어넣는 방법도 있을거에요.