SlideShare une entreprise Scribd logo
1  sur  61
Télécharger pour lire hors ligne
카카오톡의 서버사이드 코틀린
유용하(indy.jones)
kakao corp.(톡메시징파트)
________ ________ ________ ________ ________ __
/ / // // / // // / _==--------_ --
/ / / / / / / / / / / / / / / /  |
/ <:/ / / <:/ / / / / / / /__ ___ 
/ / // / / / / // / / / / / / | . . :|
/___/___/ /___/___/ /___/___/ /___/___/ /_______/ / / | __.__ :|
::::::/::::::/::::::/::::::/:::::::/ / | /::::: .:|
______/______/______/______/_______/ | _ ^ _/ .:/
________ ________ ____ ________  .:/
/ // // / / / / _ ..:/
/__ __/ / / / / / / / / / / /"------""
:/ /:/ / / /___/ / <:/ / / . . . 
/ / // / / / // / /_/ | / ::::: | |
/__/ / /___/___/ /_______/ /___/___/ / | ::::::: |/
::/ /:::::: :::::::/::::::/ / | ::::: |
__/ ______/_______/______/ | | |
## 카카오톡에 오신것을 환영합니다!
kakaotalk$
서비스 구성
LOCO
메시지
전송
채팅방
미디어
전송
WEBAPP
가입 인증 친구
프로필 설정 톡검색
LOCO
단말의 API 요청 수
메시지
전송
채팅방
미디어
전송
WEBAPP
가입 인증 친구
프로필 설정 톡검색
50B+ / day
800K+ / sec
평소 피크
6.5M+ / sec
역대 최대
LOCO
단말의 API 요청 수
메시지
전송
채팅방
미디어
전송
WEBAPP
가입 인증 친구
프로필 설정 톡검색
평소 피크
역대 최대
하루에 500억+
1초에 80만+
1초에 650만+
생활 속의 서비스
1:0
1:1
2:1
2:2
2:3
3:3 4:3
경기 종료
생활 속의 서비스
x4
생활 속의 서비스
무중단
무점검
무장애 😰
7년
‘겁나 빠른 황소’ 프로젝트 (LOCO) 2011
2017~
카카오톡 서버 구조 개선 프로젝트
개발 언어로 코틀린 (for JVM) 도입
기존 컴포넌트 개선을 위한 대체, 서비스 투입
신규 플랫폼용 컴포넌트 개발, 검증용도 서비스 투입2017
2018
Brewery
코틀린 (for JVM) 선택의 배경
✔ 적정한 성능/안정성, 개발/운영의 편의성
✔ 다양한 목적의 서버 환경에 검증된 자바의 생태계를 이용
✔ 생산성이 좋은 새로운 언어
✔ 적정 수준의 러닝 커브
도입을 고민할 때 할 만한 걱정들
개발 환경은 쓸 만 한가요?
언어로 생산성과 안전함이 향상된다?
잘 돌아가나요?
자바와 어느 정도 호환되나요?
문법
그래서
생태계
개발 환경
개발 환경은 쓸 만 한가요?
언어로 생산성과 안전함이 향상된다?
잘 돌아가나요?
자바와 어느 정도 호환되나요?
문법
그래서
생태계
개발 환경
버전 업데이트 시 변화가 크지 않음
1.0 ~ 1.3(preview)의 문법, API 하위 호환
역사
https://github.com/JetBrains/Kotlin
1.0.0
오픈소스
1.1.0 1.2.0
안드로이드 공식 지원
M1~M14, 1.0 Beta 1~4 1.3-M1
릴리즈
하위 호환
Build Tool
Gradle
buildscript {
ext.kotlin_version = '1.2.60'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin'
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
Maven (v3)
<properties>
<kotlin.version>1.2.60</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugins>
</build>
kotlin-gradle-plugin
kotlin-maven-plugin
apply plugin: 'kotlin'
kotlin-stdlib
kotlin-stdlib
Gradle Maven (v3)
Build Tool
buildscript {
ext.kotlin_version = '1.2.60'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin'
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
<properties>
<kotlin.version>1.2.60</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugins>
</build>
apply plugin: 'kotlin'
kotlin-stdlib
kotlin-stdlib
kotlin-gradle-plugin
kotlin-maven-plugin
*.kt
*.java
*.class
*.class
kotlinc
javac
*자바 파일 혼재하는 경우
compileJava
compileKotlin
개발 환경
IntelliJ IDEA, Eclipse,
✔ 증분 컴파일 (Incremental compilation)
✔ 자동 완성
✔ 코드 리팩토링
✔ 자바 to 코틀린 코드 변환 (파일, 클립보드)
✔ 디버거
개발 환경은 쓸 만 한가요?
언어로 생산성과 안전함이 향상된다?
잘 돌아가나요?
자바와 어느 정도 호환되나요?
문법
그래서
생태계
개발 환경
https://kotlinlang.org
클래스, 인터페이스, 함수의 호환
class KotlinClass<T> :
JavaInterface<T> {
fun foo(arg: Int): String { … }
}
interface KotlinInterface<T> {
}
class JavaClass<T>
implements KotlinInterface<T> {
String foo(int arg) { … }
}
interface JavaInterface<T> {
}
Kotlin Java
val java = JavaClass<Int>()
java.foo(1)
KotlinClass<Integer> kotlin =
new KotlinClass<>();
kotlin.foo(1);
Annotation
import org.springframework.web.bind.annotation.*
import org.springframework.web.servlet.config.annotation.EnableWebMvc
import javax.inject.Inject
@Import(BroadcastConfig::class)
@EnableWebMvc
@RestController
class BroadcastController {
@Inject
private lateinit var httpClient: HttpClient
@PostMapping("/broadcast")
fun broadcast(@RequestBody request: BroadcastRequest) {
}
}
Compile-time Annotation은 kapt 빌드 플러그인 사용
메소드/필드 호환으로 자바의 Runtime Annotation이 동일하게 동작
기본 데이터 타입
java.lang.Object
int, java.lang.Integer
double, java.lang.Double
java.lang.String
java.util.Collection<E>
java.util.List<E>
java.util.Set<E>
java.util.Map<K, V>
Object[]
int[]
kotlin.Any
kotlin.Int
kotlin.Double
kotlin.String
kotlin.collections.Collection<E>
kotlin.collections.MutableCollection<E>
kotlin.collections.List<E>
kotlin.collections.MutableList<E>
kotlin.collections.Set<E>
kotlin.collections.MutableSet<E>
kotlin.collections.Map<K, V>
kotlin.collections.MutableMap<K, V>
kotlin.Array<Any>
kotlin.IntArray
Bytecode
Kotlin Java
(등등의 primitive 타입)
Object
원시 타입
문자열
컬렉션
배열
자바 솔루션과의 연동
Lettuce
(Redis Client)
JDBC
SLF4J / Logback
Apache Curator
(ZooKeeper)
Guava
Mockito
Spring
Netty
RxJavagRPC
JUnit
Apache Kafka Client
Hystrix
개발 환경은 쓸 만 한가요?
언어로 생산성과 안전함이 향상된다?
잘 돌아가나요?
자바와 어느 정도 호환되나요?
문법
그래서
생태계
개발 환경
중복 최소화
// Java
class Host {
private final String name;
private final int port;
private int weight;
Host(String name, int port, int weight) {
this.name = name;
this.port = port;
this.weight = weight;
}
public String getName() { return name; }
public int getPort() { return port; }
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
@Override
public boolean equals(Object obj) { return false; }
@Override
public int hashCode() { return 0; }
@Override
public String toString() { return ""; }
}
// Java (with Lombok)
import lombok.*;
@AllArgsConstructor
@ToString
@EqualsAndHashCode
class Host {
@Getter @NonNull private final String name;
@Getter private final int port;
@Getter @Setter private int weight;
}
// Java (with Lombok)
import lombok.*;
@AllArgsConstructor
@ToString
@EqualsAndHashCode
class Host {
@Getter @NonNull private final String name;
@Getter private final int port;
@Getter @Setter private int weight;
}
Too many annotations
Lombok
중복 최소화
// Java
class Host {
private final String name;
private final int port;
private int weight;
Host(String name, int port, int weight) {
this.name = name;
this.port = port;
this.weight = weight;
}
public String getName() { return name; }
public int getPort() { return port; }
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
@Override
public boolean equals(Object obj) { return false; }
@Override
public int hashCode() { return 0; }
@Override
public String toString() { return ""; }
}
// Java (with Lombok)
import lombok.*;
@AllArgsConstructor
@ToString
@EqualsAndHashCode
class Host {
@Getter @NonNull private final String name;
@Getter private final int port;
@Getter @Setter private int weight;
}
Lombok
Kotlin
// Kotlin
data class Host(
val name: String,
val port: Int,
var weight: Int
)
중복 최소화
// Java
class Host {
private final String name;
private final int port;
private int weight;
Host(String name, int port, int weight) {
this.name = name;
this.port = port;
this.weight = weight;
}
public String getName() { return name; }
public int getPort() { return port; }
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
@Override
public boolean equals(Object obj) { return false; }
@Override
public int hashCode() { return 0; }
@Override
public String toString() { return ""; }
}
Kotlin
// Kotlin
data class Host(
val name: String,
val port: Int,
var weight: Int
)
val host = Host("kakao.com", 443, 1)
println("${host.name}:${host.port}")
host.weight = 2
안전한 코드
코딩의 실수로 인한 오류를 방지하는 방법
✔ 유효한 패턴 적용, 안티 패턴을 지양
✔ 테스트 작성
✔ 공개된 API의 문서화
✔ 문법에서 실수 가능성을 막아 컴파일 시점에 오류를 방지
안전한 코드
정적 타입: 더 엄격한 타입 체크
Nullable 타입을 문법에서 구분
Primitive 타입, Boxed 타입 구분 없음:
Int, Long, Float, Double, Byte, Short, Char, Boolean 클래스 이용

특수 타입: Any, Nothing, Unit
개선된 타입 시스템
안전한 코드: Nullable 타입
Not-null Type Nullable Type
var str: String
str = null str = null
if (str != null) {
val len: Int = str.length
}
val len: Int? = str?.length
val len: Int = str?.length ?: 0
var str: String?
Smart Cast
“컴파일 시점”에 NPE를 방지한다.
Optional을 문법에서 강제한다.
그래도 자바와 호환 과정에서는 발생할 수 있다.
val len: Int = str.length val len: Int = str.length
안전한 코드: 불변 컬렉션
list.set(0, 100)
list[0] = 100
list.add(100)
list.remove(0)
map.put("key", 1)
map["key"] = 1
map.remove("key")
“컴파일 시점”에 자료의 변경을 막는다.
그래도 자바에 넘겼을 때는 변경될 수 있다.
Immutable List Immutable Map
val list: List<Int>
val i = list.get(0)
val i = list[0]
val map: Map<String, Int>
val i = map.get("key")
val i = map["key"]
변경용 API 변경용 API
안전한 코드: 불변 컬렉션
list.set(0, 100)
list[0] = 100
list.add(100)
list.remove(0)
map.put("key", 1)
map["key"] = 1
map.remove("key")
Mutable List Mutable Map
val list: MutableList<Int>
val i = list.get(0)
val i = list[0]
val map: MutableMap<String, Int>
val i = map.get("key")
val i = map["key"]
변경용 API 변경용 API
* List<T>의 sub-interface * Map<K, V>의 sub-interface
안전한 코드: final
불변 변수 val를 권장 (final 변수)
상속 제한이 디폴트 (final 클래스, 함수)
open class PushServiceImpl(private val pushService: PushService)
: PushService {
open override fun push(request: PushRequest) {
// ...
}
}
val max = 1 // final
max = 100
의외로 변경이 필요한 변수는 많지 않다.
통제되지 않은 상속에서 문제가 발생한다.
단 Spring AOP는 open이 필요. 😳 -> kotlin-spring 플러그인
명확한 코드
val properties: Properties = // ...
val timeout = properties.getInt("timeout")
fun Properties.getInt(key: String): Int =
this.getProperty(key).toInt()
// Java (decompiled - pseudo code)
class PropertiesUtilsKt {
static int getInt(Properties receiver, String key) {
return Integer.parseInt(receiver.getProperty(key));
}
}
// Java
int timeout = PropertiesUtilsKt.getInt(properties, "timeout");
확장함수
명확한 코드
if (StringUtils.isEmpty(str)) return
명확한 코드
if (StringUtils.isEmpty(str)) return
if (str.isNullOrEmpty()) return
명확한 코드
if (StringUtils.isEmpty(str)) return
if (str.isNullOrEmpty()) return
😃 Utility, Helper 클래스 대체 (의존성 제거 가능)
😃 클래스의 핵심 기능과 확장 기능 구현 분리
😃 상속 없이 기존의 클래스의 기능을 추가
😞 기존 클래스에 새 인터페이스 적용은 안 됨
확장함수
간결함
스마트 캐스트 (Smart Cast)
override fun channelRead(ctx: ChannelHandlerContext, msg: Any) {
if (msg is HttpRequest) {
if (msg.method() == HttpMethod.GET) {
// ...
}
}
}
HttpRequest req = (HttpRequest) msg;
if (req.method().equals(HttpMethod.GET)) {
// ...
}
간결함
스마트 캐스트 (Smart Cast)
override fun channelRead(ctx: ChannelHandlerContext, msg: Any) {
if (msg is HttpRequest) {
if (msg.method() == HttpMethod.GET) {
// ...
}
}
}
간결함
스마트 캐스트 (Smart Cast)
override fun channelRead(ctx: ChannelHandlerContext, msg: Any) {
if (msg is HttpRequest) {
if (msg.method() == HttpMethod.GET) {
// ...
}
}
}
fun foo(str: String?) {
if (str == null) throw IllegalArgumentException()
val length = str.length
}
코틀린 방식의 Guard 처리
Not-null 타입 (String)
간결함
val members = if (response.status == 0) {
logger.info("members: {}", response.members)
response.members
} else {
emptyList()
}
조건문도 값을 가지는 표현문 (Expression)
val apiHostName = when(env) {
Environment.PRODUCTION -> "api.dommain.name"
Environment.ALPHA -> "alpha-api.dommain.name"
Environment.BETA -> "beta-api.dommain.name"
else -> throw IllegalArgumentException()
}
‘Nothing’ 타입
선언형 문장으로 임시 변수 사용을 줄일 수 있다.
println("[" + index + "] " + request.length)
println("[$index] ${request.length}”)
if (version.compareTo(minVersion) < 0) { }
if (version < minVersion) { }
val member= objectMapper.readValue(json, Member::class.java)
val member = objectMapper.readValue<Member>(json)
val member: Member = objectMapper.readValue(json)
간결함
인라인 제네릭 함수 + reified 타입 파라미터
연산자 오버로드
스트링 템플릿
if (version.equals(minVersion)) { }
if (version == minVersion) { }
==는 equals()
유용한 기능
람다 파라미터
list.forEach {
println(it)
}
val value = map.getOrPut(key) {
calculateValue()
}
list.forEach({ str ->
println(str)
})
val map: ConcurrentHashMap<String, Int>
val value = map.getOrPut(key, {
calculateValue()
})
DSL로 이용하기 좋은 문법
유용한 기능
함수형 유틸리티
val addresses: List<Server> = params
.filter { it.isNotBlank() }
.map {
it.split(Regex(":"), 2)
.let { Server(it[0], it[1].toIntOrNull() ?: 80) }
}
class ServerNode(val address: HostAndPort){
private val logger = LoggerFactory.getLogger(javaClass)
.apply { info("Initializing with {}", address) }
}
apply, let, run, also,
Collection, Iterable의 확장 함수로 제공
Any의 확장 함수로 제공되어 모든 expr에 대해 사용 가능
강력한 기능
suspend fun lastMessages(chatRoomId: ChatRoomId, maxCachedCount: Int): List<Message> {
val cached = async { messageService.recent(chatRoomId, maxCachedCount) }
val fetched = async { requestChatLogs(chatRoomId) }
return (cached.await() + fetched.await())
.distinctBy { it.messageId }
.sortedBy { it.messageId }
}
😃 비동기 구현에서 Future, RxJava 대비 장점
🤔 1.3부터 정식 패키지에 포함되지만 1.3이 아직 베타
😱 StackTrace가 제대로 안 나오는 경우가 있다.
코루틴
비동기 로직을
가독성이 높은 절차적인 코드로 작성
기본적으로 컨텍스트 스위칭 없이 동작하여 성능이 좋음
자바와 코틀린 비교
* 코드의 특성에 따라 달라질 수 있음
* RxJava2 기반으로 작성된 모듈
* Compile Time은 kapt 제외한 순수한 컴파일 시간
인라인 함수
익명 클래스
null 체크
메타 데이터
66% x2.2 x6.5
자바 컴파일이 빠른거 '
코드 라인 수 바이트코드 사이즈 컴파일 시간
자바8 코틀린같은 동작을 하는
...증분 컴파일은 체감상 빠른데..
개발 환경은 쓸 만 한가요?
언어로 생산성과 안전함이 향상된다?
잘 돌아가나요?
자바와 어느 정도 호환되나요?
문법
그래서
생태계
개발 환경
Broadcast Service
gRPC-java
RxJava2 Guice
Presence Service
gRPC-java
RxJava2
gRPC-java
ZooKeeper RedisPrometheuspapi
HTTP/2 HTTP/2
gRPC-java
550K / sec 120K / sec
* 일부에 대해서만 검증 용으로 서비스
Broadcast Service
gRPC-java
Presence Service
gRPC-java
Routing Service
gRPC-
java
Vert.x
Vert.x
ZooKeeperPrometheus
Clients
Apps
HTTP/2, HTTP/1.1
Services
RxJava2 Guice
Routing Service
gRPC-
java
Vert.x
Vert.x
300K / sec
700K / sec
* 일부에 대해서만 검증 용으로 서비스
WebApp Routing
Service
Undertow2
Spring Framework
Spring Framework
Kafka Redis
Prometheuspapi
Consul
Clients
Apps
Spring Framework
70K / sec
WebApp Routing
Service
Undertow2
Spring Framework
한계 상황에서의 안정성
성공 & 에러
CPU
응답 시간 분포
Load
정상 서비스 한계 상황 정상 회복
Java
코틀린과 자바의 성능
CPU
응답 시간
KotlinJava + Kotlin
Java + Kotlin
RSS Mem Java + Kotlin
OpenJDK
JDK7 부터 기본 기능으로는 OracleJDK와 차이가 없음
기술 지원이 없으며 업데이트를 지속적으로 할 필요
OracleJDK과의 차이점
Brewery 프로젝트에 OpenJDK10 적용
코틀린&자바 빌드: 문제 없음 (코틀린 코드는 kotlinc에서)
성능 및 안정성: JDK10에 준하는 결과
카카오톡 서비스 적용
마이그레이션
⚠ 자바 코드/클래스 연동시 타입 주의 (Nullable 등)
⚠ Lombok 적용된 자바 코드와는 같은 모듈에 사용하기 힘듬
⚠ Spring에서는 특정 클래스/함수를 open해줘야 함
⚠ Immutable 데이터로 리팩토링하는 것은 생각보다 큰 일
✔ 새로운 프로젝트: 처음부터 코틀린
✔수정이 앞으로도 많을 프로젝트: 모델, 유틸리티부터 리팩토링
✔ 그 외 잘 돌아가고 있는 자바 프로젝트: 잘 돌아가게 두자
✔kotlin-spring 플러그인을 쓰자
✔delombok을..
도입을 고민할 때 할 만한 걱정들
개발 환경은 쓸 만 한가요?
언어로 생산성과 안전함이 향상된다?
잘 돌아가나요?
자바와 어느 정도 호환되나요?
문법
그래서
생태계
개발 환경
요약
이미 안정화된 언어와 개발 환경
생산성과 가독성 높은 문법
하위 호환할 레거시 문법이 없음
잘 돌아갑니다. 😃
자바와 완전한 호환으로 생태계 공유
프레임웍의 러닝 커브가 없음
문법
그래서
생태계
개발 환경
________ ________ ________ ________ ________ __
/ / // // / // // / _==--------_ --
/ / / / / / / / / / / / / / / /  |
/ <:/ / / <:/ / / / / / / /__ ___ 
/ / // / / / / // / / / / / / | . . :|
/___/___/ /___/___/ /___/___/ /___/___/ /_______/ / / | __.__ :|
::::::/::::::/::::::/::::::/:::::::/ / | /::::: .:|
______/______/______/______/_______/ | _ ^ _/ .:/
________ ________ ____ ________  .:/
/ // // / / / / _ ..:/
/__ __/ / / / / / / / / / / /"------""
:/ /:/ / / /___/ / <:/ / / . . . 
/ / // / / / // / /_/ | / ::::: | |
/__/ / /___/___/ /_______/ /___/___/ / | ::::::: |/
::/ /:::::: :::::::/::::::/ / | ::::: |
__/ ______/_______/______/ | | |
## 참석해 주셔서 감사합니다!
QNA$

Contenu connexe

Tendances

How to steal and modify data using Business Logic flaws - Insecure Direct Obj...
How to steal and modify data using Business Logic flaws - Insecure Direct Obj...How to steal and modify data using Business Logic flaws - Insecure Direct Obj...
How to steal and modify data using Business Logic flaws - Insecure Direct Obj...Frans Rosén
 
Integrating Apache Kafka and Elastic Using the Connect Framework
Integrating Apache Kafka and Elastic Using the Connect FrameworkIntegrating Apache Kafka and Elastic Using the Connect Framework
Integrating Apache Kafka and Elastic Using the Connect Frameworkconfluent
 
The Secret Life of a Bug Bounty Hunter – Frans Rosén @ Security Fest 2016
The Secret Life of a Bug Bounty Hunter – Frans Rosén @ Security Fest 2016The Secret Life of a Bug Bounty Hunter – Frans Rosén @ Security Fest 2016
The Secret Life of a Bug Bounty Hunter – Frans Rosén @ Security Fest 2016Frans Rosén
 
[OPD 2019] Attacking JWT tokens
[OPD 2019] Attacking JWT tokens[OPD 2019] Attacking JWT tokens
[OPD 2019] Attacking JWT tokensOWASP
 
HTTP by Hand: Exploring HTTP/1.0, 1.1 and 2.0
HTTP by Hand: Exploring HTTP/1.0, 1.1 and 2.0HTTP by Hand: Exploring HTTP/1.0, 1.1 and 2.0
HTTP by Hand: Exploring HTTP/1.0, 1.1 and 2.0Cory Forsyth
 
Intelligent Auto-scaling of Kafka Consumers with Workload Prediction | Ming S...
Intelligent Auto-scaling of Kafka Consumers with Workload Prediction | Ming S...Intelligent Auto-scaling of Kafka Consumers with Workload Prediction | Ming S...
Intelligent Auto-scaling of Kafka Consumers with Workload Prediction | Ming S...HostedbyConfluent
 
Splunk as a_big_data_platform_for_developers_spring_one2gx
Splunk as a_big_data_platform_for_developers_spring_one2gxSplunk as a_big_data_platform_for_developers_spring_one2gx
Splunk as a_big_data_platform_for_developers_spring_one2gxDamien Dallimore
 
WAF Bypass Techniques - Using HTTP Standard and Web Servers’ Behaviour
WAF Bypass Techniques - Using HTTP Standard and Web Servers’ BehaviourWAF Bypass Techniques - Using HTTP Standard and Web Servers’ Behaviour
WAF Bypass Techniques - Using HTTP Standard and Web Servers’ BehaviourSoroush Dalili
 
[오픈소스컨설팅] EFK Stack 소개와 설치 방법
[오픈소스컨설팅] EFK Stack 소개와 설치 방법[오픈소스컨설팅] EFK Stack 소개와 설치 방법
[오픈소스컨설팅] EFK Stack 소개와 설치 방법Open Source Consulting
 
Tuning kafka pipelines
Tuning kafka pipelinesTuning kafka pipelines
Tuning kafka pipelinesSumant Tambe
 
Exploring Java Heap Dumps (Oracle Code One 2018)
Exploring Java Heap Dumps (Oracle Code One 2018)Exploring Java Heap Dumps (Oracle Code One 2018)
Exploring Java Heap Dumps (Oracle Code One 2018)Ryan Cuprak
 
Testes em uma arquitetura com messageria/streaming (Kafka)
Testes em uma arquitetura com messageria/streaming (Kafka)Testes em uma arquitetura com messageria/streaming (Kafka)
Testes em uma arquitetura com messageria/streaming (Kafka)Robson Agapito Correa
 
Elastic Stack Introduction
Elastic Stack IntroductionElastic Stack Introduction
Elastic Stack IntroductionVikram Shinde
 
Time based CAPTCHA protected SQL injection through SOAP-webservice
Time based CAPTCHA protected SQL injection through SOAP-webserviceTime based CAPTCHA protected SQL injection through SOAP-webservice
Time based CAPTCHA protected SQL injection through SOAP-webserviceFrans Rosén
 
Elasticsearch in Netflix
Elasticsearch in NetflixElasticsearch in Netflix
Elasticsearch in NetflixDanny Yuan
 
DevFest 2022 - Skaffold 2 Deep Dive Taipei.pdf
DevFest 2022 - Skaffold 2 Deep Dive Taipei.pdfDevFest 2022 - Skaffold 2 Deep Dive Taipei.pdf
DevFest 2022 - Skaffold 2 Deep Dive Taipei.pdfKAI CHU CHUNG
 
From Generator to Fiber the Road to Coroutine in PHP
From Generator to Fiber the Road to Coroutine in PHPFrom Generator to Fiber the Road to Coroutine in PHP
From Generator to Fiber the Road to Coroutine in PHPAlbert Chen
 
엘라스틱서치, 로그스태시, 키바나
엘라스틱서치, 로그스태시, 키바나엘라스틱서치, 로그스태시, 키바나
엘라스틱서치, 로그스태시, 키바나종민 김
 
JWT: jku x5u
JWT: jku x5uJWT: jku x5u
JWT: jku x5usnyff
 

Tendances (20)

How to steal and modify data using Business Logic flaws - Insecure Direct Obj...
How to steal and modify data using Business Logic flaws - Insecure Direct Obj...How to steal and modify data using Business Logic flaws - Insecure Direct Obj...
How to steal and modify data using Business Logic flaws - Insecure Direct Obj...
 
Integrating Apache Kafka and Elastic Using the Connect Framework
Integrating Apache Kafka and Elastic Using the Connect FrameworkIntegrating Apache Kafka and Elastic Using the Connect Framework
Integrating Apache Kafka and Elastic Using the Connect Framework
 
The Secret Life of a Bug Bounty Hunter – Frans Rosén @ Security Fest 2016
The Secret Life of a Bug Bounty Hunter – Frans Rosén @ Security Fest 2016The Secret Life of a Bug Bounty Hunter – Frans Rosén @ Security Fest 2016
The Secret Life of a Bug Bounty Hunter – Frans Rosén @ Security Fest 2016
 
[OPD 2019] Attacking JWT tokens
[OPD 2019] Attacking JWT tokens[OPD 2019] Attacking JWT tokens
[OPD 2019] Attacking JWT tokens
 
HTTP by Hand: Exploring HTTP/1.0, 1.1 and 2.0
HTTP by Hand: Exploring HTTP/1.0, 1.1 and 2.0HTTP by Hand: Exploring HTTP/1.0, 1.1 and 2.0
HTTP by Hand: Exploring HTTP/1.0, 1.1 and 2.0
 
Intelligent Auto-scaling of Kafka Consumers with Workload Prediction | Ming S...
Intelligent Auto-scaling of Kafka Consumers with Workload Prediction | Ming S...Intelligent Auto-scaling of Kafka Consumers with Workload Prediction | Ming S...
Intelligent Auto-scaling of Kafka Consumers with Workload Prediction | Ming S...
 
Splunk as a_big_data_platform_for_developers_spring_one2gx
Splunk as a_big_data_platform_for_developers_spring_one2gxSplunk as a_big_data_platform_for_developers_spring_one2gx
Splunk as a_big_data_platform_for_developers_spring_one2gx
 
WAF Bypass Techniques - Using HTTP Standard and Web Servers’ Behaviour
WAF Bypass Techniques - Using HTTP Standard and Web Servers’ BehaviourWAF Bypass Techniques - Using HTTP Standard and Web Servers’ Behaviour
WAF Bypass Techniques - Using HTTP Standard and Web Servers’ Behaviour
 
[오픈소스컨설팅] EFK Stack 소개와 설치 방법
[오픈소스컨설팅] EFK Stack 소개와 설치 방법[오픈소스컨설팅] EFK Stack 소개와 설치 방법
[오픈소스컨설팅] EFK Stack 소개와 설치 방법
 
Tuning kafka pipelines
Tuning kafka pipelinesTuning kafka pipelines
Tuning kafka pipelines
 
Exploring Java Heap Dumps (Oracle Code One 2018)
Exploring Java Heap Dumps (Oracle Code One 2018)Exploring Java Heap Dumps (Oracle Code One 2018)
Exploring Java Heap Dumps (Oracle Code One 2018)
 
Testes em uma arquitetura com messageria/streaming (Kafka)
Testes em uma arquitetura com messageria/streaming (Kafka)Testes em uma arquitetura com messageria/streaming (Kafka)
Testes em uma arquitetura com messageria/streaming (Kafka)
 
Elastic Stack Introduction
Elastic Stack IntroductionElastic Stack Introduction
Elastic Stack Introduction
 
Time based CAPTCHA protected SQL injection through SOAP-webservice
Time based CAPTCHA protected SQL injection through SOAP-webserviceTime based CAPTCHA protected SQL injection through SOAP-webservice
Time based CAPTCHA protected SQL injection through SOAP-webservice
 
Elasticsearch in Netflix
Elasticsearch in NetflixElasticsearch in Netflix
Elasticsearch in Netflix
 
Frans Rosén Keynote at BSides Ahmedabad
Frans Rosén Keynote at BSides AhmedabadFrans Rosén Keynote at BSides Ahmedabad
Frans Rosén Keynote at BSides Ahmedabad
 
DevFest 2022 - Skaffold 2 Deep Dive Taipei.pdf
DevFest 2022 - Skaffold 2 Deep Dive Taipei.pdfDevFest 2022 - Skaffold 2 Deep Dive Taipei.pdf
DevFest 2022 - Skaffold 2 Deep Dive Taipei.pdf
 
From Generator to Fiber the Road to Coroutine in PHP
From Generator to Fiber the Road to Coroutine in PHPFrom Generator to Fiber the Road to Coroutine in PHP
From Generator to Fiber the Road to Coroutine in PHP
 
엘라스틱서치, 로그스태시, 키바나
엘라스틱서치, 로그스태시, 키바나엘라스틱서치, 로그스태시, 키바나
엘라스틱서치, 로그스태시, 키바나
 
JWT: jku x5u
JWT: jku x5uJWT: jku x5u
JWT: jku x5u
 

Similaire à 카카오톡의 서버사이드 코틀린

코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우Arawn Park
 
Javascript 교육자료 pdf
Javascript 교육자료 pdfJavascript 교육자료 pdf
Javascript 교육자료 pdfHyosang Hong
 
I phone 2 release
I phone 2 releaseI phone 2 release
I phone 2 releaseJaehyeuk Oh
 
Jdk(java) 7 - 5. invoke-dynamic
Jdk(java) 7 - 5. invoke-dynamicJdk(java) 7 - 5. invoke-dynamic
Jdk(java) 7 - 5. invoke-dynamicknight1128
 
Why what how kotlin
Why what how kotlinWhy what how kotlin
Why what how kotlinSewonKo
 
[KGC2014] 두 마리 토끼를 잡기 위한 C++ - C# 혼합 멀티플랫폼 게임 아키텍처 설계
[KGC2014] 두 마리 토끼를 잡기 위한 C++ - C#  혼합 멀티플랫폼 게임 아키텍처 설계[KGC2014] 두 마리 토끼를 잡기 위한 C++ - C#  혼합 멀티플랫폼 게임 아키텍처 설계
[KGC2014] 두 마리 토끼를 잡기 위한 C++ - C# 혼합 멀티플랫폼 게임 아키텍처 설계Sungkyun Kim
 
Java Virtual Machine, Call stack, Java Byte Code
Java Virtual Machine, Call stack, Java Byte CodeJava Virtual Machine, Call stack, Java Byte Code
Java Virtual Machine, Call stack, Java Byte CodeJavajigi Jaesung
 
Angular2 가기전 Type script소개
 Angular2 가기전 Type script소개 Angular2 가기전 Type script소개
Angular2 가기전 Type script소개Dong Jun Kwon
 
Domain Specific Languages With Groovy
Domain Specific Languages With GroovyDomain Specific Languages With Groovy
Domain Specific Languages With GroovyTommy C. Kang
 
Start IoT with JavaScript - 1.기초
Start IoT with JavaScript - 1.기초Start IoT with JavaScript - 1.기초
Start IoT with JavaScript - 1.기초Park Jonggun
 
Scala, Scalability
Scala, ScalabilityScala, Scalability
Scala, ScalabilityDongwook Lee
 
Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기jongho jeong
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기현철 조
 
NODE.JS 글로벌 기업 적용 사례 그리고, real-time 어플리케이션 개발하기
NODE.JS 글로벌 기업 적용 사례  그리고, real-time 어플리케이션 개발하기NODE.JS 글로벌 기업 적용 사례  그리고, real-time 어플리케이션 개발하기
NODE.JS 글로벌 기업 적용 사례 그리고, real-time 어플리케이션 개발하기John Kim
 
자바8 나머지 공개
자바8 나머지 공개자바8 나머지 공개
자바8 나머지 공개Sungchul Park
 
[A1]루비는 패셔니스타
[A1]루비는 패셔니스타[A1]루비는 패셔니스타
[A1]루비는 패셔니스타NAVER D2
 

Similaire à 카카오톡의 서버사이드 코틀린 (20)

코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우
 
Javascript 교육자료 pdf
Javascript 교육자료 pdfJavascript 교육자료 pdf
Javascript 교육자료 pdf
 
I phone 2 release
I phone 2 releaseI phone 2 release
I phone 2 release
 
Jdk(java) 7 - 5. invoke-dynamic
Jdk(java) 7 - 5. invoke-dynamicJdk(java) 7 - 5. invoke-dynamic
Jdk(java) 7 - 5. invoke-dynamic
 
Why what how kotlin
Why what how kotlinWhy what how kotlin
Why what how kotlin
 
[KGC2014] 두 마리 토끼를 잡기 위한 C++ - C# 혼합 멀티플랫폼 게임 아키텍처 설계
[KGC2014] 두 마리 토끼를 잡기 위한 C++ - C#  혼합 멀티플랫폼 게임 아키텍처 설계[KGC2014] 두 마리 토끼를 잡기 위한 C++ - C#  혼합 멀티플랫폼 게임 아키텍처 설계
[KGC2014] 두 마리 토끼를 잡기 위한 C++ - C# 혼합 멀티플랫폼 게임 아키텍처 설계
 
Java Virtual Machine, Call stack, Java Byte Code
Java Virtual Machine, Call stack, Java Byte CodeJava Virtual Machine, Call stack, Java Byte Code
Java Virtual Machine, Call stack, Java Byte Code
 
2. 엔티티 매핑(entity mapping) 2 3 롬복(lombok)소개-1
2. 엔티티 매핑(entity mapping) 2 3 롬복(lombok)소개-12. 엔티티 매핑(entity mapping) 2 3 롬복(lombok)소개-1
2. 엔티티 매핑(entity mapping) 2 3 롬복(lombok)소개-1
 
Angular2 가기전 Type script소개
 Angular2 가기전 Type script소개 Angular2 가기전 Type script소개
Angular2 가기전 Type script소개
 
Domain Specific Languages With Groovy
Domain Specific Languages With GroovyDomain Specific Languages With Groovy
Domain Specific Languages With Groovy
 
Java tutorial
Java tutorialJava tutorial
Java tutorial
 
Start IoT with JavaScript - 1.기초
Start IoT with JavaScript - 1.기초Start IoT with JavaScript - 1.기초
Start IoT with JavaScript - 1.기초
 
Scala, Scalability
Scala, ScalabilityScala, Scalability
Scala, Scalability
 
Scalability
ScalabilityScalability
Scalability
 
Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
 
Node.js intro
Node.js introNode.js intro
Node.js intro
 
NODE.JS 글로벌 기업 적용 사례 그리고, real-time 어플리케이션 개발하기
NODE.JS 글로벌 기업 적용 사례  그리고, real-time 어플리케이션 개발하기NODE.JS 글로벌 기업 적용 사례  그리고, real-time 어플리케이션 개발하기
NODE.JS 글로벌 기업 적용 사례 그리고, real-time 어플리케이션 개발하기
 
자바8 나머지 공개
자바8 나머지 공개자바8 나머지 공개
자바8 나머지 공개
 
[A1]루비는 패셔니스타
[A1]루비는 패셔니스타[A1]루비는 패셔니스타
[A1]루비는 패셔니스타
 

Plus de if kakao

바닥부터 시작하는 Vue 테스트와 리팩토링
바닥부터 시작하는 Vue 테스트와 리팩토링바닥부터 시작하는 Vue 테스트와 리팩토링
바닥부터 시작하는 Vue 테스트와 리팩토링if kakao
 
카카오커머스를 지탱하는 Angular
카카오커머스를 지탱하는 Angular카카오커머스를 지탱하는 Angular
카카오커머스를 지탱하는 Angularif kakao
 
프렌즈타임 웹앱 삽질기
프렌즈타임 웹앱 삽질기프렌즈타임 웹앱 삽질기
프렌즈타임 웹앱 삽질기if kakao
 
카프카 기반의 대규모 모니터링 플랫폼 개발이야기
카프카 기반의 대규모 모니터링 플랫폼 개발이야기카프카 기반의 대규모 모니터링 플랫폼 개발이야기
카프카 기반의 대규모 모니터링 플랫폼 개발이야기if kakao
 
TOROS N2 - lightweight approximate Nearest Neighbor library
TOROS N2 - lightweight approximate Nearest Neighbor libraryTOROS N2 - lightweight approximate Nearest Neighbor library
TOROS N2 - lightweight approximate Nearest Neighbor libraryif kakao
 
딥러닝을 이용한 얼굴 인식
딥러닝을 이용한 얼굴 인식딥러닝을 이용한 얼굴 인식
딥러닝을 이용한 얼굴 인식if kakao
 
딥러닝을 활용한 뉴스 메타 태깅
딥러닝을 활용한 뉴스 메타 태깅딥러닝을 활용한 뉴스 메타 태깅
딥러닝을 활용한 뉴스 메타 태깅if kakao
 
눈으로 듣는 음악 추천 시스템
눈으로 듣는 음악 추천 시스템눈으로 듣는 음악 추천 시스템
눈으로 듣는 음악 추천 시스템if kakao
 
Keynote / 2018
Keynote / 2018Keynote / 2018
Keynote / 2018if kakao
 
카카오 봇 플랫폼 소개
카카오 봇 플랫폼 소개카카오 봇 플랫폼 소개
카카오 봇 플랫폼 소개if kakao
 
다음웹툰의 UX(Animation, Transition, Custom View)
다음웹툰의 UX(Animation, Transition, Custom View)다음웹툰의 UX(Animation, Transition, Custom View)
다음웹툰의 UX(Animation, Transition, Custom View)if kakao
 
모바일 게임플랫폼과 인프라 구축 경험기
모바일 게임플랫폼과 인프라 구축 경험기모바일 게임플랫폼과 인프라 구축 경험기
모바일 게임플랫폼과 인프라 구축 경험기if kakao
 
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개if kakao
 
카카오뱅크 모바일앱 개발 이야기
카카오뱅크 모바일앱 개발 이야기카카오뱅크 모바일앱 개발 이야기
카카오뱅크 모바일앱 개발 이야기if kakao
 
다음 모바일 첫 화면 개선기
다음 모바일 첫 화면 개선기다음 모바일 첫 화면 개선기
다음 모바일 첫 화면 개선기if kakao
 
글로벌 게임 플랫폼에서 무정지, 무점검 서버 개발과 운영 사례
글로벌 게임 플랫폼에서 무정지, 무점검 서버 개발과 운영 사례글로벌 게임 플랫폼에서 무정지, 무점검 서버 개발과 운영 사례
글로벌 게임 플랫폼에서 무정지, 무점검 서버 개발과 운영 사례if kakao
 
액티브X 없는 블록체인 기반 PKI 시스템
액티브X 없는 블록체인 기반 PKI 시스템액티브X 없는 블록체인 기반 PKI 시스템
액티브X 없는 블록체인 기반 PKI 시스템if kakao
 
Klaytn: Service-Oriented Enterprise-Grade Public Blockchain Platform
Klaytn: Service-Oriented Enterprise-Grade Public Blockchain PlatformKlaytn: Service-Oriented Enterprise-Grade Public Blockchain Platform
Klaytn: Service-Oriented Enterprise-Grade Public Blockchain Platformif kakao
 
Kakao Cloud Native Platform, 9rum
Kakao Cloud Native Platform, 9rumKakao Cloud Native Platform, 9rum
Kakao Cloud Native Platform, 9rumif kakao
 
카프카, 산전수전 노하우
카프카, 산전수전 노하우카프카, 산전수전 노하우
카프카, 산전수전 노하우if kakao
 

Plus de if kakao (20)

바닥부터 시작하는 Vue 테스트와 리팩토링
바닥부터 시작하는 Vue 테스트와 리팩토링바닥부터 시작하는 Vue 테스트와 리팩토링
바닥부터 시작하는 Vue 테스트와 리팩토링
 
카카오커머스를 지탱하는 Angular
카카오커머스를 지탱하는 Angular카카오커머스를 지탱하는 Angular
카카오커머스를 지탱하는 Angular
 
프렌즈타임 웹앱 삽질기
프렌즈타임 웹앱 삽질기프렌즈타임 웹앱 삽질기
프렌즈타임 웹앱 삽질기
 
카프카 기반의 대규모 모니터링 플랫폼 개발이야기
카프카 기반의 대규모 모니터링 플랫폼 개발이야기카프카 기반의 대규모 모니터링 플랫폼 개발이야기
카프카 기반의 대규모 모니터링 플랫폼 개발이야기
 
TOROS N2 - lightweight approximate Nearest Neighbor library
TOROS N2 - lightweight approximate Nearest Neighbor libraryTOROS N2 - lightweight approximate Nearest Neighbor library
TOROS N2 - lightweight approximate Nearest Neighbor library
 
딥러닝을 이용한 얼굴 인식
딥러닝을 이용한 얼굴 인식딥러닝을 이용한 얼굴 인식
딥러닝을 이용한 얼굴 인식
 
딥러닝을 활용한 뉴스 메타 태깅
딥러닝을 활용한 뉴스 메타 태깅딥러닝을 활용한 뉴스 메타 태깅
딥러닝을 활용한 뉴스 메타 태깅
 
눈으로 듣는 음악 추천 시스템
눈으로 듣는 음악 추천 시스템눈으로 듣는 음악 추천 시스템
눈으로 듣는 음악 추천 시스템
 
Keynote / 2018
Keynote / 2018Keynote / 2018
Keynote / 2018
 
카카오 봇 플랫폼 소개
카카오 봇 플랫폼 소개카카오 봇 플랫폼 소개
카카오 봇 플랫폼 소개
 
다음웹툰의 UX(Animation, Transition, Custom View)
다음웹툰의 UX(Animation, Transition, Custom View)다음웹툰의 UX(Animation, Transition, Custom View)
다음웹툰의 UX(Animation, Transition, Custom View)
 
모바일 게임플랫폼과 인프라 구축 경험기
모바일 게임플랫폼과 인프라 구축 경험기모바일 게임플랫폼과 인프라 구축 경험기
모바일 게임플랫폼과 인프라 구축 경험기
 
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
 
카카오뱅크 모바일앱 개발 이야기
카카오뱅크 모바일앱 개발 이야기카카오뱅크 모바일앱 개발 이야기
카카오뱅크 모바일앱 개발 이야기
 
다음 모바일 첫 화면 개선기
다음 모바일 첫 화면 개선기다음 모바일 첫 화면 개선기
다음 모바일 첫 화면 개선기
 
글로벌 게임 플랫폼에서 무정지, 무점검 서버 개발과 운영 사례
글로벌 게임 플랫폼에서 무정지, 무점검 서버 개발과 운영 사례글로벌 게임 플랫폼에서 무정지, 무점검 서버 개발과 운영 사례
글로벌 게임 플랫폼에서 무정지, 무점검 서버 개발과 운영 사례
 
액티브X 없는 블록체인 기반 PKI 시스템
액티브X 없는 블록체인 기반 PKI 시스템액티브X 없는 블록체인 기반 PKI 시스템
액티브X 없는 블록체인 기반 PKI 시스템
 
Klaytn: Service-Oriented Enterprise-Grade Public Blockchain Platform
Klaytn: Service-Oriented Enterprise-Grade Public Blockchain PlatformKlaytn: Service-Oriented Enterprise-Grade Public Blockchain Platform
Klaytn: Service-Oriented Enterprise-Grade Public Blockchain Platform
 
Kakao Cloud Native Platform, 9rum
Kakao Cloud Native Platform, 9rumKakao Cloud Native Platform, 9rum
Kakao Cloud Native Platform, 9rum
 
카프카, 산전수전 노하우
카프카, 산전수전 노하우카프카, 산전수전 노하우
카프카, 산전수전 노하우
 

카카오톡의 서버사이드 코틀린

  • 2. ________ ________ ________ ________ ________ __ / / // // / // // / _==--------_ -- / / / / / / / / / / / / / / / / | / <:/ / / <:/ / / / / / / /__ ___ / / // / / / / // / / / / / / | . . :| /___/___/ /___/___/ /___/___/ /___/___/ /_______/ / / | __.__ :| ::::::/::::::/::::::/::::::/:::::::/ / | /::::: .:| ______/______/______/______/_______/ | _ ^ _/ .:/ ________ ________ ____ ________ .:/ / // // / / / / _ ..:/ /__ __/ / / / / / / / / / / /"------"" :/ /:/ / / /___/ / <:/ / / . . . / / // / / / // / /_/ | / ::::: | | /__/ / /___/___/ /_______/ /___/___/ / | ::::::: |/ ::/ /:::::: :::::::/::::::/ / | ::::: | __/ ______/_______/______/ | | | ## 카카오톡에 오신것을 환영합니다! kakaotalk$
  • 3.
  • 4.
  • 6. LOCO 단말의 API 요청 수 메시지 전송 채팅방 미디어 전송 WEBAPP 가입 인증 친구 프로필 설정 톡검색 50B+ / day 800K+ / sec 평소 피크 6.5M+ / sec 역대 최대
  • 7. LOCO 단말의 API 요청 수 메시지 전송 채팅방 미디어 전송 WEBAPP 가입 인증 친구 프로필 설정 톡검색 평소 피크 역대 최대 하루에 500억+ 1초에 80만+ 1초에 650만+
  • 10. 생활 속의 서비스 무중단 무점검 무장애 😰 7년 ‘겁나 빠른 황소’ 프로젝트 (LOCO) 2011
  • 11. 2017~ 카카오톡 서버 구조 개선 프로젝트 개발 언어로 코틀린 (for JVM) 도입 기존 컴포넌트 개선을 위한 대체, 서비스 투입 신규 플랫폼용 컴포넌트 개발, 검증용도 서비스 투입2017 2018 Brewery
  • 12. 코틀린 (for JVM) 선택의 배경 ✔ 적정한 성능/안정성, 개발/운영의 편의성 ✔ 다양한 목적의 서버 환경에 검증된 자바의 생태계를 이용 ✔ 생산성이 좋은 새로운 언어 ✔ 적정 수준의 러닝 커브
  • 13. 도입을 고민할 때 할 만한 걱정들 개발 환경은 쓸 만 한가요? 언어로 생산성과 안전함이 향상된다? 잘 돌아가나요? 자바와 어느 정도 호환되나요? 문법 그래서 생태계 개발 환경
  • 14. 개발 환경은 쓸 만 한가요? 언어로 생산성과 안전함이 향상된다? 잘 돌아가나요? 자바와 어느 정도 호환되나요? 문법 그래서 생태계 개발 환경
  • 15. 버전 업데이트 시 변화가 크지 않음 1.0 ~ 1.3(preview)의 문법, API 하위 호환 역사 https://github.com/JetBrains/Kotlin 1.0.0 오픈소스 1.1.0 1.2.0 안드로이드 공식 지원 M1~M14, 1.0 Beta 1~4 1.3-M1 릴리즈 하위 호환
  • 16. Build Tool Gradle buildscript { ext.kotlin_version = '1.2.60' repositories { mavenCentral() } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } apply plugin: 'kotlin' dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" } Maven (v3) <properties> <kotlin.version>1.2.60</kotlin.version> </properties> <dependencies> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-stdlib</artifactId> <version>${kotlin.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-plugin</artifactId> <version>${kotlin.version}</version> <executions> <execution> <id>compile</id> <phase>compile</phase> <goals> <goal>compile</goal> </goals> </execution> <execution> <id>test-compile</id> <phase>test-compile</phase> <goals> <goal>test-compile</goal> </goals> </execution> </executions> </plugin> <plugins> </build> kotlin-gradle-plugin kotlin-maven-plugin apply plugin: 'kotlin' kotlin-stdlib kotlin-stdlib
  • 17. Gradle Maven (v3) Build Tool buildscript { ext.kotlin_version = '1.2.60' repositories { mavenCentral() } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } apply plugin: 'kotlin' dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" } <properties> <kotlin.version>1.2.60</kotlin.version> </properties> <dependencies> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-stdlib</artifactId> <version>${kotlin.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-plugin</artifactId> <version>${kotlin.version}</version> <executions> <execution> <id>compile</id> <phase>compile</phase> <goals> <goal>compile</goal> </goals> </execution> <execution> <id>test-compile</id> <phase>test-compile</phase> <goals> <goal>test-compile</goal> </goals> </execution> </executions> </plugin> <plugins> </build> apply plugin: 'kotlin' kotlin-stdlib kotlin-stdlib kotlin-gradle-plugin kotlin-maven-plugin *.kt *.java *.class *.class kotlinc javac *자바 파일 혼재하는 경우 compileJava compileKotlin
  • 18. 개발 환경 IntelliJ IDEA, Eclipse, ✔ 증분 컴파일 (Incremental compilation) ✔ 자동 완성 ✔ 코드 리팩토링 ✔ 자바 to 코틀린 코드 변환 (파일, 클립보드) ✔ 디버거
  • 19. 개발 환경은 쓸 만 한가요? 언어로 생산성과 안전함이 향상된다? 잘 돌아가나요? 자바와 어느 정도 호환되나요? 문법 그래서 생태계 개발 환경
  • 21. 클래스, 인터페이스, 함수의 호환 class KotlinClass<T> : JavaInterface<T> { fun foo(arg: Int): String { … } } interface KotlinInterface<T> { } class JavaClass<T> implements KotlinInterface<T> { String foo(int arg) { … } } interface JavaInterface<T> { } Kotlin Java val java = JavaClass<Int>() java.foo(1) KotlinClass<Integer> kotlin = new KotlinClass<>(); kotlin.foo(1);
  • 22. Annotation import org.springframework.web.bind.annotation.* import org.springframework.web.servlet.config.annotation.EnableWebMvc import javax.inject.Inject @Import(BroadcastConfig::class) @EnableWebMvc @RestController class BroadcastController { @Inject private lateinit var httpClient: HttpClient @PostMapping("/broadcast") fun broadcast(@RequestBody request: BroadcastRequest) { } } Compile-time Annotation은 kapt 빌드 플러그인 사용 메소드/필드 호환으로 자바의 Runtime Annotation이 동일하게 동작
  • 23. 기본 데이터 타입 java.lang.Object int, java.lang.Integer double, java.lang.Double java.lang.String java.util.Collection<E> java.util.List<E> java.util.Set<E> java.util.Map<K, V> Object[] int[] kotlin.Any kotlin.Int kotlin.Double kotlin.String kotlin.collections.Collection<E> kotlin.collections.MutableCollection<E> kotlin.collections.List<E> kotlin.collections.MutableList<E> kotlin.collections.Set<E> kotlin.collections.MutableSet<E> kotlin.collections.Map<K, V> kotlin.collections.MutableMap<K, V> kotlin.Array<Any> kotlin.IntArray Bytecode Kotlin Java (등등의 primitive 타입) Object 원시 타입 문자열 컬렉션 배열
  • 24. 자바 솔루션과의 연동 Lettuce (Redis Client) JDBC SLF4J / Logback Apache Curator (ZooKeeper) Guava Mockito Spring Netty RxJavagRPC JUnit Apache Kafka Client Hystrix
  • 25. 개발 환경은 쓸 만 한가요? 언어로 생산성과 안전함이 향상된다? 잘 돌아가나요? 자바와 어느 정도 호환되나요? 문법 그래서 생태계 개발 환경
  • 26. 중복 최소화 // Java class Host { private final String name; private final int port; private int weight; Host(String name, int port, int weight) { this.name = name; this.port = port; this.weight = weight; } public String getName() { return name; } public int getPort() { return port; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } @Override public boolean equals(Object obj) { return false; } @Override public int hashCode() { return 0; } @Override public String toString() { return ""; } } // Java (with Lombok) import lombok.*; @AllArgsConstructor @ToString @EqualsAndHashCode class Host { @Getter @NonNull private final String name; @Getter private final int port; @Getter @Setter private int weight; } // Java (with Lombok) import lombok.*; @AllArgsConstructor @ToString @EqualsAndHashCode class Host { @Getter @NonNull private final String name; @Getter private final int port; @Getter @Setter private int weight; } Too many annotations Lombok
  • 27. 중복 최소화 // Java class Host { private final String name; private final int port; private int weight; Host(String name, int port, int weight) { this.name = name; this.port = port; this.weight = weight; } public String getName() { return name; } public int getPort() { return port; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } @Override public boolean equals(Object obj) { return false; } @Override public int hashCode() { return 0; } @Override public String toString() { return ""; } } // Java (with Lombok) import lombok.*; @AllArgsConstructor @ToString @EqualsAndHashCode class Host { @Getter @NonNull private final String name; @Getter private final int port; @Getter @Setter private int weight; } Lombok Kotlin // Kotlin data class Host( val name: String, val port: Int, var weight: Int )
  • 28. 중복 최소화 // Java class Host { private final String name; private final int port; private int weight; Host(String name, int port, int weight) { this.name = name; this.port = port; this.weight = weight; } public String getName() { return name; } public int getPort() { return port; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } @Override public boolean equals(Object obj) { return false; } @Override public int hashCode() { return 0; } @Override public String toString() { return ""; } } Kotlin // Kotlin data class Host( val name: String, val port: Int, var weight: Int ) val host = Host("kakao.com", 443, 1) println("${host.name}:${host.port}") host.weight = 2
  • 29. 안전한 코드 코딩의 실수로 인한 오류를 방지하는 방법 ✔ 유효한 패턴 적용, 안티 패턴을 지양 ✔ 테스트 작성 ✔ 공개된 API의 문서화 ✔ 문법에서 실수 가능성을 막아 컴파일 시점에 오류를 방지
  • 30. 안전한 코드 정적 타입: 더 엄격한 타입 체크 Nullable 타입을 문법에서 구분 Primitive 타입, Boxed 타입 구분 없음: Int, Long, Float, Double, Byte, Short, Char, Boolean 클래스 이용 특수 타입: Any, Nothing, Unit 개선된 타입 시스템
  • 31. 안전한 코드: Nullable 타입 Not-null Type Nullable Type var str: String str = null str = null if (str != null) { val len: Int = str.length } val len: Int? = str?.length val len: Int = str?.length ?: 0 var str: String? Smart Cast “컴파일 시점”에 NPE를 방지한다. Optional을 문법에서 강제한다. 그래도 자바와 호환 과정에서는 발생할 수 있다. val len: Int = str.length val len: Int = str.length
  • 32. 안전한 코드: 불변 컬렉션 list.set(0, 100) list[0] = 100 list.add(100) list.remove(0) map.put("key", 1) map["key"] = 1 map.remove("key") “컴파일 시점”에 자료의 변경을 막는다. 그래도 자바에 넘겼을 때는 변경될 수 있다. Immutable List Immutable Map val list: List<Int> val i = list.get(0) val i = list[0] val map: Map<String, Int> val i = map.get("key") val i = map["key"] 변경용 API 변경용 API
  • 33. 안전한 코드: 불변 컬렉션 list.set(0, 100) list[0] = 100 list.add(100) list.remove(0) map.put("key", 1) map["key"] = 1 map.remove("key") Mutable List Mutable Map val list: MutableList<Int> val i = list.get(0) val i = list[0] val map: MutableMap<String, Int> val i = map.get("key") val i = map["key"] 변경용 API 변경용 API * List<T>의 sub-interface * Map<K, V>의 sub-interface
  • 34. 안전한 코드: final 불변 변수 val를 권장 (final 변수) 상속 제한이 디폴트 (final 클래스, 함수) open class PushServiceImpl(private val pushService: PushService) : PushService { open override fun push(request: PushRequest) { // ... } } val max = 1 // final max = 100 의외로 변경이 필요한 변수는 많지 않다. 통제되지 않은 상속에서 문제가 발생한다. 단 Spring AOP는 open이 필요. 😳 -> kotlin-spring 플러그인
  • 35. 명확한 코드 val properties: Properties = // ... val timeout = properties.getInt("timeout") fun Properties.getInt(key: String): Int = this.getProperty(key).toInt() // Java (decompiled - pseudo code) class PropertiesUtilsKt { static int getInt(Properties receiver, String key) { return Integer.parseInt(receiver.getProperty(key)); } } // Java int timeout = PropertiesUtilsKt.getInt(properties, "timeout"); 확장함수
  • 37. 명확한 코드 if (StringUtils.isEmpty(str)) return if (str.isNullOrEmpty()) return
  • 38. 명확한 코드 if (StringUtils.isEmpty(str)) return if (str.isNullOrEmpty()) return 😃 Utility, Helper 클래스 대체 (의존성 제거 가능) 😃 클래스의 핵심 기능과 확장 기능 구현 분리 😃 상속 없이 기존의 클래스의 기능을 추가 😞 기존 클래스에 새 인터페이스 적용은 안 됨 확장함수
  • 39. 간결함 스마트 캐스트 (Smart Cast) override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { if (msg is HttpRequest) { if (msg.method() == HttpMethod.GET) { // ... } } } HttpRequest req = (HttpRequest) msg; if (req.method().equals(HttpMethod.GET)) { // ... }
  • 40. 간결함 스마트 캐스트 (Smart Cast) override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { if (msg is HttpRequest) { if (msg.method() == HttpMethod.GET) { // ... } } }
  • 41. 간결함 스마트 캐스트 (Smart Cast) override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { if (msg is HttpRequest) { if (msg.method() == HttpMethod.GET) { // ... } } } fun foo(str: String?) { if (str == null) throw IllegalArgumentException() val length = str.length } 코틀린 방식의 Guard 처리 Not-null 타입 (String)
  • 42. 간결함 val members = if (response.status == 0) { logger.info("members: {}", response.members) response.members } else { emptyList() } 조건문도 값을 가지는 표현문 (Expression) val apiHostName = when(env) { Environment.PRODUCTION -> "api.dommain.name" Environment.ALPHA -> "alpha-api.dommain.name" Environment.BETA -> "beta-api.dommain.name" else -> throw IllegalArgumentException() } ‘Nothing’ 타입 선언형 문장으로 임시 변수 사용을 줄일 수 있다.
  • 43. println("[" + index + "] " + request.length) println("[$index] ${request.length}”) if (version.compareTo(minVersion) < 0) { } if (version < minVersion) { } val member= objectMapper.readValue(json, Member::class.java) val member = objectMapper.readValue<Member>(json) val member: Member = objectMapper.readValue(json) 간결함 인라인 제네릭 함수 + reified 타입 파라미터 연산자 오버로드 스트링 템플릿 if (version.equals(minVersion)) { } if (version == minVersion) { } ==는 equals()
  • 44. 유용한 기능 람다 파라미터 list.forEach { println(it) } val value = map.getOrPut(key) { calculateValue() } list.forEach({ str -> println(str) }) val map: ConcurrentHashMap<String, Int> val value = map.getOrPut(key, { calculateValue() }) DSL로 이용하기 좋은 문법
  • 45. 유용한 기능 함수형 유틸리티 val addresses: List<Server> = params .filter { it.isNotBlank() } .map { it.split(Regex(":"), 2) .let { Server(it[0], it[1].toIntOrNull() ?: 80) } } class ServerNode(val address: HostAndPort){ private val logger = LoggerFactory.getLogger(javaClass) .apply { info("Initializing with {}", address) } } apply, let, run, also, Collection, Iterable의 확장 함수로 제공 Any의 확장 함수로 제공되어 모든 expr에 대해 사용 가능
  • 46. 강력한 기능 suspend fun lastMessages(chatRoomId: ChatRoomId, maxCachedCount: Int): List<Message> { val cached = async { messageService.recent(chatRoomId, maxCachedCount) } val fetched = async { requestChatLogs(chatRoomId) } return (cached.await() + fetched.await()) .distinctBy { it.messageId } .sortedBy { it.messageId } } 😃 비동기 구현에서 Future, RxJava 대비 장점 🤔 1.3부터 정식 패키지에 포함되지만 1.3이 아직 베타 😱 StackTrace가 제대로 안 나오는 경우가 있다. 코루틴 비동기 로직을 가독성이 높은 절차적인 코드로 작성 기본적으로 컨텍스트 스위칭 없이 동작하여 성능이 좋음
  • 47. 자바와 코틀린 비교 * 코드의 특성에 따라 달라질 수 있음 * RxJava2 기반으로 작성된 모듈 * Compile Time은 kapt 제외한 순수한 컴파일 시간 인라인 함수 익명 클래스 null 체크 메타 데이터 66% x2.2 x6.5 자바 컴파일이 빠른거 ' 코드 라인 수 바이트코드 사이즈 컴파일 시간 자바8 코틀린같은 동작을 하는 ...증분 컴파일은 체감상 빠른데..
  • 48. 개발 환경은 쓸 만 한가요? 언어로 생산성과 안전함이 향상된다? 잘 돌아가나요? 자바와 어느 정도 호환되나요? 문법 그래서 생태계 개발 환경
  • 49. Broadcast Service gRPC-java RxJava2 Guice Presence Service gRPC-java RxJava2 gRPC-java ZooKeeper RedisPrometheuspapi HTTP/2 HTTP/2
  • 50. gRPC-java 550K / sec 120K / sec * 일부에 대해서만 검증 용으로 서비스 Broadcast Service gRPC-java Presence Service gRPC-java
  • 52. Routing Service gRPC- java Vert.x Vert.x 300K / sec 700K / sec * 일부에 대해서만 검증 용으로 서비스
  • 53. WebApp Routing Service Undertow2 Spring Framework Spring Framework Kafka Redis Prometheuspapi Consul Clients Apps
  • 54. Spring Framework 70K / sec WebApp Routing Service Undertow2 Spring Framework
  • 55. 한계 상황에서의 안정성 성공 & 에러 CPU 응답 시간 분포 Load 정상 서비스 한계 상황 정상 회복
  • 56. Java 코틀린과 자바의 성능 CPU 응답 시간 KotlinJava + Kotlin Java + Kotlin RSS Mem Java + Kotlin
  • 57. OpenJDK JDK7 부터 기본 기능으로는 OracleJDK와 차이가 없음 기술 지원이 없으며 업데이트를 지속적으로 할 필요 OracleJDK과의 차이점 Brewery 프로젝트에 OpenJDK10 적용 코틀린&자바 빌드: 문제 없음 (코틀린 코드는 kotlinc에서) 성능 및 안정성: JDK10에 준하는 결과 카카오톡 서비스 적용
  • 58. 마이그레이션 ⚠ 자바 코드/클래스 연동시 타입 주의 (Nullable 등) ⚠ Lombok 적용된 자바 코드와는 같은 모듈에 사용하기 힘듬 ⚠ Spring에서는 특정 클래스/함수를 open해줘야 함 ⚠ Immutable 데이터로 리팩토링하는 것은 생각보다 큰 일 ✔ 새로운 프로젝트: 처음부터 코틀린 ✔수정이 앞으로도 많을 프로젝트: 모델, 유틸리티부터 리팩토링 ✔ 그 외 잘 돌아가고 있는 자바 프로젝트: 잘 돌아가게 두자 ✔kotlin-spring 플러그인을 쓰자 ✔delombok을..
  • 59. 도입을 고민할 때 할 만한 걱정들 개발 환경은 쓸 만 한가요? 언어로 생산성과 안전함이 향상된다? 잘 돌아가나요? 자바와 어느 정도 호환되나요? 문법 그래서 생태계 개발 환경
  • 60. 요약 이미 안정화된 언어와 개발 환경 생산성과 가독성 높은 문법 하위 호환할 레거시 문법이 없음 잘 돌아갑니다. 😃 자바와 완전한 호환으로 생태계 공유 프레임웍의 러닝 커브가 없음 문법 그래서 생태계 개발 환경
  • 61. ________ ________ ________ ________ ________ __ / / // // / // // / _==--------_ -- / / / / / / / / / / / / / / / / | / <:/ / / <:/ / / / / / / /__ ___ / / // / / / / // / / / / / / | . . :| /___/___/ /___/___/ /___/___/ /___/___/ /_______/ / / | __.__ :| ::::::/::::::/::::::/::::::/:::::::/ / | /::::: .:| ______/______/______/______/_______/ | _ ^ _/ .:/ ________ ________ ____ ________ .:/ / // // / / / / _ ..:/ /__ __/ / / / / / / / / / / /"------"" :/ /:/ / / /___/ / <:/ / / . . . / / // / / / // / /_/ | / ::::: | | /__/ / /___/___/ /_______/ /___/___/ / | ::::::: |/ ::/ /:::::: :::::::/::::::/ / | ::::: | __/ ______/_______/______/ | | | ## 참석해 주셔서 감사합니다! QNA$