문제 상황
배포 환경은 Jenkins에서 빌드 후 jar 파일과 기타 파일을 전송하고 EC2 인스턴스에서 docker로 컨테이너를 올립니다.
Firebase 관한 Config 설정 후 로컬에서 제대로 작동하는 것을 확인하고 배포를 했는데, Docker의 로그를 확인하니 다음과 같은 예외가 발생하여 앱 실행에 실패했습니다.
문제가 생긴 부분은 새로 추가한 부분인 FirebaseConfig 클래스 였고 코드는 다음과 같습니다.
@Configuration
public class FirebaseConfig {
@Value("${firebase.keyPath}")
private String keyPath;
@PostConstruct
void init() throws IOException {
FileInputStream serviceAccount = new FileInputStream(keyPath);
FirebaseOptions options = FirebaseOptions.builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.build();
FirebaseApp.initializeApp(options);
}
}
Firebase SDK 인증에 필요한 Key가 저장되어있는 경로를 Properties에 설정한 값으로 주입을 받고 이후에 FirebaseApp 초기화를 진행합니다. 이때 설정해 놓은 경로는 "src/main/resoures/serviceAccountKey.json" 이었는데, 배포시 이 경로에 해당하는 파일을 찾을 수가 없어 문제가 생긴 것이었습니다.
해결 방법
IDE에서 실행시켰을 때 문제가 없던 이유는 IDE가 프로젝트 디렉터리를 현재 작업 디렉토리로 사용하고 애플리케이션이 읽을 수 있는 src/main/resources 디렉터리가 위치해 있기 때문에 문제가 없지만, 배포하려는 EC2 인스턴스에서는 해당 프로젝트 디렉토리가 존재하지 않고, jar 파일을 빌드하면 리소스는 루트 디렉토리에 위치하게 됩니다. 그래서 위치에 해당하는 파일을 찾을 수가 없는 것이었습니다.
jar tf build/libs/noti-0.0.1-SNAPSHOT.jar
명령어를 통해 jar 파일의 내부를 확인하면 다음과 같습니다.
리소스의 파일들이 루트 디렉토리로 이동한 것을 볼 수 있고, 어플리케이션에서 리소스를 로드하기 위해서는 특정 파일 위치가 아닌 클래스 경로에서 로드하는 방법으로 해결 할 수 있습니다.
@Configuration
public class FirebaseConfig {
@Value("${firebase.keyPath}")
private String keyPath;
@PostConstruct
void init() throws IOException {
InputStream serviceAccount = getClass().getResourceAsStream(keyPath);
if (Objects.isNull(serviceAccount)) {
throw new NullPointerException("service account is null");
}
FirebaseOptions options = FirebaseOptions.builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.build();
FirebaseApp.initializeApp(options);
}
}
위의 jar의 위치를 보면 classes/serviceAccountKey.json 이기 때문에 properties의 firebase.keyPath 경로를 "/serviceAccountKey.json"으로 변경했습니다.
getResourceAsStream(keyPath) 는 주어진 리소스의 클래스 경로를 살펴보고 해당 리소스를 로드하고, 앞 슬래시는 로더가 클래스 경로의 베이스에서 읽도록 지시합니다.
null 예외 상황에 대해 처리도 추가했습니다.
참고
https://www.baeldung.com/java-classpath-resource-cannot-be-opened
https://stackoverflow.com/questions/23547488/filenotfoundexception-in-src-main-resources
'java' 카테고리의 다른 글
이펙티브 자바 - ITEM 5 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 (0) | 2024.05.20 |
---|---|
mockStatic 사용시 자원해제 문제 (0) | 2023.10.03 |
JAVA - 기본 타입(primitive type) (0) | 2023.02.08 |