사람들 대부분 스마트폰을 가지고 다니는 세상에서 스마트폰으로 무엇을 할수 있을까요?
안드로이드 앱시장 또는 애플 앱시장에서 유료, 무료로 필요한 어플을 다운로도해서 설치할수 있습니다.
그리고 직접 앱을 개발할수 도 있겠지요.
앱을 개발하기엔 개발환경이 무겁고 테스트하기에도 쉽지 않은것 같습니다.
그러면 구지 앱을 만들지 않고 웹앱을 만들면 어떨까?
스마트폰 화면에서 아이콘을 클릭하면 바로 웹브라우저가 기동되고 웹을 통해 정보를 주고 받으면 편할것 같은 생각이 드네요.

구축환경은 대충 이렇습니다.
Client
  안드로이드 스마트폰, 애블 아이폰
  
Server
  Node.js
  Html5 로 웹화면 설계
  Jdbc 로 SQL Server 접근

기존 웹서버를 운영한다면 간단하지 않을까 싶습니다.

그래서 Node.js 에서  SQL Server 에 JDBC로 접근할수 있는 방법이 나와 있을까?

=> 추가
node-tds 모듈이 제공되네요.

 일단 MS SQL에서 JDBC Driver를 내놓은 것 같네요.

아직 자세히 들여다 보지는 않았지만 개발흐름의 변화를 감지하게 되는것도 같습니다.

Introducing the Microsoft Driver for Node.JS for SQL Server
출처) http://blogs.msdn.com/b/sqlphp/archive/2012/06/08/introducing-the-microsoft-driver-for-node-js-for-sql-server.aspx


블로그 이미지

희망잡이

,


화면을 캡쳐할 필요가 가끔씩 있는데 이것을 동영상으로 만들어 주는 프로그램도 있습니다.

스크린 리코드( Screenr.com )

사용법도 편하고 작업하는 방법, 노하우를 동영상으로 만들어서 배포할수도 있습니다.



위의 영상은 스크린리코드를 사용해서 내가 엑셀작업하는 방법을 녹화한 것입니다.

깔끔하게 녹화되네요.

아쉬운게 있다면 소스가 ScreenR 회사에 있다는 것입니다.


블로그 이미지

희망잡이

,



크롬 브라우저를 쓰면서 구글의 웹어플리케이션 활용도가 점점 더 많아지고 있습니다.

인터넷 익스플로러가 느리게 작동해서 크롬을 설치하여 사용하기 시작했습니다.

지금까지는 윈도우환경에서 바탕화면에 프로그램 아이콘을 배치하여 사용자환경을 구축하여 사용해 왔습니다.

크롬을 설치하고 나서 바탕화면이 필요가 없어질 것 같은 예감이 드는군요.

그 이유는 구글에서 크롬을 중심으로 웹어플리케이션을 등록 관리할수 있는 프로세스가 있다는 겁니다.

필요한 프로그램을 찾아서 크롬에 추가하여 아이콘을 배치할수가 있습니다.



업무중에 간단하게 메모하거나 웹 브라우저로 정보를 검색하다가 기억해야 될 사이틀를 찾았을때 간단하게 저장할수 있는게 있으면 좋겠다 라고 생각을 해보았을 것입니다.

일반적으로는 이면지에 간단하게 메모해 두었다가 다이어리로 옮겨적거나 아니면 포스트잇에 적어서 잊어버리지 않도록 모니터 하단에 붙여두곤하지요.

좀 정리를 잘 하는 친구는 포스트잇 보드를 구입해서 거기다가 자기가 해야될 목록을 붙여두고 완료하면 떼서 제거하기도 하더라고요. 오늘 해야할 목록을 관리하기가 쉬울겁니다.

그런데 구글 크롬용 웹어플리케이션중에 Hiuz Link Manger 란 프로그램이 있습니다.

포스트잇처럼 더블클릭을 하면 화면에 만들어지고  제목, 웹화면주소(링크), 내용 을 입력해서 관리할수 있습니다.

