라이브러리와 API

라이브러리와 API (Libraries and APIs)

Kotlin을 최대한 활용하려면 기존 라이브러리와 API를 사용하세요. 그러면 바퀴를 다시 발명하는 데 시간을 쓰지 않고, 코딩하는 데 더 많은 시간을 쓸 수 있어요.

라이브러리는 공통 작업을 단순화하는 재사용 가능한 코드를 배포해요. 라이브러리 안에는 관련된 클래스, 함수, 유틸리티를 묶어 주는 패키지와 객체가 있어요. 라이브러리는 개발자가 코드에서 쓸 수 있는 함수·클래스·프로퍼티의 집합인 API(Application Programming Interface)를 노출해요.

이제 Kotlin으로 무엇을 할 수 있는지 함께 살펴볼게요.

출처: Kotlin 공식문서

본문

표준 라이브러리 (The standard library)

Kotlin에는 코드를 간결하고 표현력 있게 만들어 주는 필수 타입, 함수, 컬렉션, 유틸리티를 제공하는 **표준 라이브러리(standard library)**가 있어요. 표준 라이브러리의 상당 부분(kotlin 패키지의 모든 것)은 명시적으로 import 하지 않아도 어떤 Kotlin 파일에서든 바로 사용할 수 있어요:

fun main() {
    val text = "emosewa si niltoK"
    
   // Use the reversed() function from the standard library
    val reversedText = text.reversed()

    // Use the print() function from the standard library
    print(reversedText)
    // Kotlin is awesome
}

그런데 표준 라이브러리의 일부 부분은 코드에서 사용하려면 import가 필요해요. 예를 들어 표준 라이브러리의 시간 측정 기능을 쓰려면 kotlin.time 패키지를 import 해야 해요.

파일 맨 위에 import 키워드 뒤에 필요한 패키지를 적으면 돼요:

import kotlin.time.*

별표 *는 **와일드카드 import(wildcard import)**로, 패키지 안의 모든 것을 import 하라고 Kotlin에 알려줘요. 별표 *는 동반 객체(companion object)에는 쓸 수 없어요. 대신 사용하려는 동반 객체의 멤버를 명시적으로 선언해야 해요.

예를 들어:

import kotlin.time.Duration
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.minutes

fun main() {
    val thirtyMinutes: Duration = 30.minutes
    val halfHour: Duration = 0.5.hours
    println(thirtyMinutes == halfHour)
    // true
}

이 예시는:

  • Duration 클래스와 그 동반 객체의 hours, minutes 확장 프로퍼티를 import 해요.
  • minutes 프로퍼티를 써서 30을 30분짜리 Duration으로 변환해요.
  • hours 프로퍼티를 써서 0.5를 30분짜리 Duration으로 변환해요.
  • 두 Duration이 같은지 확인하고 결과를 출력해요.

만들기 전에 먼저 검색하세요 (Search before you build)

직접 코드를 쓰기로 결정하기 전에 표준 라이브러리에 이미 원하는 것이 있는지 확인해 보세요. 표준 라이브러리가 이미 많은 클래스·함수·프로퍼티를 제공하는 영역 목록은 다음과 같아요:

  • Collections (컬렉션)
  • Sequences (시퀀스)
  • String manipulation (문자열 처리)
  • Time management (시간 관리)

표준 라이브러리에 그 밖에 무엇이 더 있는지 알아보려면 표준 라이브러리의 API 레퍼런스를 살펴보세요.

Kotlin 라이브러리 (Kotlin libraries)

표준 라이브러리는 흔한 사용 사례를 많이 다루지만, 다루지 못하는 경우도 있어요. 다행히 Kotlin 팀과 커뮤니티는 표준 라이브러리를 보완하는 다양한 라이브러리를 개발했어요. 예를 들어 kotlinx-datetime은 여러 플랫폼에서 시간을 관리하는 데 도움을 줘요.

유용한 라이브러리는 Kotlin의 검색 플랫폼에서 찾을 수 있어요. 사용하려면 의존성(dependency)이나 플러그인을 추가하는 것 같은 별도의 단계를 거쳐야 해요. 각 라이브러리에는 Kotlin 프로젝트에 포함시키는 방법을 설명한 GitHub 저장소가 있어요.

라이브러리를 추가하면 그 안의 어떤 패키지든 import 할 수 있어요. 뉴욕의 현재 시간을 구하기 위해 kotlinx-datetime 패키지를 import 하는 예시를 볼게요:

import kotlinx.datetime.*

fun main() {
    val now = Clock.System.now() // Get current instant
    println("Current instant: $now")

    val zone = TimeZone.of("America/New_York")
    val localDateTime = now.toLocalDateTime(zone)
    println("Local date-time in NY: $localDateTime")
}

