kotlin internal class

kotlin의 internal은 같은 모듈 내에서만 접근 가능한 가시성 제한자

 

Kotlin의 가시성 제한자

public    // 어디서나 접근 가능 (기본값)
private   // 같은 파일/클래스 내에서만
protected // 같은 클래스와 서브클래스에서만
internal  // 같은 모듈 내에서만

 

1. 모듈 단위 캡슐화

// Module A (core 모듈)
internal class DatabaseHelper {
    internal fun connect() { }
}

internal val config = Config()

// Module A 내 다른 파일에서
val helper = DatabaseHelper() // ✅ OK
helper.connect()              // ✅ OK

// Module B (api 모듈)에서
val helper = DatabaseHelper() // ❌ 컴파일 에러

 

Java와의 차이

Java에는 internal이 없습니다. Java의 package-private(default)과 비슷하지만 더 강력

// 같은 패키지 내에서만 접근 가능
class Helper{}

// 같은 모듈 내에서만 접근 가능
internal calss Helper

 

 

실무 활용 예시

예시 1: 유틸리티 클래스 숨기기

// payment-service 모듈
// StringUtils.kt
internal object StringUtils {
    fun sanitize(input: String): String {
        // 내부 구현
    }
}

// payment-service 모듈
// UserService.kt (같은 모듈)
class UserService {
    fun createUser(name: String) {
        val sanitized = StringUtils.sanitize(name) // ✅ OK
    }
}

// order-service 모듈에서
class OrderService(
    private val paymentService: PaymentService  // ✅ 사용 가능
) {
    fun checkout() {
        paymentService.processPayment("1234-5678", 10000)
        
        // ❌ 직접 암호화 불가 (internal이라 접근 불가)
        // StringUtils.encrypt("1234")
        
        // ❌ 직접 검증 불가 (internal이라 접근 불가)
        // StringUtils().validateCard("1234")
    }
}

 

 

예시 2: 구현체 숨기고 인터페이스만 공개

// 공개 인터페이스
interface PaymentProcessor {
    fun process(amount: Int)
}

// 내부 구현체들
internal class KakaoPayProcessor : PaymentProcessor {
    override fun process(amount: Int) { }
}

internal class NaverPayProcessor : PaymentProcessor {
    override fun process(amount: Int) { }
}

// 팩토리만 공개
object PaymentFactory {
    fun create(type: String): PaymentProcessor {
        return when(type) {
            "kakao" -> KakaoPayProcessor()
            "naver" -> NaverPayProcessor()
            else -> throw IllegalArgumentException()
        }
    }
}

 

 

예시 3: Spring Boot에서 활용

// 도메인 모듈
internal class UserValidator {
    fun validate(user: User): Boolean { }
}

@Service
class UserService(
    private val userValidator: UserValidator // ✅ 같은 모듈이므로 주입 가능
) {
    fun register(user: User) {
        require(userValidator.validate(user))
        // ...
    }
}
```

## 모듈이란?

Gradle/Maven 기준:
- 하나의 **Gradle/Maven 프로젝트** = 하나의 모듈
- IntelliJ 모듈
- 하나의 **JAR** 파일
```
project/
├── core/          # 모듈 1
│   └── build.gradle.kts
├── api/           # 모듈 2
│   └── build.gradle.kts
└── settings.gradle.kts

 

 

언제 사용할까?

internal 사용

- 모듈 내부 구현체를 숨기고 싶을 때

- 유틸리티 클래스를 외부에 노출하고 싶지 않을 때

- 멀티모듈 프로젝트에서 모듈 간 결합도를 낮추고 싶을 때

- 모듈의 공개 API와 내부 구현을 명확히 분리

 

public 사용

- 다른 모듈에서 사용해야 하는 API

- 라이브러리의 공개 인터페이스