간단하게 적어두었다가 활용할수 있는 좋은 어플리케이션인것 같습니다.

Chrome Web Store 로 들어가서 Hiuz 로 조회하시면 찾을수 있고 크롬에 추가 버튼을 클릭하시면 됩니다.


블로그 이미지

희망잡이

,


원문사이트 : Martin fowler - Inversion of Control Containers and the Dependency Injection pattern

http://martinfowler.com/articles/injection.html

Inversion of Control Containers and the Dependency Injection pattern

( 통제 구역의 반전 과 의존성 주입 패턴 )

자바 커뮤니티에는 수많은 프로젝트을 가지고 응집된 어플리케이션을 위한 컴포넌트를 구성하도록 도와주는 경량의 컨테이너가 다양하게 나타났습니다.

이러한 컨테이너가 가진 기본적이고 공통된 패턴은 그들은 어떻게 연결시킬수 있는지에 대한 것입니다.

Inversion of control, Dependency Injection, Service Locator

Components and Services

컴포넌트은 변경없이 어플리케이션이 사용할수 있도록 고안되어진 소프트웨어의 묶음을 의미합니다.

여기서 변경없이는 어플리케이션이 컴포넌트의 소스를 바꿀수 없다는 뜻이고 행동은 바꿀수 있다를 의미합니다.

서비스는 외부 어플리케이션에 의해 사용되어질수 있는 컴포넌트를 의미합니다.


순진한 예제

특별한 감독이 제작한 영화 목록을 제공하는 컴포넌트를 작성할려고 합니다.

class MovieLister ...

  public Movie[] moivesDiretedBy( String arg ) {

    List allMovies = finder.findAll();

    for ( Iterator it = allMovies.iterator() ; it.hasNext(); ) {

      Movie movie = (Movie) it.next();

      if (!movie.getDirector().equals(arg)) it.remove();

   }

   return ( Movie[] ) allMovies.toArray( new Movie[Movies.size()])

}

이 기사의 핵심은 Finder 오브젝트 입니다. 특히 우리가 어떻게 리스트 오브젝트를 하나의 특별한 finder 오브젝트를 연결시킬것인지 입니다.  이게 왜 흥미로운것이야 하면 나는 나의 사랑스러운  moviesDirectedBy 메소드가 저장된 모든 영화들로 부터 완전히 독립되어지기를 원하기 때문입니다.

모든영화정보를 가져오는 인터페이스를 작성합니다.

public interface MovieFinder {

  List findAll();

}

이 인터페이스를 사용하는 실제 클래스를 작성해 봅니다.

class MovieLister ...

  private MovieFinder finder;

  public MovieLister() {

finder = new ColonDelimitedMovieFinder("movies1.txt");

 }

이 인터페이스로 인해서 영화를 콜론으로 텍스트파일을 작성해서 처리할수 있는 멋진 프로그램이 되었습니다.

나의 동료들도 충분히 이 프로그램을 사용할수 있어서 더욱 멋지게 보입니다.

그러나 다른형태로 저장된 영화리스틀 파일들은 어떻게 해야 할까요? sql database, xml file, web service, other text file.

이러한 경우에 우리는 이 형태에 맞는것을 처리할수 있는 또다른 클래스를 필요로 합니다.

Figure 1

Figure 1: The dependencies using a simple creation in the lister class

이것은 plugin 개념과 비슷할 것입니다.

여기서 핵심은 이러한 프로그램들을 어떻게 어플리케이션으로 모을수 있느냐 하는 것입니다. 

경량의 컨테이너가 이것을 구현하기 위해서 필요한 것인 Inversion Of Control 입니다.

Inversion Of Control

프레임워크의 일반적인 특징입니다. 따라서 경량 컨테이너가 inversion of control 을 사용하기 때문에 특별하다고 말하는 것은 내차가 휠을 가지고 있기때문에 특별하다고 말하는 것과 별반 차이가 없습니다.

