소개

Redis는 Remote Dictionary System의 약자로, C로 개발된 오픈 소스 Key-Value Store이다. Redis는 종종 데이터 구조 서버(data structures server)라고 불리는데, 이는 Redis가 일련의 명령어들을 통해 가변적인 데이터 구조에 접근할 수 있는 환경을 제공하기 때문이다. Redis에서 데이터는 TCP 소켓과 간단한 프로토콜을사용하는 Server-Client 모델을 통해 전송된다.

Redis의 데이터 구조는 다음과 같은 특징을 가진다.

  • 모든 데이터는 Memory에서 수정되고 제공되지만, Redis의 이 데이터들을 Disk에 저장한다. 이것은 Redis가 빠른 속도를 제공할 뿐만 아니라, 데이터의 비휘발성 역시 보장한다는 뜻이다.
  • 다른 고수준의 프로그래밍 언어에서 개발된 같은 데이터 구조에 비해 메모리를 덜 사용한다.
  • Redis는 데이터베이스에서 흔히 찾을 수 있는 복제(replication), 조정 가능한 수준의 내구성(tunable levels of durability), 클러스터(cluster), 높은 안정성(high availability)과 같은 특징들 역시 제공한다.

Redis를 이해할 수 있는 쉬운 예는, 이를 더 복잡한(그리고 발전된) 버전의 memcached라고 생각하는 것이다. SET, GET과 같은 명령어 외에도, Redis는 Lists, Sets, 그리고 Sorted Sets 등의 복잡한 데이터 형과 관련된 연산들 역시 제공한다.

데이터 타입

Redis는 단순한 키-값 저장소(key-value store)가 아닌, 여러 종류의 값을 지원하는 데이터 구조 서버(data structures server)이다. 다른 전통적인 Key-Value Store는 string 키와 값만을 제공하지만, Redis에서는 string 외에도 다른 복잡한 데이터 구조를 값으로 사용할 수 있다.

1. Strings

Redis String은 가장 간단한 타입의 값이며, binary-safe하다. 이는 받는 모든 데이터를 text가 아닌 binary로 받는다는 것이고, 따라서 “foo”와 같은 string부터 JPEG파일까지 모든 2진 데이터를 사용할 수 있다.
Redis의 Key 역시 String 타입이다. 한 가지 재미있는 점은, 빈 문자열 역시 키로 사용될 수 있다는 것이다. 하지만 너무 짧거나 긴 키는 좋지 않은 생각이다. 키는 “comment:1234:reply-to”와 같이 스키마와 대시(-), 점(.)을 사용하여 만드는 것이 좋다. 키가 너무 길어진다면 해싱하는 것도 좋다. 키의 최대값은 512 MB이다.
String의 명령어로는 SET, GET, DEL, INCR, INCRBY, DECR, DECRBY, EXISTS 등이 있다.

2. Lists

리스트는 어떤 방법으로 구현되었는지에 따라 그 특징과 쓰임새가 달라지는데, Redis의 List는 Linked List의 일종이다. 따라서 새 요소를 리스트의 head나 tail에 추가하는데 걸리는 시간이 리스트의 크기와 관계없이 일정하다. 하지만 인덱스를 통해 각각의 요소에 접근하는데 걸리는 시간은 Array에 비해 그렇게 빠르지 않다. Redis List의 경우, 데이터베이스 시스템은 매우 긴 리스트에 최대한 빨리 새 요소를 추가하는 것이 중요하므로 Linked List를 사용했다. 다른 장점은 상수 시간 내에 길이를 알아내는 것이 가능하다는 것이다. 그러나 인덱스를 통해 데이터에 빠르게 접근하는게 중요할 수도 있기 때문에, Redis는 Sorted set 역시 제공한다.
List의 명령어로는 LPUSH, RPUSH, LPOP, RPOP, LRANGE, RRANGE이, LTRIM, RTRIM 등이 있다.

3. Hashes

Redis Hash는 Key-Value Table이다. Java의 Hashtable이나 C#의 Dictionary를 생각하면 쉽다. 간단한 예제를 통해 사용법을 알아보자.
Hash의 명령어로는 HMSET, HGET, HGETALL, HMGET, HINCRBY 등이 있다.

