logo
logo
언어
Kotlin
자바가 실행되는 환경에서 자바를 대체할 수 있도록 개발된 언어
StackOverflow 질문 수: 96614
Github Stars : ★ 48426
사용 기업
직장
금융/보험
패션
교육
이커머스
소셜/컨텐츠
부동산/인테리어
여행
기타
푸드테크
모빌리티
헬스케어
인공지능
종합
블록체인
techstack-logo
플렉스
techstack-logo
렌딧
techstack-logo
토스랩
techstack-logo
핀다
techstack-logo
드라마앤컴퍼니
techstack-logo
딜리셔스
techstack-logo
뤼이드
techstack-logo
에이블리
techstack-logo
트렌비
techstack-logo
드림어스컴퍼니
techstack-logo
스푼
techstack-logo
클래스101
techstack-logo
디셈버앤컴퍼니
techstack-logo
직방
techstack-logo
당근
techstack-logo
마이리얼트립
techstack-logo
버킷플레이스
techstack-logo
와디즈
더 보기
기술 블로그 글
카카오
코틀린을 활용한 안전한 효과 처리
안녕하세요, 전자문서 서비스의 서버를 개발하고 있는 Alan입니다.스프링(Spring)으로 서버를 개발하다 보면 데이터베이스를 사용하는 경우가 곧잘 있습니다. 이때 트랜잭션 처리를 직접 구현하기보다는 스프링의 지원을 받아 구현하는 것이 일반적인 과정입니다. 특히, 트랜잭션의 처리 방식을 정확하게 알지 못하더라도 프레임워크가 모든 과정을 대신 처리해 주기 때문에 러닝 커브가 낮다는 것이 큰 장점인데요. 그러다 보니 지나치게 프레임워크에 의존하여 안전하지 않은 코드를 무심코 작성하게 되는 경우가 종종 있는 것 같습니다.이번 글에서는 독자분들께 통상 효과적인 처리 방식이라 생각하는 스프링 프레임워크를 통한 트랜잭션 처리가 잠재적으로 가져올 수 있는 위험성을 소개하고 살펴보겠습니다. 또한, 이 문제를 해결하기 위한 방법으로 최근 스프링과 조합되어 사용되는 비중이 점차 증가하고 있는 코틀린(Kotlin)을 활용하여 잠재된 위험성을 줄이는 방식 또한 알아보도록 하겠습니다.프로그램의 효과현대의 프로그램은 격리된 환경에서 단독으로 실행되는 것이 아니라 사용자의 다양한 요구사항에 맞추어 데이터베이스에서 정보를 읽거나, 다른 프로그램과 HTTP 프로토콜을 사용한 통신으로 데이터를 주고받습니다. 이렇게 프로그램이 외부 세계와 상호 작용하는 것을 통칭 ‘효과’라고 부릅니다.아래 코드 예시와 같이, 전통적인 프로그램은 외부 세계와 상호 작용을 처리하는 컨텍스트(Context)를 함수에 직접 전달해야 했습니다.이러한 방식은 함수가 어떤 효과를 수행할 것인지 명시적으로 표현할 수 있지만, 개발자가 모든 과정을 하나하나 처리해야 한다는 단점이 있습니다. 예를 들어 데이터베이스에 데이터를 저장하려면 트랜잭션을 시작하고, 데이터를 저장하고, 트랜잭션을 커밋하는 과정을 모두 직접 처리해야 합니다. 게다가 코드의 실행 과정에서 예외가 발생할 수도 있으므로 이를 대비한 방어 로직 또한 작성해야 합니다.최근에는 개발자가 이러한 과정을 직접 구현하기보다는 프레임워크에게 처리를 일임하는 것이 각광받고 있습니다. 특히 백엔드 개발에서 주로 사용하는 스프링은 이 효과를 손쉽게 처리할 수 있도록 DI와 AOP를 지원합니다.아래 예시와 같이, 스프링 프레임워크에선 함수에 @Transactional 어노테이션을 추가하기만 하면 트랜잭션의 모든 과정을 스프링이 대신 처리하도록 구현이 가능합니다. AOP를 통한 효과를 처리하는 방법은 굉장히 유용하기는 하지만, 아쉬운 부분도 있습니다. 바로 모든 클래스와 함수에 어노테이션을 아무런 제약이 없이 설정할 수 있다는 점입니다. 이러한 유연성은 엉뚱한 곳에 효과를 부여하거나 반대로 반드시 필요한 곳에는 효과를 부여하지 못하는 부작용(Side effect)을 가져올 수 있습니다.그렇다면 효과를 안전하게 처리하려면 어떻게 해야 할까요? 전통적인 방식에서는 효과 처리에 지나친 자율성이 부여되었기 때문에 작성된 코드의 동작을 예측하기 어렵게 만들었습니다. 따라서, 이러한 생각을 스프링 프레임워크에서도 도입하여 자율성을 제약한다면, 코드의 동작을 보다 예측 가능하도록 변경할 수 있을 것입니다.지금부터는 코틀린을 활용하여 안전하게 효과를 처리하는 방법을 알아보도록 하겠습니다.코틀린에서 제약 조건을 설정하는 방법은 바로 확장 함수(Extension function)를 정의하는 것입니다.확장 함수는 함수의 이름 앞에 수신 객체 타입을 지정하여 정의할 수 있습니다. 확장 함수는 이름처럼 수신 객체 타입에 기능을 추가하는 용도로도 쓰이지만, 반대로 생각하면 확장 함수를 해당 수신 객체가 있을 때만 사용할 수 있도록 제약하는 방식으로도 사용할 수도 있습니다.save 함수에 DatabaseContext라는 수신 객체 타입을 설정하면 컨텍스트 없이는 단독으로는 save 함수를 호출할 수 없습니다.이제 코틀린의 확장 함수를 사용해서 스프링 예제 코드를 개선해 보도록 하겠습니다. 코드의 요구사항은 아래와 같습니다.• 상품을 삭제하는 프로그램을 개발한다.• 상품을 삭제하는 함수는 반드시 트랜잭션 범위 안에서만 호출해야 한다.스프링에서는 함수를 트랜잭션 범위 안에서만 호출할 수 있도록 만들고 싶다면 아래와 같이 @Transactional 어노테이션을 추가하고 MANDATORY 옵션을 설정하기만 하면 됩니다.그런데 만약 @Transactional 어노테이션이 누락된 채로 코드가 작성되었다면 어떤 위험이 있을까요? AOP 방식의 트랜잭션은 컴파일 타임에는 호출 관계에 대한 문법 에러를 감지할 방법이 없습니다. 따라서 런타임에 함수를 호출하게 되면 서버에서 에러가 발생하게 됩니다.그렇다면 이 문제를 해결할 수 있는 근본적인 해결책은 무엇일까요? 가장 좋은 방법은 요구 사항 그대로 트랜잭션이 없는 경우, 컴파일 타임에 에러가 감지되도록 하여 개발자의 실수를 방지하는 것입니다. 이때, 아래 예시와 같이 코틀린을 사용한다면 delete 함수에 트랜잭션을 처리해 줄 특별한 컨텍스트를 지정하여 이 목표를 쉽게 달성할 수 있습니다.개선된 코드에서는 delete 함수에 @Transactional을 지정하는 대신에 DatabaseContext를 수신 객체 타입으로 지정하였습니다. 지금부터는 확장 함수의 특성으로 인해 DatabaseContext와 ProductComponent가 모두 주입된 영역에서만 delete 함수를 호출할 수 있습니다. 즉, 잘못된 코드를 억지로 사용하고 싶어도 컴파일 과정에서 문법 에러가 감지되어 컴파일이 실패하게 됩니다. 이는 기존에는 런타임 시점에서야 감지할 수 있었던 에러가 원천적으로 차단될 수 있다는 것을 시사하며, 효과를 안전하게 처리하는 방식에 한 발짝 가까워졌음을 의미합니다.고차 함수로 효과 함수 전달코틀린은 함수를 인자로 받거나 리턴할 수 있는 고차 함수를 지원합니다. 코틀린의 고차 함수를 적용한 예시는 아래와 같습니다.기존에 살펴보았던 delete 함수는 이제 상품을 직접 삭제하는 것이 아니라, 상품을 삭제하는 함수를 리턴하는 고차 함수로 작성되었습니다. 물론 리턴되는 함수에도 DatabaseContext가 수신 객체 타입으로 지정할 수 있기 때문에 제약 사항도 잘 지켜지고 있습니다.효과 함
kotlin
spring
라인
Req-Saver로 캐시의 골칫거리 'Thundering Herd 문제' 쉽게 풀기!
안녕하세요. LINE+ Contents Service Engineering 조직에서 백엔드 개발을 맡고 있는 양강현, 이병찬입니다. 저희가 속해 있는 Contents Server Engineering에서는 Tech Group이라는 조직을 운영하고 있습니다. Tech Group은 여러 조직이 공통으로 직면한 문제를 해결하기 위해 활동하면서, 특히 대량의 트래픽을 효율적으로 처리하는 방안을 모색했습니다. 이 과정에서 캐싱 프로세스를 고도화하는 작업을 진행했고, 그 결과 'Req-Saver'라는 사내용 라이브 러리를 개발했습니다.이 글에서는 Req-Saver를 개발한 배경과 세부 기능을 상세히 소개하고자 합니다.일반적으로 애플리케이션이 캐시를 활용하는 방법보통 애플리케이션이 캐시를 이용하는 모습은 아래와 같습니다.클라이언트가 어떤 요청을 했을 때 그 요청에 맞는 내용이 캐시에 있으면 클라이언트는 바로 응답을 받습니다. 만약 캐시에 없다면 캐시 뒤에 위치한 백엔드 데이터 스토어(DB, 서버, 파일 등)에서 데이터를 가져온 후 캐시에 저장합니다(위 그림에서는 편의상 'MySQL'로 표현).이와 같은 구조에서 만약 N개의 클라이언트 요청이 들어왔다고 가정해 보겠습니다. 이때 캐시에 N개의 요청에 맞는 내용이 없으면 N개 요청 모두가 백엔드 데이터 스토어에 데이터를 요청하며, N개의 요청이 원하는 값이 같다고 해도 N번의 요청이 그대로 진행됩니다. 더불어 특별한 조치를 취하지 않는다면 백엔드 데이터 스토어에서 받은 데이터를 캐시에 N번 기록하는 작업도 진행됩니다. 이는 백엔드 스토어와 캐시 모두에 부하를 일으키는 원인이 되며, 이를 'Thundering Herd 문제'라고도 합니다.Req-Saver 개발은 바로 이 'Thundering Herd 문제'를 해결할 수 있는 방법을 모색하는 과정에서 시작됐습니다.Req-Saver의 아이디어이 문제는 백엔드 데이터 스토어를 향하는 클라이언트의 요청을 어떻게 하면 줄일 수 있을지가 관건이었고, 캐시 히트 여부에 따라 두 가지 아이디어를 적용할 수 있다고 생각했습니다.요청받은 데이터가 캐시에 존재하지 않을 때요청받은 데이터가 캐시에 존재하지 않아 백엔드 스토어에서 가져와 캐시에 적재해야 할 때, 애플리케이션 단에서 로컬 혹은 글로벌 락(lock)을 이용해 특정 요청만 백엔드 스토어로 보내고 나머지 요청은 락을 잡은 요청이 캐시에 데이터를 생성할 때까지 대기한다면 문제를 해결할 수 있습니다.요청받은 데이터가 캐시에 존재할 때요청받은 데이터가 캐시에 존재해 바로 클라이언트에게 응답하는 경우에도 미래를 위한 예방 조치를 할 수 있습니다. 예를 들어 조회하고자 하는 캐시의 TTL(time to live)이 10초이고 클라이언트가 해당 캐시를 조회할 때 TTL이 2~3초 정도 남은 시점이라면 캐시 만료를 기다리지 말고 바로 캐시 TTL을 갱신하는 것입니다. 이를 통해 일정한 트래픽이 들어온다는 전제하에 캐시가 만료되는 공백 시간 없이 마치 캐시가 연속적으로 존재하는 것과 같은 효과를 기대할 수 있습니다.위 내용 을 시간 그래프 형태로 비교하면 아래와 같습니다.각 아이디어를 어떻게 구현했는지 하나씩 살펴보겠습니다.요청받은 데이터가 캐시에 존재하지 않을 때이 경우에는 락(lock) 메커니즘을 적극 활용했습니다.락은 크게 로컬 락과 글로벌 락이 있는데요. 먼저 글로벌 락은 라이브러리 입장에서 개발자가 어떤 분산(distributed) 락을 사용할지 모르기 때문에 단순히 함수를 주입받는 방법으로 구현했습니다. 개발자가 Req-Saver의 인스턴스를 생성할 때 주입한 글로벌 락 함수를 애플리케이션 단에서 실행함으로써 글로벌 락을 취득했다고 인식한 후, 락을 취득한 요청이 대표로 데이터 취득 및 캐시 적재 작업을 진행합니다. 락을 취득하지 못한 요청들은 설정된 시간 동안 데이터가 캐시에 적재되기를 기다립니다.로컬 락은 세마포어(semaphore)를 적극 사용 중이며, 락 취득이 서버 인스턴스마다 진행된다는 점만 빼고 나머지 작동 방식은 위 그림과 같습니다.요청받은 데이터가 캐시에 존재할 때이 경우 역시 락 메커니즘을 적극적으로 활용하지만 전자와 살짝 다른 부분이 있습니다.우선 캐시에 데이터가 존재하기 때문에 락을 취득하지 못한 요청들이 캐시에 데이터가 적재되기를 기다릴 필요가 없습니다. 바로 클라이언트에게 응답하면 됩니다. 락을 취득한 요청 역시 바로 클라이언트에게 응답하며, 비동기로 캐시 갱신을 진행합니다.Req-Saver의 작동 원리를 순서도로 정리하면 아래와 같습니다.Req-Saver의 모듈은 크게 코어 모듈과 Spring 모듈, 지원 모듈로 나눌 수 있습니다. 각 모듈을 살펴보겠습니다.코어 모듈은 각 플랫폼에 맞게 사용할 수 있도록 아래 세 가지로 구성했습니다. 각 모듈에는 메인 메서드와 설정 파일이 포함돼 있습니다.• core: 일반적인 순차적 블로킹(sequencial-blocking) 메서드 환경 하에서의 코어 로직이 포함되어 있습니다.• core-reactor: Reactor 기반의 코어 로직이 포함되어 있습니다.• core-kotlin-coroutine: Kotlin Coroutine 기반의 코어 로직이 포함되어 있습니다.개발자는 각자의 환경에 맞는 코어 모듈을 로 가져와서 설정 작업을 진행한 후 인스턴스 생성과 동시에 메인 메서드를 실행해 Req-Saver의 기능을 사용할 수 있습니다.아래는 Req-Saver 인스턴스를 생성한 후 실제 캐시 데이터 취득 및 저장에 활용하는 샘플 코드입니다.Spring 프레임워크에서 아래와 같이 Bean으로 생성한 후 사용할 수도 있습니다.코어 모듈에서 더 나아가, Req-Saver를 Spring 프레임워크에서 흔히 사용하는 , 같은 애너테이션(annotation)처럼 편리하게 사용할 수 있도록 Spring 기반의 모듈도 구성했습니다.Spring 기반 모듈은 앞서 말씀드린 코어 모듈을 기반으로 , 라는 애너테이션으로 Req-Saver를 사용할 수 있도록 제공하며, 저희 개발 팀에서 주로 사용하는 기술 스택에 맞게 MVC와 WebFlux, WebFlux Kotlin Coroutine의 세 가지 모듈로 구성했습니다.
kotlin
redis
spring
SK텔레콤
Java 를 아시면 Kotlin 을 배워 보세요
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를 만든 회사죠)[JetBrain 사의 회사 로고]Kotlin 이란 이름은 JetBrain 의 개발센터가 있는 러시아의 상트페리트루르크에 있는 코틀린 섬에서 이름을 따왔다고 합니다.(참고로 JetBrain 은 체코의 회사 입니다). 우리는 언제쯤 "월미도", "제주도" 이런 프로그램을 만들 수 있을까요?[블로그 내용과 별 상관이 없는 코틀린 섬의 지도]Kotlin 은 Java 와 100% 호환을 목표로 하고 있습니다.그렇기에 기존 Java Library 를 그대로 사용할 수 있으며, 반대로 Java 에서도 Kotlin 을 사용할 수 있습니다.Kotlin 은 일반적으로 서버상의 코드(웹 애플리켕션의 Back-End), 안드로이드 디바이스에서 실행되는 모바일 애플리케이션에 사용할 수 있습니다.그리고 특이하게 자바 스크립트를 지원해서 브라우저나 Node 에서도 실행이 가능 합니다.Java 와 마찬가지로 컴파일에 타입을 검사하는 정적 타입을 지원합니다.하지만, Java 와 다른 점은 타입 추론 (type infernece) 를 통해서 변수의 타입을 생략 할 수도 있습니다Java에서도 Functional Interface 와 Lambda 를 통해 일부 함수형 프로그래밍을 지원하지만 Kotlin 에서는 보다 완벽하게 함수형 프로그래밍을 지원합니다.즉, 함수를 파라미터로 받거나 함수를 반환할 수 있습니다.컴파일러, 라이브러리 및 도구등이 모두 오픈 소스이며 Apache2 라이선스를 사용해서 무료료 사용할 수 있습니다.Intelli-J Commucation 버전 및 Ultimate(이건 구매해야 되죠) 지원이 가능합니다.Kotlin 에서는 val, var 라는 변수 타입을 지원합니다.먼저 val 은 value 의 약자이며 Java 의 final 변수와 동일합니다.(한번 값이 지정되면 변경 불가능)var 는 variable 의 약자이며 Java 의 final 이 아닌 변수와 동일합니다.(값 변경 가능)kotlin 에서는 언어적 특성상 변수를 가급적 val 로 선언하는 것을 권고하고 있습니다.변수명 뒤에 : 를 입력하고 타입명을 적어 주시면 됩니다.변수의 이름은 name 이고 타입은 String 입니다. (식의 마지막 ; 는 생략 가능합니다, 코드에서는 생략했지만 final 이기 때문에 ``값을 무조건 대입해줘야 합니다)"David" 은 명시적으로 타입이 String 이기 때문에 타입 생략이 가능 합니다.name을 윗줄의 코드에서 val 로 지정했기 때문에 다른 이름을 지정하면 컴파일 오류가 발생합니다.java 에서는 항상 매개변수를 사용하기전에 null 체크를 해줘야 합니다.Java8 이후부터는 Optional 이 도입되면서 null 체크에 보다 유연성이 생겼지만, 그래도 이 부분은 항시 신경을 써야 합니다.Kotlin 에서는 변수 선언시에 이 변수가 null 을 허용할 것인지, 안 할 것인지를 선언할 수 있습니다.변수의 이름은 age 이며 타입 뒤에 ? 를 표시해서 Null 이 들어올 수도 있습니다.**Safe call **: 와 같이 프로퍼티에 직접 접근할 경우 age 가 Null 이면 NPE(Null Point Exception)이 발생할 수 있씁니다.safe call 은 ? 를 사용해서 프로퍼티에 접근하며, 만약 프로퍼티가 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 연산자는 엘비스 프레슬리의 머리모양을 따서 만들었다고 합니다.[왜 엘비스인지 아직도 이해가 안되는 그림]Kotlin 에서는 대부분의 문(statement)를 값으로 표현할 수 있는 표현식(statement) 로 간주합니다.그러다보니 Java 에서는 불가능했던 if 문을 표현식인 값으로 표현할 수 있습니다.(변수에 할당하거나 바로 리턴할 수 있습니다)위와 같은 코드로 if를 표현식으로 바로 리턴 할 수도 있습니다.그리고 자바의 switch 문과 비슷한 when 을 사용해서 조건 식을 보다 세밀하고 다양하게 표현할 수 있습니다.when 또한 표현식으로 간주되어 변수에 값을 할당할 수도 있고 바로 리턴을 할 수도 있습니다.when 으로 조건을 세분해서 String 으로 리턴 합니다. in 과 .. 을 사용해서 조건이 포함되는지를 표현하고 -> 사용해서 조건에 해당하는 값을 지정 합니다.대표적인 반복문인 for 언어를 살펴 보겠습니다. Java 에서는 로 조건문의 분기값을 지정하는데,Kotlin 에서는 when 에서 살펴봤던 in 과 .. 을 통해 증감을 표현합니다.숫자가 내려갈 경우에
java
kotlin
카카오페이
여러 제휴사와 연동하는 신규 프로젝트 개발기 2편
안녕하세요, 카카오페이 보험마켓파티의 카펀입니다. 카카오페이 자동차보험 비교 서비스를 개발하며 마주한 문제와, 이들에 대한 고민을 소개하고 있습니다. 1편에서는 여러 제휴사 관리를 위한 공통 구조, 여러 제휴사를 호출할 때의 병렬 및 비동기 처리에 대해 소개해 드렸습니다. 2편에서는 사용자 입력에 대한 검증과 테스트 코드를 작성하는 방법에 대해 다루어 보겠습니다.🔗 여러 제휴사와 연동하는 신규 프로젝트 1편사용자 입력과 유효성 검증은 어떻게 다루어야 할까?유효성 검증을 하는 이유서비스를 매우 단순히 생각해 보면, 사용자는 아래와 같은 흐름으로 사용하게 됩니다.• 사용자는 클라이언트에 필요한 값을 입력한다.• 클라이언트는 서버에 값을 전달한다.• 서버는 제휴사에 값을 전달하고, 응답을 받는다.• 서버는 클라이언트에 응답을 보낸다.• 클라이언트는 사용자에게 응답을 보여 준다.이 중에서 눈여겨보고자 하는 단계는 ‘클라이언트는 서버에 값을 전달한다’ 단계입니다. 사람이 입력한 값을 시스템에 전달하는 과정이다 보니, 입력 가능한 값의 범위를 엄밀하게 정의해 두지 않으면 온갖 잘못된 값이 들어올 수 있습니다. 이렇게 잘못된 값이 들어오기 시작하면, 예상치 못한 동작의 원인이 되거나, 서버로부터 받은 응답을 신뢰할 수 없게 됩니다.사용자의 입력을 검증하는 것 역시 크게 두 가지로 나눌 수 있습니다.• 사용자의 입력을 클라이언트에서 검증하고, 잘못된 입력에 대해서는 경고를 표시한다.• 클라이언트에서 전달하는 값을 서버에서 검증하고, 잘못된 입력에 대해서는 Client-Error로 응답한다.이 중 어떤 방법을 선택하는 것이 좋을까요? 저는 둘 다 병행해야 한다고 생각합니다. 각기 검증의 역할과 목적이 다르기 때문인데요.클라이언트의 경우에는, 잘못된 입력값에 대해 사용자에게 알려 주고, 올바른 값을 선택할 수 있도록 안내하기 위한 검증을 진행합니다. 동시에 잘못된 값이 서버로 넘어가는 것을 막아 주는 역할을 합니다.서버의 경우에는, 입력값이 시스템으로 전달되기 전에 마지막으로 확인을 하는 역할입니다. 이 단계에서 검증을 통과하지 못하면 애플리케이션이 정상 진행될 수는 없지만, 상대적으로 더 엄격하고 확실하게 검증할 수 있습니다.서버 단계 검증이 특히 중요한 이유는, 클라이언트에서 의도와 상관없이 잘못된 값을 넘겨줄 수도 있다는 점입니다. 여러 경우의 수가 겹치다 보면, 클라이언트의 검증이 완벽하지 않을 수 있습니다. 예상하지 못한 사용자의 입력이 가능한 경우에도, 서버에서 이를 최종 확인해서 막아야 합니다. 또한 클라이언트는 사용자에게 노출되어 있기 때문에, 나쁜 의도를 가지고 서버에 잘못된 값을 보내도록 조작하는 등의 리스크 역시 존재합니다. 서버 단계에서의 검증을 통해 이러한 리스크를 줄일 수 있습니다.Kotlin Contracts는 Kotlin 1.3에서 추가되었습니다. 주된 역할은, 코드 분석 시 컴파일러가 모르는 정보를 사용자가 알고 있을 때, 그 정보를 알려주는 것입니다.이를 잘 이용한 것이 Kotlin의 , 와 같이 조건을 검증하는 것입니다.
kotlin
Copyright © 2024. Codenary All Rights Reserved.