문제는 통제의 어떤 관점을 그들이 도치하고 있느냐 하는 것입니다. 내가 처음 접했던 것은 유저 인터페이스의 메인 통제에서 였습니다. 초기의 유저 인터페이스는 어플리케이션 프로그램에 의해 통제되어졌습니다. 당신의 일련의 명령을 가집니다. 성명을 기입하시오. 주소을 입력하시요. 당신의 프로그램은 프람프트로 이끌고 각 항목의 응답을 가져가는 식으로 흘러갑니다.

GUI환경에서 UI프레임워크는 주된 흐름을 포함하고 대신에 당신의 프로그램은 각 항목을 위해 이벤트핸들러를 제공합니다.

프로그램의 주된 통제가 프레임워크에서 벗어나서 도치되어진 것입니다.

새로운 형식의 컨테이너에서 Inversion은 그들이 어떻게 플러그인 구현체를 찾는냐에 대한 것입니다.

나의 예제에서 lister 는 finder 구현체를 직접 그것을 인스턴스화 해서 찾았습니다.

이러한 형식은 finder를 하나의 플러그인이 될수 없도록 만듭니다.

컨테이너가 사용하는 접근법은 플러그인의 사용자가 규약을 따르는것을 보장합니다. 이 규약은 분리된 어셈블러 모듈이 구현을 lister 에 주입할수 있도록 허락하는 것입니다.

용어상에서 혼란이 생길것 같아서 Inversion of control 을 Dependency Injection 으로 사용하고자 합니다.

어플리케이션에서 의존성을 제거하는 방법으로 Dependency Injection 그리고 Service Locator 가 있습니다.

Forms of Dependency Injection

Figure 2

Figure 2: The dependencies for a Dependency Injector

Constructor Injection with PicoContainer

Setter Injection with Spring

Interface Injection with Avalon


블로그 이미지

희망잡이

,

OSGi 디자인

정보기술(IT) 2012. 10. 24. 12:01


문서출처 : http://www.osgi.org/blog/2006/04/details-are-important-when-you-are.html

 

당신은 어디에서 디자인을 시작할 것인가?  훌룡하게 잘 디자인되어진 OSGi는 무엇인가?

OSGi Framework은 컴포넌트를 위한 환경은 제공한다.

컴포넌트들로 디자인하는것은 주된 주류흐름이 아니고 확립된 규칙도 거의 없는 실정이다.

컴포넌트란 무엇인가?  OSGi 컴포넌트는 서비스를 통하여 기능을 공급하는 동적으로 전개될수 있는 단위이다. 보통 자바 인터페이스로 정의되어진다.

OGGi Log Component 예

이 번들이 시작되어지면 주변세계에 Log Service 와 Log Reader Service 를 공급한다.  다른 번들은  이 서비스를 얻어서 사용한다.

디자인 관점에서 그려보면 통신을 위해 포트를 가진 블랙박스로 컴포넌트로 다룰 수 있다.

UML에 표준모듈과 인터페이스 심볼이 존재한다는 것을 안다. 그러나 그들로는 결코 이룰수 없다.

나는 보통 번들로는 원을 ,서비스로는 삼각형을 사용한다.

서비스는 번들에 의해 3가지의 다른방식으로 사용되어 질수 있다.

1. Consumer – The bundle that gets the service is the consumer. The arrow from the bundle attaches to the horizontal or vertical line on a service triangle. An OSGi service can be consumed many times by any bundle. Many bundles can therefore connect to the horizontal or vertical line of the triangle.
2. Implementer – The bundle that implements the service must register it. This is depicted by drawing a line to a corner of the triangle. An OSGi service can be registered many times by the same or different bundles.
3. Listener – A listener bundle connects to one of the angled lines of the triangle. A listener is notified of registrations, modifications and unregistrations of the service. A service can have many listeners.


None of the bundles has a dependency on any of the other bundles. I might bore you, but I can not stress enough how important this concept is!


