스프링프레임워크를 사용해서 Restful API를 개발할때, RequestHeader 정보를 가져오는 방법이다.

요즈음에 대세가된 SpringBoot를 이용할 경우에 다른 설정은 크게 필요하지는 않다.

 

"@RestController"를 이용하여, 컨트롤러를 선언해주고, "@GetMapping" 어노테이션을 이용하여, "http://localhost:8080/headerinfo" 라고 호출하였을때, 실행되도로 정의했다. 이때 호출되는 RequestHeader값은 "@RequestHeader" 어노테이션을이용하여 "headers"라는 변수를 통해서 넘겨받을 수 있다.

package net.happyzoo.happzoo;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

import java.util.Map;

@SpringBootApplication
@Slf4j
public class HappzooApplication {

@RestController
public static class GetControllerPractice
{
@GetMapping("/headerinfo")
Mono<Map<String, String>> getHeaderInfo(@RequestHeader HttpHeaders headers)
{
log.info(headers.toSingleValueMap().toString());

return Mono.just(headers.toSingleValueMap());
}

}


public static void main(String[] args) {
SpringApplication.run(HappzooApplication.class, args);
}

}

위는 Sample 코드이며, Lombok을 이용하여 @Slf4j를 선언해주면, 로그를 남길수 있도록 했는데, Lombok를 사용하지않으면, 선언에서 제외하면 된다.


실행 결과는 다음과 같이 Map의 형태로 반환해서 Mono로 전달하면 Client에서 결과값을 받을수 있다.

return Mono.just(headers.toSingleValueMap());


Terminal에서는 

  curl -X GET http://localhost:8080/headerinfo

와 같이 명령을 실행해서 호출하거나, Chrome 브라우져에서 실행해보면 확인할 수 있다.

IntelliJ에 내장된 Rest Client를 이용해서 호출한 결과이다. Json의 Object형태로 결과를 받아왔다.





WRITTEN BY
행복상자
행복한 마음으로 매일을 살고 싶은 개발자 입니다.

트랙백  0 , 댓글  0개가 달렸습니다.
secret

VS Code는 회사에서도, 집에서도 많이 사용하는 IDE이다.

오늘은 간단하게 테스트할 것이 있어서 띄웠는데, MacOS에는 nodeJS가 설치가 되어 있지 않았다.

간단하게, "nodeJS"를 설치하고, 내친김에 Express를 설치하려고 한다.


NodeJS는 "https://nodejs.org/ko/" 또는 "https://nodejs.org/en/" 에서 다은 받아 설치하면, 된다. 
브로우저가 설치되어 있는 OS에 따라서 다운해서 설치할 바이너리가 달라진다. 



위 화면에 두개의 버전이 있는데, "10.14.2 LTS" 버전을 설치하기로 한다.

윈도우즈와 MacOS 버전 모두 바이너리 버전으로 설치하기 때문에, 다운 받아서 실행하면 바로 설치가 가능하다. (다른 방식으로 cli 명령으로 설치도 가능한데, 오늘은 쉽게 가기로 한다.)


설치가 완료되었으면, 설치 버전을 확인해 본다. nodeJS설치할때 같이 설치되는 패키지 매니져인 npm의 버전과 nodeJS의 버전을 아래과 같이 확인해 본다.

mymac$ npm -v

6.4.1

mymac$ node -v

v10.14.2


이번에는 nodeJS를 이용하여 웹을 개발할때 사용하는 Express 라는 Framework을 설치할 차례다.

Express는 "https://expressjs.com/ko/starter"에 나오는 순서대로 설치하면 된다.


아래와 같이 npm을 이용하여 express 패키지를 설치한다.  만약 설치시 권한문제로 설치가 단되면 sudo 명령을 사용해서 "sudo npm install express"와 같이 실행하면 된다.

mymac$ sudo npm install express

...


mymac$ sudo npm install express-generator -g 

...


자 이제 마지막으로, express를  이용하여 web 프로젝트를 생성해 본다.

아래의 "- e" 옵션은 templet엔진을 "ejs"를 사용하겠다는 옵션이다.

mymac$ express -e showdata

   create : showdata/

   create : showdata/public/

   create : showdata/public/javascripts/

   create : showdata/public/images/

   create : showdata/public/stylesheets/

   create : showdata/public/stylesheets/style.css

   create : showdata/routes/

   create : showdata/routes/index.js

   create : showdata/routes/users.js

   create : showdata/views/

   create : showdata/views/error.ejs

   create : showdata/views/index.ejs

   create : showdata/app.js

   create : showdata/package.json

   create : showdata/bin/

   create : showdata/bin/www


