데스크탑은 성능이 뛰어난 부품들을 구입한뒤에 조립해서 사용하면 되지만 노트북은 다릅니다.

고장이 났을때 부품을 교체하기도 힘들고 한번 고장나면 수리비도 만만치 않습니다.

그래서 노트북을 선택할때 중요한 것이 AS인데... hp, 도시바, 레노버 등은 외산으로 as가 취약합니다.

그다음에 선택해야 할 점이 노트북 무게 입니다.

노트북을 데스크탑 대용으로 사용할 목적이라면 14~15인치의 odd 장치를 포함하고 있는 것을 고르면 될듯 합니다.

가격도 저렴합니다.

그러나 휴대를 목적으로 한다면 이야기는 달라 집니다. 12 ~ 13인치가 적당할듯합니다. 

무게도 1.5KG 정도 이라고 하네요.

그리고 발열, 소음 도 고려해야 합니다. 레노버가 강하다고 하네요.

노트북 키를 누르는 감도, 노트북 가격도 중요할 겁니다.

무엇보다 노트북 용도가 중요하리라고 봅니다. 게임을 하거나 동영상을 편집할 목적이라면 성능이 뛰어난 것을 골라야 합니다.

하지만 논문작성이나 웹서핑, 블로그 작성, 엑셀, 파워포인터 작업이라면 뛰어난 성능은 불필요할 듯합니다.

레노버에 사용되는 CPU i3, i5, i7 이 있는데 i3 정도면 만족할 듯하네요.

하루정도 인터넷을 뒤지다가 눈에 들어온 노트북이 있습니다. 

LENOVO 싱크패드 X220i 4286-PH4


화상통화가 대세이기에 비디오 와 오디오 성능이 중요합니다.

스카이프로 화상통화를 할려고 하면 노트북에 웹캠이 있어야 하겠지요. 그리고 사운도도 좋아야 하고요.

이정도의 노트북이면 직장에서 사용하기엔 좋을듯 합니다.


블로그 이미지

희망잡이

,




25주년 기념 공연이 런던 로얄 알버트 홀

팬텀과 크리스틴 역을 맡았던 라민 카림루(Ramin Karimloo)와 시에라 보게스(Sierra Boggess)가 영광스러운 기념 무대에 올라 팬텀과 크리스틴을 연기합니다.

한정된 공간에서 어떻게 이런 효과와 감동을 이끌어 낼수 있는지 감탄이 절로 나옵니다.

무대연출가라는 직업도 매력이 있을듯 합니다. 

팬텀이 크리스틴에게 Sing for me. Sing~ 하는 장면

드라이아이스가 흐르는 무대위를 배를 타고 가는 장면

볼거리가 많습니다.

오페라가 끝나고 앤드류 로이드 웨버가 나와서 소감을 이야기 하기 시작합니다.

이전에 공연에 참석했던 팬텀역을 맡았던 배우들. 그리고 크리스틴역의 원년멤버 사라 브라이트만.



또 다른 감동과 즐거움을 주네요.

뮤지컬의 천재 작곡가 앤드류 로이드 웨버~  

오페라의 유령, 더 캣츠 등을 작곡했다고 합니다.

세월의 향기를 느낄수 있는 멋진 공연이네요.




블로그 이미지

희망잡이

,


원문사이트 : 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


블로그 이미지

희망잡이

,


데이비드 닉 라일리 저자 소개

