대한민국 행정구역 DB화 하기

구동현·2024년 5월 14일

땅땅땅 프로젝트를 개발하면서, 내가 사는 동네의 위도와 경도를 지명과 함께 db화를 시켜야 할 필요성이 있었습니다. 이 게시물에서 엑셀에 있는 대한민국 행정구역 이름과 위도, 경도를 db화 하는 과정을 다루겠습니다.
깃허브 보러가기


프로젝트 생성

의존성 생성하기

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'com.mysql:mysql-connector-j'
    ...

    //POI
    implementation 'org.apache.poi:poi:5.2.3'
    implementation group: 'org.apache.poi', name: 'poi-ooxml', version: '5.2.4'
}

엑셀 파일 준비


이러한 엑셀 파일을 src/main/resources에 준비해줍니다.


Entity와 Repository

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "admin_district")
public class AdminDistrict {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String state;

    @Column
    private String county;

    @Column
    private String city;

    @Column
    private String district;

    @Column
    private String village;

    @Column
    private Double x;

    @Column
    private Double y;

    public AdminDistrict(
        String state,
        String county,
        String city,
        String district,
        String village,
        Double x,
        Double y
    ) {
        this.state = state;
        this.county = county;
        this.city = city;
        this.district = district;
        this.village = village;
        this.x = x;
        this.y = y;
    }

}

AdminDistrict(행정구역)이라는 Entity를 생성했습니다.

Column들의 이름은 미국 행정구역에서 따왔는데요,
아무래도 한국 행정구역의 이름을 따오면 Do, Si이런식이라 예약어에 걸리기도 하고, 직관성을 가져오기 위해서 미국 행정구역을 따왔습니다.

위도와 경도는 x,y로 결정합니다.


Service 생성

@Slf4j(topic = "AdminDistrictService")
@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class AdminDistrictService {

    private final static String excelDirectory = "src/main/resources/AdminDistrictExcel.xlsx";

    private final AdminDistrictRepository adminDistrictRepository;

    @Transactional
    public void createAdminDistrict() {

        try (FileInputStream file = new FileInputStream(excelDirectory)) {

            List<AdminDistrict> townList = new ArrayList<>();
            Workbook workbook = WorkbookFactory.create(file);
            int sheets = workbook.getNumberOfSheets();

            for (int i = 0; i < sheets; i++) {
                Sheet sheet = workbook.getSheetAt(i);

                for (int j = 1; j < sheet.getPhysicalNumberOfRows(); j++) {
                    Row row = sheet.getRow(j);

                    townList.add(new AdminDistrict(
                        row.getCell(0).getStringCellValue(),
                        row.getCell(1).getStringCellValue(),
                        row.getCell(2).getStringCellValue(),
                        row.getCell(3).getStringCellValue(),
                        row.getCell(4).getStringCellValue(),
                        row.getCell(5).getNumericCellValue(),
                        row.getCell(6).getNumericCellValue()
                    ));
                }

            }

            adminDistrictRepository.saveAll(townList);

        } catch (IOException | EncryptedDocumentException e) {
            log.error(e.getMessage());
        }

    }

}

Apache POI를 통해 엑셀 파일을 읽어오는 과정입니다.

FileInputStream file = new FileInputStream(excelDirectory)

엑셀 파일을 디렉토리주소를 통해 가져오는 과정입니다.

Workbook workbook = WorkbookFactory.create(file)

가져온 file을 WorkbookFactory를 통해 workbook으로 생성합니다.

Sheet sheet = workbook.getSheetAt(i);

제가 준비한 엑셀파일에는 sheet로 경기도, 강원도, 경상남도,,, 식으로 분리가 되어있어서 일단 sheet별로 순회합니다.

Row row = sheet.getRow(j);

sheet안에 있는 Row를 순회하면서 값들을 통해 엔티티를 생성해줍니다. 생성한 엔티티를 db에 넣어줍니다.


이런 메소드를 실행시켜주기 위해서 테스트 코드가 필요합니다.

@SpringBootTest
class CityDbDdangApplicationTests {

    @Autowired
    AdminDistrictService adminDistrictService;

    @Test
    @Rollback(false)
    @DisplayName("townList 엑셀 파일 DB에 저장")
    void saveTownListDB() {
        //given, when,then
        adminDistrictService.createAdminDistrict();
    }

}

DB에 저장하기 위한 용도이니,
Rollback을 false로 지정해줍니다.


테스트 코드 실행하기


정상적으로 실행이 잘 되네요!

DB에도 값이 잘 들어간 것을 볼 수 있습니다.

profile
개발합시다

0개의 댓글