프로젝트가 생성이 되었으면 실행을 해보자.

아래와 같이 "showdata" 디렉토리로 이동해 들어가서, npm을 이용하여 기본 패키지를 설치하고, "npm start" 명령으로 서버를 동작시킨다.

mymac$ cd showdata

mymac$ npm install

mymac$ npm start


기본 포트는 3000번 포트를 사용하므로, 브라우저에서 "http://localhost:3000"을 치면 다음과 같은 화면이 나타나게 된다. 


만약, 실행 포트를 바꾸고 싶다면, "showdata/bin/www" 파일을 열어서 변경하면 된다.


 


  


 


WRITTEN BY
행복상자
행복한 마음으로 매일을 살고 싶은 개발자 입니다.

트랙백  0 , 댓글  0개가 달렸습니다.
secret

아주 오래전(약 2년 6개월전)에 글을 쓰기는 했는데, 마무리 짓지 못했던 글인데, 요즘은 await과 async 키워드를 통해서 자연스럽게 사용하고 있어서 필요가 없을 수 있다. 이전에 내부에 Timer와 간단한  Queue를 만들어서  batch 작업을 수행하는데 사용했었다. 


(Async와 Awat 키워드를 사용하거나, Promise를 이용해서 제어하는 것이 아래 방식보다는 훌륭하다.)


Node Js를 이용하여, 개발할 경우에 싱글 쓰레드가 하나의 CPU Core에서도 자연스럽고 부드럽고 너무도 가볍게 동작하는 것을 보고 놀랐었다.

I/O에 대한 Blocking 문제를 자체적으로 처리해주는 똘똘한 녀석이라고, 자랑스러워하였지만, Callback hell이라고 불리우는 지저분해지는 코드는 또다른 문제를 안겨주기도 한다. 


개인적으로는 시각적으로 가독성이 떨어지는 코드는 좋아 하지 않기 때문에, 머신의 성능이 보장해주는 한도에서 가능하면 가독성이 좋고, 이해하기 좋은 코드를 쓰는 것을 좋아한다.

그리고, 리펙토링을 꼭 해서 좀 더 중복을 없애고, 보기 좋은 짜임새 있도록 만들고는 혼자 좋아라 한다.


Node Js의 Callback 함수 호출은 굉장히 개발을 쉽게 해주기도 하지만, 중첩된 콜백과 이벤트 방식으로 인해 사용하기가 쉽지 않다. 오히려 UI가 있는 Visual Basic은 event호출에 의한 callback 함수가 UI 개발에 직관성을 높이고 코드를 분리해 줄수 있지만, 스크립트와 같은 순차적인 작업은 불편하기 짝이 없다.


이때문에 node Js에서는 Sync함수들을 별도로 제작해서 제공하고 있는 것으로 보인다.