1
2
3
4
5
6
> hmset user:1000 username antirez birthyear 1977 verified 1
OK
> hget user:1000 username
"antirez"
> hget user:1000 birthyear
"1977"

4. Sets

Redis Set은 정렬되지 않은(unordered) 문자열의 집합이다. 집합이기 때문에 중복되는 요소는 하나로 처리한다. Set은 객체 간 관계를 표현하기 좋다. 간단한 예로, 우리는 Set을 이용해 태그를 달 수 있다.
Set의 명령어로는 SADD, SMEMBERS, SISMEMBER, SPOP 등이 있다.

5. Sorted Sets

Redis Sorted Set은 Set과 Hash를 섞어 놓은 것과 비슷하다. Sorted Set은 Set과 같이 중복되지 않는 String Element로 구성되어 있지만, score라는 실수값에 의해 오름차순으로 정렬된다는 특징을 가진다. 정렬이 되어 있기 때문에 range나 rank에 따른 query가 가능하다.
Sorted Set의 명령어로는 ZADD, ZRANGE, ZREVRANGE, ZRANGEBYSCORE, ZRANK 등이 있다.

설치

다음은 Redis 공식 홈페이지의 Download 페이지에서 제공하는 가이드이다.

1
2
3
4
$ wget http://download.redis.io/releases/redis-3.0.2.tar.gz
$ tar xzf redis-3.0.2.tar.gz
$ cd redis-3.0.2
$ make

이대로 해서 별 문제가 없다면 다행이지만, 내 경우 리눅스를 설치하고 나서 따로 해둔게 없었기 때문에 Redis 설치 과정에서 해야 할 것이 몇가지 더 있었다. 발생한 문제는 세 가지였는데, 마지막 내용은

1
2
3
4
5
6
7
cd src && make all
make[1]: Entering directory `/home/ubuntu/redis-3.0.2/src’
CC adlist.o
/bin/sh: 1: cc: not found
make[1]: *** [adlist.o] Error 127
make[1]: Leaving directory `/home/ubuntu/redis-3.0.2/src’
make: *** [all] Error 2

이 오류의 해결책이다. redis-3.0.2 폴더 내에서 명령어를 입력해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
make가 없는 경우
$ sudo apt-get install make
$ make

gcc가 없는 경우
$ sudo apt-get update
$ sudo apt-get install make
$ sudo apt-get install gcc
$ make

그 외
$ cd deps
$ make hiredis lua jemalloc line noise
$ cd ..
$ make

설치 후 set, get, del 명령어를 사용하여 간단하게 테스트를 해봤다.

1
2
3
4
5
6
7
8
9
10
$ src/redis-server &
$ src/redis-cli
127.0.0.1:6379> set foo bar
OK
127.0.0.1:6379> get foo
"bar"
127.0.0.1:6379> del foo
(integer) 1
127.0.0.1:6379> get foo
(nil)

PATH 설정을 해 두면 더 편하게 사용할 수 있다. redis-3.0.2 폴더의 상위 폴더에서 아래 명령어를 입력한다. /etc/enviroment의 PATH 끝에 :/usr/lib/redis-3.0.2/src를 추가해주자. 참고로 이는 우분투 기준이며, Mac OS X나 CentOS에서는 홈 폴더의 .profile 혹은 .bash_profile을 수정해주면 된다.

1
2
3
$ sudo mv redis-3.0.2 /usr/lib
$ sudo vi /etc/enviroment
$ source /etc/enviroment

참고

Redis 공식 홈페이지
Redis GitHub
조대협의 블로그

Comment and share

RESTful API

in backend

소개

REST는 Representational State Transfer의 약자로, 네트워크 어플리케이션을 디자인하기 위한 아키텍쳐 스타일이다. 이것은 장비 간 통신을 위해 CORBA, RPC, 혹은 SOAP등의 복잡한 방법을 사용하는 대신, 간단하게 HTTP를 이용하는 것을 목적으로 한다.
REST는 자원 지향 구조(Resource Oriented Architecture)로 웹 사이트의 이미지, 텍스트, DB 내용 등의 모든 자원에 고유한 URI를 부여한다. 한 가지 알아두어야 할 것은, REST가 표준은 아니라는 것이다. 월드 와이드 웹의 표준을 개발하고 장려하는 W3C는 REST를 사용하라고 하지는 않는다.