1949년 영국에서 태어났다. 캠브리지대학교에서 경제학을 전공했으며 1975년 GM 디트로이트 디젤 앨리슨 사업부에 입사하면서 GM과의 인연이 시작되었다. 이후 벨기에, 미국, 멕시코, 유럽 등 전세계 GM 지사를 거치며 GM 발전에 혁혁한 공로를 세웠다. 2002년 GM대우 사장으로 임명되어 한국에 첫발을 내딛은 후 불과 3년만에 적자투성이의 옛 대우자동차를 흑자기업으로 정상화시킨 것은 물론 1,725명의 정리해고자 중 희망자 전원을 복직시켜 반목과 투쟁의 노사관계에 익숙해 있던 많은 사람들을 놀라게 했다. 이것은 밤을 새워 노조원들과 소주잔을 기울이고, 함께 뛰고 땀흘리며, 강화도 봉천산 정상에서 돼지머리를 놓고 노조위원장과 고사를 지냈던 그의 상생경영이 이뤄낸 값진 결실이었다. GM 대우에서의 성과를 인정받아 2006년 7월 GM 아시아태평양지역본부 사장 겸 GM 대우 이사회 회장으로 승진해 중국 상하이로 자리를 옮겼다. 그를 떠나보내는 고별식에서 이성재 전 노조위원장이 ‘당신을 언제나 기억하겠습니다’라고 쓰인 감사패를 전달한 것도 대한민국 노조역사상 유례가 없는 일로 회자되고 있다. 그의 각별했던 한국과 한국인에 대한 애정은 현재 진행형으로, 최근에도 그는 틈날 때마다 한국에 들러 지인들과 소주잔을 기울이고 있다


데이비드 닉 라일리 씨가 회사를 방문하여 자동차부품회사의 글로벌 전략에 대한 마음가짐에 대해서 강연을 하였습니다.

강연장이 천장이 낮고 시멘트 바닥이라 소리울임이 심해서 잘 듣지는 못했지만 통역을 동반한 강연이라서 그런대로 내용을 이해할수 있었습니다. 통역자도 가끔씩 문장을 잘못알아 들어서 실수도 했습니다.

2000년 초반에 대우가 몰락하면서 GM이 인수를 했을때 CEO로 왔던게 기억이 납니다.

GM대우로 부터 부품 납품가를 받지 못해 부품공급을 중단한적도 있었던 정말 어려웠던 시기 였습니다.

이시절 100% 신차 라는 광고카피를 사용하여 홍보되었던 차 라세티. 유일하게 많이 판매된 차량이고 글로벌 카로 인정 받은 차입니다.

내가 최초로 구입한 차이면서 지금까지 무난하게 몰고 다니고 있습니다.

CEO 분들이 강연할때 사용하는 언어는 뭔지 특별한게 있는거 같습니다. 의사전달을 명확하게 하기 위해 귀에 익숙한 단어들을 대부분 사용합니다. 회사의 CFO 이셨던 이스라엘 출신의 그 분도 참 편한 영어를 사용했었습니다.

경쟁이란...

회사 내부에서 동료들끼리 하는 것이 아니라 회사 외부에서 경쟁자들과 해야 하는 것입니다. 회사동료들 끼리는 협업을 통한 하나의 팀으로서 나아가야 합니다.

조직이란...

회사의 일반적인 조직구조는 삼각형입니다. 무한경쟁사회에서 살아남기 위한 조직을 역삼각형입니다.

사원이 신뢰와 믿음을 받고 있다는 것을 느끼게 할수 있도록 위에 있는 임원진이 노력하는 구조를 말합니다.

할수 있다는 생각과 뭐든지 하고 싶도록 근무환경을 만들어 주는 것. 이것이 발전할수 있는 조직구조입니다.

어떻게 살아가야 하는지...

어렸을때 4개월동안 산속에서 자신이 무엇을 하고 싶은지, 그리고 누구인지를 생각할수 있는 시간을 가진적이 있다고 하더군요.

그때 생각했던 것이 지금까지 살아오는 힘이 되었다고 합니다.

삶의 철학을 가진다는것이 싶지는 않지만 살아가는데 필요한 것인거 같습니다.


GM대우사장으로서 부임하여 노조와의 관계를 정상화하는데 많은 노력을 하였다고 합니다. 

가장 먼저  대한민국의 문화, 인간관계를 파악하고 노조에게 접근했다고 하네요.

오늘 강연하는 모습을 보니 따뜻하고 푸근한 느낌을 풍기는  분이었습니다.



블로그 이미지

희망잡이

,

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


블로그 이미지

희망잡이

,