컨텍스트 추상화
컨텍스트 추상화 (Contextual Abstractions) 요약
이번 장에서는 Scala 3의 컨텍스트 추상화(Contextual Abstractions) 주제를 전반적으로 훑어봐요. 여기서 다루는 내용은 다음과 같아요.
- 확장 메서드 (Extension Methods)
- Given 인스턴스와 Using 절 (Given Instances and Using Clauses)
- 컨텍스트 바운드 (Context Bounds)
- Given 임포트 (Given Imports)
- 타입 클래스 (Type Classes)
- 다중 버전 동등성 (Multiversal Equality)
- 암시적 변환 (Implicit Conversions)
이 기능들은 모두 **용어 추론(term inference)**이라는 핵심 아이디어의 변형이에요. 용어 추론이란, 타입이 주어지면 컴파일러가 그 타입을 가지는 "정식(canonical)" 용어를 합성해 내는 것을 말해요.
여기에 더해 이 장에서는 다루지 않는 고급 주제도 몇 가지 있어요.
- 조건부 Given 인스턴스 (Conditional Given Instances)
- 타입 클래스 파생 (Type Class Derivation)
- 컨텍스트 함수 (Context Functions)
- By-Name 컨텍스트 파라미터 (By-Name Context Parameters)
- Scala 2 암시적(implicit)과의 관계 (Relationship with Scala 2 Implicits)
이 주제들은 Reference 문서에서 자세히 다루고 있어요.
출처: Scala 3 Book
본문
Scala 3의 컨텍스트 추상화는 "어떤 타입이 필요하다"는 사실을 컴파일러가 알아서 처리해 주도록 만드는 기능의 모음이에요.
가장 먼저 만나게 될 건 확장 메서드예요. 확장 메서드를 쓰면 기존 타입에 마치 그 타입의 메서드인 것처럼 새로운 메서드를 추가할 수 있어요. 예를 들어 Int에 제곱을 구하는 메서드를 붙이고 싶다면 extension 블록을 쓰면 돼요. 그래서 3.squared처럼 자연스럽게 호출할 수 있죠.
다음으로 given 인스턴스와 using 절이 있어요. 어떤 값이 필요할 때 호출하는 쪽이 매번 그 값을 넘겨주는 대신, 컴파일러가 적절한 given 인스턴스를 찾아 자동으로 채워 넣어줘요. 이 둘을 함께 쓰면 코드에서 반복적으로 전달해야 했던 "보일러플레이트"를 크게 줄일 수 있어요.
컨텍스트 바운드는 타입 파라미터에 "이 타입에 대한 given 인스턴스가 반드시 존재해야 한다"는 제약을 거는 문법이에요. 예를 들어 정렬을 하려면 Ordering이라는 given이 필요한데, 이런 요구를 타입 시그니처에 간결하게 표현할 수 있게 해주죠.
given 임포트는 특정 범위 안에 있는 given 인스턴스만 골라서 가져오는 기능이에요. 주로 어느 given을 사용할지 명시적으로 제어하고 싶을 때 유용해요.
이 개념들이 합쳐지면 타입 클래스를 구현할 수 있어요. 타입 클래스는 행동(동작)을 정의해 두고, 여러 타입에 대해 그 행동을 각각 다르게 채워 넣는 패턴이에요. 컴파일러가 적절한 구현을 자동으로 찾아주기 때문에, 코드를 호출하는 쪽에서는 필요한 given만 잘 갖춰 두면 돼요.
다중 버전 동등성은 ==와 !=로 서로 관련 없는 타입끼리 비교하는 걸 컴파일 타임에 막아주는 기능이에요. 가령 Person을 Planet과 비교하려는 건 의미가 없잖아요. 그런 실수를 미리 걸러내 주죠.
마지막으로 암시적 변환은 어떤 타입을 다른 타입으로 자동 변환해 주는 기능이에요. 다만 남용하면 코드가 무엇을 하는지 읽기 어려워지기 때문에, 꼭 필요한 경우에만 신중하게 쓰는 게 좋아요.
이 모든 기능의 밑바탕에는 "타입이 주어지면 그 타입에 맞는 정식 용어를 컴파일러가 합성한다"는 용어 추론이라는 한 가지 아이디어가 있어요. 이 한 가지를 이해하면 위 기능들이 서로 어떻게 이어지는지도 자연스럽게 보여요.