▶ 개발에 있어 가장 중요한 것 : input과 output의 흐름을 파악하는 것



▶ 디렉토리명에는 괄호를 넣지말라



▶ 개발에 있어서 문제점을 파악할 때는, 데이터 흐름의 구분을 지어놓고 한 스텝씩 진행하는 방식이 요구된다.

1. 전체 데이터의 흐름에서 각 스텝을 나눈다.

2. 구문이나 환경변수 등 각 스텝에 했던 일들을 정리한다.

3. 하나하나 천천히 보면서 문제점을 파악해본다.



▶ access로그와 error 로그 보는 것을 생활화하라

데이터의 이동뿐만 아니라 어디서 에러가 나는지 집어낼 수 있다



▶ 되도록 코드를 쓰지마라

무슨 말인가하면, 같은 동작은 실행한다면 되도록 코드를 간결하게 쓰고 장황하게 쓰지않는 쪽이 좋다는 의미이다. 코드는 길어지면 길어질 수록 가독성이 떨어지고 어디에서 에러가 났는지 확인하기 어렵기 때문이다. 



▶ 개발의 기본 마인드

1.기능은 되도록 닫기(클래스나 메서드 단위별로 제한된 기능만을 갖기)
2.
메인터넌스와 코드 효율성을 증대하기 위해 확장성은 넓히기

3. 누구나 코드를 보면 이해할 수 있도록 적기




▶ 숫자나 문자열등 직접정보가 코드안에 포함되어 있으면 안되는 이유 : 수정요소가 발생할 시 그 숫자나 문자열은 사용한 모든곳을 하나하나 수정해야하는 불상사가 생길 수 있다.




▶ 부하 테스트시 포함되는 조건들

인스턴스 : aws의 인스턴스 

프로세스 : 가동된 어플리케이션의 수

스레드 : 하나의 서버에 접속한 사람수: 예를 들어 2명이서 서버 접속하면 스레드는 2개 -> 자바 스레드의 개념추가할 필요있음*



▶ ssh는 /var/empty/sshd에 의해 기동되는데, 이는 root에 의해 소유 되지 않으면 오류가 난다.
(
https://support.microsoft.com/ja-jp/help/4092816/ssh-fails-because-var-empty-sshd-is-not-owned-by-root-and-is-not-group)


/var/empty/sshd 디렉토리가 루트에 의해 소유 디어 있어야 하고, 그룹이나 특정인이 writable의 권한을 가지고 있으면 ssh가 실행되지 않는다. 따라서 아래와 같은 명령어로 이 문제를 고칠 수 있다.


chmod 755 /var/empty/sshd;chown root:root /var/empty/sshd;service sshd restart




▶ 문제가 있다면 혼자서 멍때리지 말고 로그를 봐라.

배경 : fluentd가 반응하지 않아서 혼자 설정파일 수십번 바꾸고 바보짓을 했는데, 로그보니까 금방해결 되었다. 










본글출처:https://sharryhong.github.io/2017/09/27/cs-tcp-http/


TCP와 HTTP

OSI 7 계층 모형OSI 7 계층 모형


TCP(Transmission Control Protocol)

전송 계층(Transport layer)에 위치한다.

네트워크의 정보 전달을 통제하는 프로토콜이자 인터넷을 이루는 핵심 프로토콜의 하나

웹 브라우저들이 월드 와이드 웹에서 서버에 연결할 때 사용되며, 이메일 전송이나 파일 전송에도 사용된다.

근거리 통신망이나 인트라넷, 인터넷에 연결된 컴퓨터에서 실행되는 프로그램 간에 일련의 옥텟을 안정적으로, 순서대로, 에러없이 교환할 수 있게 한다.


Transport layer

계층 구조의 네트워크 구성요소와 프로토콜 내에서 송신자와 수신자를 연결하는 통신 서비스를 제공한다.

연결 지향 데이터 스트림 지원, 신뢰성, 흐름 제어, 그리고 다중화와 같은 편리한 서비스를 제공한다.



HTTP(Hyper-Text Transfer Protocol) 

http는 application 계층에서 동작 한다. 이 계층에서 동작하는 프로토콜은 http  말고도 smtp, IMAP 등이 있다. 

개념적으로 살펴 보자면 HTTP, HTTPS, FTP 등의 프로토콜은 TCP/IP  이 위에서 동작하는 거라고 볼수ㅣ있다.

그중 http는 tcp/ip 위에서 어떤 형태로 웹에서 작동할지를 정해놓은  통신프로토콜일 뿐이다. 이 프로토콜위에서  http (하이퍼텍스트)를 전송 하는 규약)임.




