시니어 Android 개발자 면접 질문: Kotlin, Compose, 아키텍처

Milad Bonakdar
작성자
Kotlin 코루틴, Jetpack Compose 상태, 앱 아키텍처, 성능, 테스트, 오프라인 우선 데이터, 보안을 중심으로 시니어 Android 면접을 준비하세요.
소개
시니어 Android 개발자 면접에서는 아키텍처 트레이드오프, 라이프사이클에 안전한 동시성, Compose 상태 소유권, 오프라인 우선 데이터 흐름, 성능 진단, 테스트 전략, 보안을 설명할 수 있어야 합니다. 좋은 답변은 어떤 API를 쓰는지에서 끝나지 않고, 제품 제약에 왜 맞는지와 프로덕션에서 어떻게 디버깅할지도 보여줍니다.
이 가이드는 실전 체크리스트로 활용하세요. Kotlin 코루틴과 Flow, ViewModel과 상태 관리, Room 기반 repository, Compose와 레거시 UI 선택, 시작 시간과 메모리, 그리고 본인의 앱에서 설명할 수 있는 사례를 먼저 준비하는 것이 좋습니다.
이 질문들을 활용하는 방법
- 각 답변을 짧은 의사결정으로 연습하세요: 맥락, 트레이드오프, 구현, 실패 모드.
- 기술 선택을 더 빠른 시작, 안정적인 오프라인 읽기, 안전한 토큰 저장, 라이프사이클 버그 감소 같은 사용자 영향과 연결하세요.
- 아키텍처, 성능, 테스트, 보안에 대해 실제 프로젝트 사례를 하나씩 준비하세요.
고급 Kotlin & 언어 기능 (5 문제)
1. Kotlin 코루틴과 스레드에 비해 장점을 설명하세요.
답변: 코루틴은 비동기 코드를 순차적으로 작성할 수 있게 해주는 경량 동시성 기본 요소입니다.
- 스레드에 비해 장점:
- 경량: 성능 문제 없이 수천 개의 코루틴을 생성할 수 있습니다.
- 구조화된 동시성: 부모-자식 관계는 적절한 정리를 보장합니다.
- 취소 지원: 내장된 취소 전파
- 예외 처리: 구조화된 예외 처리
- 주요 구성 요소:
- CoroutineScope: 라이프사이클을 정의합니다.
- Dispatchers: 실행 컨텍스트를 제어합니다 (Main, IO, Default).
- suspend functions: 일시 중지 및 재개될 수 있습니다.
희소성: 매우 흔함 난이도: 어려움
2. Sealed 클래스란 무엇이며 언제 사용해야 할까요?
답변: Sealed 클래스는 모든 하위 클래스가 컴파일 시간에 알려진 제한된 클래스 계층 구조를 나타냅니다.
- 장점:
- 완전한
when표현식 - 타입 안전 상태 관리
- 복잡한 데이터에 대한 열거형보다 나음
- 완전한
- 사용 사례: 상태, 결과, 탐색 이벤트를 나타냅니다.
희소성: 흔함 난이도: 중간
3. Kotlin Flow를 설명하고 LiveData와 어떻게 다른지 설명하세요.
답변: Flow는 값을 순차적으로 방출하는 Kotlin의 콜드 비동기 스트림입니다.
- Flow vs LiveData:
- Flow: 콜드 스트림, 연산자 지원, 라이프사이클 인식 아님, 더 유연함
- LiveData: 핫 스트림, 라이프사이클 인식, Android 특정, UI에 더 간단함
- Flow 유형:
- Flow: 콜드 스트림 (수집 시 시작)
- StateFlow: 현재 상태가 있는 핫 스트림
- SharedFlow: 이벤트를 위한 핫 스트림
희소성: 매우 흔함 난이도: 어려움
4. Inline 함수란 무엇이며 언제 사용해야 할까요?
답변: Inline 함수는 함수 호출 오버헤드를 피하기 위해 함수 본문을 호출 사이트로 복사합니다.
- 장점:
- 람다 할당 오버헤드 제거
- 람다에서 비지역 반환 허용
- 고차 함수에 대한 더 나은 성능
- 사용 사례: 람다 매개변수가 있는 고차 함수
- Trade-off: 코드 크기 증가
희소성: 중간 난이도: 어려움
5. Kotlin에서 Delegation을 설명하세요.
답변: Delegation을 사용하면 객체가 일부 책임을 다른 객체에 위임할 수 있습니다.
- 클래스 Delegation:
by키워드 - 속성 Delegation: Lazy, observable, delegates
- 장점: 코드 재사용, 상속보다 구성
희소성: 중간 난이도: 중간
아키텍처 패턴 (6 문제)
6. MVVM 아키텍처와 장점을 설명하세요.
답변: MVVM (Model-View-ViewModel)은 UI 로직과 비즈니스 로직을 분리합니다.
- Model: 데이터 레이어 (repositories, data sources)
- View: UI 레이어 (Activities, Fragments, Composables)
- ViewModel: 프레젠테이션 로직, 구성 변경에서 살아남음
- 장점: 테스트 가능, 관심사 분리, 라이프사이클 인식
희소성: 매우 흔함 난이도: 중간
7. Clean Architecture란 무엇이며 Android에서 어떻게 구현하나요?
답변: Clean Architecture는 코드를 명확한 종속성이 있는 레이어로 분리합니다.
- Presentation: UI, ViewModels
- Domain: Use Cases, Business Logic, Entities
- Data: Repositories, Data Sources (API, Database)
- 종속성 규칙: 내부 레이어는 외부 레이어에 대해 알지 못합니다.
희소성: 흔함 난이도: 어려움
8. Dependency Injection과 Dagger/Hilt를 설명하세요.
답변: Dependency Injection은 클래스 내부에서 종속성을 생성하는 대신 클래스에 종속성을 제공합니다.
- 장점: 테스트 가능성, 느슨한 결합, 재사용성
- Dagger: 컴파일 시간 DI 프레임워크
- Hilt: Android용 간소화된 Dagger
희소성: 매우 흔함 난이도: 어려움
9. Repository 패턴이란 무엇이며 왜 사용해야 할까요?
답변: Repository 패턴은 데이터 소스를 추상화하여 데이터 액세스를 위한 깔끔한 API를 제공합니다.
- 장점:
- 단일 소스 진실
- 중앙 집중식 데이터 로직
- 데이터 소스 전환 용이
- 테스트 가능
- 구현: 여러 데이터 소스 간 조정
희소성: 매우 흔함 난이도: 중간
10. Single Activity 아키텍처를 설명하세요.
답변: Single Activity 아키텍처는 Navigation Component에서 관리하는 여러 Fragments가 있는 하나의 Activity를 사용합니다.
- 장점:
- 간소화된 탐색
- 프래그먼트 간 공유 ViewModels
- 더 나은 애니메이션
- 더 쉬운 딥 링크
- Navigation Component: 프래그먼트 트랜잭션, 백 스택, 인수를 처리합니다.
희소성: 흔함 난이도: 중간
11. MVI (Model-View-Intent) 아키텍처란 무엇인가요?
답변: MVI는 Redux에서 영감을 받은 단방향 데이터 흐름 아키텍처입니다.
- 구성 요소:
- Model: UI 상태를 나타냅니다.
- View: 상태를 렌더링하고 intents를 내보냅니다.
- Intent: 사용자 작업/이벤트
- 장점: 예측 가능한 상태, 쉬운 디버깅, 시간 여행 디버깅
희소성: 중간 난이도: 어려움
성능 및 최적화 (5 문제)
12. RecyclerView 성능을 어떻게 최적화하나요?
답변: 여러 전략이 RecyclerView 스크롤 성능을 향상시킵니다.
- ViewHolder 패턴: 뷰 재사용 (내장)
- DiffUtil: 효율적인 목록 업데이트
- Stable IDs:
getItemId()를 재정의하고setHasStableIds(true)를 설정합니다. - Prefetching: 프리페치 거리 증가
- 이미지 로딩: 적절한 크기 조정을 통해 Glide/Coil과 같은 라이브러리 사용
- 과도한 작업 방지:
onBindViewHolder에서 비용이 많이 드는 계산을 수행하지 마십시오. - 중첩된 RecyclerViews:
setRecycledViewPool()및setHasFixedSize(true)를 설정합니다.
희소성: 매우 흔함 난이도: 중간
13. Android에서 메모리 누수를 감지하고 수정하는 방법은 무엇인가요?
답변: 메모리 누수는 객체가 필요한 것보다 오래 메모리에 보관될 때 발생합니다.
- 일반적인 원인:
- 컨텍스트 누수 (Activity/Fragment 참조)
- 정적 참조
- 익명 내부 클래스
- 등록되지 않은 리스너
- 취소되지 않은 코루틴
- 감지 도구:
- LeakCanary 라이브러리
- Android Studio Memory Profiler
- 힙 덤프
희소성: 매우 흔함 난이도: 중간
14. 앱 시작 시간을 어떻게 최적화하나요?
답변: 더 빠른 시작은 사용자 경험을 향상시킵니다.
- Lazy Initialization: 필요한 경우에만 객체를 초기화합니다.
- Application.onCreate()에서 과도한 작업 방지:
- 백그라운드 스레드로 이동
- 중요하지 않은 초기화 연기
- Content Providers: 최소화하거나 lazy-load합니다.
- 종속성 감소: 라이브러리가 적을수록 시작 속도가 빨라집니다.
- App Startup Library: 구조화된 초기화
- Baseline Profiles: AOT (Ahead-of-time) 컴파일 힌트
희소성: 흔함 난이도: 중간
15. 비트맵 로딩 및 캐싱을 효율적으로 처리하는 방법은 무엇인가요?
답변: 효율적인 이미지 처리는 성능에 매우 중요합니다.
- 라이브러리: Glide, Coil (자동으로 캐싱 처리)
- 수동 최적화:
- 다운샘플링 (더 작은 이미지 로드)
- 메모리 캐시 (LruCache)
- 디스크 캐시
- 비트맵 풀링
희소성: 흔함 난이도: 어려움
16. ANR이란 무엇이며 어떻게 방지하나요?
답변: ANR (Application Not Responding)은 기본 스레드가 너무 오랫동안 차단될 때 발생합니다.
- 원인:
- 기본 스레드에서 과도한 계산
- 기본 스레드에서 네트워크 호출
- 기본 스레드에서 데이터베이스 작업
- 데드락
- 예방:
- 과도한 작업을 백그라운드 스레드로 이동
- 적절한 디스패처로 코루틴 사용
- 기본 스레드에서 동기화된 블록 방지
- 백그라운드 작업에 WorkManager 사용


