기존에 작성하던 Scala+Spark 애플리케이션을 어떻게 구동하고 데이터를 클라이언트 측에 어떻게 전달할까 고민중이였다.
지금은 IntellJ IDEA를 통해 Scala 애플리케이션을 실행하고 있지만 운영 환경에서 불가능한 일이고, sbt CLI를 통한 실행의 경우에도 메인 백엔드 서버에서 sbt 명령을 실행시키는 시나리오부터 문제지만 실행시켰다고 해도 그 결과를 서버로 받아오는 방법 또한 알 수 없기 때문에 다른 방법을 생각해야했다.
첫 번째로 생각한 방법은 Spring 서버 코드에 Scala 코드를 포함시키는 방법이였는데, Scala도 JVM 기반의 언어이고 실제로 같은 JVM 기반의 언어인 Kotlin 또한 하나의 Spring 서버 코드 내에서 Java와 함께 사용될 수 있으니 가능할거라고 생각했다.
그러나 그건 내 착각이였고.. 기본적으로 Spring 프레임워크 내에서 Scala 코드를 사용할 수 있는 것에는 문제가 없었지만 Spark를 사용하는 코드에서 정말 많은 문제가 생겼다.
Spring에서는 Slf4j 구현체로 Logback
을 사용하는데 Spark에서는 reload4j
를 사용함에 따라 로깅 라이브러리의 의존성 충돌 발생
→ build.gradle에서 reload4j
모듈을 제외시켜서 일단 해결
Java로 작성된 Controller 메서드에서 Scala 클래스를 찾지 못하는 문제 발생
Java 컴파일러가 import 문에 대응하는 Scala 클래스를 찾지 못해서 컴파일 에러가 발생한 것으로 빌드 과정에서 Scala 코드가 제대로 컴파일되지 않은 것.
→ Java 컴파일러는 Scala 코드를 컴파일할 수 없어서 빌드 과정에서 Java 컴파일러와 Scala 컴파일러가 각각의 언어 코드를 컴파일해야함. Scala 컴파일러가 Java 컴파일러보다 먼저 동작하면 되지 않을까? 싶어서 Scala 코드가 먼저 컴파일되도록 build.gradle에 compileJava.dependsOn compileScala
코드를 추가해봤더니 순환 의존성 에러를 만났다.
Circular dependency between the following tasks:
:compileJava
\--- :compileScala
\--- :compileJava (*)
에러 로그를 보면 기본적으로 Gradle의 빌드 과정에서 Scala 컴파일 task가 Java 컴파일 task에 의존하도록 설정되어 있는 것 같아서 Scala 코드가 먼저 컴파일되도록 하는 것은 힘들어보였다. 그래서 찾은 다음 방법은 전체 코드를 Scala 컴파일러가 모두 컴파일하도록 하는 것인데, Java 컴파일러와 달리 Scala 컴파일러는 Java 코드를 컴파일할 수 있어서 가능한 방법이었다. 아래와 같이 각 컴파일러의 source directory set을 설정해줌으로써 Scala 컴파일러가 Java 코드까지 컴파일하게 할 수 있었다.
sourceSets {
main {
scala {
srcDirs = ['src/main/scala', 'src/main/java']
}
java {
srcDirs = []
}
}
}
로그 확인 불가
이제 드디어 빌드에 성공하고 Spring 서버가 구동이 되기 시작했다! 이제 됐겠지 하고 Spark 코드를 실행해봤는데..
다시 로그 관련 의존성 문제가 생겼다. 앞서서 Spark이 사용하는 로깅 모듈을 해서 생긴 문제인 것으로 보여서 제외 모듈을 reload4j
에서 logback
으로 변경해줬다. 그 결과 당연히 Spring의 로깅 모듈이 없어졌기 때문에 서버 실행 간에 Spring 관련 로그가 모두 사라졌고 이 뿐만 아니라 웬걸 Spark 코드에서 발생하는 로그조차 제대로 표시되지 않았다. 거기에 실제 Spark 코드는 아무런 동작도 하지 않고 로그조차 볼 수 없는 상태가 되니 이 방법을 접을 때가 됐다는 생각이 들었다.
호환되는 Spring 버전을 찾아나서기보다는 Scala로 구현 가능한 웹 프레임워크인 Play Framework에 도전하기로 했다.
📌 Spring 공식 문서에 따르면 Spring for Apache Hadoop은 2.7.3 버전(Hadoop 버전은 2.5.0)까지만 공식 지원되었고, 이후 버전에 대한 지원 소식은 없다. Spark는 기본적으로 Hadoop 생태계에 위치해 있기에 Spark에 대한 최신 버전에 대한 추가 지원 또한 중단된 것으로 보인다 😢
https://stackoverflow.com/questions/48022211/how-to-make-compilekotlin-dependson-compilejava-in-gradle
https://spring.io/projects/spring-hadoop