데이터 형태

tcp : byte array(binary)로 정보를 통신

http: String으로 정보를 통신




연결방식

tcp : 언제나 서버와 연결되어있어야하며, request 없이도 recevie가 일어난다.

http: keep-alive로 지속적인 연결은 가능하지만 기본적으론 close로 되어 있으며, request를 하여야만 recevie가 일어난다.


CIDR(Classless Inter-Domain Routing) 표기법


CIDR표기법허용 IP
192.0.0.0/8192.0.0.0 ~ 192.255.255.255
192.168.0.0/16192.168.0.0 ~192.168.255.255
192.168.67.0/24192.168.67.0 ~ 192.168.67.255



'0/n'은 
IP주소에서 처음부터 n비트수 만큼이 네트워크 주소를 의미하고, 나머지 뒤의 비트들은 호스트 주소임을 의미합니다.

예를 들어
10.25.0.0/16 = 00001010 00011001 00000000 00000000

빨간색은 네트워크 주소, 파란색은 호스트 주소를 의미합니다. 





IP/CIDR

Δ to last IP addr

Mask

Hosts (*)

Class

Notes

a.b.c.d/32

+0.0.0.0

255.255.255.255

1

1/256 C

 

a.b.c.d/31

+0.0.0.1

255.255.255.254

2

1/128 C

d = 0 ... (2n) ... 254

a.b.c.d/30

+0.0.0.3

255.255.255.252

4

1/64 C

d = 0 ... (4n) ... 252

a.b.c.d/29

+0.0.0.7

255.255.255.248

8

1/32 C

d = 0 ... (8n) ... 248

a.b.c.d/28

+0.0.0.15

255.255.255.240

16

1/16 C

d = 0 ... (16n) ... 240

a.b.c.d/27

+0.0.0.31

255.255.255.224

32

1/8 C

d = 0 ... (32n) ... 224

a.b.c.d/26

+0.0.0.63

255.255.255.192

64

1/4 C

d = 0, 64, 128, 192

a.b.c.d/25

+0.0.0.127

255.255.255.128

128

1/2 C

d = 0, 128

a.b.c.0/24

+0.0.0.255

255.255.255.000

256

1 C

 

a.b.c.0/23

+0.0.1.255

255.255.254.000

512

2 C

c = 0 ... (2n) ... 254

a.b.c.0/22

+0.0.3.255

255.255.252.000

1,024

4 C

c = 0 ... (4n) ... 252

a.b.c.0/21

+0.0.7.255

255.255.248.000

2,048

8 C

c = 0 ... (8n) ... 248

a.b.c.0/20

+0.0.15.255

255.255.240.000

4,096

16 C

c = 0 ... (16n) ... 240

a.b.c.0/19

+0.0.31.255

255.255.224.000

8,192

32 C

c = 0 ... (32n) ... 224

a.b.c.0/18

+0.0.63.255

255.255.192.000

16,384

64 C

c = 0, 64, 128, 192

a.b.c.0/17

+0.0.127.255

255.255.128.000

32,768

128 C

c = 0, 128

a.b.0.0/16

+0.0.255.255

255.255.000.000

65,536

256 C = 1 B

 

a.b.0.0/15

+0.1.255.255

255.254.000.000

131,072

2 B

b = 0 ... (2n) ... 254

a.b.0.0/14

+0.3.255.255

255.252.000.000

262,144

4 B

b = 0 ... (4n) ... 252

a.b.0.0/13

+0.7.255.255

255.248.000.000

524,288

8 B

b = 0 ... (8n) ... 248

a.b.0.0/12

+0.15.255.255

255.240.000.000

1,048,576

16 B

b = 0 ... (16n) ... 240

a.b.0.0/11

+0.31.255.255

255.224.000.000

2,097,152

32 B

b = 0 ... (32n) ... 224

a.b.0.0/10

+0.63.255.255

255.192.000.000

4,194,304

64 B

b = 0, 64, 128, 192

a.b.0.0/9

+0.127.255.255

255.128.000.000

8,388,608

128 B

b = 0, 128

a.0.0.0/8

+0.255.255.255

255.000.000.000

16,777,216

256 B = 1 A

 

a.0.0.0/7

+1.255.255.255

254.000.000.000

33,554,432

2 A

a = 0 ... (2n) ... 254

a.0.0.0/6

+3.255.255.255

252.000.000.000

67,108,864

4 A

a = 0 ... (4n) ... 252

a.0.0.0/5

+7.255.255.255

248.000.000.000

134,217,728

8 A

a = 0 ... (8n) ... 248

a.0.0.0/4

+15.255.255.255

240.000.000.000

268,435,456

16 A

a = 0 ... (16n) ... 240

a.0.0.0/3

+31.255.255.255

224.000.000.000

536,870,912

32 A

a = 0 ... (32n) ... 224

a.0.0.0/2

+63.255.255.255

192.000.000.000

1,073,741,824

64 A

a = 0, 64, 128, 192

a.0.0.0/1

+127.255.255.255

128.000.000.000

2,147,483,648

128 A

a = 0, 128

0.0.0.0/0

+255.255.255.255

000.000.000.000

4,294,967,296

256 A

 

 

참고.
http://en.wikipedia.org/wiki/CIDR



출처: http://jjeong.tistory.com/396 [jjeong]

문법

Object.assign(target, ...sources)

인자

target
타켓 오브젝트
sources
하나 이상의 소스 오브젝트

리턴값

타겟 오브젝트

설명

소스 프로퍼티와 동일한 프로퍼티의 키를 가진 타켓 오브젝트의 프로퍼티들은 소스 오브젝트의 프로퍼티로 덮어쓰기 될 것입니다.

Object.assign() 메소드는 열거할 수 있는 소스 오브젝트의 프로퍼티들만 타켓 오브젝트로 복사합니다. 이 메소드는 소스 오브젝트 대상으로 게터를 호출하고, 타켓 오브젝트 대상으로 세터를 호출합니다.
따라서, 소스 오브젝트의 프로퍼티를 그냥 단순히 복사하거나, 새로운 프로퍼티를 생성하는 것이 아니라, 타켓 오브젝트의 프로퍼티를 게터와 세터를 이용하여 할당할 수도 있습니다.
 먄약, 병합되는 소스 오브젝트가 게터를 포함하고 있다면, 새로운 프로퍼티를 타겟의 프로토타입에 병합하는 것은 알맞지 않을 것입니다. 열거가능성을 포함한 프로퍼티를  프로토타입으로 복사하기 위해서는 Object.getOwnPropertyDescriptor() 와  Object.defineProperty() 을 사용하시기 바랍니다.

String 과 Symbol 프로퍼티 둘 다 복사될 것입니다.

프로퍼티가 쓰기불가능(non-writable) 등과 같이 만약 에러가 발생할 수 있는 상황에서는,  TypeError 가 발생하고 타겟 오브젝트에는 변화가 없을 것입니다.

Object.assign() 메소드는 null 이나 undefined 는 반환하지 않으니 주의하세요.

예제들

객체 복제하기

var obj = { a: 1 };
var copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }

깊은 복제에 대한 주의사항

깊은 복제에 대해서는 대안적인 방법을 사용할 필요가 있습니다. 왜냐하면, Object.assign()는 타겟 오브젝트에 할당을 할 때, 프로퍼티의 참조를 복사하기 때문입니다.

function test() {
  let a = { b: {c:4} , d: { e: {f:1}} }
  let g = Object.assign({},a)
  let h = JSON.parse(JSON.stringify(a));
  console.log(g.d) // { e: { f: 1 } }
  g.d.e = 32
  console.log('g.d.e set to 32.') // g.d.e set to 32.
  console.log(g) // { b: { c: 4 }, d: { e: 32 } }
  console.log(a) // { b: { c: 4 }, d: { e: 32 } }
  console.log(h) // { b: { c: 4 }, d: { e: { f: 1 } } }
  h.d.e = 54
  console.log('h.d.e set to 54.') // h.d.e set to 54.
  console.log(g) // { b: { c: 4 }, d: { e: 32 } }
  console.log(a) // { b: { c: 4 }, d: { e: 32 } }
  console.log(h) // { b: { c: 4 }, d: { e: 54 } }
}
test();

객체 병합하기

var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };

var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1);  // { a: 1, b: 2, c: 3 }, 타겟 오브젝트, 그 자체도 변화합니다.

같은 프로퍼티를 가지고 있는 객체 병합하기

var o1 = { a: 1, b: 1, c: 1 };
var o2 = { b: 2, c: 2 };
var o3 = { c: 3 };

var obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }

다른 오브젝트가 가지고 있는 똑같은 프로퍼티들은 인수의 순서에 따라 덮어 씌여질 것입니다.

심볼 타입 프로퍼티 복사하기

var o1 = { a: 1 };
var o2 = { [Symbol('foo')]: 2 };

var obj = Object.assign({}, o1, o2);
console.log(obj); // { a : 1, [Symbol("foo")]: 2 } (cf. bug 1207182 on Firefox)
Object.getOwnPropertySymbols(obj); // [Symbol(foo)]

프로토타입 체인 위에 있는 프로퍼티와 열거할 수 없는 프로퍼티들은 복사되지 않습니다

var obj = Object.create({ foo: 1 }, { // foo는 변수 obj의 프로토타입 체인 위에 있습니다.
  bar: {
    value: 2  // 변수 bar는 non-enumerable 프로퍼티입니다. 따라서 복사되지 않을 것입니다.
  },
  baz: {
    value: 3,
    enumerable: true  // 변수 baz는 그 자체도 enumerable 프로퍼티입니다. 따라서 복사될 것입니다.
  }
});

var copy = Object.assign({}, obj);
console.log(copy); // { baz: 3 }

원시 타입들은 객체로 변환될 것입니다

var v1 = 'abc';
var v2 = true;
var v3 = 10;
var v4 = Symbol('foo');

var obj = Object.assign({}, v1, null, v2, undefined, v3, v4); 
// null과 undefined는 무시될 것입니다.
// String wrapper만이 enumerable 프로퍼티를 가지고 있음을 주의하세요.
console.log(obj); // { "0": "a", "1": "b", "2": "c" }

예외는 진행중인 복사 작업을 중지시킬 것입니다

var target = Object.defineProperty({}, 'foo', {
  value: 1,
  writable: false
}); // target.foo is a read-only property

Object.assign(target, { bar: 2 }, { foo2: 3, foo: 3, foo3: 3 }, { baz: 4 });
// TypeError: "foo" is read-only
// The Exception is thrown when assigning target.foo

console.log(target.bar);  // 2, 첫 번째 소스 오브젝트는 성공적으로 복사되었습니다.
console.log(target.foo2); // 3, 두 번째 소스 프로젝트의 첫 번째 프로퍼티도 성공적으로 복사되었습니다.
console.log(target.foo);  // 1, 예외는 여기서 던져집니다.
console.log(target.foo3); // undefined, Object.assign() 메소드는 끝났습니다. 변수 foo3는 복사되지 않습니다.
console.log(target.baz);  // undefined, 세 번째 소스 오브젝트, 역시 복사되지 않습니다.

복사 접근자들

var obj = {
  foo: 1,
  get bar() {
    return 2;
  }
};

var copy = Object.assign({}, obj); 
console.log(copy); 
// { foo: 1, bar: 2 }, copy.bar의 값은 obj.bar'의 게터가 리턴해주는 값입니다.

// 이것은 모든 descriptors를 복사하는 할당 함수입니다.
function completeAssign(target, ...sources) {
  sources.forEach(source => {
    let descriptors = Object.keys(source).reduce((descriptors, key) => {
      descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
      return descriptors;
    }, {});
    // 기본적으로, Object.assign는 열거할 수 있는 Symbol도 복사합니다.
    Object.getOwnPropertySymbols(source).forEach(sym => {
      let descriptor = Object.getOwnPropertyDescriptor(source, sym);
      if (descriptor.enumerable) {
        descriptors[sym] = descriptor;
      }
    });
    Object.defineProperties(target, descriptors);
  });
  return target;
}

var copy = completeAssign({}, obj);
console.log(copy);
// { foo:1, get bar() { return 2 } }







라인과 같은 경우는 외부 url(웹훅)로 메시지를 직접 쏴준다. 즉, 라인서버가 외부에 리퀘스트를 보내면 외부에서 라인서버로 레스폰스를 해주는 일반적인 방식이다. 그러나 스카이프 비즈니스 어카운트의 경우 위와같은 플로우를 따른다.


1. login

스카이프는 유저로부터 받은 메시지를 가지고 있다가, 외부로부터 userID와 password가 요청과 들어오면, 그  userID와 password에 맞는 엑세스 토큰을 외부에 레스폰한다.


2. listen

엑세스토큰을 받은 외부서버는 엑세스 토큰으로 다시한번 스카이프에 요청하고, 그 엑세스토큰이 일치하면 드디어 메세지를 레스폰한다. 이때 외부서버는 login과 listen을 일정한 간격으로 지속적인 요청을 스카이프 서버에 보내야 하는데, 이를 pooling이라 한다.





출처 : https://blog.outsider.ne.kr/1159

