티스토리 뷰
컨셉
- JetBrains 사에서 만든 언어
- JVM 기반 언어
- .java에서 컴파일된 .class 파일을 동일하게 코틀린에서도 사용
- 자바에서 소스파일을 .java로 사용하듯 코틀린에서 같은 레벨에 .kt 파일로 정의됨
- 코틀린이 자바와 100% 호환될 수 있는 이유: 코틀린도 .class 파일로 컴파일되기 때문. 따라서 import를 통해 코틀린 소스코드 내에서 자바 라이브러리, 스프링 등을 참조할 수 있음(import 시 이미 컴파일된 class를 참조하기 때문)
- 2016년 코틀린 1.0 릴리즈, 스프링 프레임워크 5.0부터 코틀린 공식 지원, gradle의 경우 Groovy에 더해 Kotlin DSL 지원
- JetBrains 사에서 코틀린 기반의 백엔드 애플리케이션 프레임워크 Ktor 및 Exposed ORM 프레임워크 지원
- 참고로 코틀린은 위처럼 JVM에서 실행하도록 .class 파일로 컴파일되도록 할 수도 있지만 자바스크립트로도 컴파일이 가능함(ex. 코틀린으로 작성하고 자바스크립트로 컴파일 후 NodeJS로 실행)
cf, 자바 컴파일 방식에 대한 포스팅: https://jh-labs.tistory.com/26
특징
1. null safety ***
ex1) null이 될 수 있는 변수에 '?' 연산자 활용
ex2) Elvis 연산자 (?:)
// as-is (kotlin)
val l: Int = if (b != null) b.length else -1
// to-be (kotlin)
val l = b?.length ?: -1
// as-is (java)
String name = null;
System.out.println(Objects.requireNonNullElse(name, "not_found_name"))
// to-be (kotlin)
var name: String? = null
print(name ?: "not_found_name")
- '특정 값이 null일 경우 어떤 값을 default 값으로 할 것인가'에 대한 개념
2. coroutine 개념 제공
- 비동기 코드를 보다 간결하게 작성할 수 있도록 제공되는 기능으로 코틀린 자체 개념은 아님
- 코루틴은 '하나의 쓰레드 내에서 또른 다른 쓰레드에서' 실행되는 '여러 작업 단위'
(정의된 코루틴을 새로운 쓰레드에서 실행시킬지에 대한 여부는 디스패처에 따라 다름)
- 쓰레드 내 또 다른 경량 쓰레드라고 불릴 만큼 가벼움
- 여러 쓰레드가 CPU를 점유하기 위해 발생되는 context switching 없이 하나의 쓰레드 내에서 비동기 처리가 가능하도록 설계됨(비동기처리를 위한 쓰레드 간 context switching 비용이 절감되는 장점이 있음, 엄밀히 말하면 Context Switching이 발생할할 가능성을 줄임)
- 기존 OS레벨의 context switching이 애플리케이션 레벨에서 이루어지는 느낌
// build.gradle.kts
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
}
- 코루틴은 메소드 정의 시 suspend 키워드를 추가하여 정의할 수 있음
- suspend로 정의된 코루틴은 async 키워드로 호출하여 사용할 수 있음
- 종료 시점은 block해서 기다릴 경우 await 키워드로 코루틴 리턴값을 받아올 수 있음
cf. 코틀린 코루틴 포스팅: https://jh-labs.tistory.com/904
3. 그 외 사소한 장점들
3-1) 정적 타입 언어
- 컴파일 시점(.class를 만드는 시점)에 타입이 결정되는 정적 타입 언어이기 때문에 런타임 중에 변수의 타입이 변경되지 않음
- 정적 타입 언어는 자바와 같은 특징
3-2) 간결한 문법
- 자바에 비해 문법이 간결하기 때문에 가독성과 생산성이 높고 오류 가능성이 적어짐
- 이는 코틀린 언어 자체적으로 다양한 디자인 패턴기법, 이펙티브 자바 특징들을 제공하기 때문
[예시]
/*
* 언어 차원에서 제공되는 기능
*/
// 1. data class: equals(), hashCode(), toString() 등 메소드 자동 생성
data class Student(
val name: String,
val age: Int,
val email: String
)
// 2. object: 싱글톤 객체로 취급됨
object Person {
const val name: String = "name1"
}
// 3. 메소드가 클래스 레벨에 위치할 수 있음
// top-level 함수, 전역 함수(global function)로 취급
fun main() {
// 4. new 키워드 없이 객체 생성
val student = Student("name1", 11, "email@email.com")
println(student) // Student(name=name1, age=11, email=email@email.com) 출력
}
- data class는 자바의 equals(), hashCode(), toString() 등 메소드를 자동 생성한다.
- 기본적으로 object 키워드는 지연 초기화(lazy initialization) 기반 singleton 객체를 만든다. 호출 시점에 singleton을 생성할 경우 프로그램 시작 시점에 호출(?)하면 된다
- top-level 함수는 실제로 JVM 상에서 클래스 내부의 정적(static) 메소드로 변환되며(프로그램 로딩 시 JVM 메소드 영역에 바로 위치하게 됨, 동적 클래스 로딩X) 이때 코틀린 컴파일러는 해당 함수가 속한 파일명을 기반으로 하는 임의의 클래스를 내부적으로 생성하고, 그 안에 top-level 함수를 정적 메소드로 변환하여 포함함(결국 JVM에서 로딩되어야 하기 때문)
- top-level 함수는 유틸성 메소드 정의 시 적합
3-3) 타입 추론
- val, var 키워드를 통해 변수 선언 시 타입 추론 가능
- reference, primitive type 모두 가능
- val 키워드: 자바에서 final 변수 역할, 컴파일 시 getter 자동생성됨
- var 키워드: 자바에서 final이 없는 일반 변수 선언과 같음, 컴파일시 getter, setter 자동생성됨
- 코틀린에선 원시(primitive) 타입을 직접 제공하지 않지만, 컴파일러는 적절한 상황에서 효율적으로 변환 수행
3-4) 자바와 100% 상호 운용 가능
- 스프링과 같이 자바로 작성된 모든 기능, 라이브러리를 사용할 수 있다.
- ex) 자바 NIO(Non-blocking I/O) 패키지의 direct buffer를 코틀린에서 호출
import java.nio.ByteBuffer
fun main() {
val buffer = ByteBuffer.allocateDirect(1024)
// direct buffer를 사용하는 코드 작성
}
- 위와 같이 import 시 이미 컴파일된 클래스를 참조하기 때문에 코틀린에서 자바를 100% 상호 운용할 수 있음
Reference
- https://blog.siner.io/2021/12/25/java-compile/
- 자바 컴파일 방식 및 JIT, https://jh-labs.tistory.com/26
- kotlin docs, https://kotlinlang.org/docs/home.html
- kotlin null safety docs, https://kotlinlang.org/docs/null-safety.html
- kotlin Coroutines docs, https://kotlinlang.org/docs/coroutines-overview.html
- Coroutines, https://en.wikipedia.org/wiki/Coroutine
'[ 백엔드 개발 ] > [ Java,Kotlin ]' 카테고리의 다른 글
비동기와 병렬성은 다루는 방법: 코틀린 코루틴(Kotlin Coroutine) 1 (1) | 2024.05.26 |
---|---|
[Netty] Blocking I/O, Non-Blocking I/O, 동기, 비동기 처리에 대한 고찰 (0) | 2023.05.05 |
[JAVA] 스트림과 병렬스트림 (parallelStream) (0) | 2022.06.08 |
[JAVA] Stream I/O vs Channel I/O (0) | 2022.05.01 |
[JAVA] 인터페이스의 발전 과정 (0) | 2022.04.16 |
- Total
- Today
- Yesterday
- 코틀린
- 우분투
- jvm
- kafka
- db
- Non-Blocking
- Kotlin
- Java
- spring
- 쿠버네티스
- RDB
- Linux
- github actions
- GitOps
- docker
- ci/cd
- argocd
- Controller
- Kubernetes
- K8s
- LFCS
- Stream
- 컨트롤러
- rolling update
- go
- CICD
- container
- 카프카
- ubuntu
- golang
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |