본문 바로가기
Server

6.기본 모바일 서버 만들기(2)

by Doromi 2018. 1. 10.
728x90
반응형

3-2-5.cowboy 사용하기

 

cowboy의 흐름도를 보면 client에서 받은 HTTP요청을 처리하는 순서를 알 수 있다.

acceptor에서 클라이언트의 접속을 수락->Erlang 프로세스를 생성

클라이언트의 요청 패킷 하나당 Erlang 프로세스 하나가 생성되는 것이다.

그 다음 parser에서 socket을 읽어 패킷을 처리하게 된다.

에러가 없다면 onrequest->router->handler를 거쳐서 클라이언트로 응답 패킷을 전달한다.

우리가 신경 쓸 부분은 router->handler 이부분이다.

 

3-2-5에서 작성할 코드 부분이 이 부분으로, 각종 기능들을 이 부분을 통해서 연동시킬 것이다.

 

먼저 코드 작업을 하기 위해 cowboy 소스를 받아와서 project에 연동 시켜야 한다.

 

IntelliJ를 실행 시켜서 앞에서 만든 프로젝트를 불러온다.

프로젝트에 New->File 이름은 rebar.config라는 파일을 프로젝트에 추가한다.

 

{deps,[
{cowboy, ".*", {git, "git://github.com/extend/cowboy.git", {tag, "1.0.1"}}}
]}.

이 내용을 추가한다.(deps항목에 cowboy 추가하기)

 

메뉴 Run->Edit Configurations 클릭 Erlang Rebar항목에 이전에 compile추가했듯이  하나 더 추가해준다.

 

 

그 다음 바로 Run에서 get-deps를 실행한다.

 

 

그러면 하단 창에 cowboy와 관련된 코드들을 자동으로 다운 받는 것을 확인할 수 있다.

프로젝트 디렉토리에 자동으로 deps라는 폴더가 생성되고, cowboy,cowlib,ranch가 추가된다.

cowlib은 cowboy에서 사용하는 각종 유틸리티들의 모음

ranch는 cowboy에서 사용하는 TCP socket 라이브러리

우리는 cowboy만 사용하면 되므로 신경 안써도 된다.

 

이 프로젝트에서 모듈들을 사용하기 위해서는 추가된 deps의 모듈들을 실행 스크립트에 적어 주어야 한다.

first.bat. 파일을 수정하겠다.

 

 

 

 

werl을 실행할 때에 인자 값으로 vm.args 파일의 내용을 포함시키라는 뜻

 

 

 

 

그 다음 프로젝트에 vm.args 텍스트 파일을 추가한다.

 

 

-pa ./bin
-pa ./deps/cowboy/ebin
-pa ./deps/cowlib/ebin
-pa ./deps/ranch/ebin
-eval "application:start(start)"

기존 설정 값들을 vm.args 파일로 만들어서 관리 쉽게 한다.

 

 

 

Run->Run->Compile 컴파일 후에, Run->Run->First 실행하면 실행된다.

변한 것은 없지만, cowboy module을 실행할 수 있는 모든 준비가 된 상태이다.

서버가 실행된 것은 아니지만, start 어플리케이션은 실행된 것이다.

 

cowboy module이 정상적으로 로딩 되었는지 확인하려면 module_info()함수를 실행해보면 된다.

 

 

 

 

 

 

 

 

 

 

3-2-6.Cowboy,Router,Handler 작성

 

실제로 Cowboy HTTP Server를 실행시키기 위해 router와 handler 부분을 작성해 보자.

 

start_app.erl파일을 수정하겠다.

 

start(_StartType, _StartArgs) ->
%% 필요한 어플리케이션 실행
ok = application:start(crypto),
ok = application:start(cowlib),
ok = application:start(ranch),
ok = application:start(cowboy),

%% Cowboy Router 설정
Dispatch = cowboy_router:compile([
{'_',[
{"/hello/world", start_http, []}
]}
]),
%% HTTP Server 실행
{ok,_} = cowboy:start_http(http,100,[{port, 6060}],[
{env, [{dispatch, Dispatch}]}
]),
case start_sup:start_link() of
{ok, Pid} ->
io:format("start ok~n"),
{ok, Pid};
Error ->
Error
end.

대충 어떤 데이터가 들어간다 라고만 알고 넘어가겠다.

 

crypto는 암호화 관련된 어플리케이션으로 cowboy를 실행시키려면 미리 실행시켜주어야 한다.

cowlib,ranch,cowboy를 순서대로 실행시킨 다음에 Cowboy의 Router를 설정한다.

이를 위해서 cowboy_router모듈의 compile이란 함수를 실행하면 된다.

형식은 cowboy_router:compile(Routes)

 

Cowboy_router:compile의 인자값은 Routes라는 하나의 변수인데, List 형식으로 다음과 같이 여려 개의 Host데이터 입력할 수 있다.

 

Routes = [Host1,Host2,....HostN].

 

