[Scala] implicit keyword (2) - Implicit class

Scala에서 implicit keyword를 사용하는 또 다른 예제는 Implicit class 이다. Implicit class는 이미 존재하는 class에 새로운 함수를 추가하여 확장하기 위해서 사용된다. 정확히 말하면 원래 있던 클래스 자체를 바꾸지는 않고, class를 implicit conversion해서 호출할 수 있는 함수를 추가할 수 있게 해준다. Standard library에 있는 implicit class 의 대표적인 예는 Duration class들 이다. 위의 예제에서 보듯이 DurationInt 와 DurationDouble 이라는 implicit class 가 각각 Int 와 Double 을 확장시켜서 seconds / milliseconds / nanoseconds 같은 method를 추가해서 Duration 객체를 만들 수 있게 해준다. 이 설명을 보면 지난 글 에서 설명해줬던 implicit converter가 해줄 수 있는 일과 크게 다르지 않아 보인다. 사실 Implicit class는 implicit converter의 syntactic sugar 에 불과하다. 내부적으로 implicit class 로 정의된 class 는 class 의 이름과 같은 implicit converter를 같은 scope에 추가한다. 즉, 아래와 같이 정의된 implicit class 는 다음과 같이 변환된다. 내부적으로 implicit converter에 해당하는 함수를 정의하는 것이기 때문에 몇 가지 제약사항이 있다. 첫 번째 제약사항으로 implicit class 는 trait 이나 class 나 object 안에 정의되어야 한다. 이는 함수의 정의가 trait 이나 class 나 object 안에 정의되어야 하기 때문이다. 그래서 보통 implicit class들 은 package object 안에 정의된다. 두 번째 제약사항은 non-implicit인 parameter가 반드시 1개인 constru

[Scala] implicit keyword (1) - implicit converter

Implicit converter가 하는 일은 이름 그대로 value를 적절한 type으로 implicit하게 convert 하는 것이다. Scala는 기본적으로 strong typed language이기 때문에 implicit conversion을 지원하지 않는다. 함수를 호출할 때 함수의 symbol에 맞지 않으면 바로 컴파일에러가 발생한다. implicit conversion을 하기 위해서는 해당 scope 안에 implicit converter를 구현해두어야 한다. Implicit converter의 선언은 다음과 같다. Implicit converter는 unary function 에 implicit keyword를 붙여주는 것으로 정의된다. 이렇게 Implicit converter를 구현해두면, sizeToRectangle 함수가 정의되어 있는 scope에서는 Size 객체가 Rectangle 객체로 implicit conversion이 가능해진다. 예를 들어 Scala에서 자주 쓰이는 Option 이라는 class 를 보자. Option은 c#의 nullable 과 유사한 type으로 원소가 없을 수 있는 객체 이다. 이는 다른 관점에서 보면 최대 원소가 1개인 collection이라고 볼 수 있고, Option 을 사용할 때 collection처럼 list comprehensive method 1) 를 사용하는 것을 권장한다. 하지만 Option 코드 를 보면 Option 은 Iterable 이나 Traversable 을 상속받지 않았고, 일부 함수를 제외하고 collection처럼 이용는데 필요한 모든 함수를 가지고 있지도 않다. 대신 Option 을 Iterable 로 변환해주는 option2Iterable 이라는 implicit converter가 있기 때문에 Iterable 이 필요한 경우 자동으로 변환해서 넘겨준다. Implicit converter에 대응되는 개념이 다른 언어에 없는 것은 아니다. C++에서는 un

[Scala] implicit keyword (0)

Scala 의 가장 인상적인 keyword를 말하라고 하면 많은 사람이 implicit 을 꼽을 것이다. implicit 은 scala의 확장성에 무한한 힘을 주는 keyword임과 동시에 코드를 읽을 때 헬 게이트를 여는 주범이기도 하다. 1) implicit keywod는 Implicit converter, Implicit class, Implicit parameter의 3가지 목적으로 이용된다. 앞으로 3번에 걸쳐서 각각에 대해 설명하도록 하겠다. 1) 개인적으로 코딩할 때 대부분 언어를 vim으로 작업해왔지만, scala를 배우면서 IntelliJ 라는 IDE 를 사용하기 시작했다.

[MongoDB] ObjectId에 대해서