The whiteboard pattern is an example of inversion of control (IoC). That is: “Do not call us, we will call you”.

If you need something from the world or have something useful functionality to offer to the world, register a service and wait till somebody calls you.

The best litmus test for a service is: “Do I decrease coupling”?

블로그 이미지

희망잡이

,




출처 : http://www.pendrivelinux.com/universal-usb-installer-easy-as-1-2-3/

 

Universal USB Installer is a Live Linux USB Creator that allows you to choose from a selection of Linux Distributions to put on your USB Flash Drive. The Universal USB Installer is easy to use. Simply choose a Live Linux Distribution, the ISO file, your Flash Drive and, Click Install. Other features include; Persistence (if available), and the ability to format the flash drive (recommended) to ensure a clean install. Upon completion, you should have a ready to run bootable USB Flash Drive with your select Linux version installed.

 

Universal-USB-Installer-1.8.0.8.exe – October 26, 2010 – Changes

Updated the PLoP Entry and Fixed the Lubuntu 10.10 entry so that Persistence would work.

USB Flash Drive Creation Prerequisites:

  • Universal-USB-Installer-1.8.0.8.exe
  • Windows XP/Vista/7 to create the USB (Win 98/2K WILL NOT Work!)
  • Fat32 Formatted Flash Drive
  • PC with a BIOS that can boot from USB
  • Your Favorite Linux ISO

A Linux based version of this tool is in the works for those Die Hard Linux users who prefer not to useWindows. For now, you can visit the "How to install Linux from a Linux CD" section for individual tutorials.

Notes: If you run Universal USB Installer from the same directory containing an installable ISO, the script will autodetect the ISO and bypass step 2 once the proper Distro has been selected.


This tool does not support installing and booting from multiple Linux Distributions. Only One Distribution can be installed at any given point in time. However, we do offer a MultibootISOs USB Creator for this purpose.

To try an unlisted ISO, for example "Ubuntu Mini Remix 10.10", use the last option in Step 1, "Try Some Other Live Linux ISO". Please inform me of unlisted Linux ISOs you get to work via this option!


블로그 이미지

희망잡이

,




출처 : http://www.pendrivelinux.com/put-gentoo-10-1-live-dvd-on-usb-from-windows/

Put Gentoo 10.1 Live DVD on USB from Windows

How to Install and run Gentoo 10.1 from a USB Flash Drive 

Note: Running Gentoo 10.1 from USB performs like the Live CD. Currently a persistence feature is outside the scope of this tutorial.

  1. Download the Gentoo 10.1 LiveDVD ISO (livedvd-x86-amd64-32ul-10.1.iso)
  2. Download and run our Universal USB Installer, select Gentoo 10.1 and follow the onscreen instructions
  3. Reboot your PC and set your system BIOS or Boot Menu to boot from the USB device, save your changes and reboot

Upon reboot, you should have a successful launch of Gentoo USB Linux from your USB memory stick.

예전에 리눅스교육과정에서 우연히 알게된 배포판... 젠투...

웹브라우징하는 단말기로 쓰이던 컴퓨터를 젠투를 설치하면서 그 깊이를 알게되었다.

 

LIVE CD를 CD에 굽고 BIOS에서 CD 부팅을 최우선순위로 하여 설치했었다.

그런데 최근 기술이 발전했는지는 모르겠지만, 두가지 방법이 추가된것으로 보인다.

1. LIVE CD를 DVD로 구워서 설치하기 => 위절차와 똑 같음.

2. LIVE CD를 USB로 구워서 설치하기

=> 이걸로 설치하는 방법은 없는것으로 보임...

 

다시 한번 gentoo linux handbook 을 읽어본다.

=> Downloading and Burning the Installation CDs 유심히 읽어봐야 할듯 하다.

You can download any of the Installation CDs from one of our mirrors. The Installation CDs are located in the releases/amd64/autobuilds/current-iso/ directory

 

다운로드 파일명 : install-amd64-minimal-20101021.iso

