Scala
Scala
1. 개요
Scala는 강력한 타입 시스템(Strongly Typed)을 기반으로 객체지향 프로그래밍(OOP)과 함수형 프로그래밍(FP)의 특성을 하나로 통합한 정적 타입의 고수준 프로그래밍 언어이다. 이름은 'Scalable Language'의 약자로, 작은 스크립트부터 대규모 엔터프라이즈 시스템까지 확장 가능한 언어를 지향한다는 의미를 담고 있다. Java 가상 머신(JVM) 위에서 동작하므로 Java 생태계의 방대한 라이브러리를 그대로 사용할 수 있으며, 컴파일 시 Java 바이트코드로 변환되어 실행된다.
2. 주요 특징 및 설계 철학
Scala는 Java의 복잡성과 반복적인 코드를 줄이면서도, 강력한 타입 시스템을 통해 런타임 오류를 최소화하는 것을 목표로 설계되었다.
- 정적 타입 시스템 및 타입 추론: 컴파일 시점에 타입을 결정하지만,
val x = 10과 같이 타입을 명시하지 않아도 컴파일러가 문맥을 통해 타입을 추론(Type Inference)하여 개발자의 편의성을 높인다. - 불변성(Immutability) 지향: 상태 변경으로 인한 부작용(Side Effect)을 줄이기 위해 기본적으로 불변 데이터를 권장한다.
- Java 상호 운용성: JVM 기반 언어로서 Java 클래스를 호출하거나, 반대로 Java에서 Scala 코드를 호출하는 것이 매우 자유롭다.
Java vs Scala 주요 차이점 비교
| 구분 | Java | Scala |
|---|---|---|
| 프로그래밍 패러다임 | 객체지향 중심 (최근 FP 요소 도입) | 객체지향 + 함수형 프로그래밍 통합 |
| 변수 선언 | 기본적으로 가변(Mutable) | val(불변)과 var(가변)를 명확히 구분 |
| 타입 추론 | 제한적 (Java 10 var 도입) |
매우 강력하고 광범위한 타입 추론 |
| Null 처리 | null 참조 및 Optional 클래스 |
Option 타입을 통한 타입 수준의 안전성 확보 |
| 코드 간결성 | 보일러플레이트 코드가 많은 편 | 매우 간결한 문법 (Case Class, 패턴 매칭 등) |
3. 핵심 문법 및 개념
변수 선언 및 데이터 타입
Scala 3에서는 간결한 문법을 통해 변수를 선언하며, 변경 가능 여부를 반드시 결정해야 한다.
* val: 불변(Immutable) 변수. 한 번 할당하면 값을 바꿀 수 없다. (Java의 final과 유사)
* var: 가변(Mutable) 변수. 값을 재할당할 수 있다.
케이스 클래스(Case Class)와 패턴 매칭(Pattern Matching)
케이스 클래스는 불변 데이터를 저장하기 위해 최적화된 특수 클래스로, equals, hashCode, toString 메서드가 자동으로 구현되며 패턴 매칭에 최적화되어 있다. 패턴 매칭은 값의 형태나 타입에 따라 분기 처리를 수행하는 강력한 조건문이다.
// 케이스 클래스 정의
case class User(name: String, age: Int)
val user1 = User("Alice", 25)
val user2 = User("Bob", 30)
// 패턴 매칭 활용
val result = user1 match {
case User("Alice", age) => s"Alice is $age years old"
case User(name, age) if age >= 30 => s"$name is an adult"
case _ => "Unknown user"
}
println(result) // 출력: Alice is 25 years old
4. 함수형 프로그래밍 (FP) 요소
Scala는 함수를 '일급 시민(First-class citizen)'으로 취급하여, 함수를 변수에 할당하거나 다른 함수의 인자로 전달하고, 결과값으로 반환할 수 있다.
- 고차 함수(Higher-order functions): 함수를 인자로 받거나 함수를 반환하는 함수이다.
- 익명 함수(Anonymous functions): 이름 없이 정의되는 함수로, 람다식(Lambda expression) 형태로 작성한다.
- Option 타입:
null을 직접 사용하는 대신Some(value)또는None을 사용하여 값이 없을 가능성을 타입 시스템에서 강제함으로써NullPointerException을 방지한다.
컬렉션 API 활용 예시
val numbers = List(1, 2, 3, 4, 5)
// map: 각 요소에 함수를 적용하여 새로운 리스트 생성
val doubled = numbers.map(_ * 2) // List(2, 4, 6, 8, 10)
// filter: 조건에 맞는 요소만 추출
val evens = numbers.filter(_ % 2 == 0) // List(2, 4)
// fold: 초기값과 연산 함수를 이용해 하나의 값으로 축약
val sum = numbers.fold(0)(_ + _) // 15
5. 표준 라이브러리 컬렉션 체계
Scala의 컬렉션 라이브러리는 매우 체계적으로 설계되어 있으며, 기본적으로 scala.collection.immutable 패키지가 임포트되어 사용된다.
주요 컬렉션 타입
| 타입 | 특징 | 주요 사용 사례 | 성능 특이사항 |
|---|---|---|---|
| List | 단일 연결 리스트 (불변) | 함수형 프로그래밍, 스택 구조 | 머리(Head) 추가/삭제는 $O(1)$, 랜덤 액세스는 $O(n)$ |
| Vector | 효율적인 랜덤 액세스 시퀀스 (불변) | 대규모 데이터셋, 인덱스 기반 접근 | 랜덤 액세스 및 업데이트 모두 $O(\log_{32} n)$으로 매우 빠름 |
| Set | 중복 없는 요소 집합 | 고유 값 관리, 집합 연산 | 요소 존재 여부 확인에 최적화 |
| Map | 키-값 쌍의 집합 | 사전식 데이터 관리, 캐싱 | 키를 통한 값 조회에 최적화 |
| Buffer | 가변적인 시퀀스 (가변) | 빈번한 요소 추가/삭제가 필요한 경우 | 가변 상태를 유지하며 동적 크기 조절 가능 |
6. 고급 기능 및 타입 시스템
- 트레이트(Trait): Java의 인터페이스와 유사하지만, 상태(필드)를 가질 수 있고 구현 메서드를 포함할 수 있다. 여러 트레이트를 동시에 믹스인(Mixin)하여 다중 상속과 유사한 효과를 낼 수 있다.
trait Logger {
def log(msg: String): Unit = println(s"[LOG] $msg") // 구현 메서드 포함
}
trait Authenticator {
def authenticate(): Boolean = {
println("Authenticating...")
true
}
}
// 믹스인(Mixin)을 통한 다중 기능 결합
class UserService extends Logger with Authenticator {
def createUser(name: String): Unit = {
if (authenticate()) {
log(s"User $name created")
}
}
}
val service = new UserService()
service.createUser("Alice")
// 출력: Authenticating...
// 출력: [LOG] User Alice created
- 암시적 변환 및 파라미터(Implicit): 컴파일러가 특정 조건에서 누락된 인자를 자동으로 채워넣거나 타입을 변환하는 기능이다. Scala 3에서는
given,using키워드로 더욱 명확하게 개선되었다. - 제네릭(Generics): 다양한 데이터 타입에 대해 동일한 로직을 적용할 수 있도록 타입 파라미터를 사용한다.
7. Scala 2 vs Scala 3 주요 차이점
Scala 3는 언어의 복잡성을 줄이고 가독성을 높이는 방향으로 대대적인 개편이 이루어졌다.
| 특징 | Scala 2 | Scala 3 |
|---|---|---|
| 구문(Syntax) | 중괄호 {} 기반의 전통적 구문 |
파이썬 스타일의 들여쓰기(Optional Braces) 도입 |
| 암시적 정의 | implicit 키워드 하나로 다수 기능 수행 |
given, using으로 역할 분리 및 명확화 |
| 열거형 | Enumeration 클래스 사용 |
enum 키워드를 통한 일급 열거형 지원 |
| 타입 시스템 | 복잡한 타입 추론 및 제약 | Union Types, Intersection Types 등 도입 |
8. 개발 환경 구축 및 Hello World
환경 구축
- [ ] JDK 설치: JVM 기반이므로 JDK 11 또는 17 이상의 버전이 필요하다.
- [ ] sbt (Scala Build Tool) 설치:
- 설치: sbt 공식 홈페이지에서 설치 파일을 다운로드하거나, macOS의 경우
brew install sbt를 통해 설치한다. - 설정:
build.sbt파일을 프로젝트 루트에 생성하여 라이브러리 의존성(libraryDependencies)과 Scala 버전을 정의한다.
- 설치: sbt 공식 홈페이지에서 설치 파일을 다운로드하거나, macOS의 경우
- [ ] IDE 설치: IntelliJ IDEA(Scala 플러그인 설치) 또는 VS Code(Metals 플러그인 설치)를 권장한다.
Hello World 예제
// Scala 3 기준
@main def hello(): Unit = {
println("Hello, Scala World!")
}
object Hello extends App { println("...") } 형태로 작성한다.)
9. 생태계 및 활용 사례
Scala는 강력한 동시성 처리 능력과 데이터 처리 효율성 덕분에 특정 산업군에서 압도적인 점유율을 보인다.
- Apache Spark: 대규모 데이터 분산 처리 프레임워크로, Scala가 기본 개발 언어이며 가장 최적화된 성능을 제공한다.
- Akka: 액터 모델(Actor Model) 기반의 동시성 프레임워크로, 고가용성 및 분산 시스템 구축에 사용된다.
- Play Framework: 비동기 논블로킹(Non-blocking) I/O를 지원하는 고성능 웹 애플리케이션 프레임워크이다.
- 주요 활용 분야: 빅데이터 분석 플랫폼, 실시간 스트리밍 처리 시스템, 고성능 금융 거래 시스템 등.
분류: 기술 / 프로그래밍 / Scala
이 문서는 AI 모델(gemma-4-31b)에 의해 생성된 콘텐츠입니다.
주의사항: AI가 생성한 내용은 부정확하거나 편향된 정보를 포함할 수 있습니다. 중요한 결정을 내리기 전에 반드시 신뢰할 수 있는 출처를 통해 정보를 확인하시기 바랍니다.