이번 글에서는 spring boot에서 redis에 데이터를 CRUD 해보도록 하겠습니다. 1. Redis Server 이번 실습을 위해선 redis server가 하나 필요합니다. 저는 AWS EC2에 redis server를 구동시켰습니다. 2. application.yml application.yml 파일에 아래와 같이 redis properties 정보를 입력합니다. redis의 default port는 6379입니다. spring: redis: host: "hostname" port: 6379 3. build.gradle build.gradle 파일을 열고 아래와 같이 redis dependency를 추가합니다. spring-boot 2에서 redis dependecy는 기본 client로 le..
이번 글에서는 redis의 unique count 기능인 HyperLogLog에 대해 알아보겠습니다. 1. HyperLogLog란? 효율적인 unique item count 기능을 제공해주는 기능입니다. 예를 들어 아래와 같이 특정 사이트에 방문자수를 count 해주는 기능이 있을때 정확한 방문자수의 집계를 위해선, 동일 정보를 가진 방문자는 count에서 제외해야 합니다. 이를 구현하기 위해 기존에는 모든 unique 방문자가 들어올때마다 해당 정보를 저장해 놓고, 매번 해당 정보와 방문자를 비교하는 방법으로밖에 구현할 수 없었습니다. 따라서 대규모 사용자가 접속하는 facebook과 같은 서비스에서는 막대한 비용이 들 수 밖에 없는 구조였습니다. 만약 redis의 set을 사용해 구현한다고 하더라도,..
이번 글에서는 redis에서 geospatial data를 저장하는 방법인 geo에 대해 알아보겠습니다. 1. Geospatial이란? geospatial 이란 지도상의 object들의 위치인 지리데이터를 의미합니다. 우리가 자주 사용하는 배달의 민족이나, 카카오 택시등의 서비스에서는 이러한 geospatial 데이터를 활용해 서비스를 제공합니다. 일반적으로 geospatial object를 저장하기 위해서는 longitude와 latitude의 pair를 저장합니다. 이러한 데이터의 저장은 다른 데이터 저장소에서도 가능하지만, redis를 사용하면 대규모 geospatial object 데이터의 저장 및 조회를 very low latency로 구현할 수 있습니다. 2. GeoHash redis는 geo..
이번 글에서는 redis의 message broker 기능인 publish/subscribe에 대해 알아보겠습니다. 0. Message Broker kafka/RabbitMQ와 같은 message system에서 제공하는 message broker의 기능을 redis도 자체적으로 제공해줍니다. 아래 그림과 같이 Client-1이 ch1에 "Hello"라는 메세지를 publish하면 ch1을 구독하고 있던 Client-2는 "Hello"라는 메세지를 전달받게 됩니다. 만약 특정 메세지의 발행전에 해당 채널을 구독하고 있던 subscriber가 없다면, 해당 메세지는 사라지게됩니다. 아래 그림으로 살펴보면 client-1이 "World"라는 메세지를 발행했을 당시에는 ch2를 구독하고 있는 subscribe..
이번 글에서는 redis의 transaction에 대해 알아보도록 하겠습니다. 0. Transaction이란? transaction이란 redis의 여러 command들을 하나의 block으로 모아둔 것 입니다. transaction에서 사용하는 command에는 MULTI / EXEC / DISCARD / WATCH 등이 있습니다. redis의 transaction을 사용하면 batch 단위로 command들을 실행할 수 있습니다. batch 단위로 처리되는 command들은 실행전에 QUEUE에 serialized 된 상태로 담겨있으며, 실행시에는 QUEUE에 삽입된 순서에 맞춰 sequentailly하게 실행됩니다. transaction은 실행되는 동안에는 어떠한 request의 영향도 받지 않습니..
이번 글에서는 redis의 data type 중 Sorted Set에 대해 알아보겠습니다. 1. Sorted Set redis의 sorted set은 set과 hash가 mix된 타입입니다. sorted set은 set과 마찬가지로 unique한 elements를 가집니다. 반대로 set과는 다르게 sorted set의 모든 elements는 순서를 가집니다. 모든 sorted set의 element는 'score'라고 부르는 floating point value를 가집니다. 때문에 모든 element가 value와 mapped되는 hash의 속성을 가집니다. 2. Command Line SORTED SET TYPE에 사용할 수 있는 redis-cli 명령어 목록은 다음과 같습니다. @ KEY에 SCOR..
이번 글에서는 redis의 data type 중 set에 대해 알아보겠습니다. 1. SET redis의 set은 unordered collection of string 입니다. List와 동일하게 add / remove / test for existence of members 등의 기능을 제공합니다. set 내부의 elements의 수와 관계없이 특정 element를 검색하는 시간은 O(1)으로 동일합니다. 최대 elements의 갯수는 2^32-1 입니다. redis의 set은 여러가지 server side command를 제공합니다. 이를 이용해서 union / intersection / difference of sets 등의 기능을 매우 빠른시간에 수행할 수 있습니다. 2. Command Line ..
이번 글에서는 redis의 data type 중 Hash에 대해 알아보겠습니다. 1. Hash redis의 hash는 string field와 string value로 구현된 Map type 입니다. Hash는 Object data type을 나타내기위한 완벽한 data structure 입니다. Hash는 최대 2^32-1 field-value pair값을 저장할 수 있습니다. 2. Command Line HASH TYPE에 사용할 수 있는 redis-cli 명령어 목록은 다음과 같습니다. @ KEY의 FIELD값에 VALUE를 할당합니다. HSET [KEY] [FIELD] [VALUE] @ KEY의 하나이상의 FIELD값에 VALUE를 할당합니다. HMSET [KEY] [FIELD] .. [KEY] ..
이번 글에서는 redis의 data type 중 List에 대해 알아보겠습니다. 1. List Redis의 List는 Linked List로 구현되어 있습니다. List Type은 구현하는 구현체가 Array일 경우와 Linked List일 경우에 따라 많은 차이가 있습니다. Linked List로 구현한 List는 Data의 insert가 굉장히 빠른 반면에, indexing을 활용한 data access 속도가 Array로 구현한 List에 비해 느립니다. 2. Command Line LIST TYPE에 사용할 수 있는 redis-cli 명령어 목록은 다음과 같습니다. @ KEY의 HEAD에 VALUE를 삽입합니다. LPUSH [KEY] [VALUE] @ KEY의 HEAD에 VALUE를 삽입합니다. ..
이번 글에서는 redis의 data type 중 String에 대해 알아보겠습니다. 1. String 기본적으로 redis의 VALUE 값은 String Type으로 생성됩니다. 2. Command Line STRING TYPE에 사용할 수 있는 redis-cli 명령어 목록은 다음과 같습니다. @ 기존 KEY값이 존재하지 않는 경우에만 KEY 값을 생성합니다. SET [KEY] [VALUE] [NX] @ 기존 KEY값이 존재하는 경우에만 KEY 값을 업데이트합니다. SET [KEY] [VALUE] [XX] @ KEY의 OLD_VALUE값에 NEW_VALUE 값을 붙입니다. APPEND [KEY] [NEW_VALUE] @ KEY의 VALUE값에 +1을 합니다. STRING TYPE임에도 허용합니다. IN..
이번 글에서는 Ubuntu Linux에 redis를 설치해보겠습니다. 1. Download Redis https://redis.io/ 에서 최신 redis 파일을 다운받습니다. 다음으로 다운받은 파일을 압축을 해제합니다. 압축을 해제한 파일 경로에서 terminal을 open합니다. Terminal에서 아래와 같은 명령어를 순서대로 입력합니다. 만약 중간에 에러가 발생할 경우 파일을 삭제하고 다시한번 압축을 풀어주신 후 진행해보시면 해결될 겁니다..😅 sudo apt-get install make sudo apt-get update sudo apt-get install gcc sudo make install redis 다운로드가 완료되었습니다. 터미널을 열고 아래의 명령어를 입력해 redis를 실행합니다..
이번 글에서는 오픈소스 in-memory 데이터 저장소인 redis에 대해 알아보도록 하겠습니다. 0. Redis란? 오픈소스 in-memory data store입니다. 모든 데이터는 memory에 저장되며 휘발성 입니다. 따라서 shutdown시 데이터를 보관하기 위해 disk에 별도로 데이터 backup이 필요합니다. redis의 사용용도는 크게 아래의 세가지로 구분됩니다. • In-Memory Database : redis는 key-value 구조의 대표적인 NoSQL입니다. • Cache : temporary data를 읽고 쓰기위한 cache server로 redis가 사용됩니다. • Message Broker : redis를 사용해 메세지를 publish/subscribe 할 수 있습니다. ..
이번글에서는 MockMvc를 사용해 RestController를 test하는 방법에 대해 알아보도록 하겠습니다. 1. RestController 먼저 이번 글에서 사용할 RestController를 아래와 같이 생성했습니다. 별다른 내용없이 GET으로 "/hello"를 호출하면, "Hello World"를 return 해주는 API입니다. HelloResource @RestController @RequestMapping("/hello") public class HelloResource { @GetMapping public String helloWorld(){ return "Hello World!"; } } 2. Get API Test 이제 위에서 작성한 GET API를 테스트 해보겠습니다. 2-1) Te..
이번글에서는 test에서 특정 메서드만 override 하는 방법인 Spy에 대해 알아보도록 하겠습니다. 1. Mock Instance 우리는 이전 글에서 Stub와 Mock을 사용해 특정 인스턴스의 business logic을 override 하는 방법을 살펴보았습니다. 즉 Stub와 Mock을 사용했다면 해당 인스턴스 내부의 모든 business logic의 수행은 무력화 되며, 하드코딩으로 직접 명시한 메서드가 아닐 경우에는 null을 return 할 것입니다. 예를 들어 아래와 같은 LoanApplication을 Mock으로 생성한 경우, 아래의 모든 메서드는 실행되지 않으며, 각 메서드를 test에서 사용하고자 한다면 return 값을 직접 하드코딩해 명시해줘야 했습니다. LoanApplicat..
이번글에서는 prime number 예제를 통해 좋은 test code를 작성하는 방법에 대해 알아보도록 하겠습니다. 1. Check Prime Number 먼저 아래와 같이 Prime Number 인지 아닌지를 확인하는 NumberValidator 클래스가 있다고 가정해보겠습니다. NumberValidator public class NumberValidator { public boolean isItPrime(int number) { int maxDivisor = (int)Math.sqrt(number); for(int i=2;i
이번글에서는 Mock의 Fake 기능과, Stub를 대체하는 방법에 대해 알아보도록 하겠습니다. 1. Stub & Mock 이전까지의 글을 통해 우리는 Stub는 data를 test 할 때 사용하며, Mock은 behavior를 test 할 때 사용한다고 이해했습니다. 공통점으로는 Stub와 Mock 둘다 external dependency를 override 하는 방법으로 사용한다는 것 또한 이해할 수 있었습니다. 2. Fake 그렇다면 만약 test 할때 관심없는 부분들을 제외하고 test 하기 위해선 어떻게 해야될까요? 이와 같은 경우도 동일하게 Mock을 사용해 구현할 수 있습니다. 이를 우리는 Fake 라고 합니다. 예를 들어 test 하고자하는 business logic 내부에 아래와 같은 lo..
이번글에서는 JUnit의 Mock을 활용해 behavior를 테스트 해보도록 하겠습니다. 1. Test Behavior 1-1) Test Result 이전 글과 동일하게 ISBN Number를 예를 들어보겠습니다. 우리는 이전 글에서 Assert를 사용해 최종 결과값과 기대하는 값을 비교하는 테스트를 진행했었습니다. 예를 들어 getLocatorCode("014077396")의 최종 결과값이 "7396J4"와 같은지를 테스트 했습니다. 즉, 우리는 result를 test 했었다고 이해할 수 있습니다. Test Result Example @Test public void canGetCorrectLocatorCode(){ // Stub ExternalISBNDataService service = new Ext..
이번글에서는 JUnit의 Stub에 대해 알아보도록 하겠습니다. 1. Stub란? 테스트 용도로 하드 코딩한 값을 반환하는 구현체를 의미합니다. Stub은 주로 external service를 사용하는 code를 테스트할 때 사용합니다. 여기서 external service는 database, web service 등을 의미합니다. 우리는 databse와 connect 하거나 web service를 call 할 수 있는지에대해 test하고 싶은 것이 아닙니다. 따라서, 이와 같은 부분들은 하드코딩으로 대체하고, 우리가 test 하고자하는 business logic에 집중하고자 Stub을 사용합니다. Stub을 사용하지 않을 경우 위와 같은 external service가 down 된다면 우리가 작성한 c..
5. Refactoring 계속해서 refactoring을 진행하도록 하겠습니다. https://en.wikipedia.org/wiki/International_Standard_Book_Number 에 따르면 ISBN Number의 로직은 아래의 code를 만족해야 합니다. 따라서 이를 참고해 checkISBN 메서드를 수정해야합니다. 😎 위키피디아의 설명에 따르면 ISBN number는 0 ~ 10 digits 사이의 number라고 되어있지만, 현재의 테스트에서는 그것을 고려하지 않습니다. 해당 내용은 또다른 테스트를 작성해 만들어야 합니다. Wikipedia // Returns ISBN error syndrome, zero for a valid ISBN, non-zero for an invalid ..
이번 글에서는 TDD에 대해 알아보도록 하겠습니다. 1. TDD란? test먼저 작성하고 그 test를 통과시키는 code를 작성하는 방법입니다. 예를 들어 A+B를 더하는 메서드를 만들어야 하는 상황이라면, A+B를 더하는 메서드를 작성하기전에 그것을 테스트하는 코드를 먼저 작성합니다. 작성한 테스트는 당연히 실패할 것이고, 이제 해당 테스트가 통과할 수 있도록 메서드를 작성하면 되겠습니다. 이 때 각 테스트는 'single piece of logic'을 테스트해야 합니다. 하나의 메서드에 대해서 여러상황에 대한 테스트를 늘려나가다보면 어느새 완벽한 메서드가 만들어지게 되있을 것 입니다..😎! 2. Valid ISBN Number 이제 순서대로 TDD를 통해 코드를 작성해보도록 하겠습니다. 최종적으로 ..