데보션앱 소개페이지 바로가기
로그인 선택

신고하기

CLOSE
신고사유 (대표 사유 1개)
상세내용 (선택)
0/200
  • 신고한 게시글은 더 이상 보이지 않습니다.
  • 이용약관과 운영정책에 따라 신고사유에 해당하는지 검토 후 조치됩니다.
  • 허위 신고인 경우, 신고자의 서비스 이용이 제한될 수 있으니 유의하시어 신중하게 신고해 주세요.
(이 회원이 작성한 모든 댓글과 커뮤니티 게시물이 보이지 않고, 알림도 오지 않습니다.)

미리보기

커뮤니티

      1,234

      badge 23.06.15

      글 등록

      카테고리를 선택해주세요.

      DEVOTEE를 활성화 시키면
      지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.

      버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.

      임시저장함에 저장되었습니다. 저장일시 : 2022.5.17 14:29:08

      임시저장함

      제목을 선택하시면 이어서 작성이 가능하며,
      최대 20건까지 저장합니다.
      컨텐츠 유형, 제목, 저장일시, 삭제로 이뤄진 임시저장 목록
      컨텐츠 유형 제목 저장일 삭제

      데보션 블로그 게재 요청

      CLOSE
      • *
      • *

      본인인증

      효율적인 데보션 서비스 이용 및
      고객님의 소중한 개인정보보호를 위해
      본인인증을 진행해주세요. 본인인증 미 진행 시 로그인이 제한됩니다.
      본인인증 실패

      본인인증 로그인에 실패하였습니다.
      회원이 아니시거나 본인인증 등록이
      완료되지 않은 사용자입니다.

      회원정보 연결

      Java 를 아시면 Kotlin 을 배워 보세요

      박제영 24.05.22
      5,910 5 1
      DEVOTEE 요약
      Kotlin은 Java와 100% 호환되며, 간결한 문법과 함수형 프로그래밍 등의 장점을 제공합니다. JetBrains에서 개발한 Kotlin은 2016년에 출시되었고, Android의 공식 언어로 채택되어 인기를 끌고 있습니다. Kotlin은 정적 타입, 함수형 프로그래밍, 멀티 플랫폼 지원 등의 특징을 가지고 있으며, Java보다 간결한 코드 작성이 가능합니다.
      DEVOTEE 추천 블로그

      1. 들어가며

      Kotlin 은 JVM 과 완벽하게 호환되는 언어 입니다.

      Java 와 100% 상호호환을 하는 것을 목표로 하는 Kotlin 은 Java 언어를 아시면 보다 쉬운 이해가 가능 합니다.

      Java 보다 더 간결한 언어를 사용할 수 있고 1급 함수를 지원하기 때문에 함수형 프로그래밍을 보다 적극적으로 사용할 수 있는 장점이 있습니다.

      또한 Google Android 공식언어로 Kotlin 이 추가되었고 이에 편승하여 많은 인기를 얻고 있습니다.


      2. Kotlin 은 언제, 어디서 탄생했을까요?

      Kotlin 은 2011년 경 부터 개발을 진행해서 2016년 2월 V 1.0 이 출시 되었습니다. (현재는 1.9.24 버전이 최신 입니다)

      Kotlin 은 만든 회사는 여러분들이 잘 아실 만한 JetBrain 입니다. (Intelli-J를 만든 회사죠)

      image.png

      [JetBrain 사의 회사 로고]


      Kotlin 이란 이름은 JetBrain 의 개발센터가 있는 러시아의 상트페리트루르크에 있는 코틀린 섬에서 이름을 따왔다고 합니다.

      (참고로 JetBrain 은 체코의 회사 입니다). 우리는 언제쯤 "월미도", "제주도" 이런 프로그램을 만들 수 있을까요?

      image.png

      [블로그 내용과 별 상관이 없는 코틀린 섬의 지도]


      3. Kotlin 의 언어적 특징

      (1) Java 언어와 호환성

      Kotlin 은 Java 와 100% 호환을 목표로 하고 있습니다.

      그렇기에 기존 Java Library 를 그대로 사용할 수 있으며, 반대로 Java 에서도 Kotlin 을 사용할 수 있습니다.

      (2) 멀티 플랫폼 지원

      Kotlin 은 일반적으로 서버상의 코드(웹 애플리켕션의 Back-End), 안드로이드 디바이스에서 실행되는 모바일 애플리케이션에 사용할 수 있습니다.

      그리고 특이하게 자바 스크립트를 지원해서 브라우저나 Node 에서도 실행이 가능 합니다.

      (3) 정적 타입 지원

      Java 와 마찬가지로 컴파일에 타입을 검사하는 정적 타입을 지원합니다.

      하지만, Java 와 다른 점은 타입 추론 (type infernece) 를 통해서 변수의 타입을 생략 할 수도 있습니다

      보통, 정적이라함은 Compile 시에 동작하는 것을 의미하고 동적이라 함은 코드가 실제로 실행되는 Runtime 시에 동작하는 것을 의미 합니다.

      (4) 함수형 프로그래밍

      Java에서도 Functional Interface 와 Lambda 를 통해 일부 함수형 프로그래밍을 지원하지만 Kotlin 에서는 보다 완벽하게 함수형 프로그래밍을 지원합니다.

      즉, 함수를 파라미터로 받거나 함수를 반환할 수 있습니다.

      함수형 프로그래밍의 특징은 First-Class, immutability, non side-effect 등이 있습니다

      (5) 무료 오픈소스

      컴파일러, 라이브러리 및 도구등이 모두 오픈 소스이며 Apache2 라이선스를 사용해서 무료료 사용할 수 있습니다.

      Intelli-J Commucation 버전 및 Ultimate(이건 구매해야 되죠) 지원이 가능합니다.


      4. Kotlin 의 대표적인 언어 문법

      (1) 변수와 타입

      Kotlin 에서는 val, var 라는 변수 타입을 지원합니다.

      먼저 val 은 value 의 약자이며 Java 의 final 변수와 동일합니다.(한번 값이 지정되면 변경 불가능)

      var 는 variable 의 약자이며 Java 의 final 이 아닌 변수와 동일합니다.(값 변경 가능)

      kotlin 에서는 언어적 특성상 변수를 가급적 val 로 선언하는 것을 권고하고 있습니다.

      변수명 뒤에 : 를 입력하고 타입명을 적어 주시면 됩니다.

      val name: String 변수의 이름은 name 이고 타입은 String 입니다. (식의 마지막 ; 는 생략 가능합니다, 코드에서는 생략했지만 final 이기 때문에 ``값을 무조건 대입해줘야 합니다)

      val name = "David" "David" 은 명시적으로 타입이 String 이기 때문에 타입 생략이 가능 합니다.

      name = "James name을 윗줄의 코드에서 val 로 지정했기 때문에 다른 이름을 지정하면 컴파일 오류가 발생합니다.

      (2) Kotlin 의 Null 체크

      java 에서는 항상 매개변수를 사용하기전에 null 체크를 해줘야 합니다.

      Java8 이후부터는 Optional 이 도입되면서 null 체크에 보다 유연성이 생겼지만, 그래도 이 부분은 항시 신경을 써야 합니다.

      Kotlin 에서는 변수 선언시에 이 변수가 null 을 허용할 것인지, 안 할 것인지를 선언할 수 있습니다.

      var age: Int? = 변수의 이름은 age 이며 타입 뒤에 ? 를 표시해서 Null 이 들어올 수도 있습니다.

      **Safe call **: perspon.age 와 같이 프로퍼티에 직접 접근할 경우 age 가 Null 이면 NPE(Null Point Exception)이 발생할 수 있씁니다.

      safe call 은 perspon?.age ? 를 사용해서 프로퍼티에 접근하며, 만약 프로퍼티가 null 일 경우에는 Null 을 반환해 줍니다. (null 이 아닐 경우에는 프로퍼티의 값을 반환하겠죠)

      Elvis 연산자 : Java 에서는 Ternary Expression 이 있습니다. ? : 를 사용해서 식을 값으로 표현할 수 있는데, Kotlin 에서는 Elvis 연산자를 사용해서 간단하게 표현이 가능합니다.

      Elvis 연산자는 좌항의 식이 null 을 반환하면 우항의 값을 반환하게 표현할 수 있습니다.

      return person?.age ?: throw IllegalArgumentException("나이가 null 입니다")

      위 예제에서는 Safe Call 을 사용해서 age가 Null 일 경우 null 을 만들어내고, 엘비스 연산자(?:) 의 좌항이 null 이 됐기 때문에 연산자의 우항인 IllegalArgumentException 이 발생합니다.

      참고로, Elvis 연산자는 엘비스 프레슬리의 머리모양을 따서 만들었다고 합니다.

      image.png

      [왜 엘비스인지 아직도 이해가 안되는 그림]

      (3) if 와 when

      Kotlin 에서는 대부분의 문(statement)를 값으로 표현할 수 있는 표현식(statement) 로 간주합니다.

      그러다보니 Java 에서는 불가능했던 if 문을 표현식인 값으로 표현할 수 있습니다.(변수에 할당하거나 바로 리턴할 수 있습니다)

      fun isAdult(age: Int): Boolean{
          return if(age >=20) true else false 
      }

      위와 같은 코드로 if를 표현식으로 바로 리턴 할 수도 있습니다.

      그리고 자바의 switch 문과 비슷한 when 을 사용해서 조건 식을 보다 세밀하고 다양하게 표현할 수 있습니다.

      when 또한 표현식으로 간주되어 변수에 값을 할당할 수도 있고 바로 리턴을 할 수도 있습니다.

      fun isAdult(age: Int): String{
          return when (age) {
              in 0..10 -> "어린이"
              in 11..20 -> "청소년"
              else -> "어른"
          }
      }

      when 으로 조건을 세분해서 String 으로 리턴 합니다. in 과 .. 을 사용해서 조건이 포함되는지를 표현하고 -> 사용해서 조건에 해당하는 값을 지정 합니다.

      (4) 반복문

      대표적인 반복문인 for 언어를 살펴 보겠습니다. Java 에서는 for(int i = 0, i < 10; i++) 로 조건문의 분기값을 지정하는데,

      Kotlin 에서는 when 에서 살펴봤던 in 과 .. 을 통해 증감을 표현합니다.

          for(i in 1..10) {
              println(i)
          }

      숫자가 내려갈 경우에는 .. 이 아닌 downTo 를 사용 합니다.

          for(i in 10 downTo 1) {
              println(i)
          }

      while 문과 do while문은 거의 유사 합니다.

      (5) Kotlin 의 함수 표현

      Java 와 조금 다른 부분인데, Kotlin 에서 함수는 fun 으로 시작 합니다.

      fun main() 이름이 main 인 함수 입니다.

      만약 함수의 매개변수가 있다면 아래와 같이 매개변수를 ( ) 안에 표현합니다.

      fun main(age: Int)

      반환값이 있다고 하면 함수 마지막에 : 를 입력하고 반환 타입을 명시합니다.

      fun main(age: Int): String String 타입을 리턴 합니다.

      함수의 본문은 { } 안에 작성해 주면 되는데요, Java 와 또 다른 점은 하나의 표현식으로 표시되는 함수의 본문은 { }로 표시하지 않고 = 을 사용할 수 있습니다.

      이 경우에는 함수의 리턴타입을 추론할 수 있기 때문에 리턴 타입은 생략 가능합니다.

      fun max(a: Int, b: Int) = if (a > b) a else b 표현이 하나의 식이기 때문에 = 을 사용했고 결과값이 추론 가능하기 때문에 함수의 반환 타입을 생략 했습니다.

      Kotlin 은 Java 와 100% 호환을 목표로 합니다.

      그래서, 기존 Java 클래스나 다른 Kotlin 클래스에 어떤 함수나 필드를 추가할 수 있는 기능을 지원하는데, 이를 '확장 함수', '확장 프로퍼티' 라고 합니다.

      확장함수는 아래와 같이 확장하고 싶은 클래스(수신객체타입) 와 이 클래스에 속하는 인스턴스 객체(수신객체)를 사용해서 표현할 수 있습니다.

      fun String.lastChar(): Char = this.get(this.length - 1) String 클래스를 커스텀하게 확장해서 lastChar 라는 함수를 만들었고,

      String 클래스의 인스턴스(this)를 받아서 마지막 단어를 반환하는 함수 입니다.

      이 함수를 사용하려면 아래와 같이 사용해주면 됩니다.

      "Kotlin".lastChar()

      조심할 점은 확장함수는 오버로드되지 않고 항상 수신객체타입의 인스턴스를 반환합니다.

      (6) Kotlin 의 클래스

      Java 와 동일하게 클래스와 다영성, 상속, 인터페이스, enum 등을 지원 합니다.

      표현이 조금 다른 부분이 있는데, 이 부분만 간단히 살펴 보겠습니다.

      먼저 클래스는 접근 지시자를 생략하면 기본이 public 입니다. Java 와 조금 다른 부분이니 이 부분은 주의하셔야 될것 같아요.

      클래스는 class 키워드를 사용해서 선언 해줍니다. 특이한 점은 생성자 부분인데, 클래스 이름 뒤에 ( ) 를 입력하고 여기에 프로퍼티를 지정해 줍니다.

      class Person(
       val name: String,
       var age: Int)

      Java 와 조금, 아니 많이 틀립니다. 무엇보다 클래스의 바디 부분이 없어도 클래스 표현이 가능 합니다.

      생성자 부분에 어떤 선행작업을 하기 위해서는 init 을 명시해 줘야 합니다.

      class Person(
          val name: String,
          var age: Int
      ){
          init {
              if(age < 18){
                  throw IllegalArgumentException("나이는 18세 이상이어야 합니다")
              }
          }
      }

      class 명 뒤에 ( ) 를 사용해서 생성자를 지정해 주는데, 이 경우 자동으로 getter 와 setter 도 만들어 줍니다.

      위의 Person 클래스의 경우에는 name 은 val 로 선언했기 때문에 재할당이 불가능함으로 Getter 만 생성해주며

      age는 재할당이 가능한 var 로 선언했기 때문에 getter 와 setter 를 동시에 생성해 줍니다.

      Java 에서는 new 연산자로 클래스의 객체를 생성하는데, Kotlin 에서는 new 없이 사용가능하며 인스턴스 참조도 객체가 아닌 프로퍼티(변수) 그대로 사용 합니다.

      fun main() {
          val person = Person("Alice", 29)
          println(person.age) 
      }

      그리고 커스텀 getter 를 지원하는데, 클래스의 바디에 프로퍼티 변수를 선언하고, 이 변수의 getter를 직접 만들어 줄 수 있습니다.

      만약 이름을 무조건 대문자로 변경하는 커스텀 getter를 만들경우 아래와 같이 만들어줄 수 있습니다.

      class Person(
          val name: String,
          var age: Int
      ) {
          val isUppercase
              get() = name.uppercase()
      
          init {
              if (age < 18) {
                  throw IllegalArgumentException("나이는 18세 이상이어야 합니다")
              }
          }
      }
      
      fun main() {
          val person = Person("Alice", 29)
          println(person.age)
          println(person.isUppercase)
      }

      상속은 Java 와 동일하지만 클래스 명 뒤에 : 를 입력하고 상속할 클래스 이름을 명시해 줍니다.

      그리고 부모클래스의 이름 뒤에 생성자를 사용해서 부모 클래스의 생성자(super)를 호출해 줍니다.

      상속을 위해서 부모 클래스에 open 을 입력하고 override 하는 프로퍼티에도 open 을 명시해줘야 합니다.

      아래 코드는 Animal 과 Animal 을 상속한 Cat 클래스를 간단하게 표시했습니다.

      open class Animal(
          val species: String,
          val legCount: Int
      ) {
          open fun move() {
              println("move move")
          }
      }
      
      class Cat(
          species: String,
      ) : Animal(species, 4) {
          override fun move() {
              println("고양이가 걸어 갑니다")
          }
      }
      
      fun main() {
          val myCat = Cat("먼치킨")
          println(myCat.move())
          println(myCat.legCount)
      }

      (7) Lambda 를 사용하는 방법

      Java 에서는 Predicate, Consumer, Function, Supplier 를 사용한 함수형 프로그래밍이 가능 합니다.

      여기에 -> 를 사용한 Lambda 식으로 더 간결하게 코드를 표시할 있는데 Kotlin 에서는 보다 간결하게 표현이 가능 합니다.

      Java 의 Predicate 를 사용한 함수형 프로그래밍의 코드의 예 입니다.

      public class Fruit {
          private String color;
          private Double weight;
      
          public Fruit(String color, Double weight) {
              this.color = color;
              this.weight = weight;
          }
      
          private static List<Fruit> fruitsFilter(List<Fruit> fruits, Predicate<Fruit> filter) {
              List<Fruit> filteredFruits = new ArrayList<>();
              for (Fruit fruit : fruits) {
                  if(filter.test(fruit)) {
                      filteredFruits.add(fruit);
                  }
              }
              return filteredFruits;
          }
      
          public static void main(String[] args) {
              Fruit fruit1 = new Fruit("red", 1.0);
              Fruit fruit2 = new Fruit("yellow", 2.0);
              Fruit fruit3 = new Fruit("red", 0.5);
      
              List<Fruit> fruits = List.of(fruit1, fruit2, fruit3);
              
              //todo : 컬러가 red 인 과일만 추출
              List<Fruit> redFruits = fruitsFilter(fruits, fruit -> fruit.color.equals("red"));
              System.out.println("redFruits = " + redFruits);
              
              //todo : 무게가 1.0 이상인 과일만 추출
              List<Fruit> heavyFruits = fruitsFilter(fruits, fruit -> fruit.weight > 1.0);
              System.out.println("heavyFruits = " + heavyFruits);
      
          }
      
          @Override
          public String toString() {
              return "Fruit{" +
                      "color='" + color + '\'' +
                      ", weight=" + weight +
                      '}';
          }
      }

      위 클래스를 Kotlin 으로 변경하면 아래와 같습니다. 클래스앞에 data 를 사용하고, 생성자 프로퍼티를 사용해서 상당히 간결하게 표시가 가능합니다.

      또한 Java 코드에서는 함수를 매개변수로 전달할 수 없지만(함수형 인터페이스를 실제로 실행함), Kotlin 에서는 함수자체를 매개 변수로 전달 할 수 있습니다.

      fun main() {
          val fruits = listOf(
              KotlinFruit("red", 1.0),
              KotlinFruit("yellow", 2.0),
              KotlinFruit("red", 0.5),
          )
          //todo : 컬러가 red 인 과일만 추출
          val redFruits = filterFruits(fruits) { it.color == "red" } 
          println("redFruits = $redFruits")
      
          //todo : 무게가 1.0 이상인 과일만 추출
          val heavyFruits = filterFruits(fruits) { it.weight > 1.0 }
          println("heavyFruits = $heavyFruits")
      }
      data class KotlinFruit(
          val color: String,
          val weight: Double
      )
      
      fun filterFruits(fruits: List<KotlinFruit>, filter: (KotlinFruit) -> Boolean): List<KotlinFruit> {
          val filteredFruits = mutableListOf<KotlinFruit>()
      
          for (fruit in fruits) {
              if(filter(fruit)) {
                  filteredFruits.add(fruit)
              }
          }
          return filteredFruits
          
          //todo : 위의 코드는 Kotlin 의 filter() 를 통해 더 간결한 표시가 가능합니다
          //return fruits.filter(filter)
      }

      기분 탓인지 모르겠지만, Java 코드보다 간결해 보입니다. Kotlin 에서는 Lambda 함수를 { } 로 감싸서 사용 합니다.

      { fruit -> fruit.color == "red} -> { it.color == "red} 와 같이,

      Lambda 함수에서 매개변수가 한개일 경우 it 으로 대체해서 보다 간결하게 표시할 수 있습니다.

      또한 함수에서 마지막 파라미터에 람다를 쓸 경우에는 ( ) 오른쪽으로 Lambda 함수를 보낼 수 있습니다.

      val redFruits = filterFruits(fruits) { it.color == "red" }


      5. 마치며

      Kotlin 에서는 위에서 말씀드린 것 외에 많은 내용이 있습니다. Java 를 배우신 분은 Kotlin 을 학습하는데 도움이 되실것 같습니다.

      저 역시 Kotlin 을 걸음마 단계로 배우고 있으며 짧게나마 공부한 내용을 남겨 봅니다.

      댓글 0

      DEVOTEE를 활성화 시키면
      지금 작성한 댓글에 AI가 댓글을 달아줍니다.

      박제영 님의 최신 블로그

      더보기

      DEVOTEE 추천 블로그

      동영상 기고하기