코틀린은 자바 플랫폼에서 돌아가는 새로운 프로그래밍 언어다.
간결하고 실용적이며, 자바 코드와의 상호운용성을 중시하고, 현재 자바가 사용중인 곳이라면 대부분 코틀린을 활용할 수 있다.
간단하게 Person이라는 클래스를 정의하고 Person을 모아둔 컬렉션을 만들고 가장 나이가 많은 사람을 찾아 결과를 출력해보자.
우선 java로 구현해보자.
public class Person {
private String name;
private int age;
public Person(String name) {
this(name, null);
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
@Override
public String toString() {
return "Person(name=" + name + ", age=" + age + ")";
}
public static void main(String[] args) {
List<Person> persons = Arrays.asList(new Person("영희"), new Person("철수", 20));
Person oldestPerson = persons.stream().max(Comparator.comparingInt(Person::getAge)).orElseThrow();
System.out.println("나이가 가장 많은 사람: " + oldestPerson);
}
}
매우 긴 것을 확인할 수 있다.
이번에는 코틀린으로 구현해보자.
name과 age라는 프로퍼티가 들어간 간단한 데이터 클래스를 정의한다.
age 의 기본 값은 null이다.
엘비스 연산자라고 불리는 ?:는 age가 null인 경우 0을 반환하고, 그렇지 않은 경우 age의 값을 반환한다.
이처럼 코틀린은 자바보다 더 간결하게 코드를 작성할 수 있다.
코틀린의 주목적은 현재 자바가 사용되고 있는 모든 용도에 적합하면서 더 간결하고 생산적이며 안전한 언어를 제공하는 것이다.
코틀린은 서버 및 안드로이드에서 작동할 수 있다.
뿐만아니라 코틀린으로 작성한 코드를 자바뿐만 아니라 자바스크립트로도 컴파일 할 수 있다.
코틀린은 정적 타입 언어이지만 자바와 달리 모든 변수의 타입을 프로그래머가 직접 명시할 필요가 없다.
대부분의 경우 코틀린 컴파일러가 문맥으로부터 변수 타입을 추론하기 때문에 타입의 생략이 가능하다.
예를 들어 코틀린에서는 아래와 같이 변수를 선언한다.
해당 코드는 변수를 정의하면서 정수 값으로 초기화한다.
var로 타입을 명시하지않고 선언해도 코틀린은 이 변수의 타입을 문맥을 고려해 Int 임을 자동으로 알아낸다.
또한 코틀린의 타입 시스템은 자바와 비슷하게 작동하고, 자바에 대해 아는 내용을 코틀린에서도 쉽게 적용할 수 있다.
코틀린의 한 가지 중요한 특성은 널이 될 수 있는 타입을 지원한다는 것이다.
널이 될 수 있는 타입을 지원함에 따라 컴파일 시점에 널 포인터 예외가 발생할 수 있는지 여부를 검사할 수 있다.
그렇기 때문에 코틀린 타입 시스템이 null 값을 정확히 추적하여 널 포인터로 인해 생기는 문제를 줄여준다.
자바에서 NullPointerException을 일으키는 유형의 코드는 대부분 코틀린에서는 컴파일도 되지 않는다.
코틀린은 함수형 프로그래밍을 지원하고 함수형 프로그래밍을 사용하면 아래와 같은 장점이 있다.
첫째로 함수형 스타일로 프로그램을 작성하면 간결하게 코드를 작성할 수 있다.
함수를 값처럼 활용해 더 강력한 추상화를 이뤄 코드의 중복을 막을 수 있다.
둘쨰로 다중 스레드를 사용해도 안전하다.
다중 스레드 프로그램에서는 적절한 동기화 없이 같은 데이터를 여러 스레드가 변경하는 경우 문제가 생기는데
불변 데이터 구조를 사용하고 순수 함수를 그 데이터 구조에 적용한다면, 다중 스레드 환경에서
같은 데이터를 여러 스레드가 변경할 수 없다.
마지막으로 테스트하기가 쉽다.
이처럼 코틀린을 사용하면 객체지향과 함수형 접근 방법을 함께 조합해서 적합한 코드를 작성할 수 있다.
앞서 말한대로 코틀린은 자바와의 상호운용성에 초점을 맞춘 실용적이고 간결하며 안전한 언어이다.
예를 들어 코틀린은 프로그래머가 작성하는 코드에서 의미가 없는 부분을 줄이고
언어가 요구하는 구조를 만족시키기 위해 별 뜻은 없지만 프로그램에 꼭 넣어야하는
부수적인 요소를 줄이기 위해 많은 노력을 기울였다.
게터, 세터, 생성자 파라미터를 필드에 대입하기 위한 로직 등 자바에 존재하는 여러가지
번거로운 준비코드를 코틀린은 묵시적으로 제공하기 때문에 그러한 준비 코드로 인해 지저분해지는 일이 없다.
다음으로 코틀린은 자바보다 더 높은 수준의 안전성을 달성하되 생산성에 대한 비용은 더 적게 지불하고자 한다.
거기서 한걸음 더 나아가 실행 시점에 오류를 발생시키는 대신 컴파일 시점 검사를 통해 오류를 더 많이 방지해준다.
앞서 말했듯이 프로그램의 NullPointerException을 없애기 위해 노력한다.
코틀린의 타입 시스템은 null이 될 수 없는 값을 추적하며, 실행 시점에 NullPointerException이
발생할 수 있는 연산을 사용하는 코드를 금지한다.
어떤 타입이 널이 될 수 있는지 여부를 표시하기 위해서는 오직 "?" 하나만 추가하면 된다.
이런 기능은 애플리케이션이 NullPointerException으로 인해 갑자기 중단되는 경우를 많이 줄여준다.
코틀린이 방지해주는 다른 예외로는 ClassCastException이 있다.
어떤 객체를 다른 타입으로 캐스트하기 전에 타입을 미리 검사하지 않으면 ClassCastException이 발생할 수 있다.
코틀린에서는 타입 검사와 캐스트가 한 연사자에 의해 이뤄지기 때문에 어떠 객체의 타입을 검사했고
그 객체가 그 타입에 속한다면 해당 타입의 메소드나 필드 등의 멤버를 별도의 캐스트 없이 사용할 수 있다.
자바와 마찬가지로 코틀린도 컴파일 언어다.
코틀린 소스코드를 저장할 때는 보통 .kt 라는 확장자를 파일에 붙인다.
코틀린 컴파일러는 자바 컴파일러와 마찬가지로 .class 파일을 만들어내고 만들어진 .class 파일은
개발중인 어플리케이션의 유형에 맞는 표준 패키징 과정을 거쳐 실행될 수 있다.
가장 간단한 방식은 커맨드라인에서 kotlic 명령을 통해 코틀린 코드를 컴파일한 다음 java 명령으로 그 코드를 실행하는 것이다.
아래의 코틀린 소스코드를 컴파일 및 jar 파일로 패키징하고 실행하는 명령어를 보자.
코틀린 컴파일러로 컴파일한 코드는 코틀린 런타임 라이브러리(코틀린 자체 표준 라이브러리 클래스와 자바 API의 확장 기능) 에 의존하기 떄문에
코틀린으로 컴파일할 떄는 -include-runtime 옵션으로 런타임 라이브러리도 함께 배포해야 한다.
메이븐과 그레들 애플리케이션을 패키지할 때는 알아서 코틀린 런타임을 포함시켜 준다.
위에서 언급한 방식인 jar 파일로 패키징된 파일을 java -jar로 실행하는 것이 아니라,
이번에는 아래와 같이 kotlin 코드를 작성한 후 코틀린 컴파일러로 컴파일한 .class 파일을 java 실행파일로 실행하려 하였다.
하지만 kotlin 컴파일러가 java 컴파일러와 같이 동일한 class 파일을 만들어내어 java 실행파일로
실행이 가능할 것이라고 생각했지만 java 실행파일로 kotlin class 파일은 실행되지 않고 아래와 같은 오류가 발생한다.
반면에 kotlin 실행파일로 해당 class 파일을 실행하면 잘 실행된다.
그런데 만약 main 함수에서 args: Array<String> 를 지우고 코틀린 컴파일러로 컴파일하면 결과가 달라진다.
kotlin 실행파일로는 역시나 실행이 잘된다.
그런데 args: Array<String> 를 지우니 이번에는 java 실행파일로도 실행이 잘된다.
java 컴파일러와 kotlin 컴파일러가 만들어낸 .class 파일은 호환되기 때문에 어느 실행파일로도 실행이 가능할 것이라 생각했지만,
java 실행파일로는 args: Array<String>가 없을 떄, kotlin 실행파일은 args에 상관없이 실행이 된다.
어떤 이유에서 일까?
추가로 kt 소스파일에 package를 작성하면 kotlin 컴파일러로 컴파일한 .class 파일은 kotlin과 java 실행파일 모두 실행이 되지 않는다.
Comments