# 1장 코틀린이란 무엇이며, 왜 필요한가?

### 이번장에서는...

#### 배운점, 느낀점

1. 타입추론이 되면 개발적인 측면에서 생산성은 높아질 것 같지만, 가독성 측면에서는 좋지 않을 것 같으니 타입을 작성해주는 게 좋을 것 같다는 생각이 들어 이에 대해 이야기 나누었으면 좋겠다.
2. 책에서 표현하는 강력한 추상화라는 것은 무슨의미 일까? 객체를 생성할 때에 함수형 프로그래밍을 써서 하나의 식으로 표현해 코드 중복을 막는 그러한 추상화를 의미하는 것 일까? 어디까지를 더 강력한 추상화인지
   이야기를 나눠보고 싶다.

#### 자바랑 비슷한 점 요약

1. 정적 타입 언어
2. 클래스, 인터페이스, 제네릭스
3. 자바 8 이후부터의 함수형 프로그래밍

---

## 1장 시작

코틀린은 자바 플랫폼에서 돌아가는 새로운 프로그래밍 언어이다.

1. 간결함 -> 코드에서 의미가 없는 부분을 줄이고, 언어가 요구하는 구조를 만족시키기 위해 별 뜻은 없지만 프로그램에 꼭 넣어야하는 부수적인 요소를 줄이기 위해 노력을 기울였다더라.. Getter, Setter,
   생성자 파라미터를 필드에 대입하기 위한 로직 등 자바에 존재하는 여러 가지 번거로운 준비 코드를 코틀린은 묵시적으로 제공 및 함수형 프로그래밍 지원, 기능이 다양한 표준 라이브러리 제공
2. 실용적 -> 코틀린은 코드를 작성할 때는 객체지향과 함수형 접근 방법을 함께 조합해서 문제에 가장 적합한 도구를 사용하면 된다.
3. 자바 코드와의 상호운용성 -> 새로운 기술이나 프레임워크는 언제나 기존 프레임워크나 기술을 확장하고 개선하거나 대치하며, 기존 시스템과 새로운 코드를 통합해야만 한다. 이런 환경에서 자바 코드와 매끄럽게 상호
   운영할 수 있다는 점이 코틀린의 큰 장점
4. 안전성 -> 정적 타입 지정 언어

#### 그 밖의 장점

1. 코틀린을 사용하더라도 성능 측면에서 아무 손해가 없다. 코틀린 컴파일러가 생성한 바이트코드는 일바적인 자바 코드와 똑같이 효율적으로 실행된다. 코틀린의 런타임 시스템은 상당히 작기 때문에 컴파일 후 패키징한
   애플리케이션 크기도 자바 애플리케이션에 비해 그리 많이 늘어나지 않는다.
2. 대부분의 코틀린 표준 라이브러리 함수는 인자로 받은 람다 함수를 인라이닝 한다. 따라서 람다를 사용해도 새로운 객체가 만들어지지 않으므로 객체 증가로 인해 가비지 컬렉션이 늘어나서 프로그램이 자주 멈추는 일도
   없다.
3. 코틀린은 무료며 오픈소스다.!!