(→ node의 file system과 관련된 라이브러리 참고: https://nodejs.org/api/fs.html)


아래는 개인적으로 이러한 환경에서 사용할 수 있는 non-sync 환경에서 Timer를 이용한 간단한 Queue 방식으로 실행할 수 있는 코드이다. 예를 들명 파일에서 라인별 데이터를 읽어 들이고, 이을 Mysql과 같은 DB에 쿼리를 실행하여 데이터를 저장하거나, 반대로 데이터를 읽고 이를 분석하는 기능을 동시에 실행할 경우에 이용할 수 있다. 


var count = 10;
var queue = [];

for(var i = 0; i < 3; i++)
{
    queue.push(i+5);
}

var tid = setInterval(function() {
    if(count == 0){
     if(queue.length > 0){
            console.log("queue: " + queue.length )
          count = queue.shift();
            return;
        }

        clearInterval(tid);
    }

console.log("count " + count--);
}, 1000);



WRITTEN BY
행복상자
행복한 마음으로 매일을 살고 싶은 개발자 입니다.

트랙백  0 , 댓글  0개가 달렸습니다.
secret

Azuer와 AWS의 가상화된 인스턴스에서는 잘 동작하던 코드가, 사내 또는 특별한 환경에서 동작하지 않을 때가 있는데, 이경우는 보안 강화를 위해 설정된 방화벽과 Proxy 서버를 통해서 외부로 나가는 Traffic의 통제를 받기 때문일 것이다.


node js의 패키지를 설치를 위해서 사용하는 NPM을 사용할 때도 Proxy의 영향을 받아서 Repository에서 다운받을 패키지 설치가 원활하지 않을 수 있을때 다음과 같이 CLI상에서 명령을 실행하여 해결할 수 있다.


예로 proxy 서버의 주소가 '192.168.10.1' 이고 Port가 8080이라고 할때, 다음과 같이 실행하면 된다.

(이미 npm과  nodejs가 설치 되어있는 환경에서 실행)


   npm config set proxy http://192.168.10.1:8080

   npm config set https-proxy http://192.168.10.1:8080

   npm config set strict-ssl false


가장 마지막에 있는 strict-ssl은 HTTP Strict Transport Security(HSTS)를 사용하여 항상 HTTPS  프로토콜을 사용하도록 강제하기 위한 옵녓인데, 여기서는 False로 설정했다. 





WRITTEN BY
행복상자
행복한 마음으로 매일을 살고 싶은 개발자 입니다.

트랙백  1 , 댓글  0개가 달렸습니다.
secret

지난 몇개월동안 내가 제일 많이 이용하는 Editor는 "Eclipse" 도 아니고 "Visual Studio" 도 아닌 바로 MS의 "Visual Studio Code" 라는 Editor이다. 정식으로 1.0 버전이 아닌데도, Mac, Window PC 할 것 없이 설치해서 사용해 왔다. 

"Vi"나 "Ultra Editor" 만큼 가볍고, 사용하기 좋은 Editor...는 아니지만, 사실 "Vi" 보다는 무겁고, "Ultra Editor"보다는 많이 가볍다. 

빠른 기능 개발에 따른 버전 업그레이드는 타의 추종을 불허할 만큼 빠르게 진행되어 왔다. 더군다나, Edior 개발은 "Eclipse"를 개발해 왔던, 에릭 감마의 참여는 많은 부분들을 기대하게 만들었고, 어떤 부분들은 "Eclipse를 많이 닮았다"라고 생각하게 만들었다. (특히 단축키에서 )


이전에 Visual Studio의 코드의 일부를 오픈 소스로 재단에 기부하면서, 초기 버전으로 사용 되었던 이름은 "Code" 였었는데, 언제 부터인가 설치시에 "Visual Studio Code"로 바뀌었다.  더군다나, "Node JS"와 "NPM"이 윈도우즈 설치 버전에는 기본적으로 설치되어 있어서, Node JS를 공부하기 좋았다. (디버깅 기능도 제공된다.)


이렇게 바로 어제까지도 베타 버전을 사용하고 있었는데, 오늘 드디어 "Visual Studio Code"가 공식적으로 "1.0" 버전을 릴리즈 하게 되었다.


"Code"는 사용하기도 쉽지만 정말 가볍고, 필요한 Plug-in과 Extension들이 많이있어 사용하기가 편하고, 필요한 단축키들에 대해서 User가 직접적으로 수정하거나, 생성도 가능하다. 이번에 1.0 버전이 되면서 좋은 것은 "한글화"인데, 이전까지는 영문 버번으로만 만났었다. 

사용하는데는 영문 버전도 별로 불 편함이 없기는 하였지만, 이는 더 많은 한글화를 지원할 거라는 생각을  갖게 만들어 준다. 그러나 아직 "Editor"상에서의 한글 입력은 좀 불편하다. 입력시 잔상(?)이 남고, 커서의 위치도 입력하는 문자열이 중첩되는 것처럼 보여, 위치가 정확하지 않아 보인다. 그러나, 입력후 스페이스나 엔터키를 입력하면, 바로 정상화 되어 사용 못할 정도는 아니다.


관련된 세부 내용은 다음의 링크를 참고하면 된다.

- Visual Studio Code 1.0발표 : https://code.visualstudio.com/blogs/2016/04/14/vscode-1.0

- Visual Studio Code : https://code.visualstudio.com/

- Extension Market Place : https://marketplace.visualstudio.com/vscode


아래는 현재 가장 인기있는 Extension들이다.





WRITTEN BY
행복상자
행복한 마음으로 매일을 살고 싶은 개발자 입니다.

트랙백  0 , 댓글  2개가 달렸습니다.
  1. 좋은 정보 잘보고 갑니다
secret

회사에서 요구하는 자격조건을 만족시키기 위해서 알고리듬을 공부해야한다.

공부하는 것은 싫어하지는 않지만, 그동안 내가 개발에 필요한 알고리듬은 천재적인 어떤 사람들이 만들어 놓은 Library를 이용하는 된다고 생각해서, 만들어 놓을 것을 잘 파악해서 내가 필요한 곳에 적절하게 사용하면 된다라고 생각해 왔고, 이러한 나의 생각은 지금까지도 변함이 없다.

그런데, 대학 생활 이후로는 크게 관심을 가지지 않았었는데, 다시 되집어 가면서 보아야 하는 상황이 나에게 왔다. 

뭐, 그래도 즐기면서 하면되니까, 즐겁게 하련다.


아래의 코드는 "창의적 알고리듬"에 나오는 코드인데, 이를 조금 개선해 보았다.

코드는 다음과 같다. (코드는 짦기 때문에 따로 설명하지 않았다.)

[코드 1: 개선전]

#include "stdafx.h"

#include <stdlib.h>

#include <time.h>


int n, S[100000];


void print_array()

{

for (int i = 0; i < n; i++)

{

printf("%d ", S[i]);

}

printf("\n");

}


void swap(int ai, int bi)

{

int t = S[ai];

S[ai] = S[bi];

S[bi] = t;

}


void selection_sort(void)

{

for (int i = 0; i < n; i++)

{

for (int j = i + 1; j < n; j++)

{

if (S[i] > S[j])

{

swap(i, j);

}

}

}

}


void selection_sort(void)

{

int idx = 0;


for (int i = 0; i < n; i++)

{

idx = i;

for (int j = idx + 1; j < n; j++)

{

if (S[idx] > S[j])

{

idx = j;

}

}

swap(idx, i);

}

}


int main()

{

srand(time(NULL));

scanf("%d", &n);


for (int i = 0; i < n; i++)

{

S[i] = rand();

}


int start = clock();

selection_sort();


printf("result=%.3lf(sec)\n", (double)(clock() - start) / CLOCKS_PER_SEC);

    

print_array();

return 0;

}


아래 코드는 위 코드에서 swap함수를 호출하는 부분에서 비교 결과에 대한 array index값을 변수에 저장하여 swap()함수의 호출수를 줄였다. (아래 "코드 2"의 붉은 박스 부분 참조)

[코드 2: 개선후]

#include "stdafx.h"

#include <stdlib.h>

#include <time.h>


int n, S[100000];


void print_array()

{

for (int i = 0; i < n; i++)

{

printf("%d ", S[i]);

}

printf("\n");

}


void swap(int ai, int bi)

{

int t = S[ai];

S[ai] = S[bi];

S[bi] = t;

}



void selection_sort2(void)

{

int idx = 0;


for (int i = 0; i < n; i++)

{

idx = i;

for (int j = idx + 1; j < n; j++)

{

if (S[idx] > S[j])

{

idx = j;

}

}

swap(idx, i);

}

}


int main()

{

srand(time(NULL));

scanf("%d", &n);


for (int i = 0; i < n; i++)

{

S[i] = rand();

}


int start = clock();

selection_sort2();


printf("result=%.3lf(sec)\n", (double)(clock() - start) / CLOCKS_PER_SEC);

    

print_array();

return 0;

}

PC의 성능에 따라 다르겠지만, 코드를 실행하여, 100개에 대해서는 거의 같은 성능을 보이나, 1000개 이상에서는 성능차이가 보인다.

내 PC에서 1000개에 대해 소팅을 실행할 경우에, 
"[코드 1]"은 0.013초가 결렸고, "[코드 2]"는 0.002초로 걸린다. 약 6배정도 "[코드 2]"가 빠른 결과를 가져온다고 볼수 있다.

   



WRITTEN BY
행복상자
행복한 마음으로 매일을 살고 싶은 개발자 입니다.

트랙백  0 , 댓글  0개가 달렸습니다.
secret

최근에 AWS와 node.js를 이용하여, 프로젝트를 진행하고 있다.

이전에 Azure룰 개인적으로 이용하곤 했는데, AWS는 실제 개발과 운영의 업무가 나누어져 있어서 나는 누군가가 만들어준 인스턴스를 이용하기만 하였지, 직접 하나 하나 건들일 일이 없었다. 

그런데, 지난 1월 7일에 Amazon 한국 리젼이 오픈을 하게되면서, 나도 개인 계정을 만들어 인스턴스를 생성하고, 몇몇 기능들와 서비스들을 이용해 보고 있다. 

최근에는 S3에 파일을 업로드 하거나, 다운 받는 코드를 AWS Lambda를 이용해서 실행하도록 만들었는데, Lambda는 AWS의 S3로 새로운 파일을 올리거나 받을때, 이벤트에 따라 필요한 코드를 실행할 수 있도록 도와주는 기능인데, 따로 서버를 운영하지 않아도(돈을 아낄수 있어서 좋다.) 된다.


아래는 AWS S3로 mytest.txt라는 파이을 zlib를 이용하여 압축을 한후에, S3로 업로드하는 

코드이다.

var AWS = require('aws-sdk');

AWS.config.loadFromPath('./config.json');


var s3 = new AWS.S3({ region: 'ap-northeast-2' }); 

var fs = require('fs');

var zlib = require('zlib');


var body = fs.createReadStream('C:/mytest.txt').pipe(zlib.createGzip());

var s3obj = new AWS.S3({params: {Bucket: 'seoulbucket9999', Key: 'myKey.zip'}});

s3obj.upload({Body: body}).

  on('httpUploadProgress', function(event) { console.log(event); }).

  send(function(err, data) { console.log(err, data) });


간략하세 설명을 하면  첫줄의 'var AWS = require('aws-sdk');'는 aws-sdk 패키지를 npm을 이용해서 설치한 후에 실행할때 넣어주면 된다. 

명령은 다음과 같다.  (사용을 위해서는 윈도우와 리눅스 또는 맥에 node와 npm 패키지가 이미 설치 되어져 있어야 한다.)

npm install aws-sdk

그리고,  'AWS.config.loadFromPath('./config.json');' 는 S3에 필요한 Access-key와 secret key를 별도의 config파일에 저장해서 가져오는 기능이다. 


마지막으로 아래의 코드는 로컬에 있는 mytest.txt 파일을 zlib를 이용하여 압축해서 S3에 올리는 코드이다. 

var body = fs.createReadStream('C:/mytest.txt').pipe(zlib.createGzip());

var s3obj = new AWS.S3({params: {Bucket: 'seoulbucket9999', Key: 'myKey.zip'}});

s3obj.upload({Body: body}).

  on('httpUploadProgress', function(event) { console.log(event); }).

  send(function(err, data) { console.log(err, data) });



WRITTEN BY
행복상자
행복한 마음으로 매일을 살고 싶은 개발자 입니다.

트랙백  0 , 댓글  0개가 달렸습니다.
secret

오늘 오랜만에 Grails.com을 둘러 보았더니, Grails 2.3의 Async Support에 관련된 글이 올라왔다.

아마도 Grails 2.2에서 부터 지원하기 시작한 Suvlet 3.0의 async API에 대한 지원에 대한 것이라 관심있게 읽게 되었다. 읽다 보니 Grails의 기능 제공 보다는 Servlet 3.0에서 추가된 기능들에 대해서 알아봐야겠다는 생각이 들어 몇몇 사이트를 보면서 아래와 같이 정리하였다.

자료들을 찾다 보니, Servlet 2.5에서도 이미 제공하고 있었지만, 서버 vernder들의 상이한 기능제공으로 인해 사용하기에 적합하지 않은 부분들이 있었다고 한다. 그러나 3.0에서는 이러한 혼란 스러운 부분들이 제거되어 제공하게 되었다. Servlet 3.0은 2009년도 12월에 발표가 되었다.


[Servlet 3.0 변경사항]

배경을 약간 설명하게 되면, 기존의 Web Technology는 클라이언트(Web Browser)와 서버간의 전형적인 Request-Response 모델을 따르도록 설계되어 있었다. 이러한 구조는 Web 2.0이라는 기술적인 Trand가 변함에 따라서 작지만 많은 Request들을 연속적으로 Server에 요청을 하게 되고 이로 인한 지연과 성능적인 측변에서의 변화를 이끌어 내게 되었다. 

Servlet 3.0의 특징으로는 java web application을 위해서 3가지 configuration옵션을 제공한다. Annotation, API 그리고 Xml이용해서 configuration 변경이 가능하다. 


다음은 주요 기능들의 요약이다.


1. Annotations 추가:  기존 web.xml에서 제공하던 기능을 Annotation을 통해서 제공

- @WebServlet

- @WebListener

- @WebFilter

위 3개는 스프링 프레임워크 등을 사용해왔던 개발자라면 충분히 비슷하다고 생각할 것인데, 실제 사용번도 크게 다르지는 않다.

- @MultipartConfig

역시 스프링 프레임워크의 MultipartFile과 사용법과 용도가 유사하다.


2. Dynamic Registration of Servlet and Filters:  서블릿, 필터 클래스의 매핑과 등록 해제가 코드에서 가능

ServletContext.addServletMapping(..), ServletContext.addFilter(..)등의 ServletContext클래스를 이용하여 직접 코드상의 수정도 가능하다. 


3. Pluggability: Annotation을 통한 서블릿, 필터 정의 또는 web-fragment.xml을 통해 배포 기술자의 모듈화 가능

4. Asynchronous Support: 말 그대로 비동기 모드 지원

5. Security: Annotation을 통한 용청별 권한 이증 지원

- @RolesAllowed

- @DenyAll

- @PermitAll

- @TransportProtected


Servlet 3.0과 관련된 주요 사이트들.

- https://blogs.oracle.com/enterprisetechtips/entry/asynchronous_support_in_servlet_3

- http://www.java.net/blogs/mode/

http://ko.wikipedia.org/wiki/자바_서블릿

- http://en.wikipedia.org/wiki/Java_Servlet


[Grails 2.3 Async Support]

이제 본론으로 들어가야 할 때이다. Servlet 3.0이 생각보다 오래전에 발표되었지만, 아는 사람들과 실제 환경에서 적용하여 사용하는 사람들은 많지는 않아 보인다. 뭐.. google app engine도 최근에 지원하려고 준비고 있는 단계이니, 그럴수도 있겠지.)