이 예시는:

  • kotlinx.datetime 패키지를 import 해요.
  • Clock.System.now() 함수로 현재 시간을 담은 Instant 클래스 인스턴스를 만들고 그 결과를 now 변수에 할당해요.
  • 현재 시간을 출력해요.
  • TimeZone.of() 함수로 뉴욕의 시간대를 찾고 그 결과를 zone 변수에 할당해요.
  • 현재 시간을 담은 인스턴스에서 뉴욕 시간대를 인자로 넘겨 .toLocalDateTime() 함수를 호출해요.
  • 그 결과를 localDateTime 변수에 할당해요.
  • 뉴욕 시간대에 맞게 조정된 시간을 출력해요.

TIP: 이 예시가 사용하는 함수와 클래스를 더 자세히 살펴보려면 API 레퍼런스를 참고하세요.

API 옵트인 (Opt in to APIs)

라이브러리 작성자는 특정 API를 코드에서 사용하려면 **옵트인(opt-in)**이 필요하다고 표시할 수 있어요. 보통 API가 아직 개발 중이고 앞으로 바뀔 수 있을 때 이렇게 해요. 옵트인하지 않으면 이런 경고나 오류를 보게 돼요:

This declaration needs opt-in. Its usage should be marked with '@...' or '@OptIn(...)'

옵트인하려면 @OptIn 뒤에 괄호를 붙이고, 그 안에 API를 분류하는 클래스 이름 뒤에 콜론 두 개 ::class를 붙여 적으면 돼요.

예를 들어 표준 라이브러리의 uintArrayOf() 함수는 API 레퍼런스에 나와 있듯이 @ExperimentalUnsignedTypes에 속해요:

@ExperimentalUnsignedTypes
inline fun uintArrayOf(vararg elements: UInt): UIntArray

코드에서 옵트인은 이렇게 생겼어요:

@OptIn(ExperimentalUnsignedTypes::class)

uintArrayOf() 함수를 옵트인해 사용해 부호 없는 정수 배열을 만들고 그 요소 중 하나를 수정하는 예시를 볼게요:

@OptIn(ExperimentalUnsignedTypes::class)
fun main() {
    // Create an unsigned integer array
    val unsignedArray: UIntArray = uintArrayOf(1u, 2u, 3u, 4u, 5u)

    // Modify an element
    unsignedArray[2] = 42u
    println("Updated array: ${unsignedArray.joinToString()}")
    // Updated array: 1, 2, 42, 4, 5
}

이것이 옵트인하는 가장 쉬운 방법이지만, 다른 방법도 있어요. 자세한 내용은 옵트인 요구 사항(Opt-in requirements) 문서를 참고하세요.

연습 (Practice)

연습 1

사용자가 투자의 미래 가치를 계산하는 데 도움을 주는 금융 애플리케이션을 개발하고 있어요. 복리(compound interest)를 계산하는 공식은:

여기서:

  • A는 이자를 포함해 쌓인 금액(원금 + 이자)이에요.
  • P는 원금(초기 투자 금액)이에요.
  • r은 연간 이자율(소수)이에요.
  • n은 1년 동안 이자가 복리되는 횟수예요.
  • t는 돈을 투자한 시간(년)이에요.

코드를 다음과 같이 수정해 보세요:

  • kotlin.math 패키지에서 필요한 함수를 import 하세요.
  • calculateCompoundInterest() 함수에 복리를 적용한 최종 금액을 계산하는 본문을 추가하세요.
// Write your code here

fun calculateCompoundInterest(P: Double, r: Double, n: Int, t: Int): Double {
    // Write your code here
}

fun main() {
    val principal = 1000.0
    val rate = 0.05
    val timesCompounded = 4
    val years = 5
    val amount = calculateCompoundInterest(principal, rate, timesCompounded, years)
    println("The accumulated amount is: $amount")
    // The accumulated amount is: 1282.0372317085844
}

연습 2

프로그램에서 여러 데이터 처리 작업을 수행하는 데 걸리는 시간을 측정하고 싶어요. kotlin.time 패키지에서 올바른 import 문과 함수를 추가하도록 코드를 수정해 보세요:

// Write your code here

fun main() {
    val timeTaken = /* Write your code here */ {
        // Simulate some data processing
        val data = List(1000) { it * 2 }
        val filteredData = data.filter { it % 3 == 0 }

        // Simulate processing the filtered data
        val processedData = filteredData.map { it / 2 }
        println("Processed data")
    }

    println("Time taken: $timeTaken") // e.g. 16 ms
}

연습 3

최신 Kotlin 릴리스에서 사용할 수 있는 표준 라이브러리의 새 기능이 있어요. 시도해 보고 싶지만 옵트인이 필요해요. 이 기능은 @ExperimentalStdlibApi에 속해요. 코드에서 옵트인은 어떻게 생겨야 할까요?

다음 단계는? (What's next?)

축하해요! 중급 투어를 모두 완료했어요! 경험에 대한 피드백을 남기고 싶나요?

다음 단계로, 인기 있는 Kotlin 애플리케이션을 위한 튜토리얼을 확인해 보세요:

  • Spring Boot와 Kotlin으로 백엔드 애플리케이션 만들기
  • UI를 네이티브로 유지하면서 비즈니스 로직 공유하기
  • 비즈니스 로직과 UI 공유하기

더 알아보기