api vs implementation

api vs implementation

두가지 차이점이 있다.

아래와 같은 디펜던시 트리가 있다고 하면

LibraryD:

class ClassD {

    fun tellMeAJoke():String{
        return "You are funny :D"
    }
}

LibraryC:

class ClassC {

    fun tellMeAJoke(): String {
        return "You are funny :C"
    }
}

LibraryB:

class ClassB {

    val d = ClassD()

    fun whereIsMyJoke(): String {
        return d.tellMeAJoke()
    }
}

LibraryA:


class ClassA {

    val c = ClassC()

    fun whereIsMyJoke(): String {
        return c.tellMeAJoke()
    }
}

접근성의 차이

api를 사용하는 경우

LibraryB의 의존성

dependencies {
      . . . . 
      api project(path: ':libraryD')
}

App Module의 의존성

dependencies {
      . . . . 
      api project(path: ':libraryB')
}

App Module에서 LibraryB, LibraryD 모두 접근가능하다.

fun getJokeFromB(): String {
    return ClassB().whereIsMyjoke()
}

fun getJokeFromD(): String {
    return ClassD().tellMeAJoke()
}

implementation을 사용하는 경우

LibraryA의 의존성

dependencies {
      . . . . 
      implementation project(path: ':libraryC')
}

App Module의 의존성

dependencies {
      . . . . 
      implementation project(path: ':libraryA')
}

App Module에서 LibraryA만 접근가능하다.

fun getJokeFromA(): String {
    return ClassA().whereIsMyjoke()
}

// LibraryC에 접근하지 못하기 때문에 컴파일 에러가 발생한다.
fun getJokeFromC(): String {
    return ClassC().tellMeAJoke()
}

컴파일의 차이

api를 사용할 경우

LibraryD에서 변경이 발생하면 LibraryD를 사용할 수 있는 모든 모듈(LibraryB, ModuleX)을 재컴파일해야 한다.

implementation를 사용할 경우

LibraryC에서 변경이 발생하면 LibraryC를 사용할 수 있는 LibraryA만 재컴파일하면 된다.

Reference