오늘 읽어 본 글은 http://grails.io 에 올라온 글이다.

예제위주로 설명이 되어 있어서 이해는 어렵지 않은데 실제 코드를 만들지 않으면 별로 의미가 없을 수 있다. 나중에 꼭 해볼것을 다짐하면서...

Grails 2.3에서는 Promises패키지에 포함되어 있는 메소드들을 통해서 Async 기능을 제공하고 있다.

아래는 그 예제이다. 설명을 따로 하지 않아도 알겠지만 3개의 메소드를 async하게 실행해서, 그 결과를 wateAll 메소드를 통해서 전달 받는다.

import static grails.async.Promises.*

def p1 = task { 2 * 2 }
def p2 = task { 4 * 4 }
def p3 = task { 8 * 8 }
assert [4,16,64] == waitAll(p1, p2, p3)

아래는 GORM을 통한 query메소드를 호출하는 예제로 위의 예제와 사용법이 같다.

import static grails.async.Promises.*
def p1 = Person.async.get(1L)
def p2 = Person.async.get(2L)
def p3 = Person.async.get(3L)
def results = waitAll(p1, p2, p3)

그런데, 위의 예저들은 서블릿 3.0에서 제공하는 기능들과의 연관성이 전혀 없어 보인다.


음의 예제들이 Async 방식을 지원하는 예제로 Service를 Annotation을 통해서 Async 서비스로 노출을 시기는 코드이다. 그 아래의 코드는 모든 메소드를 Async로 실행하는 코드이다. 