```kotlin
package part1

data class Person(
    val name: String,  // 데이터 클래스
    val age: Int? = null // null 이 될 수 있는 타입(Int?)과 파라미터 디폴트 값
)

fun main(args: Array<String>) {
    val persons = listOf(
        Person("영희"),
        Person("철수", age = 29)
    ) // 이름 붙인 파라미터

    val oldest = persons.maxBy { it.age ?: 0 } // 람다 식과 엘비스 연산자
    println("나이가 가장 많은 사람: $oldest") //toString 자동 생성
}

코틀린의 특징

  1. 정적 타입 지정 언어

    1. 자바와 마찬가지로 코틀린도 정적 타입(statically typed) 지정 언어다. 정적 타입 지정이라는 말은 모든 프로그램 구성 요소의 타입을 컴파일 시점에 알 수 있고 프로그램 안에서 객체의 필드나 메서드를 사용할 떄마다 컴파일러가 타입을 검증해준다는 뜻이다.
      • 동적 타입지정 언어와는 다르다. (예: JVM에서는 Groovy나 JRuby)
      • 성능: 실행 시점에 어떤 메서드를 호출할지 알아내는 과정이 필요 없어 호출이 더 빠르다
      • 신뢰성: 컴파일러가 프로그램의 정확성을 검증한다.
      • 유지 보수성: 코드에서 다루는 객체가 어떤 타입에 속하는지 알 수 있기 때문에 처음 보는 코드를 다룰 때도 더 쉽다.
      • 도구 지원: 정적 타입 지정을 활용하면 더 안전하게 리팩토링이 가능하고 도구는 코드 완성기능 및 IDE의 다른 지원 기능도 더 잘 만들 수 도 있다.
  2. 타입 추론

    1. 자바와 달리 코틀린에서는 모든 변수의 타입을 프로그래머가 직접 명시할 필요가 없다. 대부분의 경우 코틀린 컴파일러가 문맥으로부터 변수 타입을 자동으로 유추할 수 있기 때문에 프로그래머는 타입 선언을 생략해도 된다.
    package part1
    
    val x = 1 // 코틀린은 이 변수의 타입이 Int임을 자동으로 알아낸다.
    
    fun main() {
          println(x)
    }
    
        //컴파일
        package part1;
        import kotlin.Metadata;
        @Metadata(
        mv = {1, 7, 1},
        k = 2,
        d1 = {"\\u0000\\u0010\\n\\u0000\\n\\u0002\\u0010\\b\\n\\u0002\\b\\u0003\\n\\u0002\\u0010\\u0002\\n\\u0000\\u001a\\u0006\\u0010\\u0004\\u001a\\u00020\\u0005\\"\\u0014\\u0010\\u0000\\u001a\\u00020\\u0001X\\u0086D¢\\u0006\\b\\n\\u0000\\u001a\\u0004\\b\\u0002\\u0010\\u0003¨\\u0006\\u0006"},
        d2 = {"x", "", "getX", "()I", "main", "", "playground"}
        )
        public final class TwoKt {
        private static final int x = 1;
        
        public static final int getX() {
        return x;
        }
        
        public static final void main() {
        int var0 = x;
        System.out.println(var0);
        }
        
        // $FF: synthetic method
        public static void main(String[] var0) {
              main();
            }
        }
    
  3. 널이 될 수 있는 타입을 지원

    1. 널이 될 수 있는 타입을 지원함에 따라 컴파일 시점에 널 포인터 예외(Null Pointer Exception)가 발생할 수 있는지 여부를 검사할 수 있어서 좀 더 프로그램의 신뢰성을 높일 수 있다. 어떤 타입이 널이 될 수 있는지 여부를 표시하기 위해서는 오직 ? 한 글자만 추가하면 된다.
    2. 이런 기능은 애플리케이션이 NullPointerException으로 인해 갑자기 중단되는 경우를 많이 줄여준다.
     package part1
    
     val s: String? = null // null이 될 수 있음
     val s2: String = ""   // null이 될 수 없음
     
     //val s3: String = null // Null can not be a value of a non-null type String
     
     fun main() {
     println(s)
     println(s2)
     //    println(s3)
     }
    
  4. ClassCastException 방지

    1. 어떤 객체를 다른 타입으로 캐스트하기 전에 타입을 미리 검사하지 않으면 ClassCastException 이 발생할 수도 있다. 어떤 객체의 타입을 검사했고 그 객체가 그 타입에 속한다면 해당 타입의 메서드나 필드 등의 멤버를 별도의 캐스트 없이 사용할 수 있다.
    package part1
    
    val value: String = "hello,world"
    
    fun main() {
    if (value is String)
    println(value.toUpperCase())
    }
    
  5. 함수타입에 대한 지원 -> 함수형 프로그래밍을 지원한다.

    1. 간결성 : 함수를 값처럼 활용할 수 있으면 더 강력한 추상화를 할 수 있다. 강력한 추상화를 사용해 코드 중복을 막을 수 있다.
      fun findAlice() = findPerson{ it.name == "영희"}
      fun findBob() = findPerson{ it.name == "철수"} 
      // 해당 로직에서 공통 부분을 따로 함수로 뽑아내고 서로 다른 세부사항을 인자로 전달할 수 있다. 이런 인자는 그 자체가 함수다.
      
  6. 다중 스레드를 사용해도 안전하다는 사실

    1. 불변 데이터 구조를 사용하고 순수 함수를 그 데이터 구조에 적용한다면 다중 스레드 환경에서 같은 데이터를 여러 스레드가 변경할 수 없다.
  7. 테스트하기 쉽다.

    1. 부수 효과가 있는 함수는 그 함수를 실행할 때 필요한 전체 환경을 구성하는 준비 코드가 따로 필요하지만. 순수 함수는 그런 준비 코드 없이 독립적으로 테스트할 수 있다.
  8. 상호운용성

    1. 자바 기존 라이브러리를 그대로 사용할 수 있다.
    2. 자바 메서드를 호출하너가 자바 클래스를 상속하거나 인터페이스를 구현하거나 자바 애노테이션을 적용하는 등의 일이 모두 가능하다.(유연성)
    3. 코틀린은 자바와 코틀린 소스 파일이 임의로 섞여 있어도 제대로 프로그램을 컴파일할 수 있다.

코틀린 코드 컴파일

  1. 코틀린 확장자는 .kt
  2. 코틀린 컴파일러는 자바 컴파일러가 자바 소스코드를 컴파일할 때와 마찬가지로 코틀린 소스코드를 분석해서 .class 파일을 만들어낸다. 만들어진 .class 파일은 개발 중인 애플리케이션의 유형에 맞는 표준 패키징 과정을 거쳐 실행될 수 있다.
  3. kotlinc 명령을 통해 코틀린 코드를 컴파일 한 다음 java 명령으로 그 코드를 실행
  4. 코틀린 컴파일러로 컴파일한 코드는 코틀린 런타임 라이브러리에 의존한다.
  5. 코틀린으로 컴파일한 애플리케이션을 배포할 때는 런타임 라이브러리도 함께 배포해야한다.

[출처] Kotlin IN ACTION