웹사이트나 API 서버 등을 개발할 때 보통은 로컬에 개발환경이 구축되어 있으므로 외부에서 접근하려면 외부에서 접속할 수 있는 서버에 올리거나 해야 한다. 이는 일반적인 개발 단계이기는 하지만 배포단계가 아닌 개발단계에서 외부에 열어주어야 하는 경우에는 상당히 귀찮은 일이다. 예를 들어 만들고 있는 웹사이트를 기획자나 디자이너한테 공유해서 보여주고 의견을 들어야 한다거나 폰이나 태블릿에서 접속해서 테스트를 해보아야 하는데 같은 네트워크에 접속되어 있지 않다면 수정하고 배포하는 단계가 아주 귀찮아지기 마련이다.
→로컬 서버에 요청을 보내야 하는 작업인 경우(외부에서 로컬로 웹훅을 보내는 작업, 외부에서 로컬 웹사이트에 접속해야 하는 작업), ngrok이 필요하다!

나 같은 경우는 PageSpeed Insights로 페이지 최적화를 하려고 하는데 PageSpeed Insights가 로컬에서 돌려볼 수 없고 PageSpeed Insights가 웹사이트에 접속해서 테스트하는 방식이라서 웹사이트가 퍼블릭으로 열려있어야 한다.(전에는 개발자도구에 설치가능한 확장도 있었던 것 같은데 언젠가부터 찾을 수가 없어졌다.) 배포하기 전에 잘못된 부분을 모두 수정한 다음에 배포하고 싶었는데 개발은 로컬에서 하고 있으므로 가능한 방법을 찾기 시작했다. 그 외에도 소셜 로그인을 테스트하는 등 외부 서비스가 로컬에서 개발중인 웹 애플리케이션을 호출해야 하는 경우에도 이러한 요구사항이 필요하다.

ngrok

ngrok 사이트에는 Secure tunnels to localhost라고 나와 있는데 새로운 개념이라기보다는 방화벽 넘어서 외부에서 로컬에 접속 가능하게 하는 터널 프로그램이라고 할 수 있다. 이런 프로그램이 ngrok뿐인 것은 아니지만, 위에서 설명한 상황에서 유용하게 쓸 수 있게 최적화되어 있어서 아주 쉽게 사용할 수 있다.

ngrok이 방화벽을 넘어 동작하는 구성도

이미지 출처: https://ngrok.com/

ngrok 사이트에서 Mac, Linux, Windows 프로그램을 제공하고 있다. Mac이나 Linux 같은 경우는 쉘 스크립트를 받아서 자신의 PATH아래 넣으면 다음과 같이 커맨드라인 명령어를 사용할 수 있다.

Bash
ngrok
NAME:
   ngrok - tunnel local ports to public URLs and inspect traffic

DESCRIPTION:
    ngrok exposes local networked services behinds NATs and firewalls to the
    public internet over a secure tunnel. Share local websites, build/test
    webhook consumers and self-host personal services.
    Detailed help for each command is available with 'ngrok help <command>'.
    Open http://localhost:4040 for ngrok's web interface to inspect traffic.

EXAMPLES:
    ngrok http 80                    # secure public URL for port 80 web server
    ngrok http -subdomain=baz 8080   # port 8080 available at baz.ngrok.io
    ngrok http foo.dev:80            # tunnel to host:port instead of localhost
    ngrok tcp 22                     # tunnel arbitrary TCP traffic to port 22
    ngrok tls -hostname=foo.com 443  # TLS traffic for foo.com to port 443
    ngrok start foo bar baz          # start tunnels from the configuration file

VERSION:
   2.0.19

AUTHOR:
  inconshreveable - <alan@ngrok.com>

COMMANDS:
   authtoken  save authtoken to configuration file
   credits  prints author and licensing information
   http   start an HTTP tunnel
   start  start tunnels by name from the configuration file
   tcp    start a TCP tunnel
   test   test ngrok service end-to-end
   tls    start a TLS tunnel
   update update to the latest version
   version  print the version string
   help   Shows a list of commands or help for one command


ngrok 사용방법

위 도움말에서 나오듯이 가장 많이 사용할 HTTP 서버를 외부에 열고자 하면 ngrok http 3000과 같이 실행하면 로컬의 3000 포트 즉, 127.0.0.1:3000을 ngrok 도메인과 연결해서 터널을 열어준다.

C-like
ngrok by @inconshreveable                                                                                              (Ctrl+C to quit)