import grails.async.*
class AsyncBookService {
   @DelegateAsync BookService bookService    
}

AsyncBookService asyncBookService
def findBooks(String title) {
    asyncBookService.findBooks(title)
       .onComplete { List results ->
          println "Books = ${results}"    			
       }
}







WRITTEN BY
행복상자
행복한 마음으로 매일을 살고 싶은 개발자 입니다.

트랙백  0 , 댓글  0개가 달렸습니다.
secret

스프링 프레임크를 사용하기 시작한지는, 만 5년 정도 된것 같다. 아니 정확하게 이야기하면 알기 시작한지 5년이다. 그 동안 몇개의 프로젝트에는 적극적으로 사용해왔고, 사용하려고 했었다.

솔루션을 위한 내부의 기반 프레임워크를 개발하기에도, 그 자체만으로도 스프링은 너무 훌륭하기 때문에, Application의 공통 부분을 위한 기능들만을 최적화하고, 정의하는 것 만으로도 노력대비 좋은 결과들을 낼수 있었다. 다 로드존슨 아저씨가 많은 시간을 들여서 갈고 닦고, 발전시킨 노력의 결과들이다.

시간이 흐를수록 큰 조직에서는 코드와 PC와 씨름하기 보다는 수 많은 회의와 씨름을 하는 일이 많아진다. 더군다나 같이 협업하는 사람들이 많아지면, 본인이 원치 않아도 관리자의 길에서 뛰고 있는 모습을 보게된다. 딱 지금의 나의 모습니다.