CRUD

REST에서 자원에 대한 작업은 HTTP Request를 이용한다. 작업에는 Create(생성), Read(조회), Update(수정), Delete(삭제)가 있고, 이를 줄여서 CRUD라고 한다. 여기에 대응하는 HTTP 메소드는 각각 Post, Get, Put, Delete이다. 실제로 HTTP Reqeust를 보내고 결과를 받는 부분을 살펴보자.

Request

1
2
GET /
Accept: application/userdb

Response

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
200 OK
Content-Type: application/userdb

{
"version": "1.0",
"links": [
{
"href": "/user",
"rel": "list",
"method": "GET"
},
{
"href": "/user",
"rel": "create",
"method": "POST"
}
]
}

조건

REST 아키텍쳐는 다음과 같은 6개의 조건을 가진다.

1. Uniform Interface

REST는 HTTP 표준에만 따른다면, 특정 언어나 기술에 구애받지 않고 사용이 가능한 인터페이스 스타일이다. HTTP의 창시자 중 한 사람인 Roy Fielding은 네 가지의 인터페이스 제약을 제시했다.

  • Resource-Based 의역하자면 리소스 식별 로, 각각의 리소스는 URI를 구분자로 이용하여 구분되어야 한다는 것이다. 예를 들어, http://www.google.com 은 구글의 메인 페이지를 정의한다.
  • Manipulation of Resources Through Representations 표현을 통한 리소스 처리 는 같은 리소스라도 클라이언트에 따라 다르게 보여질 수 있다는 것이다. 뉴스 사이트를 생각해보자. 데스크탑으로 접속할 때와 모바일로 접속할 때 화면은 서로 다르지만 같은 리소스를 쓰고 있다.
  • Self-descriptive Messages 자기 서술적 메시지 란 각 메시지는 자신을 어떻게 처리해야 하는지에 대한 모든 정보를 포함해야 한다는 것이다. 이러한 종류의 메시지는 state-less 혹은 context-free 라고 부르기도 한다.
  • Hypermedia as the Engine of Application State (HATEOAS) 메시지를 보내는 것은 어플리케이션의 상태를 변화시킨다. 예를 들어, 새로운 유저 정보를 서버에 POST하게 되면 유저 리스트를 하나 늘려 어플리케이션의 상태를 변화시킨다. GET을 통해 유저 목록을 요청하면 어플리케이션의 새로운 상태를 받을 수 있다. POST와 GET은 모두 hypermedia link 를 통해 수행되는데(<a href=~>, <form action=~>), 이런 방법을 통해 RESTful 어플리케이션은 하이퍼미디어를 통해 어플리케이션의 상태를 변화시킨다. 이를 어플리케이션 상태 엔진으로서의 하이퍼미디어 라고 한다.

2. Stateless

상태가 없다는 것은 각각의 요청 시에 클라이언트의 컨텍스트가 서버에 저장되지 않는다는 것이다. 클라이언트가 보내는 각각의 요청은 필요한 모든 정보를 담고 있어야 한다. 이렇게 개발하게 되면 서버는 들어오는 요청만을 처리하면 되기 때문에 구현이 단순해진다.

3. Cacheable

WWW에서와 같이, 클라이언트는 응답을 캐싱할 수 있다. 대부분의 서비스에서 CURD중 Read가 가장 빈번하게 호출되기 때문에, 응답을 캐싱하는 것은 서비스의 성능을 향상시킬 수 있다. 클라이언트가 Last-Modified 값을 보냈을 때, 컨텐츠에 변화가 없다면 서버는 304 Not Modified 를 리턴하게 되고 클라이언트에서는 캐시에 저장된 값을 이용하게 된다.

1
2
3
4
5
6
7
8
9
10
GET /partners/UK

200 OK
Last-Modified: Sun, 21 Jan 2007 09:35:19 GMT
[response]

GET /partners/UK
If-Modified-Since: Sun, 21 Jan 2007 09:35:19 GMT

304 Not Modified

4. Client-Server