Tunnel Status      online
Version            2.0.19/2.0.19
Web Interface      http://127.0.0.1:4040
Forwarding         http://7eb69b3e.ngrok.io -> localhost:3000
Forwarding         https://7eb69b3e.ngrok.io -> localhost:3000

Connections        ttl     opn     rt1     rt5     p50     p90
                   0       0       0.00    0.00    0.00    0.00

터미널 창 전체가 ngrok의 접속 상태를 알 수 있는 대시보드처럼 나온다. 앞에서 3000포트를 지정했으므로 http://7eb69b3e.ngrok.io나 https://7eb69b3e.ngrok.io로 접속하면 로컬의 http://127.0.0.1:3000로 접속을 연결해 준다. 로컬에서 간단히 웹 어플리케이션을 띄어놓고 ngrok로 연결한 뒤 바로 ngrok 주소를 공유하면 같은 네트워크가 아니더라도 어디서나 접근할 수 있다.

터미널에서 ngrok을 실행한 화면

접속할 때마다 하단에는 접속로그가 나타나고 개발 시에는 별로 중요하진 않지만, 평균 연결 시간도 알 수 있다. 간단한 명령어로 바로 로컬에서 개발 중이던 웹 애플리케이션을 공개로 열 수 있어서 최근에 애용해서 사용하고 있다. 앞에서 얘기한 PageSpeed Insights나 W3C Markup Validation같은 경우로 ngrok로 열어서 URL을 입력하면 소스를 수정하면서 바로 결과를 확인할 수 있어서 최근에 애용하고 있다.

이 외에도 tcp 접속에 터널을 만들거나 다양한 옵션이 존재하지만, 너무 많아서 아직은 기본 설정만 사용하고 있다. 그리고 ngrok은 유료 서비스라서 서브도메인이나 호스트 명을 지정하려면 유료 플랜을 사용해야 하지만 이런 요구사항 없이 간단하게 터널링을 사용하는 것은 무료플랜 뿐만 아니라 가입을 하지 않아도 사용할 수 있다. 설정파일을 만들어 놓고 사용하는 방법은 문서만으로는 서브도메인 등을 사용하지 않으면 무료 플랜에서도 사용할 수 있어야 하는데 여러 가지로 설정해 봐도 계속 subdomain은 유료플랜에서만 가능하다고 오류가 나와서 아직 설정파일은 쓰지 못하고 있다. 실행명령어가 간단해서 크게 상관은 없다.

대시보드

앞에서 터미널에도 접속 로그 등을 볼 수 있었지만(-inspect=false옵션을 주면 로그가 남지 않는다.) 실행하면 자동으로 웹에서 로그나 상태를 볼 수 있는 대시보드가 http://127.0.0.1:4040에 실행된다. 단순 개발할 때는 크게 필요하진 않아 보이지만 터미널 사용이 익숙지 않다면 웹으로 보는 것도 나쁘지 않다.

ngrok 웹 대시보드의 inspect 화면

Inspect 화면에서 접속로그를 모두 볼 수 있다.

ngrok 웹 대시보드의 status 화면

Status 화면에서는 실행된 ngrok의 설정옵션과 접속 속도 등을 확인할 수 있다.

Redis 入門(http://mayo.hatenablog.com/entry/2013/10/15/074237)

  

f:id:mayo_yamasaki:20131015074224p:plain

Redis 使うことになったので,基礎的事項を最速でマスターできるようにまとめてみる.

Redis とは

Redisは,Key-Value型のNoSQLです.
また,In Memory であるため,データ容量に対する制限はあるものの非常に高速に動作します.

どのくらい早いのかという benchmark は,ググると結構でてくると思いますので,参考を一つ.
redis、それは危険なほどのスピード

MongoDB, HBaseなどのNoSQLとの,比較記事があるので参考に.
Cassandra vs MongoDB vs CouchDB vs Redis vs Riak vs HBase vs Couchbase vs Neo4j vs Hypertable vs ElasticSearch vs Accumulo vs VoltDB vs Scalaris comparison

細かい話などは,redisドキュメント日本語訳などを参考に.


Redis Install

環境は Mac OS X を想定しています.今回は,Homebrewを使ってInstallします.

brew install redis

Install が終わると,下記のようなコマンドが使えると思います.

/usr/local/bin/redis-server
/usr/localbin/redis-cli


Redis 入門

まず,Redis の特徴として,データ構造が多彩なことが上げられます.

  • String
  • List
  • Set
  • Sorted Set
  • Hash

Sorted Set は,UniqなListのようなモノです.

起動と終了

Redis Server と,CUIのClientの起動と終了.

# redis server の起動
# 終了には C-c を使います.
$ redis-server


# redis client の起動
$ redis-cli

# redis client の終了
> exit
# 内容をdumpして終了
> shutdown

defaultでは,カレントディレクトリの ./dump.rdb に保存されます.

基本的操作

データベースの選択

Redisのデータベースは 0, 1, 2...の様な整数値のindexを持っていて,これを用いてデータベースの切り替えを行います.

> select INDEX

# default では 0 になっていて,1を選択するのであれば,下記のようになります.
> select 1
ok
[1]>
データの保存
> bgsave
データのSetとGet
# データのSet
> set KEY VALUE

# データのGet
> get KEY

# Example
> set hoge hello
ok
> get hoge
"hello"

また,複数個のデータの束縛や取得は,次のようにできる.

> mset KEY VALUE KEY VALUE
> mget KEY VALUE KEY VALUE

# Example
> mset a 1 b 2 c 3
OK
> mget a b c
1) "1"
2) "2"
3) "3"
key の表示
# 全ての key を表示
> keys *

