Kotlin 2.3 Android 면접 완벽 가이드: 이름 기반 구조 분해, KMP, 핵심 질문 정리 2026
2026년 Android 개발자 면접에서 출제되는 Kotlin 2.3 신기능을 상세히 분석합니다. 이름 기반 구조 분해, Kotlin Multiplatform, 컨텍스트 파라미터, Flow와 코루틴 코드 예제를 포함합니다.

2026년 현재, Kotlin 2.3 면접 질문은 Android 개발자 채용에서 가장 많이 검색되는 주제 중 하나로 자리잡았습니다. 이름 기반 구조 분해 선언, 안정화된 컨텍스트 파라미터, 성숙한 Kotlin Multiplatform 생태계 등 면접관들은 후보자에게 이러한 기능에 대한 깊은 이해를 기대합니다.
2026년 3월에 출시된 Kotlin 2.3.20은 이름 기반 구조 분해 선언, 컨텍스트 파라미터의 오버로드 해소 변경, C 및 TypeScript와의 KMP 상호 운용성 개선을 도입했습니다. 이러한 기능은 시니어 Android 면접에서 자주 출제됩니다.
이름 기반 구조 분해: Kotlin 2.3 면접에서 가장 빈출되는 문제
Kotlin 2.3 이전에는 구조 분해 선언이 위치 기반 componentN() 함수에 의존했습니다. 이로 인해 데이터 클래스의 프로퍼티 순서를 변경하면 기존 구조 분해 코드가 조용히 깨지는 잘 알려진 함정이 존재했습니다.
전형적인 면접 문제는 다음과 같은 시나리오를 제시합니다:
data class User(val username: String, val email: String)
fun main() {
val user = User("alice", "alice@example.com")
// Position-based: order matters, not names
val (email, username) = user
println(email) // Prints "alice" -- wrong!
println(username) // Prints "alice@example.com" -- wrong!
}Kotlin 2.3.20은 이름 기반 구조 분해를 통해 이 문제를 해결했습니다. 컴파일러에는 동작을 제어하는 세 가지 모드가 있습니다:
kotlin {
compilerOptions {
// Mode 1: Explicit syntax only
freeCompilerArgs.add("-Xname-based-destructuring=only-syntax")
// Mode 2: Warns on name mismatch
// freeCompilerArgs.add("-Xname-based-destructuring=name-mismatch")
// Mode 3: Full name-based by default
// freeCompilerArgs.add("-Xname-based-destructuring=complete")
}
}complete 모드에서는 소괄호가 이름 기반 매칭을 사용하고, 대괄호는 위치 기반 동작을 유지합니다:
data class User(val username: String, val email: String)
fun main() {
val user = User("alice", "alice@example.com")
// Name-based: matches by property name
val (email, username) = user
println(email) // "alice@example.com" -- correct
println(username) // "alice" -- correct
// Position-based: square brackets preserve old behavior
val [first, second] = user
println(first) // "alice" (component1)
println(second) // "alice@example.com" (component2)
}면접에서 높은 평가를 받는 답변은 세 가지 모드를 모두 설명하고 각각의 적용 시나리오를 명확히 합니다. only-syntax는 점진적 마이그레이션에, name-mismatch는 기존 코드의 버그 탐지에, complete는 신규 프로젝트에 적합합니다.
Android 개발자를 위한 Kotlin Multiplatform 면접 질문
KMP는 실험 단계를 벗어나 본격적인 프로덕션 환경에 진입했습니다. Google은 Android와 iOS 간 비즈니스 로직 공유를 공식적으로 지원하며, 대부분의 신규 멀티플랫폼 프로젝트는 공유 코어 아키텍처를 기본으로 채택하고 있습니다.
일반적인 면접 질문은 "공유 네트워킹 모듈을 KMP로 어떻게 구성하겠습니까?"라는 형태입니다:
import io.ktor.client.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
@Serializable
data class UserProfile(
val id: String,
val displayName: String,
val avatarUrl: String?
)
// Expect/actual pattern for platform-specific HTTP engine
expect fun createHttpClient(): HttpClient
class ApiClient {
private val client = createHttpClient()
private val json = Json { ignoreUnknownKeys = true }
// Suspend function shared across Android and iOS
suspend fun fetchProfile(userId: String): UserProfile {
val response = client.get("https://api.example.com/users/$userId")
return json.decodeFromString(response.bodyAsText())
}
}import io.ktor.client.*
import io.ktor.client.engine.okhttp.*
// Android uses OkHttp engine
actual fun createHttpClient(): HttpClient = HttpClient(OkHttp) {
engine {
config {
retryOnConnectionFailure(true)
}
}
}면접관은 후보자가 expect/actual 메커니즘, 플랫폼별 의존성, 공유 코드와 플랫폼 코드의 경계를 이해하고 있는지 평가합니다.
또 다른 빈출 질문은 Swift Export에 관한 것입니다. 2026년에는 Swift Export가 크게 발전하여, Kotlin의 suspend 함수가 Swift의 async/await에 직접 매핑되고, sealed class가 Swift의 associated value를 가진 enum으로 매핑됩니다.
컨텍스트 파라미터와 오버로드 해소 변경
컨텍스트 파라미터는 더 이상 사용되지 않는 컨텍스트 리시버 API를 대체합니다. Kotlin 2.3.20에서는 오버로드 해소에 파괴적 변경이 도입되었습니다. 컨텍스트 파라미터가 있는 선언은 더 이상 컨텍스트 파라미터가 없는 선언보다 더 구체적인 것으로 간주되지 않습니다.
class Logger {
fun info(msg: String) = println("INFO: $msg")
}
class TransactionScope {
fun execute(block: () -> Unit) = block()
}
// Function with context parameter
context(logger: Logger)
fun saveUser(id: Int) {
logger.info("Saving user $id")
}
// Overload without context -- now ambiguous in 2.3.20
fun saveUser(id: Int) {
println("Saving user $id (no logger)")
}
fun main() {
val logger = Logger()
// This now produces an ambiguity error in Kotlin 2.3.20
// context(logger) { saveUser(1) }
// Fix: rename or qualify the context-aware variant
}면접관은 이 주제를 통해 후보자가 파괴적 변경에 대한 인식과 마이그레이션 전략을 갖추고 있는지 평가합니다. 핵심 요점은 암묵적 컨텍스트 파라미터 해소를 통한 비컨텍스트 오버로드의 섀도잉이 더 이상 작동하지 않는다는 것입니다.
코루틴과 Flow: Android 면접의 최다 출제 영역
Kotlin 2.3에서 새로운 기능이 추가되었음에도 불구하고, 코루틴과 Flow는 여전히 가장 많이 테스트되는 영역입니다. 면접에서는 일반적으로 콜드 플로우와 핫 플로우의 차이, 구조화된 동시성, 취소에 대해 심층적으로 질문합니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
// Cold Flow: emits only when collected
fun userUpdates(): Flow<String> = flow {
println("Flow started") // Runs per collector
emit("User logged in")
delay(1000)
emit("User updated profile")
}
// Hot Flow: emits independently of collectors
class UserRepository {
// StateFlow holds the latest value
private val _state = MutableStateFlow("idle")
val state: StateFlow<String> = _state.asStateFlow()
// SharedFlow broadcasts to multiple collectors
private val _events = MutableSharedFlow<String>()
val events: SharedFlow<String> = _events.asSharedFlow()
suspend fun login() {
_state.value = "loading"
delay(500)
_state.value = "authenticated"
_events.emit("login_success")
}
}후속 질문에서는 Android에서 Flow를 안전하게 수집하는 방법이 자주 출제됩니다:
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
class UserViewModel(private val repo: UserRepository) : ViewModel() {
// Expose state to Compose UI
val uiState: StateFlow<String> = repo.state
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = "idle"
)
init {
// Collect events safely within ViewModel scope
viewModelScope.launch {
repo.events.collect { event ->
// Handle one-time events
println("Event received: $event")
}
}
}
}WhileSubscribed(5000) 전략은 마지막 구독자가 사라진 후 5초 동안 업스트림을 활성 상태로 유지합니다. 이를 통해 화면 회전과 같은 구성 변경 시 불필요한 재시작을 방지할 수 있습니다.
Android 면접 준비가 되셨나요?
인터랙티브 시뮬레이터, flashcards, 기술 테스트로 연습하세요.
Sealed 클래스와 완전한 when 식: 면접에서의 패턴 매칭
Sealed 클래스는 거의 모든 Android 면접에서 등장합니다. 전형적인 질문은 UI 상태를 모델링하는 것입니다:
sealed interface UiState<out T> {
data object Loading : UiState<Nothing>
data class Success<T>(val data: T) : UiState<T>
data class Error(val message: String, val retry: (() -> Unit)? = null) : UiState<Nothing>
}
// Usage in ViewModel
fun loadUsers(): Flow<UiState<List<UserProfile>>> = flow {
emit(UiState.Loading)
try {
val users = apiClient.fetchUsers()
emit(UiState.Success(users))
} catch (e: Exception) {
emit(UiState.Error(
message = e.localizedMessage ?: "Unknown error",
retry = { /* trigger reload */ }
))
}
}Kotlin에서 sealed 타입에 대한 when 식은 컴파일 시점에 완전성이 검증됩니다. 새로운 하위 타입을 추가하면 모든 곳에서 처리가 강제되므로, 런타임 버그의 한 범주 전체가 제거됩니다. 면접관은 특히 후보자가 이 패턴에서 sealed class가 아닌 sealed interface를 사용하는지 확인합니다. 인터페이스가 더 유연한 계층 구조를 가능하게 하기 때문입니다.
Kotlin/Wasm과 크로스 플랫폼 컴파일 타겟
Kotlin/Wasm은 Beta 상태에 도달하여 브라우저에서 네이티브에 가까운 성능을 제공합니다. Android 개발자의 일상 업무에서 직접적으로 다루는 경우는 아직 드물지만, 웹+모바일 제품을 보유한 기업의 면접에서는 출제될 수 있습니다.
면접에서 알아야 할 핵심 사항:
- Kotlin 2.3.20은 JS String builtins를 통해 Wasm에서 문자열 보간 성능을 4.6배 향상
- 바이너리 크기가 약 5% 감소
- 클린 빌드가 65% 빨라지고, 증분 빌드가 21% 빨라짐
@nativeInvoke어노테이션으로 Kotlin 객체를 JavaScript 함수로 동작시킬 수 있음
Kotlin/JS에서도 TypeScript에서 Kotlin 인터페이스를 구현하는 기능이 추가되어 이전의 제한이 해소되었습니다. SWC 트랜스파일 지원과 결합하여, Kotlin은 단일 코드베이스에서 Android, iOS(KMP 경유), 웹(Wasm/JS 경유), 서버 사이드까지 모든 타겟을 커버할 수 있게 되었습니다.
스코프 함수: 보기보다 까다로운 면접 필터 문제
스코프 함수(let, run, with, apply, also)는 간단해 보이지만 숙련된 Kotlin 개발자를 구분하는 효과적인 지표입니다. 전형적인 면접 질문은 "let과 apply를 어떻게 구분하여 사용합니까?"입니다.
data class Request(
var url: String = "",
var method: String = "GET",
var headers: MutableMap<String, String> = mutableMapOf(),
var body: String? = null
)
fun buildRequest(): Request {
// apply: configure an object, returns the object
return Request().apply {
url = "https://api.example.com/users"
method = "POST"
headers["Content-Type"] = "application/json"
body = "{\"name\": \"Alice\"}"
}
}
fun processNullable(input: String?) {
// let: transform nullable, returns lambda result
val length = input?.let { value ->
println("Processing: $value")
value.trim().length
} ?: 0
// also: side effects, returns the original object
input?.also { println("Logging input: $it") }
// run: execute a block with receiver, returns lambda result
val result = input?.run {
// 'this' is the string
uppercase().take(10)
}
}판단 기준은 다음과 같습니다: apply는 객체 구성(리시버 반환), let은 null 안전 변환(람다 결과 반환), also는 부수 효과(리시버 반환), run은 리시버 컨텍스트에서 결과를 계산할 때 사용합니다.
Null 안전성과 더블 뱅의 위험성
Null 안전성은 면접의 기본 주제로 확고히 자리잡고 있습니다. "왜 !!는 위험한가?"라는 질문은 후보자가 Kotlin의 타입 시스템을 근본적으로 이해하고 있는지 확인하는 것입니다.
fun findUser(id: String): User? {
// Returns null if user not found
return database.queryUser(id)
}
// Bad: !! defeats the purpose of null safety
fun riskyApproach(id: String) {
val user = findUser(id)!! // NullPointerException if null
println(user.username)
}
// Good: handle null explicitly
fun safeApproach(id: String) {
val user = findUser(id) ?: run {
println("User not found")
return
}
println(user.username)
}
// Good: provide default with Elvis operator
fun displayName(id: String): String {
return findUser(id)?.username ?: "Anonymous"
}완전한 답변에서는 !!가 테스트 코드나 플랫폼 상호 운용 경계처럼 null이 절대 발생할 수 없는 상황에서만 사용되어야 한다고 언급합니다.
연습을 시작하세요!
면접 시뮬레이터와 기술 테스트로 지식을 테스트하세요.
결론
- Kotlin 2.3.20의 이름 기반 구조 분해는 위치 의존적 버그를 제거합니다. 세 가지 컴파일러 모드(
only-syntax,name-mismatch,complete)를 숙지해야 합니다 - KMP는 2026년에 프로덕션 수준으로 안정화되었습니다. expect/actual, 공유 모듈 아키텍처, Swift Export 상호 운용에 대한 질문이 예상됩니다
- 컨텍스트 파라미터가 컨텍스트 리시버를 대체했습니다. 2.3.20의 오버로드 해소 변경은 자주 출제되는 함정 문제입니다
- 코루틴과 Flow는 Android 면접을 지배합니다.
StateFlow대SharedFlow,WhileSubscribed, 구조화된 동시성을 마스터해야 합니다 - Sealed 인터페이스는 컴파일 시점 완전성 검사를 통한 UI 상태 모델링에 적합합니다.
sealed class보다sealed interface를 선호해야 합니다 - 스코프 함수에는 명확한 판단 기준이 필요합니다: 리시버 대 인수, 반환값 대 리시버
- Null 안전성은 타협할 수 없는 항목입니다.
!!가 타입 시스템을 훼손하는 이유를 설명하고 대안을 제시할 수 있어야 합니다
연습을 시작하세요!
면접 시뮬레이터와 기술 테스트로 지식을 테스트하세요.
태그
공유
관련 기사

Jetpack Compose 면접 질문 20선 (2026년)
Jetpack Compose 면접에서 자주 출제되는 20가지 질문을 해설합니다. 리컴포지션, 상태 관리, 사이드 이펙트, 내비게이션, 성능 최적화, 아키텍처 패턴을 포괄적으로 다룹니다.

Kotlin 코루틴 완전 가이드 2026: Android 비동기 처리 마스터하기
Android 개발에 필수적인 Kotlin 코루틴을 기초부터 고급 패턴까지 체계적으로 학습합니다. suspend 함수, 스코프, 디스패처, Flow를 실전 코드와 함께 배울 수 있습니다.

Jetpack Compose: 고급 애니메이션 단계별 가이드
Compose 고급 애니메이션 완벽 가이드: 전환, AnimatedVisibility, Animatable, 제스처, 부드러운 Android 인터페이스를 위한 성능.