[FileNotFoundException] 배포 시 파일을 읽을 수 없는 문제

SEPTEMBER·2025년 1월 21일

< 작업 환경 >
IDE: IntelliJ
Spring Boot: 3.4.1
Java: 21
EC2 Linux: Ubuntu

1. 문제 인식

EC2 인스턴스를 연결하고 Spring Boot 프로젝트를 배포하려는데 서버가 실행되지 않았습니다. 로그를 확인해보니 아래와 같은 오류가 발생했습니다.

Caused by: java.io.FileNotFoundException: class path resource [location_kr.csv] cannot be resolved to absolute file path because it does not reside in the file

오류의 내용은 location_kr.csv 파일을 찾을 수가 없다는 거였습니다.

하지만 해당 파일이 있는 디렉토리에서 ls 명령어를 실행해 보면 아래와 같이 파일이 존재하는 걸 확인할 수 있습니다.

ubuntu@ip-172-31-46-72:~/study-hub/src/main/resources$ ls
application.properties  location_kr.csv  static  templates

파일이 존재하는데 파일을 인식할 수 없다면, 파일을 인식하는 방법에 문제가 있는게 아닐까 생각했습니다. 그리고 해당 파일을 인식하는 코드를 살펴보며 해답을 찾을 수 있었습니다.

2. 문제 해결

<기존 코드>

@PostConstruct
public void initLocationData() throws IOException {
    if (locationRepository.count() == 0) {
        Resource resource = new ClassPathResource("location_kr.csv");
        List<Location> locations = Files.readAllLines(resource.getFile().toPath(), StandardCharsets.UTF_8).stream()
                .map(line -> {
                    String[] parts = line.split(",");
                    return Location.builder().province(parts[0]).city(parts[1]).build();
                }).toList();
        locationRepository.saveAll(locations);
    }
}

<수정된 코드>

@PostConstruct
public void initLocationData() throws IOException {
    if (locationRepository.count() == 0) {
        Resource resource = new ClassPathResource("location_kr.csv");

        try (InputStream inputStream = resource.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
            List<Location> locations = reader.lines()
                .map(line -> {
                    String[] parts = line.split(",");
                    return Location.builder().province(parts[0]).city(parts[1]).build();
                }).toList();
            locationRepository.saveAll(locations);
        }
    }
}

- 결론 : InputStream을 사용하여 리소스를 읽도록 함

Spring Boot에서는 JAR 파일로 패키징된 애플리케이션에서 리소스를 읽을 때 ClassPathResource#getFile() 메서드가 동작하지 않을 수 있습니다. 이는 JAR 파일 내의 리소스가 파일 시스템의 파일로 표현되지 않기 때문입니다.

이때문에 resource.getFile()를 호출하여 JAR 파일 내부의 리소스를 읽으려고 했을 때 java.io.FileNotFoundException이 발생한 것입니다. 따라서 ClassPathResource#getInputStream() 메서드를 사용하여 JAR 파일 내부에서도 리소스를 읽을 수 있도록함으로써 문제를 해결할 수 있었습니다.

0개의 댓글