Host값은 클라이언트의 Host 주소와 URL을 나타내는 Path로 되어 있다.

형식은 튜플이다.

Host1 ={HostMatch, PathsList}.

PathsList는 여러 개의 Path들의 리스트이다.

PathsList = [Path1, Path2,...PathN].

 

각각 Path들은 PathMatch 그리고 해당 PathMatch와 일치했을 때 동작할 Handler 모듈 그리고 옵션 3가지의 값을 튜플 형식으로 구성하고 있다.

 

Path1 = {PathMatch, Handler, Opts}.

 

이것을 종합하면

 

cowboy_router:compile([{HostMatch, [{PathMatch, Handler, Opts}]}]).

 

HostMatch 값에는 '_'이라고 적어준다. 이것은 모든 Host에 대해서 Matching되도록 하기 위한것이다.

PathMatch에는 위락 만들 API인 /hello/world를 적어준다.

그리고 Handler 부분에는 /hello/world라는 요청이 들어왔을 때 처리를 할 Handler 모듈 이름인 start_http를 적어주면 된다.

Opts는 옵션 값을 적어주는데, 특별히 없으니까 비워둔다.

 

cowboy:start_http 함수는 실제로 소켓을 열고 서버를 구동하는 부분이다.

포트번호를 6060으로 http server를 실행시킨다는 뜻이다.

 

이제 클라이언트의 요청을 처리할 Handler 모듈을 작성해보겠다.

 

src아래에 새 얼랭 파일을 추가한다.

이름은 start_http 이고 kind는 Empty module이다.

 

 

%% API
-export([init/3, handle/2, terminate/3]).

init(_Type, Req, []) ->
{ok,Req, no_state}.

handle(Req,State) ->
{ok, Req2} = cowboy_req:reply(200, [
{<<"content-type">>, <<"text/plain">>}
], <<"{\"result\":\"Hello world!\"}">>,Req),
{ok, Req2, State}.

terminate(_Reason, _Req, _State) ->
ok.

총 3개의 함수를 만들었다. init, handle, terminate

맨 앞에 export는 외부에서 실행 가능한 함수의 리스트를 의미.

옆에 있는 숫자의 의미는 인자값의 수.

함수의 선언부 첫줄 끝에 있는 -> 이후부터 . 까지가 함수의 내용을 의미.

한 함수에서 마침표(.)은 마지막에 딱 한번 쓰고, 그 전에는 쉼표(,)를 쓴다.

 

세 함수 모두 cowboy에서 자동으로 실행하는 함수이다.

가장 간단한 구조로 동작할 수 있는 callback 함수를 추가한 것이다.

 

init 함수

패킷을 받을 때 최초로 실행되는 callback 함수

첫번째 인자 : Transport의 프로토콜 모듈을 정의할 때 사용

_Type은 특별한 Type을 설정하지 않으므로 _를 붙였다.

두번째 인자 : 클라이언트에서 전송 받은 요청 데이터가 입력되어 있는 객체

세번째 인자 : 옵션값

 

init 함수의 리턴값

튜플 구조로 3개의 값을 담는다.

첫번째 값 : 초기화한 결과값으로 이상없으면 ok, 초기화를 강제로 종료하려면 shutdown

두번째 값 : 요청 받은 데이터를 다음 callback 함수로 전달하기 위해서 Req를 그대로 적는다

세번째 값 : State 값을 넣는다, 사용하지 않으므로 no_state

 

handle 함수

실제로 클라이언트의 요청을 처리하고 응답 데이터를 작성하여 전달

 

Terminate 함수

init과 반대로 요청에 대한 모든 처리가 끝난 후에 실행되는 함수

 

%%%는 얼랭의 주석을 의미한다.

주로 %를 하나 이상 맨 앞에 써주면 주석을 의미 하는데 보통 %%, %%%을 많이 쓴다.

 

이제 컴파일하고 실행해보겠다.

이미 실행했던 창이 있다면 닫고 실행한다.

웹 브라우저를 실행시킨후 URL에 다음과 같이 입력한다.

 

http://IP주소:6060/hello/world

 

 

 

더 세밀한 테스트를 위해서는 curl을 사용하는 것이 편리하다.

 

curl은 URL을 입력받아서 서버로 전송해 주는 커맨드 라인 툴이다.

http://www.confusedbycode.com/curl/#downloads

 

curl.exe가 포함되어있는 폴더로 이동한다.

그리고 curl http://IP주소:6060/hello/world

결과를 쉽게 볼 수 있다.

-i 옵션을 주면 더 상세한 헤더를 볼 수도 있다.

 

 

 

728x90
반응형

'Server' 카테고리의 다른 글

8. 로그인(2)  (0) 2018.01.11
7. 로그인(1)  (0) 2018.01.10
5.기본 모바일 서버 만들기(1)  (0) 2018.01.07
4.개발 환경 구축하기(3)  (0) 2018.01.07
3.개발 환경 구축해보기(2)  (0) 2018.01.06