Skip to content

internal의 범위는 어디까지일까?

이진혁 edited this page Jun 10, 2021 · 3 revisions

개요

코틀린에서는 public(default), internal, protected, private이라는 접근 제어 지시자를 제공합니다.
internal을 제외한 모든 접근 제어 지시자는 익숙합니다.
자바에서 제공하는 package-private을 대신한 것이라고도 생각했지만,
코틀린에서의 패키지는 클래스를 나누는 네임스페이스의 역할만 하기 때문에
package-private이 존재할 수 없습니다.

internal은 모듈 단위로 접근을 제어하는 것으로 module-private이라고 부를 수도 있습니다.
그러면 이 모듈의 범위는 어디까지일까요?

실험해보기

모듈이라고 하면 자바 9에 추가된 모듈을 떠올릴 수도 있지만 가장 쉽게 떠오르는 것은
Gradle(그레이들) 프로젝트의 서브 프로젝트입니다.

그레이들을 이용하면 멀티 프로젝트를 구성하여 여러 프로젝트를 하나의 프로젝트 아래에 둘 수 있습니다.
이때 각 프로젝트를 모듈이라고 칭하는데 여기서 internal로 선언하면 모듈끼리 접근이 안 될 것이라고 생각했습니다.

a-project
    ㄴ b-project
        ㄴ src
            ㄴ com
                ㄴ j
                    ㄴ research
                        ㄴ B.kt
        ㄴ build.gradle.kts
    ㄴ c-project
        ㄴ src
            ㄴ com
                ㄴ j
                    ㄴ research
                        ㄴ C.kt
        ㄴ build.gradle.kts
    ㄴ build.gradle.kts

여기서 B 클래스의 접근 제어 지시자가 internal이라면
B 클래스와 C 클래스는 각각 다른 모듈에 정의되어 있기 때문에
서로 접근을 할 수 없는 형태가 됩니다.

주의사항

root-project
    ㄴ src
        ㄴ com
            ㄴ j
                ㄴ research
                    ㄴ A.kt
                    ㄴ B.kt

여기서 A 클래스의 접근 제어 지시자가 internal이고 B 클래스의 접근 제어 지시자가 public이라도
같은 모듈 안에 정의되어 있으므로 서로 접근이 가능해야 한다고 생각할 수도 있는데
이는 낮은 접근 수준에서는 높은 접근 수준에 접근할 수 있지만
높은 접근 수준에서는 낮은 접근 수준에 접근할 수 없다는 기본 원리를 해칩니다.

따라서 internal에서는 public 클래스를 참조할 수 있지만
public 클래스에서는 internal 클래스를 참조할 수 없습니다.

자바에서의 internal

자바에서는 internal과 같은 접근 제어 지시자가 존재하지 않습니다.
같은 모듈에서는 모두 접근 가능해야 하므로 public 접근 제어 지시자로 변경됩니다.

따라서 코틀린 코드에서는 접근할 수 없었던 클래스가 자바 코드에서는 접근할 수 있게 될 수도 있습니다.
그래서 코틀린 컴파일러는 코틀린 코드를 자바 코드로 변경할 때
internal 클래스의 이름과 메소드 명 등을 알아 볼 수 없게 변경하여
실수로 internal 클래스에 접근하는 것을 막습니다.

Tip!
자바의 protected는 상속 받은 클래스 뿐만 아니라 같은 패키지 내의 클래스도 접근이 가능하지만
코틀린에서는 무조건 상속 받은 클래스만 접근 가능합니다.

결론

internal로 선언된 클래스는 같은 모듈에서만 접근 가능하며
여기서의 모듈은 Gradle(그레이들)의 프로젝트 단위 등을 말합니다.