keyが存在するかを調べる

> exists KEY

# Example
> set X 10
ok
> exists X
(integer) 1
> exists Y
(integer) 0
keyの削除
del KEY
データ型を調べる
> type KEY

# Example
> set hoge hello
ok
> type hoge
string


データ構造

String

Set, Get で束縛,取得することができる基本的な型.
数値文字の操作も可能.

# Increment
> incr KEY
> incrby KEY NUMBER

# Decrement
> dicr KEY
> dicrby KEY NUMBER

# Example
> set x 10
ok
> incr x
(integer) 11
> dicrby x 10
(integer) 1
List
# 要素の追加
> lpush KEY VALUE # 左から
> rpush KEY VALUE # 右から

# 要素の取り出し
> lpop KEY VALUE
> rpop KEY VALUE

# 要素の表示
# 表示したい区間の index (0, 1, 2...) を指定する
> lrange KEY START END

# N番目の要素を表示
> lindex KEY N

# N番目の要素を更新
> lset KEY VALUE

# Listの長さを取得
> llen KEY

# 任意の区間を取得
> ltrim KEY START END


# Example
> rpush list 1
(integer) 1
> rpush list 2
(integer) 2
> lpush list 0
(integer) 3
> lrange list 0 -1
1) "0"
2) "1"
3) "2"
> lset list 1 New
ok
> lrange list 0 -1
1) "0"
2) "New"
3) "2"
Set

要素の集合.

# 要素の追加
> sadd KEY VALUE

# 要素の削除
> srem KEY VALUE

# 要素の表示
> smembers KEY

# 和集合
> sunion KEY KEY

# 積集合
> sinter KEY KEY

# 差集合
> sdiff KEY KEY


# Example
> sadd seta a
> sadd seta b
> sadd setb c
> sunion seta setb
1) "a"
2) "c"
3) "b"
Sorted Set

ソート済みのセット

# 要素の追加
> zadd KEY VALUE

# 要素の削除
> zrem KEY VALUE

# 要素の表示
> zrange KEY START END # 昇順
> zrevrange KEY START END # 降順 
Hash

Key-Value の辞書型.

# 要素の束縛
hset KEY FIELD VALUE

# 要素の取得
hget KEY FIELD

# Example
# hmset, hmgetで一括の束縛と取得が可能
> hmset dic a hoge b fuga
> hget dic a
"hoge"


Python から使う

Python からの使い方の紹介.
redis-py を使う.

redis-py の install

sudo pip install redis

Example (README.md からの引用)

>>> import redis
>>> r = redis.StrictRedis(host='localhost', port=6379, db=0)
>>> r.set('foo', 'bar')
True
>>> r.get('foo')
'bar'

最後に

雑な感じですが,以上です.
さっき始めたところなので,間違いがあるかもしれません.



[레디스 개념 및 특징]


Redis도 약자이다(REmote DIctionary Server)

Salvatore Sanfilippo라는 이탈리아 해커가 MySQL로 어떤 어플을 개발하다가 느려터졌다고 생각했고, 

직접 빠른 서버를 만들어봐야겠다고 생각했고, 

그 결과 Redis를 개발하게 되었다는 비하인드 스토리...


이 인간