공부하지 않고, 적절하게 판단하고 선택하고 방향에 대해서 이야기 할 수 있을까?
많은 고민을 하지만, 역시 시간이 절대적으로 부족하다.

요즘은 코드를 보기가 힘들정도로, 공부할 여유가 별로없다.
하지만, 사둔 책이 아깝다는 이유이든, 공부의 재미를 알았다는 이유이든 개발자로 살아가는 한은
꾸준히 배워야한다.

스프링 3.1은 또 다른 변호들을 이야기 할지는 모르겠다. 이전에 책을 보면서 정리한 내용인데 일단 올려놓는다.

[Spring Framework 3.0 - MVC]

·         스프링은 DespatcherServlet 7개의 Strategy를 기반한 MVC 프레임워크를 제공한다.

·         이중 DespatcherServlet는 가장 기본적이면서도 SpringMVC의 필수적인 기본 Servlet 역할과 스프링의 특징중의 하나인 Light-weight 컨테이너의 역할을 수행한다.

 

1.     @RequestMapping 핸들러 매핑

o    @MVC는 메소드 레벨에서 컨트롤러를 작성할 수 있다.

o    Annotation은 타입(클래스, 인터페이스)레벨뿐 아니라 메소드 레벨에도 적용 가능함.

o    @MVC 핸들러 매핑을 위해서는 DefaultAnnotationHandlerMapping이 필요하다.