USB 메모리를 연결한다.

Universal-USB-Installer 를 다운로드 하여 실행한다.

CMOS로 접근하여 부팅우선순위를 usb-hdd로 지정한다.

( 일반적인 USB메모리는 hdd로 인식한다고 함 )

 

일반적인 설치방법대로 진행하다가 에러가 발생했다.

----에러내역

Notice: (-3, 'Temporary failure in name resolution')
>>> starting rsync with rsync://rsync.gentoo.org/gentoo-portage...
>>> checking server timestamp ...
rsync: getaddrinfo: rsync.gentoo.org 873: Temporary failure in name resolution
rsync error: error in socket IO (code 10) at clientserver.c(8
>>> retry ...
Notice: (-3, 'Temporary failure in name resolution')
=> 문제점 및 해결방법

Knoppix / # less /etc/resolv.conf
/etc/resolv.conf: No such file or directory

Did you do this before chrooting?
http://www.gentoo.org/doc/en/handboo...?part=1&chap=6
cp -L /etc/resolv.conf /mnt/gentoo/etc/resolv.conf

 

네트워크를 설정하고, 파티션을 구성한다.

파티션은 부팅섹터, swap섹터, root섹터로 나눈다.

윈도우가 설정되어 있어서 파티션이 먼저 구성되어 있는 경우에는

예를 들어 sda1, sda2 가 있으면 다음 순서대로 새로 생성하면 된다.

나중에 grub에서 다중부팅을 설정할때 윈도우는 sda1에 있다고 지정하면 된다.

 

리눅스 커널을 다운로드 받아서 컴파일하고 이미지를 boot 섹터에 복사한 다음에

grub을 설정하고 재부팅했다.

그런데 dhcp에서 네트워크카드를 인식되지 않는다. (dhcp로 설정되도록 해 놨음)

 

원인을 찾아보니 realtek rtl8168d(p) 8111d(p) ethrenet nic가 커널과 잘 맞지 않는다고 한다.

그래서 realtek RTL8139 Family PCI Fast Ethernet NIC 로 교체했다.

그래서 이전버전의 네트워크 카드에 랜선을 연결하니 정상적으로 dhcp가 작동한다.

 

kde 윈도우 데스트탑환경을 구축하고 싶어서 설치해 봤다.

kde설치시에 요구되어 지는 make.conf 파일에 USE 를 설정한다.

XUSE="truetype X crypt new-login xorg xscreensaver xv xcomposite xinerama opengl aiglx"

IMAGEUSE="jpeg gif tiff png svg pdf"

MEDIAUSE="alsa mad vidix asf win32codecs dvd mp4 aac x264 xvid nsplugin mp3 real cdr"

GENERAL="samba java bzip2 symlink sqlite spell xml sql webkit mysql"

SYSTEM="hal fam dbus aoss threads mng"

NOTUSE="-arts -gtk -ipv6 -jdk -jre -cups"

KDEUSE="kde kdeenablefinal qt4 qt3support rdesktop consolekit"

USE="${NOTUSE} ${SYSTEM} ${GENERAL} ${IMAGEUSE} ${XUSE} ${KDEUSE} ${MEDIAUSE}"

 

emerge -av kdebase-meta

emerge -av kdegames-meta

emerge -av xorg-X11

env-update

source /etc/profile

useradd gentoo -m -G users,audio,wheel -s /bin/bash

This will add a user gentoo, will make possible for him to use sound-related devices (/dev/sound/*), will make possible for him to switch to root (using su) and will make /bin/bash his login shell. 

su <user>                                           (Test it as non-root user)
echo "exec startkde" > ~/.xinitrc                        (Configure X startup)
source /etc/profile                              (Update the system variables)
startx                                                             (Start KDE)
exit                                                            (Back to root)
ls /etc/X11/Sessions                                    (Look for KDE version)
nano -w /etc/rc.conf                      (Modify XSESSION and DISPLAYMANAGER)
rc-update add xdm default                      (Set graphical session at boot)
reboot                                              (Reboot and login as root)

 

정상적으로 설치되었으면 kde 데스크탑환경을 볼수 있을것이다.

sound card : realtek high definition audio, ati high definition audio device



블로그 이미지

희망잡이

,



Node 를 사용하여 Javascript 언어로 어플리케이션을 개발하기위한 기초를 다지기에 좋은 교재가 있습니다.

사이트 : http://www.nodebeginner.org/index-kr.html



구글 크롬 웹브라우저에서 사용하고 있는 V8 Javascript Engine을 사용합니다.

웹어플리케이션의 유스케이스는 아래와 같습니다.

1. 사용자는 웹브라우저로 우리의 웹어플리케이션을 이용할수 있다.

2. 사용자가 http://domain/start 를 요청하면 파일 업로드 폼이 들어있는 웰컴 페이지를 볼수 있어야 한다.

3. 업로드할 이미지 파일을 선택해서 폼으로 전송하면 해당이미지는 http://domain/upload 로 업로드 되어야 하며 업로드가 끝나면 해당페이지에 표시된다.


사용자가 웹브라우저를 통해서 REQUEST를 보내면 서버가 이 REQUEST 를 받아서 작업을 한 다음에 RESPONSE 를 보냅니다.

이 유스케이스를 구현하기 위해 필요한 기술은?

1. 웹페이지를 전송할수 있는 웹서버   => NODE.js 사용

2. REQUEST 내용에 따라 응답을 다르게 하는 방법 => 라우터(ROUTER) 구축

3. 라우팅된 REQUEST 를 처리하기 위한 로직 => 요청 핸들러(request handlers)

4. REQUEST 와 함께 넘어오는 POST 데이타를 분리해서 넘겨주는 기능 => 요청데이타핸들링(request data handling )

5. RESPONSE로 보내기 위한 웹화면 생성 => 뷰로직( view logic )

6. 사용자가 이미지를 업로드 할수 있는 기능 => 업로드 핸들링( upload handling )


main 파일을 작성하는데 파일명은 index.js 로 합니다.

그리고 서버모듈을 가지고 있는 파일명은 server.js 로 합니다.

서버모듈의 프로세스는

구현되어져 있는 http 모듈을 가져와서 http server 를 생성합니다. 포트는 8888 로 설정하는 거지요.

var http = require("http");

http.createServer(function(request, response) {

response.writeHead(200, {"Content-Type": "text/plain"});

response.write("Hello World");

response.end();

}).listen(8888);

서버실행 : node server.js

클라이언트 접속 : http://localhost:8888/


함수의 인자로 함수를 전달하기

event-driven callbacks

: 이벤트에 의해 구동되는 함수가 있고 이 함수에 인자로 넘겨진 호출되어야 할 함수가 있다면 이벤트에 의해 구동되는 함수가 인자로 넘어온 함수를 호출하도록 하는 겁니다.

즉 우리는 메소드에 함수를 넘기고, 메소드는 관련된 이벤트가 발생하면 이 함수를 거꾸로 호출(call back) 합니다.

위의 소스에서 콜백 함수는 function(request, response) 입니다.

var http = require("http");

Node.js 내부 어딘가에 http 라는 모듈이 있으며 이를 require 하고 지역변수에 할당해서 사용할수 있습니다.

이렇게 하면 지역변수가 http모듈이 제공하는 모든 public 메소드를 사용할수 있는 객체가 됩니다.

모듈의 생성과 사용하기

server.js를 모듈로 생성해할수 있습니다.

코드를 모듈로 만든다는 것은 모듈을 필요로 하는 스크립트에 제공할 기능의 일부를 export 하는 것입니다.

우리 서버모듈을 require 하는 스크립트는 단순히 서버를 시작하는것이 필요할 것입니다.

start 하는 기능 즉 함수를 만들고  이 함수를 export.start = start 형식으로 지정하면 됩니다.

내장모듈(http)을 사용하는 것처럼 외장모듈(server.js) 도 똑같이 사용하면 됩니다.

파일을 require 하고 지역변수에 할당하면  export 된 함수를 쓸수 있게 됩니다.

요청을 라우터 하기

웹브라우저의 페이지에서 요청을 보내면 url 과 정보( get방식, post방식)가 함께 전송됩니다.

우리가 필요한 정보 : request 객체를 통해 접근가능, url 모듈querystring 모듈이 필요


url.parse(string).query
                                           |
           url.parse(string).pathname      |
                       |                   |
                       |                   |
                     ------ -------------------
http://localhost:8888/start?foo=bar&hello=world
                                ---       -----
                                 |          |
                                 |          |
              querystring(string)["foo"]    |
                                            |
                         querystring(string)["hello"]

querystring 모듈을 POST 요청의 body를 파싱하는데에도 사용할 수 있습니다.

var pathname = url.parse(request.url).pathname;

여기서 /start, /upload 를 pathname 으로 구분할수 있을것입니다.

router 모듈에서 pathname 을 받아서 처리할수 있도록 합니다.

정리하면 server.js 모듈이 start 할때 router 모듈을 인자로 받아서 실행을 하면서 콜백함수 onRequest에서 router 를 호출하는것으로 흘러갑니다.

동사들의(verbs) 나라에서의 실행(execution)

functional programming 에 대한 이야기 - 무엇인가를 해야 할때 명사보다는 동사의 행동이 필요하다.

실제 request handler 로 라우팅(routing) 하기

라우터를 통해 라우팅된 실제 비지니스로직을 수행하는 requestHandlers 모듈을 만들 필요가 있습니다.

두개의 기능이 모듈에서 export 되어야 합니다.

exports.start = start;

exports.upload = upload;

request handler는 지금은 두개 있지만 실제 어플리케이션에서는 handler의 수가 늘어나고 다양해 질것입니다.

라우터에서 request 와 handler를 매핑하거나 if code 문을 쓰는것은 추악함 이상이 될것입니다.

javascript 의 객체는 키 값이 문자열인 사전(dictionary) 이라고 생각하세요. 이름 값의 컬렉션. 이 값에는 문자일수 도 숫자일수 도 함수일수도 있다는 것입니다.

requestHandler 의 리스트를 객체로 넘기고 느슨한 연결을 위해 이 객체를 router 로 주사하려고 합니다.

index.js 에서 

var handle = {};

handle["/"] = requestHandlers.start;

handle["/start"] = requestHandlers.start;

handle["/upload"] = requestHandlers.upload;

여기서의 handle 을 server 가 시작할때 라우터 와 함께 handle 을 넘겨줍니다.

라우터는 pathname 과 handle 을 인자로 받아서 pathname 에 해당하는 handle 키에 해당하는 값의 함수를 콜백합니다.

if (typeof handle[pathname] === 'function') {

   handle[pathname]();

  } else {

    console.log("No request handler found for " + pathname);

  }

request handler 가 응답하게 만들기

request 처리란 request 에 응답하는 것입니다.

해서는 안되는 것 : 직관적인 접근방식 => 반환값으로 응답데이타를 유저에게 보내는 방식

Blocking 과 non-Blocking

start request handler 에서 10초 동안 기다리도록 수정합니다. ( start time  과 현재 시간을 비교하여 구현 )

/**

function start() {

  console.log("Request handler 'start' was called.");

  function sleep(milliSeconds) {

    var startTime = new Date().getTime();

    while (new Date().getTime() < startTime + milliSeconds);

  }

  sleep(10000);

  return "Hello Start";

}

**/

여기서 10초 동안 sleep 하거나 오랜시간 걸리는 계산작업을 하는 경우에 operation이 blocking 되어 있다고 합니다.

 Node.js는 다수의 동시작업을 처리할 수 있지만 thread를 나누는 방식으로 하지 않습니다. 

 사실 Node.js는 단일 thread입니다. 

 대신, Node.js는 동시작업을 event loop을 실행해서 처리하며 개발자들은 이것을 사용할 수 있습니다. 

 우리는 blocking 동작을 피하고 non-blocking 동작을 사용해야만 합니다.

그러기 위해서는 callback 으로 함수를 다른 함수에게 넘겨야 합니다.

/**

var exec = require("child_process").exec;

function start() {

  console.log("Request handler 'start' was called.");

  var content = "empty";

  exec("ls -lah", function (error, stdout, stderr) {

    content = stdout;

  });

  return content;

}

**/

위 start 함수의 실행결과는 empty 가 바로 출력이 됩니다.

우리는 새로운 Node.js 모듈인 child_process를 사용했습니다. 

매우 단순하지만 쓸모가 많은 non-blocking 동작인 exec()을 사용하기 위해서 입니다.

그렇지만 그 이유는 exec()을 호출하자 마자 Node.js는 이어서 return content;를 실행합니다. 

바로 이 시점에 content는 여전히 "empty" 입니다. 

왜냐하면 exec()은 비동기적으로 동작하기 때문에 exec()에 전달된 callback 함수는 아직 호출되지 않았던 것이죠.


request handler 가 non-blocking 방식으로 동작하면서 응답하기

현재 우리 애플리케이션은 사용자에게 보여주고 싶은 content를 

request handler에서 HTTP server로 전달할 수 있습니다. 

다음과 같은 여러 애플리케이션 레이어들을 거쳐 넘기는 식으로 식으로 말입니다. 

(request handler -> router -> server).


새로운 접근 방법은 다음과 같습니다: 

content를 server로 보내는 대신 server를 content로 보낼겁니다. 

좀 더 자세히 이야기 하면, response 객체 (server의 callback 함수인 onRequest() 에서 얻은)를 

router를 통해 request handler에게 주사(inject) 합니다. 

이제 handler는 이 객체가 가진 함수들을 이용해서 스스로 요청에 응답할 수 있게 되었습니다.


POST 요청 처리하기

textarea 를 하나 제공해서 사용자가 내용을 채우고 submit 해서 post 요청을 서버로 보내는 시나리오 입니다

requestHandler.js 의 start 함수에 testarea를 포함하는 html을 response 하도록 수정합니다.

function start(response) {

  console.log("Request handler 'start' was called.");

  var body = '<html>'+

    '<head>'+

    '<meta http-equiv="Content-Type" content="text/html; '+

    'charset=UTF-8" />'+

    '</head>'+

    '<body>'+

    '<form action="/upload" method="post">'+

    '<textarea name="text" rows="20" cols="60"></textarea>'+

    '<input type="submit" value="Submit text" />'+

    '</form>'+

    '</body>'+

    '</html>';

    response.writeHead(200, {"Content-Type": "text/html"});

    response.write(body);

    response.end();

}

POST 요청은 상당히 클겁니다. 

누구도 사용자가 몇 메가바이트의 텍스트를 입력하는 것을 막을 수 없겠죠. 

전체 데이터 블록을 하나로 처리하는 것은 blocking operation 방법이 될 것입니다.

전체 프로세스를 non-blocking 으로 만들려면, 

POST 데이터를 작은 청크로 나누고 특정 이벤트 때마다 

callback을 호출하는 방식으로 만들어야 합니다.



참고사이트

김종령의 생각 : http://jongryong.wordpress.com/tag/node-js/

screenr.com 웹기반동영상 제작편집 : http://ktk350.blog.me/100144575612

Node.js란? : http://www.ibm.com/developerworks/kr/library/os-nodejs/index.html

CoffeeScript 의 첫경험 : http://www.ibm.com/developerworks/kr/library/os-nodejs/index.html

html5로 flac파일 재생하기 : aurora.js, ofmlabs 의 github

The Node Beginner Book Korean Edition : http://www.nodebeginner.org/index-kr.html


블로그 이미지

희망잡이

,