[레디스 특징


1. 오픈 소스 소프트웨어고,

2. 디스크가 아닌 메모리 기반의 데이터 저장소이다. (In-Memory data structure store) 

3. NoSQL & Cache 솔루션이며 메모리 기반으로 구성된다.

4. 명시적으로 삭제, expire를 설정하지 않으면 데이터는 삭제되지 않는다(영구적 보존)

5. 여러대의 서버 구성 가능하다.

6. 데이터베이스로 사용될 수 있으며, Cache로도 사용될 수 있는 기술이다.

7. 성능은 서버에 따라 다르나 초당 2만 ~ 10만회 수행한다. 


Memory 위에서 동작하는 Key/value 저장소(Store)인 레디스는 NoSQL DBMS로 분류되며 동시에 Memcached와 같은 인메모리(In-memory) 솔루션으로 분리된다. 

성능은 Memcached이 갖고 있는 좋은점을 기반으로 만들어졌기 때문에 Memcached보다 우수하긴하지만 더욱 복잡하며, 다양한 데이터 구조체를 지원하기 때문에 Message Queue, Shared memory, Remote Dictionary 용도로 사용될 수도 있다. 

대부분의 언어를 사용할 수 있지만, Linux를 이용하기를 권장하고 있다.

그리고, 안전한 데이터의 보관과 백업을 위해 두 가지 방법을 제공한다.


1. 다른 서버의 메모리에 실시간으로 복사본을 남길 수 있다. 

2. 디스크에 직접 저장하는 방법도 존재한다.


NoSQL 중에서도 Redis가 주목을 받는 이유는 다음과 같다.

- 데이터 저장소로 입력/출력이 가장 빠른 메모리를 채택.

- 단순한 구조의 데이터 모델인 Key-Value 방식을 통해 빠른 속도.

- 캐시 및 데이터 스토어에 유리.

- 다양한 API 지원.


Redis는 페이스북, 인스타그램, 네이버 LINE 서비스, StackOverflow, 블리자드 등 대형 서비스 없체들이 사용자들의 대규모 메세지를 실시간으로 처리하기 위하여 사용하고 있다.


※인메모리 캐시(In-memory Cache)란?


메모리 캐시 기반의 제품이 많은 시스템에서 사용되는 이유는 단연 성능!!!

캐시 방식을 통해 DB Read의 부하를 감소할 수 있기 때문이다.

서비스 요청이 증가하여 DB요청이 많아지면 DB서버 부하가 증가하게 되는데 메모리 

캐시가 적용되면 성능 및 처리속도가 향상된다.


[레디스 장점]


1. 리스트, 배열과 같은 데이터를 처리하는데 유용하다.

 - value 값으로 문자열, 리스트, Set, Sorted set, Hash 등 여러 데이터 형식을 지원.

 - 따라서 다양한 방식으로 데이터를 활용할 수 있다. 

 - 리스트형 데이터 입력과 삭제가 MySQL에 비해서 10배정도 빠르다고 한다.

 - 

2. 여러 프로세스에서 동시에 같은 key에 대한 갱신을 요청할 경우,

   Atomic 처리로 데이터 부정합 방지 Atomic처리 함수를 제공(뭔 소린지 모르겠다...)


3. 메모리를 활용하면서 영속적인 데이터 보존

 - 명령어로 명시적으로 삭제, expires를 설정하지 않으면 데이터가 삭제되지 않는다.

 - 스냅샷(기억장치) 기능을 제공하여 메모리의 내용을 *.rdb 파일로 저장하여 해당 시점으로 복구할 수 있다.


4. Redis Server는 1개의 싱글 쓰레드로 수행되며, 따라서 서버 하나에 여러개의 서버를  

   띄우는 것이 가능하다.

 - Master - Slave 형식으로 구성이 가능함

 - 데이터 분실 위험을 없애주는 것이 바로 위 Master - Slave 방식이다.



위 기능을 이용하면 실시간으로 데이터를 다른 서버에 복제한다. 

즉, Master server가 down되어도, slave server로 접속하면 바로 서비스를 계속할 수 있다.

그리고 레디스의 성능을 거의 떨어뜨리지 않고 디스크 쓰기 기능을 제공한다. 

레디스 시작 시 이 데이터를 읽어 들어므로 데이터 분실 위험은 거의 없다고 봐도 된다.


5. Redis에는 5가지의 데이터형을 사용할 수 있다.

 - String

 - Lists

 - Sets

 - Sorted sets

 - Hashs



다음 블로그에서...



[참고 사이트]


http://ojava.tistory.com/70

http://bcho.tistory.com/654

http://mydb.tistory.com/210

http://redis.io/documentation

http://crystalcube.co.kr/176 



출처: http://codingmania.tistory.com/18 [개발새발하는 개발]

+ Recent posts