o    DefaultAnnotationHandlerMapping은 기본 핸들러 이므로 다른 Handler Mapping bean이 명시적으로 등록이 되지 않았다면, 기본으로 사용이 가능하다.

o    만약, 다른 핸들러 매핑 빈이 등록이 되었다면, DefaultAnnotationHandlerMapping
명시적으로 등록을 해주어야 사용이 가능하다.

2.     Class/Method 결합 Mapping 정보

o    DefaultAnnotationHandlerMapping

·         @RequestMapping 애노테이션을 활용해서 타입레벨과 메소드 레벨 지원하며
타입레벨을 기본으로 삼고, 메소드 레벨의 어노테이션 정보는 타입레벨의 매핑을 세분화 하는데 사용한다.

o    @RequestMapping Annotation

·         Spring[] value(): URL 패턴

1.     String 배열 타입으로 URL 패턴을 지정해서 사용

2.     URL 패턴은 ANT 스타일과 와일드카드를 사용이 가능하다.

·         @RequestMapping("/hellow")

·         @RequestMapping("/admin/**/user")

·         @RequestMapping("/hellow", "/hi")

3.     "{ }"를 사용할때는, "{ }"의 위치에 해당하는 내용을 컨트롤러 Method에서 파라메터로 전달받을 수 있다. "{ }"에 들어가는 변수를 "path variable"이라고 부른다.

·         @RequestMapping("/user/{userid}")

·         RequestMethoe{} method(): HTTP Request Method

1.     Request Method GET, HEAD, POST, PUT, DELET, OPTIONS, TRACE 7개의 HTTP 메소드가 정의되어 있다

2.     HTTP 메소드를 추가하면 요청 메소드에 따라 다른 메소드를 매핑해 줄 수 있다.

·         @RequestMapping(value="/user/add", method=RequestMethod.GET)

3.     정의된 메소드 이외의 사용시 "HTTP 405 - Method Not Allowed"를 받음.

4.     타입레벨에서 URL을 주고 HTTP 요청 메소드를 지정할 경우 URL 생략가능.

·         @RequestMapping(method=RequestMethod.GET)

·         String[] params(): Request Parameter

1.     이것은 요청 Parameter와 그 값을 비교해서 매핑해 주는 것이다.

2.     같은 URL을 사용하지만, Parameter값에 따라 다른 작업을 할 때 사용한다.

·         @RequestMapping(value="/user/edit", params="type=admin")

3.     특정 Parameter 값이 존재하지 않아야 한다는 조건을 둘 경우 사용

·         @RequestMapping(value="/user/edit", params="!type")

·         String[] header(): HTTP 헤더

1.     Header 정보에 따라 매핑이 가능하다.