지난번에 shard key를 설명한 글 을 썼을 때 댓글 로 ObjectId 에 관한 얘기가 나왔었다. 그래서 sharding과 큰 연관은 없지만, 이번 기회에 ObjectId에 관해서 먼저 설명하고 가는 게 좋을 것 같아서 sharding에 관한 것은 뒤로 미루고 이번에는 ObjectId에 대해 먼저 설명하고 가도록 하겠다. ObjectId란 무엇인가 ObjectId는 같은 document 내에서 유일함이 보장되는 12 byte binary data다. 전통적인 centralized 되어 있는 시스템이라면 한 collection 내에서 유일함을 보장하는 것을 쉽게 할 수 있다. 하지만 sharding을 하는 MongoDB에서 유일함을 보장하는 것은 기존과는 다른 솔루션이 필요하다. 그리고 이 방법을 설명하는 게 사실상 ObjectId의 모든 것을 설명하는 것이다. 왜 ObjectId를 사용하는가 전통적인 RDBMS 에서 Primary key 를 만들 때는 DB 서버로 data를 보내서 중복되지 않는 key를 골라서 1) 그 값을 key로 저장하는 방식을 이용한다. 하지만 MongoDB와 같은 분산 database에서는 key를 서버에서 만들지 않고 클라이언트에서 만든다. 그 이유는 MongoDB가 query를 날릴 shard를 결정하는 방식 을 보면 알 수 있다. MongoDB는 자신이 필요한 shard에게만 query를 요청한다. 다시 말해서 client에 해당하는 mongos 2) 가 config server 의 data를 토대로 어떤 shard가 어느 범위의 값을 가졌는지를 저장하고 있다가 query를 요청할 때 자신이 필요로 하는 shard에게만 요청한다. 따라서 shard key 에 해당하는 data가 미완성인 상태로 서버에 저장하도록 요청할 수 없고, client가 ObjectId를 생성하여 값을 저장하도록 요청한다. 3) ObjectId의 구성 ObjectId는 크게 4부분으로 구성되어 있다. ObjectId의 처음 4 by

[ZooKeeper] (2) zookeeper server는 어떠게 구성되는가?

이미지
ensemble 테스트 환경이나 개발 환경에서는 stand-alone mode를 이용하여 한 대의 ZooKeeper 서버만을 실행하여 사용할 수 있지만, 이렇게 되면 ZooKeeper의 큰 장점인 availability를 크게 해치게 된다. 그래서 실제 배포 환경에서는 보통 최소 3대의 ZooKeeper 서버를 cluster로 묶어서 배포하는 것이 일반적이다. 이때 ZooKeeper cluster를 ensemble이라고 부른다. 같은 ZooKeeper ensemble에 포함된 서버는 모두 같은 data를 저장함으로써 특정 서버가 SPOF (Single Point Of Failure)가 되는 일을 막는다. 그렇다면 분산 된 환경에서 모든 서버에 같은 data가 저장되는 것을 어떻게 보장해줄 수 있을까? Leader ZooKeeper ensemble에는 외부에는 공개되지 않지만, 내부적으로 사용되는 leader가 있다. client는 ensemble에 포함된 어떤 서버에게도 query를 날릴 수 있다. 서버는 query를 받으면 이 query를 ensemble의 leader에게 전달해 주고, leader가 모든 서버에 같은 data가 저장되는 것을 보장해 준다. Two phase commit ZooKeeper는 모든 follower가 leader와 같은 data를 가지고 있는 것을 보장하기 위하여 간략화된 two phase commit 을 사용한다. leader는 request에 대해서 follower에 해당하는 server들에게 propose message를 보낸다. propose message를 받은 follower는 해당 proposal에 대해서 local disk에 commit log를 저장하고 ack message를 보낸다. leader는 Follower로부터 받은 ack이 quorum (보통은 n/2 + 1이다.) 을 넘으면 모든 Follower들에게 Commit을 날린다. Commit을 받으면 zookeeper는 commit lo

[Graphics] Sprite는 무엇인가

Sprite는 렌더링 파이프라인을 타지 않고 target(screen이든 FBO든)에 직접 그림을 그릴 수 있게 해주는 2D bitmap을 의미한다. Sprite에 그린 그림은 rendering pipeline을 타지 않기 때문에 transform 이나 다른 효과들과 독립적으로 화면에 보이게 된다. 이러한 특성 때문에 3D게임에서 UI를 그릴 때 이용된다.

Service Provider Interface란?

Service Provider Interface (a.k.a. SPI)는 extensible한 코드를 작성하기 위해서 Java 진영에서 주로 쓰이는 방법이다. 보통의 API들은 구현체의 Interface를 외부로 공개하여 구현체를 사용하는 주체가 자신의 환경에 맞게 사용한다. 반면에 SPI는 사용자가 구현해야 할 Interface를 정의한다. SPI 사용자(보통은 driver vendor)가 자신의 환경에 맞는 구현체를 직접 정의하여 제공하면 SPI를 제공해준 service에서는 제공 받은 구현체를 불러다 사용하는 형태로 동작한다. 대표적인 예로 Java Cryptography Extension 가 있다.

이 블로그의 인기 게시물

[C++] enum class - 안전하고 쓰기 쉬운 enum

Log Aggregator 비교 - Scribe, Flume, Fluentd, logstash

RAII는 무엇인가

[Python] cache 데코레이터로 최적화하기

[Web] SpeechSynthesis - TTS API