search:

scala에서 resources 디렉터리 파일 사용하기

09 Jan 2021

목차

1. 개요

sbt도 java maven의 디렉터리 구조를 사용한다. 따라서 src/main/resources/ 디렉터리에 존재하는 파일은 자동으로 읽을 수 있다.

sbt를 이용하여 scala 언어에서 resources 디렉터리의 파일을 읽는 예제 코드를 작성해봤다.

실제 작동하는 코드는 github repository에 등록해두었으니 참고바란다.

예제 코드에서는 단순히 파일을 읽는 것 이외에 hocon file의 include() 기능도 추가해두었다. hocon 파일에 대해서는 본인이 작성한 HOCON 파일, pureconfig, pyhocon 포스팅을 참고하도록 한다.

2. 예제 코드

2-1) json file 읽기

// 1. 파일 읽기: classpath에 존재하는 파일
println(scala.io.Source.fromInputStream(getClass.getClassLoader.getResourceAsStream("conf.json")).mkString)

// 2. 파일 읽기: 절대 경로로 입력
//    위 방식과 차이점: getClassLoader()가 없다
println(scala.io.Source.fromInputStream(getClass.getResourceAsStream("/conf.json")).mkString)

// 3. 파일 경로 출력하기
val res = getClass.getResource("/conf.json")
println(res.getPath)

실행 결과에서 파일 내용이 출력되는 것은 당연하다.

res.getPath의 경로를 잘 봐두면 좋은데 IntelliJ 등 IDE에서 실행하면 경로가 아래처럼 출력된다.

/path/to/project/target/scala-2.12/classes/conf.json

fat jar에서 수행하면 다음과 같이 출력된다.

file:/path/to/project/target/scala-2.12/example.jar!/conf.json

즉, 소스 코드 상태의 resources 디렉터리와 상관없이 수행 시에는 build 경로로 이동하는 것을 볼 수 있다. 특히 assembly 이후에는 jar 안에 포함된다. 따라서 assembly 이후에는 원본 파일을 수정한다 하더라도 수정된 내용이 jar에 반영되지 않는다.

2-2) hocon file 사용하기

단순히 hocon file을 읽는 것은 쉬워서 include()가 제대로 작동하는 예제를 작성하였다.

val configUrl: URL = getClass.getClassLoader.getResource("app1.conf")

val myConfig: MyConfig = getConfigFromURL(configUrl)

println(myConfig)

private def getConfigFromURL(config: URL): MyConfig = {
  implicit def hint[T] = ProductHint[T](ConfigFieldMapping(CamelCase, CamelCase))

  pureconfig.loadConfigOrThrow[MyConfig](ConfigFactory.parseURL(config).resolve)
}

위 테스트에서는 다음과 같이 두 개의 파일을 사용하였다.

  • app1.conf
      {
        name = my-program
        include classpath("include/inc.conf")
      }
    
  • include/inc.conf
      {
        server {
          hostname = localhost
          port = 8080
        }
      }
    

실행 결과는 다음과 같다.

MyConfig(my-program,Server(localhost,8080))

3. sbt에서 resource 디렉터리 변경하기

기본 resources 디렉터리는 src/main/resources/ 이다. build.sbt에 아래 내용을 추가하면 경로를 변경할 수 있다.

Compile / resourceDirectory := baseDirectory.value / "resources"

아래의 내용을 추가하면 임의의 경로를 resources에 추가할 수 있다.

Compile / unmanagedResourceDirectories += baseDirectory.value / "conf"

4. 참고 자료

  • https://stackoverflow.com/a/42155532/2930152
  • http://fruzenshtein.com/scala-working-with-resources-folders-files/
  • https://www.scala-sbt.org/1.x/docs/Howto-Customizing-Paths.html