·         @RequestMapping(value="/view", headers = "content-type="text/*")

 

o    Type level 매핑과 Method level 매핑의 결합

·   타입(클래스오 인터페이스)레벨에 붙는 @RequestMapping은 타입내의 모든 매핑용 메소드의 공통 조건을 지정할대 사용한다.

·   메소드 레벨의 매핑은 클래스 레벨의 매핑을 상속한다.

      1. 컨트롤러가 각각 /user/add, /user/edit, /user/delete URL에 매핑

@RequestMapping("/user")

public class UserController{

@RequestMapping("/add") public String add(){ }

@RequestMapping("/edit") public String edit(){ }

@RequestMapping("/delete") public String delete(){ }

}

2.     타입 레벨의 URL패턴에 * **를 사용하여 매핑 가능

·         /user/*

·         /user/**  

·         타입레벨에서 공통의 매핑을 정의하고, 메소드 별로 세분화 해서 사용

 

o    Method 레벨 단독 매핑

·   공통 매핑 조건이 없을 경우, 조건을 주지 않고 메소드 레벨에 정의해서 사용.

·   이렇게 정의하지 않는다면, 클래스 자체가 매핑이 되지 않는다.

·   만약, @Controller 애노테이션을 붙여서 자동 빈 스캔을 사용할 경우는, 클래스 레벨의 @RequestMapping을 생략할 수 있다.

o    Type 레밸 단독 매핑

·   클래스 레벨의 URL 패턴이 /*로 끝나는 경우, apthem 레벨의 URL 패턴으로 메소드 이름을 사용할 수 있음.

·   아래는 /user/add /user/edit 로 각각 매핑

@RequestMapping("/user/*")

Public class UserController {

@RequestMapping public String add( ) { }

@RequestMapping public String edit( ) { }

}

 

 

 

 

 


WRITTEN BY
행복상자
행복한 마음으로 매일을 살고 싶은 개발자 입니다.

트랙백  0 , 댓글  0개가 달렸습니다.
secret
[정말 나의 게으름으로 글 하나가 또 묻혀져 있었다.]
[지난 번의 1번글을 비슷한 시기에 쓰고, 연달아 정리하려고 했는데]
[또 다시, 뒤 늦게 글을 올리게 되었다. 미안하고 죄송하고, 부끄럽다.] 


 트위터의 API를 사용하기 위해서 필요한 내용들을 간략하게 정리해 봤다. 세부 내용들과 참고해야할 항목들도 정리했는데, 이전 기억을 살리기 보다는 FQA를 이용해서 접근하였다. 따라서 필요한 내용들은 Twitter의 개발자 가이드와 웹 사이트를 이용해서 확인 가능하다.
 
간략하게 정리하였지만, 기본적인 API들에 대한 지원은 Twitter에서 라기보다는 이를 이용한 Wraper 클래스들은 우리의 선배 또는 휼륭한 다른 개발자 들이 이미 개발하여 놓았다. 이를 잘 활용하는 것은 또 다른 문제이고, 다른 영역이라 생각하지만, 자신에 맞는 언어와 라이브러리를 잘 찾아 쓰는 것은 시행착오와 시간을 줄여주는 활동이다.

웹사이트에는 Web site를 위해서 Twitter에서 제공되는 기능들도 설명되어져 있다. (나의 관심사와는 좀 거리가 있어서, 생략...)



[Twitter API 이용하기]
 
  1. Developer document를 읽어봐야 한다.
    • Developer Guide 어떤 Framework 가지고 개발하더라고 반드시 읽어야 기본 문서이다.
  1. Twitter Libraries
    • Twitter 사용해서 List 가져오거나 Oauth 위한 라이브러리들은 아래에 정리되어 있다. 아래 링크를 참조해서 사용하고 있는 또는 필요로 하는 라이브러리를 사용하면 된다. (현재는 13 언어에서 지원하고 있다.)
  1. Twitter Character 140자로 정해져 있다.
  1. REST API 버전 정보는 현재 version 1 되어 있다.
  1. Twitter API 사용하기
    • Open Api 사용할 앱을 등록한다. (아래의 링크에서 등록)
      • Application Name Unique 해야 된다.
      • 작년(2010) OAuth 방식으로 바뀐 이후에, ID/Password 방식이 아니라, 인증키를 얻어야 사용이 가능하다.
  1. Twitter API 사용 제한
    • 인증 방식에 따라 다양하게 사용량이 정의되어 있다.
      • Unauthenticated call: 150 requests/hour
      • OAuth call: 350 requests/hour
    • 유휴하지 않은 OAuth 정보를 포함하게 되면,
      • 인증 받은 메소드: 에러 response 반환한다. (with HTTP 401 error)
      • 인증 받은 메소드: 다음과 같은 헤더 정보를 포함된 Response 받게 된다. 인증 받지 않았기 때문에, API 호출 제한은 Unauthenticated call 따른다.
        • X-Warning: Invalid OAuth credentials detected
      • HTTP GET commend 요청한 메소드들은 사용량의 제약을 받으나, POST commend 제약이 없다.(아래 문서 참조)

 

  • API 사용 제한량 알기
    • REST API 사용 제약에 도달하면, HTTP 400 Response code 받게 된다.
    • Search 또는 Streaming API 사용량이 한계치에 도달할 경우는 HTTP 420 response code 반환한다.

 

  • Search API 사용량 제한
    • REST API 제한이 없다. (그러나, 제약을 위해서 모든 요청은 IP 단위로 관리된다.)
    • 사용량이 한계치 도달 , HTTP 420 response code 받는다.


'공부하는 것 > Twitter API & Twitter4j' 카테고리의 다른 글

Twitter REST API (2)  (0) 2011.10.24
Twitter REST API (1)  (0) 2011.09.14

WRITTEN BY
행복상자
행복한 마음으로 매일을 살고 싶은 개발자 입니다.

트랙백  0 , 댓글  0개가 달렸습니다.
secret