Uniform Interface는 서버로부터 클라이언트를 분리한다. 클라이언트는 데이터베이스를 신경 쓸 필요가 없고, 사용자 인증이나 컨텍스트를 관리한다. 서버의 경우 유저 인터페이스나 유저 상태를 신경 쓸 필요 없이 API 제공, 데이터 저장, 그리고 로직 처리의 역할만을 담당하게 되어 더 간단해지고 확장이 쉬워진다. 이렇게 역할 구분이 확실해지면 서로의 개발에 있어 의존성이 줄어들게 된다.

5. Layered System

클라이언트는 API 서버만 호출할 뿐, 자신이 대상 서버에 직접 연결되었는지 혹은 중간 서버를 통해 연결되었는지 알 수 없다. 하지만 서버는 다중 계층으로 구성될 수 있다. 서버는 API 서버에 로드밸런싱, 공유 캐시, 암호화 등을 수행하는 계층을 추가해서 유연한 구조로 개발될 수 있다.

6. Code on Demand (optional)

서버는 Java Applet이나 JavaScript와 같이 클라이언트가 실행할 수 있는 코드을 전송하여 클라이언트의 기능을 확장시킬 수 있다. 이것은 REST 아키텍쳐에서 필수는 아니다.

참고

Wikipedia
REST API Tutorial
remotti blog
SLiPP 스터디
조대협의 블로그
일관성 있는 웹 서비스 인터페이스 설계를 위한 REST API 디자인 규칙

Comment and share

참 오래도 기다렸다. 2011년, 막 고등학교에 들어갔을 때 자주 활동하던 카페에 글이 하나 올라왔다. 소프트웨어 마에스트로 2기 과정에 지원하신단다. 마에스트로라, 얼마나 대단한 인재를 양성하는지 궁금해졌다. 모집 요강은 어렵지 않게 찾을 수 있었다. 내 주의를 끈 것은 지원금이었다. 하고싶은 공부를 하면서 돈을 받다니, 역시 뭐든지 잘 하면 도움이 되는구나.

그렇지만 나는 선뜻 지원서를 쓰지 못했다. 내 실력에 대해 자신감이 없었기 때문이었다. 매년 지원 공고를 보고, 지원을 망설였지만 아직은 아니라는 생각이 자꾸 발목을 잡았다. 그렇게 4년이라는 시간이 흘러 21살이 됐다. 소프트웨어 마에스트로 말고도 대학 졸업 전까지 해보고 싶은 것들이 많았다. 더 이상 망설이면 너무 늦어버릴 것 같았다.

지원 마감까지는 아직 일주일 정도의 시간이 남아 있었다. 급한 대로 대학 입시 때 작성했던 자기소개서를 이리저리 뜯어고쳤다. 할 말은 산더민데, 글자 수 제한은 빡빡했다. 문득 이렇게 짧은 글 안에 내가 겪은 경험들을 다 녹여낼 수 있을지, 또 그걸 보고 지원자를 제대로 평가할 수 있을지 궁금해졌다. 몇몇 블로그의 후기 글을 찾아 본 바로는 실적에 관심이 많다고 하던데, 자기소개서의 분량을 고려해봤을 때 아마 포트폴리오에서 서류 당락이 결정되지 않나 싶다. 나는 개발하여 일년째 서비스 중인 게임과 약 세달간 개발한 게임 엔진, 그리고 비교적 최근에 개발한 랜덤 채팅 서비스를 썼다.

마감을 2~3일 앞두고는 센터에서 전화가 하루에 한 번 꼴로 왔다. 금요일이 마감이고, 당일은 지원자가 몰려 접속이 원활하지 않으니 미리 제출해 달라는 내용이었다. 이쪽도 실적을 내야 하니 어떻게 해서든 지원자 수를 끌어올려야 하나 보다.

지원하고 나서는 학교 생활에 치여 발표도 잊고 지냈는데, 어느 날 점심때 즈음 일어나 핸드폰을 확인하니 문자가 와 있었다. 서류 전형에 합격했으니 면접을 보러 오란다. 솔직히 말해서 나는 면접에는 어느 정도 자신감이 있었다. 아직까지 면접 경험이 많지 않아 그런 것인지는 모르겠다만, 서류에서 다 써내지 못한 나의 능력과 열정을 어필하는 것이 좋았다. 그런데 이번 기수부터는 면접 과정에 집단 토의라는게 추가됐다. 생면부지의 남들과 토의를 한다는 것은 꽤 큰 부담이었다.

