Scala 신입 프레임워크 기술면접
새 면접Q. Scala에서 불변(immutable) 컬렉션과 가변(mutable) 컬렉션의 차이점은 무엇이며, 기본적으로 어떤 것을 사용하는 것이 권장되나요?
Scala 표준 라이브러리에서 import 없이 사용할 수 있는 컬렉션의 종류를 생각해보세요.
불변 컬렉션은 한번 생성되면 내용을 변경할 수 없으며, 변경 작업 시 새로운 컬렉션을 반환합니다. 가변 컬렉션은 내부 상태를 직접 수정할 수 있습니다. Scala는 기본적으로 불변 컬렉션을 권장하며, scala.collection.immutable 패키지가 기본으로 임포트됩니다. 불변 컬렉션은 스레드 안전성을 제공하고 함수형 프로그래밍 원칙에 부합하여 예측 가능한 코드를 작성할 수 있게 합니다. 가변 컬렉션이 필요한 경우에는 명시적으로 scala.collection.mutable을 임포트해야 합니다.
- • 불변 컬렉션은 변경 시 새로운 객체 반환
- • 기본적으로 불변 컬렉션 사용 권장
- • 스레드 안전성과 함수형 프로그래밍 원칙
멀티스레드 환경에서 안전하게 데이터를 공유하고 동시성 버그를 방지할 때 사용됩니다.
성능이 중요한 상황에서 불변 컬렉션 사용 시 발생할 수 있는 문제점과 해결 방법은 무엇인가요?
Q. Scala의 Option 타입이 무엇이며, null 대신 Option을 사용하는 이유는 무엇인가요?
값이 있을 수도 있고 없을 수도 있는 상황을 타입 시스템으로 어떻게 표현하는지 생각해보세요.
Option은 값이 있을 수도 있고 없을 수도 있는 상황을 타입으로 명시적으로 표현하는 컨테이너입니다. Some과 None 두 가지 서브타입을 가지며, Some은 값이 있는 경우, None은 값이 없는 경우를 나타냅니다. null을 사용하면 NullPointerException이 런타임에 발생할 수 있지만, Option을 사용하면 컴파일 타임에 값의 부재를 처리하도록 강제합니다. 이를 통해 더 안전하고 명시적인 코드를 작성할 수 있으며, map, flatMap, getOrElse 등의 메서드로 함수형 스타일로 처리할 수 있습니다.
- • 값의 존재 여부를 타입으로 표현
- • Some과 None 서브타입
- • 컴파일 타임 안전성 제공
데이터베이스 조회 결과나 API 응답처럼 값이 없을 수 있는 상황을 안전하게 처리할 때 사용됩니다.
Option 타입을 다룰 때 getOrElse와 match 표현식 중 어떤 것을 선택하는 기준은 무엇인가요?
Q. Scala의 패턴 매칭(Pattern Matching)은 무엇이며, Java의 switch-case 문과 어떤 차이점이 있나요?
타입 검사, 값 추출, 표현식으로서의 특성을 고려해보세요.
패턴 매칭은 match 키워드를 사용하여 값의 구조와 타입을 검사하고 분해하는 강력한 기능입니다. Java의 switch-case와 달리 표현식으로 동작하여 값을 반환하며, 기본 타입뿐만 아니라 케이스 클래스, 튜플, 리스트 등 복잡한 데이터 구조도 매칭할 수 있습니다. 타입 검사와 값 추출을 동시에 수행할 수 있으며, 가드 조건을 추가할 수도 있습니다. 컴파일러가 모든 케이스를 다루었는지 검사하여 누락된 패턴을 경고해주므로 더 안전한 코드를 작성할 수 있습니다.
- • 표현식으로 동작하여 값 반환
- • 복잡한 데이터 구조 매칭 가능
- • 타입 검사와 값 추출 동시 수행
JSON 파싱 결과나 HTTP 응답 처리 시 다양한 응답 타입을 구조적으로 분기할 때 사용됩니다.
패턴 매칭에서 와일드카드 패턴(_)을 사용할 때 주의해야 할 점은 무엇인가요?
Q. Scala 컬렉션의 map과 flatMap의 차이점을 설명하고, 각각 어떤 상황에서 사용하나요?
각 메서드가 반환하는 결과의 구조가 어떻게 다른지 생각해보세요.
map은 컬렉션의 각 요소에 함수를 적용하여 변환된 새로운 컬렉션을 반환합니다. flatMap은 map과 동일하게 함수를 적용하지만, 각 요소가 컬렉션을 반환할 때 이를 하나의 평평한 컬렉션으로 합쳐줍니다. 예를 들어 List(1,2,3)에 x => List(x, x*2)를 map하면 중첩된 리스트가 되지만, flatMap하면 평평한 단일 리스트가 됩니다. flatMap은 Option이나 Try 같은 컨테이너 타입을 다룰 때나, 각 요소가 여러 결과를 생성할 수 있는 상황에서 주로 사용됩니다.
- • map은 1:1 변환, flatMap은 1:N 변환 후 평탄화
- • flatMap은 중첩 구조를 제거
- • Option, Try 등 모나딕 타입 체이닝에 활용
여러 API 호출 결과를 조합하거나, 중첩된 데이터 구조를 평탄화하여 처리할 때 사용됩니다.
for-comprehension이 내부적으로 map과 flatMap으로 변환되는 과정을 설명할 수 있나요?
Q. Scala의 케이스 클래스(Case Class)가 일반 클래스와 다른 점은 무엇이며, 어떤 기능들을 자동으로 제공하나요?
case 키워드를 붙이면 컴파일러가 자동으로 생성해주는 메서드들을 생각해보세요.
케이스 클래스는 case 키워드를 붙여 정의하며, 불변 데이터 모델링에 최적화된 클래스입니다. 컴파일러가 자동으로 equals, hashCode, toString 메서드를 생성하여 값 기반 비교가 가능합니다. 또한 apply 메서드가 생성되어 new 키워드 없이 인스턴스를 생성할 수 있고, copy 메서드로 일부 필드만 변경한 새 인스턴스를 쉽게 만들 수 있습니다. 패턴 매칭에서 자동으로 분해할 수 있으며, 생성자 파라미터가 자동으로 public val 필드가 됩니다.
- • equals, hashCode, toString 자동 생성
- • apply와 copy 메서드 제공
- • 패턴 매칭 지원
도메인 모델이나 DTO를 정의할 때 보일러플레이트 코드 없이 불변 데이터 구조를 만들 때 사용됩니다.
케이스 클래스를 상속할 때 발생할 수 있는 문제점은 무엇인가요?
Q. Scala의 Trait은 무엇이며, Java의 인터페이스와 어떤 차이점이 있나요?
구현 코드 포함 여부와 다중 상속 가능성을 고려해보세요.
Trait은 메서드 시그니처뿐만 아니라 구체적인 구현도 포함할 수 있는 재사용 가능한 코드 단위입니다. Java의 인터페이스와 달리 필드를 가질 수 있고, 생성자 파라미터는 가질 수 없습니다. 클래스는 여러 Trait을 with 키워드로 믹스인할 수 있어 다중 상속의 이점을 얻을 수 있습니다. Trait은 선형화(linearization) 규칙에 따라 메서드 호출 순서가 결정되며, 이를 통해 다이아몬드 문제를 해결합니다. 추상 메서드와 구현된 메서드를 함께 제공하여 유연한 코드 재사용이 가능합니다.
- • 구현 코드와 필드 포함 가능
- • 다중 믹스인 지원
- • 선형화를 통한 메서드 해결
로깅, 캐싱, 인증 같은 횡단 관심사를 여러 클래스에 조합하여 적용할 때 사용됩니다.
여러 Trait을 믹스인할 때 메서드 충돌이 발생하면 어떻게 해결되나요?
Q. Scala 컬렉션에서 fold, foldLeft, foldRight의 차이점과 각각의 사용 시나리오를 설명해주세요.
연산 방향과 초기값의 위치, 타입 추론 관점에서 생각해보세요.
fold는 결합 법칙이 성립하는 연산에 사용되며 병렬 처리가 가능하지만, 연산 순서가 보장되지 않습니다. foldLeft는 왼쪽에서 오른쪽으로 순차적으로 누적 연산을 수행하며, 꼬리 재귀 최적화가 가능하여 스택 오버플로우 위험이 없습니다. foldRight는 오른쪽에서 왼쪽으로 연산하며, 리스트 구조를 유지하는 연산에 유용하지만 스택을 사용하여 큰 컬렉션에서는 위험할 수 있습니다. foldLeft가 타입 추론이 더 잘 되어 일반적으로 많이 사용되며, 연산 순서가 중요한 경우 명시적으로 방향을 선택해야 합니다.
- • fold는 순서 무관, 병렬 처리 가능
- • foldLeft는 꼬리 재귀 최적화
- • foldRight는 구조 유지에 유용하나 스택 사용
데이터 집계, 합계 계산, 리스트 변환 등 컬렉션의 모든 요소를 하나의 결과로 축약할 때 사용됩니다.
reduce와 fold의 차이점은 무엇이며, 빈 컬렉션에 대해 어떻게 동작하나요?
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!