아버지에게 조언을 구했더니, 집단토의는 토의를 이끄는 사람이 점수를 잘 받으니 다른 사람들의 의견을 정리해서 말해보라 하셨다. 그런데 막상 토의를 하게 되니 말을 꺼내는 것조차 쉽지 않았다. 한 사람의 말이 끝나면 생각을 정리할 틈도 없이 다른 사람이 말을 이어나갔다. 처음에는 적잖이 당황해서 말은 하지 못하고, 다른 사람들의 의견을 정리하고 내 논리도 다듬었다. 다행히 중간부터는 무리 없이 끼어들어 이야기 할 수 있었다. 총 8명 중 세 분은 옷도 정장을 차려입고 오셨는데, 대학원생 혹은 군필 정도로 나이가 꽤 있어 보였고 의견도 거침없이 내셨다. 아마 이분들이 가장 좋은 점수를 받게 되지 않을까 싶다.

3일 뒤에는 코딩 테스트와 면접을 봤다. 준비된 문제가 넉넉잡아 100개는 되어 보였다. 코딩 테스트는 세 명이서 같은 문제를 풀게 되어 있는데, 셋 중 한 명이 문제를 뽑고 다 같이 그 문제를 푸는 방식이다. 비주얼 스튜디오와 이클립스가 있었고, 들은 바로는 파이썬도 깔려있다고 한다. 문제는 그렇게 어렵지 않았다. 어떤 언어를 쓸지 약간 고민하다 자바로 만들고 난 뒤, 시간이 남아 C#으로도 해보다 주어진 시간이 끝났다. 참고로 내 경우 코딩 테스트는 결과만 확인하고 별다른 질문 없이 끝났다.

면접장에 들어가 인사를 하고 발표를 시작했다. 발표는 서류에 담지 못했던 내용 위주로 준비했다. 창업 팀 경험과 프로젝트들, 그리고 프로그래밍을 시작한 과정을 담았다. 끝내고 나니 프레젠테이션을 깔끔하게 잘 만들었다는 이야기와 함께, 발표를 준비해온 사람이 많지 않다고 하셨다. 그러니 혹시 이 글을 보고 소프트웨어 마에스트로에 지원하려는 분은 발표를 준비해가길 바란다. 가산점이 있을 지도 모르니까!

면접은 주로 포트폴리오로 냈던 프로젝트와 향후 계획에 관한 내용이었다. 게임은 유저 수가 얼마나 되는지, 게임 엔진은 내가 얼마나 노력해서 만들었는지 어필해보라고 하셨고, 채팅 서비스에서는 프로토콜 관련 질문을 하셨는데 내가 아는 부분이 아니어서 잘 모르겠다고 대답했다. 프로젝트를 몇 명이서 작업했는지는 꼭 한번씩 물어보셨다.

지원자 중 지원금만 받고 실제 프로젝트에 참여하지 않는 사람이 많아서 그런지 향후 계획에서도 여러가지 질문이 나왔다. 나는 내 목표는 3단계의 5천만원이니 걱정하지 않으셔도 된다고 말씀드렸다. 면접관 중 한분은 끈질기게 휴학을 권하셨다. 본래 2학기에 12학점만 듣고 주 3~4일 정도 서울에 올라올 계획이었는데, 시간을 많이 써야 한다면 휴학도 할만한 것 같다. 학점도 그리 잘 나온 편이 아니라 오히려 솔깃했다.

상당한 압박 면접이라고 들었는데 어차피 떨어질 거라 그런 것인지, 그 반대인지는 모르겠으나 나는 꽤 편안하게 본 것 같다. 이렇게 4년의 기다림이 끝이 났다. 대단하지도 않은 이야기를 참 길게도 썼다. 모쪼록 좋은 결과가 나오길 바란다.

Comment and share

  • page 1 of 1

InJung Chung

author.bio


CTO @tenb


Seoul, Korea