728x90

HTML5 에는 로컬 자원을 활용하는 유용한 기능들이 포함되어 있다
대표적인 예로 웹 스토로지, 웹 데이타베이스, 어플리케이션 캐시등을 들 수 있다

이 블로그에서 이 들 스펙에 대해 간략하게 다루었었다
: [HTML5] Web Storage
: [HTML5] 오프라인 웹 어플리케이션
: [HTML5] Web SQL Database

이와같은 로컬 자원을 활용하면 웹 응용프로그램의 사용성, 응답성, 성능등과 같은 전반적인 효율성을 꾀할 수 있어 많은 활용도가 기대된다

이들 기술의 기능적 구현에 대한 이해와 더불어 환경에 대한 이해도 같이 해 두면 유용할 것이다
이전 글에서는 기술의 개요와 구현에 대해 살펴보았다면 이 글에서는 로컬 자원의 저장 위치와 한계 용량, 지속 기간 등의 환경적 요인들을 살펴 보고 이들 기술의 이해의 폭을 넓히고자 한다

그럼 이제부터 HTML5에서 로컬 자원을 어디에, 얼마나, 언제까지 저장하는지 살펴 보도록 하자.
참고로 로컬 영역에 대한 내용이다 보니 클라이언트 PC의 OS와 브라우저의 종류, 버전에 따라  내용이 조금씩 다를 수 있음을 밝혀 둔다. 그리고 가정을 하건대, 로컬 디스크의 용량은 무제한이라고 가정해 둔다. 기술별 최대 용량을 따져보는 와중에 컴퓨터 하드디스크 자체에 여유공간이 없다면 아무런 소용이 없기 때문이다

이 글은 윈도우 XP를 사용하고 IE8, 그외 브라우저(크롬,사파리등)은 현재시점(2010.10.19) 최신버전을 사용하고 있는 것을 기준으로 하고 있다

어디에 저장되는가?
대부분의 로컬자원은 OS의 사용자별 어플리케이션 데이터 공간에 저장된다
윈도우 XP에서는 'C:\Documents and Settings\사용자계정\Local Settings\Application Data' 가 어플리케이션 데이터를 저장하는 공간이며 이 디렉터리 하위에 있는 각 브라우저별 폴더에 로컬자원이 저장된다
윈도우에서 'C:\Documents and Settings\사용자계정' 의 경로는 %userprofile%로 대체 된다

LocalStorage
크롬: %userprofile%\Local Settings\Application Data\Google\Chrome\User Data\Default\Local Storage
사파리: %userprofile%\Local Settings\Application Data\Apple Computer\Safari\LocalStorage
파폭: %userprofile%\mkex\Application Data\Mozilla\Firefox\Profiles\xxx.default\webappsstore.sqlite 파일
오페라: %userprofile%\Application Data\Opera\Opera\pstorage
IE8: %userprofile%\Local Settings\Application Data\Microsoft\Internet Explorer\DOMStore

SessionStorage
세션스토로지의 경우 브라우저 프로세스의 메모리 영역에 저장되므로 물리적인 시스템 디렉터리에 저장되지 않는다. 따라서 데이터 저장을 위한 별도의 디렉터리 경로가 없다

Web SQL Database
크롬: %userprofile%\Local Settings\Application Data\Google\Chrome\User Data\Default\databases
사파리: %userprofile%\Local Settings\Application Data\Apple Computer\Safari\Databases
파폭: 지원되지 않음
오페라: %userprofile%\Application Data\Opera\Opera\pstorage

Application Cache
크롬: %userprofile%\Local Settings\Application Data\Google\Chrome\User Data\Default\Application Cache
사파리: %userprofile%\Local Settings\Application Data\Apple Computer\Safari\ApplicationCache.db 파일
파폭: %userprofile%\Local Settings\Application Data\Mozilla\Firefox\Profiles\xxxxx.default\OfflineCache
오페라: %userprofile%\Local Settings\Application Data\Opera\Opera\application_cache


얼마나 저장되는가?
LocalStorage
로컬스토로지의 경우 브라우저마다 최대 저장용량이 다를 수 있다. 더 엄밀히 말하면 브라우저, 도메인마다 최대 용량이 다를 수 있다. 로컬스토로지는 같은 도메인 정책보안을 따르기 때문에 최대 용량 역시 도메인별로 한정을 하고 있다. 예를 들어 파이어폭스는 도메인당 최대 5MB 까지 가능하다
표준 스펙에 의하면 5MB를 최대 용량으로 권장하고 있으니 대체로 다른 브라우저도 이와 비슷할 것으로 보인다. 만일 한 도메인에 localStorage의 값을 5MB 이상 저장해야 한다면 브라우저가 이를 지원하는지 따져봐야 한다. (IE8의 경우 도메인당 10MB를 지원하는 것 같다)
(기존 쿠키가 4KB로 제한을 둔 것에 비하면 5MB 공간은 웹 환경에서 상당량이라 할 수 있다) 

SessionStorage
세션스토로지의 경우 전역적인 공간이 아닌 브라우저 컨텍스트 영역에 저장되므로 브라우저 프로세스, 메모리와 연관이 있다. 이런 특징에 기인했는지 최대용량에 대한 언급을 찾을 수 없다. 다시 말해 브라우저 자체적으로 용량에 대한 제한을 두는지 localStorage 와 합쳐서 도메인당 용량을 계산하는지 아니면 브라우저 컨텍스트에서 사용 가능한 시스템의 메모리 크기에 의존하는지 등에 대한 언급은 없지만 개인적으로는 후자, 즉 브라우저 프로세스가 사용하는 시스템 메모리 크기에 의존하지 않을까 예상해 본다

Web SQL Database
웹 데이터베이스 용량의 기준은 LocalStorage와 개념적으로 유사하다.
즉 브라우저별로 최대 용량이 다를 수 있으며 도메인 단위로 관리된다.
그러나 LocalStorage 비해 용량의 유연성이 더 크다. 다시말해 더 큰 크기의 데이터저장이 가능하다는 것이다
HTML5 표준 사양에는 DB 용량에 대한 규정을 별도로 두지 않고 있으며 브라우저의 정책에 따라  DB용량의 기준이 다를 수 있다는 것을 명심하자DB를 생성하는 openDatabase 함수의 estimatedSize 매개변수에 생성하고자 하는 DB의 크기를 바이트 단위로 지정할 수 있는데 이 크기는 DB의 대략적인 크기를 지정하는 것으로 브라우저마다 그 적용이 다를 수 있다는 것이다.
openDatabase(in DOMString name, in DOMString version, in DOMString displayName, 
                                         in unsigned long estimatedSize, in optional DatabaseCallback creationCallback);


사파리 브라우저를 통해 DB 용량에 대한 내용을 체크 해 보자
다음 코드와 같이 기가(GB)단위의 큰 DB를 생성한다

var db = window.openDatabase("myDB","1.0", "테스트용DB", 1024*1024*1024);

사파리에서 위 코드를 실행하면 다음 그림과 같이 허용할 것인지 대화상자가 나오고 사용자가 허용하면 정상적으로 DB가 생성된다. (심지어 크롬과 오페라는 허용 여부를 묻지도 않고 생성해 준다)



그러나 브라우저마다 기본적으로 설정한 기본 크기는 있다. 사파리의 경우 기본 5MB 이며 환경설정에서 이를 변경할 수 있다. 아래화면은 '사파리의 기본설정->보안탭 화면' 인데 기본 5MB 설정에, 500M까지 변경 가능하다. 여기에서 설정한 기본크기 보다 작은 크기의 DB를 생성하면 자동으로 기본크기가 적용되며 반대로 기본크기보다 큰 DB를 생성하면 앞서 본것과 같이 허용을 묻는 대화상자가 나타나는 것이다
이때 openDatabase에서 명시한 DB크기가 설정되는 것이 아니라 브라우저의 임의의 계산식에 의해 좀더 넉넉한 공간을 확보하게 되는데 위 예에서 1G DB를 생성했는데 1.2G 로 잡힌 이유도 여기에 있다


이렇듯 사파리에서는 DB크기를 유연하게 관리하는 것으로 미루어보건대, 만일 기존에 생성된 DB의 크기보다 더 큰 데이터를 입력하려고 하면 자동으로 크기가 일정부분 확대될 것으로 예상된다
(일반적인 DBMS 가 그러한 것 처럼...)

참고로 기존에 생성된 DB의 크기를 다음과 같이 수동으로 변경이 가능하다.
아래 화면은 사파리에의서 기존에 생성된 DB를 도메인별로 나타내고 각 DB의 현재 크기와 최대 크기를 명시하고 있는 화면이다. 여기서 도메인별 DB 최대 크기를 사용자가 변경할 수 있다


크롬브라우저는 '옵션->고급설정탭->컨텐츠설정->쿠키->쿠키및기타사이트데이터표시'에서 확인 가능하다


오페라브라우저는 '설정->환경설정->고급설정탭->저장공간'에서 확인 가능하다


결론적으로 웹 데이타베이스의 용량은 특별히 제한을 가해 두지 않은 듯 하며 유연한 확장이 가능해 보인다
다만 브라우저마다 그 기준이 다를 수 있기 때문에 필요할 경우 브라우저 사양서을 확인하면 좋을 것이다

용량에 특별히 제한을 가해 두지 않았다는 것이 무제한으로 사용가능하다는 의미는 아니다.
당연하겠지만 하드디스크의 용량을 넘어설 수 없으며 그게 아니더라도 너무 무리한 용량은 예상치 않은 동작을 유발할 수도 있다. 사파리의 경우 자동으로 계산되는 최대크기가 매우 가변적인다.

예를들어 10G로 생성하면 2.3G로 잡고 7G로 생성하면 3.4G로 잡고 100G로 잡으면 최대크기는 오히려 기본크기로 잡히는 등 예측할 수 없는 결과를 보여 주고 있다. 따라서 너무 무리한 크기 설정은 피하는 것이 좋으며 서버급 DB가 아닌 로컬 DB에서 이와같이 과도한 크기를 이용하는 시나리오가 있다면 설계를 잘 못한 것일 수도 있다. 그리고 최대크기라는 기준이 큰 의미가 없을 수도 있다. 사파리에서 최대크기를 명시하더라도 실제 데이터를 저장하고 있는 시스템 디렉터리 파일은 현재크기로만 존재한다. 그리고 데이터 입력이 증가할 수록 용량은 점점 확장된다.

결론적으로 특별히 제한을 가해 두지 않았다는 의미는 사용할 만큼의 충분한 공간을 제공한다 라는 의미로 해석하기 바란다


Application Cache
어플리케이션 캐시의 저장 용량을 따져보는 것은 어찌보면 무의미 할 수 있다
로컬스토로지나 웹데이타베이스와 같은 것은 저장소라는 개념이 명확해서 사용 가능한 공간, 용량이라는 개념을 적용시킬 수 있으나 어플리케이션 캐시는 이런 개념과는 조금 다르기 때문이다.
그러나 이것 역시 로컬의 어딘가에 저장되어 캐시 되기에 굳이 용량에 대한 관점으로 본다고 하면, 어플리케이션 캐시가 저장되는 시스템 하드디스크의 크기라고 말할 수 있겠다.

다만 IE의 임시인터넷파일과 같이 저장공간에 제한을 둘 수도 있는데 이것과 관련해서도 역시 각 브라우저 정책에 따른다는 것이다.

HTML5 스펙에서는 어플리케이션 캐시에 대한 디스크 공간을 다음과 같이 설명하고 있다.
User agents should consider applying constraints on disk usage of application caches.
User agents should allow users to see how much space each domain is using, and may offer the user the ability to delete specific application caches.
 


언제까지 저장되는가?
LocalStorage
로컬스토로지는 특수한 상황이 아니라면 영구적으로 데이터를 보관한다
특수한 상황이라 하면, 사용자가 직접 데이터를 삭제하거나 브라우저를 제거하거나 OS를 재설치하는 것을 말한다. 이러한 특수한 상황이 아니라면 데이터는 영구적으로 보관된다

SessionStorage
세션스토로지는 브라우저 창이 닫힐 때 까지 보관된다. 엄밀히 말하면 브라우저컨텍스트라는 일종의 프로세스 도메인이 활성화되어 있는 동안만 데이터가 유지된다. 쉽게 말해 브라우저 창이 열려 있는 동안 데이터가 보관 된다고 생각하면 되겠다

Web SQL Database
웹 데이터베이스는 LocalStorage와 같이 특수한 상황이 아니라면 영구적으로 데이터를 보관한다

Application Cache
어플리케이션 캐시에 보관되는 데이터의 유효기간을 따지는 것은 앞서 용량을 따지는 것보다 더 무의미하다
앞서 다른 기술들과 마찬가지로 특수한 상황이 아니라면 영구적으로 보관될 것이며 캐시를 업데이트 하거나 캐시 저장공간이 꽉 찾을 경우 덮어 쓰는 등의 시나리오에서 일부 갱신되거나 유실될 수 있을 것이다

728x90
태생적으로 웹은 로컬 혹은 네이티브 환경보다 느릴 수 밖에 없는 구조이다

HTML5 의 등장으로 웹이 응용프로그램화가 가능해졌다고는 하지만 웹이라는 환경에 기인하는 이상 네이티브 응용프로그램의 속도나 성능을 기대하기는 어렵다는 것이 사실이다

HTML5를 적극 지지하는 한 사람인 필자 역시 이 부분은 냉정하게 생각해봐야 한다고 본다
혹여 누군가, HTML5만 이용하면 기존 응용프로그램의 수준과 동일하게 구현할 수 있다고 한다면 일단 의심해 봐야 한다. 그 수준이라는 것이 기능적인 측면에서만 바라본다면 그럴 수 있으나 속도나 보안성과 같은 응용프로그램의 기능,비기능적 측면을 모두 따져 본다면 결코 만만한 것이 아니다

예컨대 오프라인 어플리케이션 캐시, 웹 워커, 웹 스토로지, 웹 데이타베이스를 활용해 응용프로그램의 성능을 향상시킬 수 있으며 현재 가속화되고 있는 브라우저 성능 개선도 웹 응용프로그램의 성능향상에 상당부분 기여한다. 하지만 저 건너편, 웹에 있는 원격지의 데이터에 많은 부분 의존할 수 밖에 없는 환경과 OS위에서 동작하는 브라우저 환경, 인터프리터 방식의 해석 환경, 전송계층보다 한단계 위인 응용계층의 통신 활용이 빈번한 웹이 네이티비의 그것과 완전성을 같이 한다는 것은 어불성설이다

이러한 문제는 시각의 차이에서 기인하기도 한다.
과연 웹 응용프로그램이 네이티브응용프로그램과 그 성격이 같으냐는 문제를 고려해 봐야 한다
HTML5가 추구하는 바가 웹이 모든 네이티브 응용환경을 대체하겠다는 것은 아니다
기존의 웹 보다 그 경계를 낮출 수 있는 수단으로써의 웹이 어찌보면 더 적합할 수도 있다
물론 웹이 네이티브 환경보다 더 많이 가진 여러 장점들은 일일이 논하지 않겠다

HTML5에 대한 업계, 개발자, 사용자의 기대가 큰 것은 좋은 현상이다
태생적으로 다른 두 환경을 동일시 하기는 힘들지만 그럼에도 불구하고 이런 기대를 져버리지 않기 위해 분명 고래해 볼 점은 있겠다.

넘을 수 있는 벽인가 아닌가를 따지는 것도 중요하지만 그 전에 HTML5 그리고 웹환경이 가진 일종의 단점을 집어 보자. 대표적으로 다음의 3가지를 들 수 있겠다

- 느린 속도
이건 HTML5의 단점이 아니라 웹의 단점이다. 오히려 HTML5는 느린 웹을 향상시켰다
그러나 여전히 네이티브의 그것과 비교하면 느릴 수 밖에 없다.
전용 앱이 아닌 모바일 웹을 채택하지 못하는 많은 이유가 여기에 기인하기도 한다

- 불안한 호환성
이건 언젠가 해결될 문제이기도 하다
현재 HTML5 를 지원하는 브라우저마다 조금씩 다른 지원형태를 보인다
상용 서비스를 개발하는 입장에서 참으로 피곤한 문제라 하겠다

- 느린 대응
예전부터 HTML5 표준화 시점에 대해 말이 많았다
한 업체에서 주도적으로 개발하는 다른 제품과는 달리 여러 업체가 그것도 표준화 기구와 맞물려 작업을 하다 보니 느릴 수 밖에 없다. 실시간 환경, 급변하는 환경에서는 어울리지 않는다
표준화가 완료되더라도 이후 환경변화에 대한 빠른 대응이 가능할지 의문이 드는 대목이다


그래서 최적이 중요하다
웹의 장점, 웹의 단점, 웹의 이상, 웹의 한계, 그리고 비즈니스의 접목...
모든 것이 가능하지도 모든 것이 불가능하지도 않다는 시각. 다만 최적의 방안만이 존재한다는 시각.
이런 시각을 위해서는 정확한 지식과 유연한 지혜가 필요하다

HTML5 가 대세이며 그가 할 수 있는 일은 매우 많으며 우리 비즈니스를 이렇게 해결할 수 있겠다라는 청사진을 제시할 수 있으려면 HTML5의 한계, 나아가 웹의 한계에 대해서도 정확히 집어 낼 수 있어야 하겠다

=> [m오피스 프레임워크③]MEAP 도입의 고려 사항그리고 느린 표준화?

구글, 크롬OS 발표, 기대와 혼란!

Posted in 일상 // Posted at 2010. 10. 18. 12:07
728x90
구글에서 크롬 OS 를 발표 했다고 한다
이건 뭐,.. 플랫폼의 춘추 전국 시대인가? 그 어느때와 달리 플랫폼 홍수시대가 아닌가 싶다

크롬 OS는 리눅스위에 돌아가는 크롬 브라우저 기반의 OS라고 하며, 우선 타블렛 PC 를 겨냥한 플랫폼이라고 한다. 여태껏 구굴 안드로이드의 범용화를 예상했던 시나리오와 정면으로 충돌되는 발표이다

안드로이드와 크롬OS를 설명하는 구글의 관계자는 다음과 같이 말한다
안드로이드는 작은 스크린 사이즈를 가지는 모바일 폰을 위주로 개발되었고, 크롬은 10인치 가량의 큰 스크린 사이즈를 가지는 넷북을 위해 적합하게 개발되어 서로 충돌하지 않는다

그리고 업계의 이런 구분도 있다
업계는 당초 구글이 일반 인터넷을 쓰면서 온라인에서 시간을 보내는 이들에게 브라우저형 플랫폼인 크롬OS를 내놓고, 안드로이드를 통해서는 설치형 애플리케이션을 활용하는 사용자들을 겨냥한 것으로 구분키도 했다

뭣이 어떻든, 이건 혼란이랄 수 밖에 없다.  음...
그러나 혼란이 야기될 수 밖에 없는 시대적 흐름과 그 혼란으로 변화할 환경에 초점을 맞출 필요도 있다

=> 구글 크롬OS 출시 임박…PC시장 또 흔들
=> 한 곳을 향한 두가지 길…구글의 ‘안드로이드’와 ‘크롬OS’


요즘 차세대 웹 환경에 꽂혀 있던 나에게.. 그나마 고무적인 사실은,
크롬 OS가 웹 브라우저에 기반한 OS이며 여기에서 운용될 많은 어플리케이션들이 바로 웹 어플리케이션이라는 점이다. 관련 기사의 일부를 발췌 한다
웹브라우저가 OS였고 웹페이지가 애플리케이션이었다
사용자가 크롬OS 안에서 설치 또는 저장할 수 있는 것은 브라우저로 접근하는 웹애플리케이션 뿐이다


플랫폼의 홍수 속에서도 한가지 분명한 사실은, 웹이라는 환경의 저변확대라는 점이다
오픈, 표준, 공유, 경량의 개념이 수용되는 이상 웹 환경은 그 중심에 있을 수 밖에 없을 것이다

그리고 웹 기반 어플리케이션이라는 환경과 하드디스카와같은 저장장치가 없어 기존 PC의 수 많은 응용프로그램을 사용할 수 없다는 여러 지적에 대해서는, '크로모팅(Chromoting)’ 이라는 기능으로 응수하고 있다. 별도의 PC환경을 갖춘 단말기에 접속하는 개념이라 굉장히 불편해 보이지만 이것 역시 일종의 클라우드의 개념이 들어간 서비스가 아닌가 싶다

=> 구글 크롬OS, 윈도SW도 지원하나




이번 구글의 크롬 OS 발표를 보면서 두 가지 키워드가 떠오른다.
바로 '클라우드'와 ''이다

순수한 단말로써의 장치, 설치가 아닌 접속의 개념이 철학이 녹아든 OS가 아닌가 싶다
=> 구글크롬 앱스토어 10월 등장···게임공간 진입

윈도우, 리눅스와 같은 기존 OS와의 경쟁?, PC시장 혼란?
글쎄.. 새로운 플랫폼이 등장할 때 마다 기존 플랫폼과의 교체가능성 및 혼란을 언급하지만 당장 수년간의 직접적인 변화는 없을 것으로 보인다. 다만 일종의 공생관계나 상호보완적 관계를 유지하다가, 종국에 합치가 되는 시점에서의 기준은 플랫폼의 우수성이 아니라 시장의 변화,환경의 변화에 기인하는 결과가 나오지 않을까 싶다

마지막으로 크롬 OS를 설치한 블로그의 내용을 훓어 보자.
기존에 생각했던 OS와는 개념적으로 많이 다르다는 것을 알 수 있다
=> 크롬 OS 설치기
728x90

MKEXDev.NET 의 로고가 필요하게 된 적이 있었다

대학생에게 무료로 개발도구를 배포하는 마이크로소프트의 DreamSpark 이벤트에 후원 커뮤니티로 선정되어 사이트 로고를 보내줘야 했다. 당시 내 사이트에는 특별한 로고가 없었으나 MS 프로모션 담당자는 이미지로 된 로고를 원했다. 그래서 급조하기로 했는데 개발을 주제로 한 사이트라 뭐.. 특별한 디자인을 하고 싶지는 않았다. 그냥 텍스트에 간단한 효과를 줘서 깔끔하게만 보이면 되겠다 싶었다.

그래서 아는 디자이너에게 매우 심플하게 만들어 달라고 부탁해서 나온 로고가 바로 아래와 같은 모습니다.
심플하면서도 깔끔한 텍스트 기반의 로고로 개인적으로 흡족하며 지금까지 사이트 로고로 사용하고 있다



이를 계기로 문득, 텍스트를 입력하면 간단한 효과만 처리해서 이미지로 변환해 주는 툴이 있으면 좋겠다는 생각이 들었는데 마침 HTML5를 접하면서 간단하게라도 데모격으로 한번 만들어 보자고 맘을 먹었다

목표는 완성도가 아니라 기능을 구현하면서 HTML5를 익히자는 것이므로 툴의 완성도는 기대하지 말기 바란다

CSS3 ?  Canvas ?
텍스트에 효과를 주는 방법은 많다. HTML5 관련 스펙만 봐도 CSS3 혹은 Canvas 를 이용할 수 있다
CSS의 Transform 이나 text-stroke, opacity, Gradients 등과 같은 기능만으로도 화려한 텍스트 효과처리가 가능하다. 그러나 앞서도 밝혔지만 CSS 보다는 HTML5 주요 기능을 익히는 것이 목적이므로 Canvas를 이용하기로 결정했다. Canvas를 이용해도 텍스트 크기, 그라디에이션, 색상, 폰트, 그림자, 투명도 등 처리가 가능하다
게다가 Canvas의 내용을 이미지로 변환할 수 있으니 더욱 적합하다는 생각을 하게 되었다


데모 실행
코드를 보기 전에 먼저 데모 실행화면을 살펴 보자


하단 텍스트상자에 글자를 입력하면 상단의 캔버스에 표시되며 몇 가지 텍스트 효과를 줄 수 있다
이 모든 텍스트 효과처리는 HTML5 Canvas 관련 기능을 이용한 것이며 캔버스의 최종 결과를 이미지로 변환시켜 주는 기능이 지원된다. 텍스트상자에 글이 입력되거나 삭제될 때 바로바로 그 내용이 캔버스로 반영되며 텍스트 효과도 즉시 적용되어 캔버스에 나타난다.

참고로 텍스트 효과는 데모에 적용된 기능 이외에도 그림자 효과, 그라디에이션 효과 등 더 다양한 처리가 가능하지만 데모에서는 기본적인 효과만 집중했음을 밝힌다

IE8 이전 버전을 제외한 크롬, 사파리, 오페라에서 실행 가능하며, 다음의 주소에서 확인할 수 있다
http://mkexdev.net/m/textToImageByCanvas.html


구현 하기
전체 코드를 보기 전에 몇 가지 핵심적인 내용을 살펴 보자

자바스크립트 키 관련 이벤트
HTML5 Canvas API 설명전에 먼저 자바스크립트의 키 관련 이벤트를 짚고 넘어가자
자바스크립트에는 키보드 입력과 관련된 총 3개의 이벤트가 제공된다.

keydown, keyup, keypress 가 그것인데 이들 이벤트는 키 입력에 반응하는 것이 조금씩 다르다
keydown 과 keyup 은 유사하지만하지만 keypress 는 이 둘과 약간 차이가 있는데 데모 제작과 관련해 주목해야 할 것은 keypress 는 백스페이스키(<-) 에 반응하지 않는다는 것이다.

그리고 keydown 과 keyup 의 경우 이벤트로 넘겨진 keyCode 에는 영문 대/소문자를 구분하지 않고 모두 대문자로 취급한다는 것이다. 제작하고자 하는 데모는 대/소문자를 구분해야 하며 백스페이스키로 글자를 삭제해야 하기 때문에 하나의 이벤트로 만족할 수 없었다. 즉 keypress 이벤트로 문자 입력을 처리하고 keyup으로 백스페이스와 Delete키에 반응하도록 처리했다는 것을 먼저 알린다

아래 코드와 같이 두 이벤트를 동시에 정의해서 문자 키 입력에 두 이벤트가 반응하지만, 백스페이스와 Delete 키 등의 특수키에는 keyup 이벤트만 반응한다. keyup 이벤트는 일반 문자 입력은 무시하도록 처리한다.
<input type="text" id="myText" size="60" onkeypress="inputText(event.keyCode);"   onkeyup="inputBackSpace(event.keyCode);">


캔버스 지우기
캔버스의 내용을 모두 지우기 위해서는 몇 가지 방법이 있지만,
기본적으로 캔버스의 너비 혹은 높이 정보를 다시 설정하면 캔버스내용이 모두 지워진다고 알려져 있다
canvas.width = canvas.width;

그러나 이 방법은 현재 사파리와 파이어폭스에서만 정상 동작한다
브라우저마다 HTML5 지원 현황이 달라서 발생하는 문제로 보인다.따라서 모든 브라우저에서 동작하도록 하려면 clearRect 로 캔버스 내용을 명시적으로 지워줘야 한다

아래 코드와 같이 (0,0) 부터 캔버스의 너비,높이만큼이 사각형 영역을 지움으로써 캔버스를 초기화 할 수 있다
context.clearRect(0,0,canvas.width, canvas.height);


캔버스에 텍스트 그리는 방법
Canvas의 2D Context 를 통해 각종 그리기 작업을 할 수 있는데 텍스트의 경우 fillText 와 strokeText 메서드를 통해 그릴 수 있다. fillText는 속이 찬 텍스트, strokeText는 테두리만 있는 텍스트를 그릴 수 있다

데모에서는 텍스트상자에 글자가 입력될 때 마다 바로바로 캔버스에 그리기를 수행하는데,
이때 입력된 글자 하나씩 캔버스에 그리는 방법과 캔버스를 지우고 텍스트상자에 지금까지 입력된 전체 내용을 다시 그리는 방법 중 하나를 택해야 한다

전자의 경우 텍스트가 입력되는 위치를 직접 지정해 줘야 하기 때문에 조금 복잡하며 후자의 경우 매번 캔버스를 지우고 다시 그리는 작업을 해 줘야 하기 때문에 조금 비효율적이다

따라서 데모에서는 전자의 경우처럼 텍스트 입력 시 마다 글자 하나씩 캔버스에 입력하기로 했으며 이때 알아야 하는 입력 위치는 다음과 같이 measureText 메서드를 통해 전체 문자열의 길이를 구함으로써 해결하였다
(텍스트 상자가 멀티라인을 지원하지 않기 때문에 Y 좌표는 필요치 않다)
var textWidth = context.measureText(text).width;
context.fillText(text, textWidth  , 0);  //글자가 위치할 캔버스 X 좌표를 설정한다

다만 백스페이스키(<-)와 Delete 키를 눌렀을 때 글자가 지워지는 것은 심플한 처리를 위해,캔버스 내용을 지우고 다시 입력하는 후자의 방식을 따르기로 했다.
(글자 지우기 역시 clearRect 를 통해 정해진 글자 영역만 지울 수 있지만 이 경우 x 좌표의 변화와 폰트 크기에 따른 clearRect 크기 변경 등 신경 쓸 부분이 많아 오히려 버그 유발 요인이 될 수 있어 사용을 피하기로 했다)
context.clearRect(0,0,canvas.width, canvas.height);  //캔버스를 지우고
context.fillText(text, 0, 0);                                    //다시 전체 글자를 그린다


그리고 텍스트에 폰트, 색상과 같은 효과 처리는 2D Context의 속성들을 통해 이뤄지는데 이미 입력된 내용은 반영되지 않기 때문에 이때도 역시 캔버스를 지우고 다시 그리는 방식을 취한다 


기타 살펴볼 내용
캔버스를 통한 텍스트 효과 처리시 다음의 주요 코드가 이용 되었다

: context.textBaseline = "top"
 캔버스에 텍스트가 위치하는 수평 기준선을 top 으로 해 줌으로써  글자가 기준선 아래로 표시되도록 한다

: context.font = "20px  'Tahoma'"
font 속성을 통해 캔버스에 표시될 텍스트 폰트를 처리하는데 css 의 폰트 속성과 같이 정의할 수 있다

: context.fillStyle = "red"   , context.strokeStyle
fillStyle 속성을 통해 채우기 스타일을 지정할 수 있다. 기본은 검정이다. strokeStyle 속성은 선의 색상을 지정하는데 이용한다

: String.fromCharCode(keyCode)
HTML5 , Canvas와는 무관하지만 데모에서는 유용하다. 키 이벤트로 넘여온 keyCode 를 문자로 변환해 주는 자바스크립트 내장 함수이다. 한 글자씩 입력 할 경우 필요하다

: 캔버스 내용을 이미지로 변환하기
이미 살펴본 내용이다. 캔버스의 toDataURL 메서드를 통해 이미지데이터문자열을 기반으로 이미지객체를 생성한다. [HTML5 실습] Canvas에 그린 그림을 이미지로 만들기

이것으로 구현을 위한 핵심적인 내용을 대략 살표 보았다. 이제 전체 코드를 제시한다
전체 코드는 http://mkexdev.net/m/textToImageByCanvas.html 의 소스보기를 통해서도 볼 수 있다

<!DOCTYPE html>
<html>
<head></head>
<body>
  <form name="myForm">
  <canvas id="cv" width="400" height="70" style="position: relative; border: 1px solid #000;"></canvas> 
  <button onclick="clearCanvas()">Clear</button>
  <input type="button" onclick="convertImage()" value="이미지로변환">
  <img id="myImage">
  <br>   
  <input type="radio" name="isFill" value="Fill" onchange="chkFill();" checked>Fill
  <input type="radio" name="isFill" value="Stroke" onchange="chkFill();">Stroke
  <br> 
  Font: <input id="fontSize" type="range" min="10" max="60" step="5" value="50" onchange="changeFont();" />
        <select id="fontFace" onchange="changeFont();">
         <option value="Tahoma" selected>Tahoma</option>
         <option value="Verdana">Verdana</option>
         <option value="Gulim">Gulim</option>
         <option value="Georgia">Georgia</option>
         <option value="Symbol">Symbol</option>
         <option value="Terminal">Terminal</option>
        </select>
  <br>
  Fill Color: <select id="fontColor" onchange="changeColor(1);">
         <option value="Black" selected>Black</option>
         <option value="Red">Red</option>
         <option value="Blue">Blue</option>
         <option value="Green">Green</option>
         <option value="Yellow">Yellow</option>
        </select>
  Stroke Color: <select id="strokeColor" onchange="changeColor(2);">
         <option value="Black" selected>Black</option>
         <option value="Red">Red</option>
         <option value="Blue">Blue</option>
         <option value="Green">Green</option>
         <option value="Yellow">Yellow</option>
        </select>
  <p>
  <input type="text" id="myText" size="60" onkeypress="inputText(event.keyCode);" onkeyup="inputBackSpace(event.keyCode);">
  <div id="msgDiv"></div> 
  </form>
</body>
</html>
<script type="text/javascript">
if(window.addEventListener){
    window.addEventListener('load', Init, false);
}
var canvas, context, myText,msgDiv
var isFill = true;
function Init() {    
  canvas = document.getElementById('cv');
  context = canvas.getContext('2d');    
  context.font = eval("'"+ document.getElementById('fontSize').value +'px '+ document.getElementById('fontFace').value+"'");   
  context.textBaseline = "top";  
  myText = document.getElementById('myText');
  myText.focus(); 
  msgDiv = document.getElementById("msgDiv"); 
}
function inputText(keyCode){   
  msgDiv.innerText = keyCode;    
 
  //글자의 가로위치를 구하기 위해 현재 입력된 문자열의 너비를 구한다
  var textWidth = context.measureText(myText.value).width;     
  drawText(String.fromCharCode(keyCode), textWidth);     
}    
function inputBackSpace(keyCode){
  if(keyCode == 8 || keyCode == 46){ //백스페이스 키와 Delete키를 받기 위한 함수
    clearCanvas();
    drawText(myText.value,0);    
  }
}
function drawText(text, posX){ 
  if(!isFill){ context.strokeText(text, posX  , 0); }
  else{ context.fillText(text, posX  , 0); }
}
function chkFill(){
  isFill = myForm.isFill[0].checked;
  clearCanvas();
  drawText(myText.value,0);
}
function changeFont(){
  clearCanvas();
  context.font = eval("'"+ document.getElementById('fontSize').value +'px '+ document.getElementById('fontFace').value+"'");
  drawText(myText.value,0); 
}
function changeColor(flag){
  clearCanvas();
  if(flag == 1){
    context.fillStyle = document.getElementById('fontColor').value;
  }
  else{
   context.strokeStyle = document.getElementById('strokeColor').value;
 }
 drawText(myText.value,0); 
}
function clearCanvas(){
   //canvas.width = canvas.width;   //사파리, 파폭에서만 동작(크롬, 오페라 X)    
   context.clearRect(0,0,canvas.width, canvas.height);  
}
function convertImage(){
  var image = new Image();
  var myImage = document.getElementById('myImage');
  myImage.src = canvas.toDataURL();
}
</script>


HTML5 Canvas+Text Example
한참 삘(feel) 받아서 데모를 제작하다가 이 사이트를 알게 되었다
=> http://whatdo.net/html5/example/#2

내가 구현하고자 했던 대부분의 기능이 제공되고 있었다.
사실 데모의 완성도를 꽤 올리고자 맘 먹고 시도하던 도중에 이 사이트를 보게 되었고 동기가 한풀 꺽였다
이미 제공되고 있는 사이트가 있으니 내가 만들고자 하는데모에 새로움은 별로 없기에 받았던 삘(feel)이 사그러져 버렸다 ㅎㅎ. 그래서 적당한 선에서 데모 제작을 완료하고 포스팅 하게 된 것이다

이 사이트를 보면 조금은 다른 방식으로 구현하고 있지만 더 많은 canvas 기능이 활용되었고 구현 방식 역시 배울점이 많아 보인다. 소스보기를 통해 분석해 보면 많은 도움을 얻게 될 것이니 반드시 참고 바란다

페이지 요소(Element) 탐색

Posted in 모바일/Javascript // Posted at 2010. 10. 12. 13:49
728x90

기본적으로 웹 페이지는 요소(Element)라고 부르는 개체들의 모음이다
div, table, img 등 각각의 태그는 특정 요소를 정의하기 위한 마크업 규칙이며 이 요소들이 모여 웹 페이지를 구성한다. 이들 요소는 기본적으로는 페이지에 정적으로 표시되지만 스타일 처리와 동적 구현을 위해 자바스크립트와 같은 언어로 핸들링 할 수 있다

이러한 핸들링을 위한 가장 첫 단계가 바로 페이지에 존재하는 요소를 찾아내는 일이다. 이를 '페이지 요소 탐색'이라 한다. 이 글에서는 페이지 요소 탐색을 위한 과거와 현재의 기술적 이슈를 다루고자 한다

document.all
아마 필자와 같은 구식(?)  웹 개발자들은 제일 먼저 document.all 을 떠 올렸을 것이다
요소에 부여된 id를 기반으로 탐색하는데 매우 낡은 방법이다.

아래와 같이 페이지의 div 요소에 "myDiv" 라는 id를 부여했다고 가정한다
<div id="myDiv">ABCD</div>

그리고 다음과 같이 이 요소를 탐색한다
var element = document.all["myDiv"]; alert(element1.nodeName);

그러나 요즘 시대에 이런 낡은 문법을 사용한다면 욕 듣기 딱 쫗다 ㅎㅎ
왜냐하면 비표준 스크립트라는 이유에서이다

document.all 은 과거 마이크로소프트의 인터넷 익스플로러에 채택된 DOM 스크립트이다.당시 넷스케이프에서는 document.layers 와 대응되는 문법이었다. 이러한 비표준 스크립트는 크로스브라우저 환경에 큰 걸림돌이기 때문에 사용을 권장하지 않는다

모든 브라우저에서 사용가능한 document.all ??
document.all 은 MS 가 IE를 위한 비표준 탐색 스크립트지만 현재 존재하는 대부분의 최신 브라우저에서 이를 지원하고 있다.  즉 IE는 물론 크롬, 사파리, 파이어폭스, 오페라에서 잘 동작한다.그럼 표준인가?? ...
그렇지 않다. 표준이라기보다는 워낙 유명한(?) 문법이라 IE호환성을 위해 각 브라우저에서 이를 지원하게 된 것일 뿐이다. 이와 관련한 다음의 글을 참고하기 바란다
=> Mozilla, document.all 부분 지원 시작!   ,  document.all 문제 해결법


document.getElementById
아마 모든 웹 개발자가 알고 있는 문법일 것이다
비표준 탐색 스크립트를 평정하고 W3C 에서 표준으로 정한 탐색 스크립트가 바로 document.getElementById 이다. 앞서 document.all을 다음과 같이 대체할 수 있다. 그리고 표준이기 때문에 브라우저 호환성이 보장된다
var element = document.getElementById("myDiv");

이제 document.all 은 잊어 버리고 document.getElementId 를 사용하자. 이미 오래전에 잊었겠지만...


document.getElementsByTagName
getElementById 와 쌍을 이루는 유명한 문법일 것이다.
getElementsByTagName는 getElementById와 마찬가지로 표준 스크립트이며 딱 두가지 차이점이 존재한다.

1) 하나 이상의 요소 즉 요소의 배열을 반환한다
getElementsByTagName 이 반환하는 것은 요소배열이다.
비록 반환되는 요소가 단 1개라도 배열 접근 형식(ex element[0]) 을 취해야 한다.

2) 요소에 부여된 ID가 아닌 태그에 기반한다
getElementById 가 요소에 부여된 ID를 기반으로 탐색을 수행한다면, getElementsByTagName는 요소의 태그명에 기반한다. 즉 div, table, img 와 같은 요소태그를 대상으로 탐색을 수행한다

이런 특징은 일종의 유연성을 제공해 준다. getElementById와 같이 ID를 기반으로 한다는 것은 일종의 규칙이다. 즉 미리 정의된 ID가 있어야 한다는 규칙이 성립해야 한다. 만일 웹 문서 파서(parse)와 같은 범용적인 외부 제작툴을 개발한다면 이런 규칙을 적용할 수 없기 때문에 공통적인 태그를 기반으로 한다는 것이 유연성이 있다는 예기이다

페이지에 다음과 같이 두개이 div가 정의되어 있다면,
<div>First Div</div>  <div>Second Div</div>

다음과 같이 전체 div요소를 탐색할 수 있다
var element = document.getElementsByTagName("div");    

for(var i = 0; i < element.length; i++){
   alert(element[i].nodeName);  
}


document.getElementsByClassName
웹킷(webkit) 기반 브라우저에서 적용한 탐색 스크립트이다.
getElementByID의 경우 ID가 부여된 단 하나의 요소만을 탐색할 뿐이며 getElementsByTagName의 경우 동일 태그의 모든 요소를 반환한다. 만일 임의의 이름이 부여된 특정 그룹을 탐색하고자 할 경우 이 두가지만으로는 한번에 만족시킬 수 없다. getElementsByClassName 은 그 이름에서도 알 수 있듯이 className 이 부여된 요소(그룹)을 반환한다.

페이지에 다음과 같이 동일한 class가 부여된 div 요소가 정의되어 있다면,
<div class="myDivClass">First Div</div>
<div class="myDivClass">Second Div</div>

다음과 같이 class 명으로 div 요소 그룹을 탐색할 수 있다

var element1 = document.getElementsByClassName("myDivClass");    
    
for(var i = 0; i < element1.length; i++){
   alert(element1[i].nodeName);  
}

참고로 아래 그래프는 getElementsByClassName 과 이와 같은 기능을 xPath, 혹은 커스텀 스크립트로 개발할 대의 스크립트 속도차이를 보여준다. 브라우저 차원에서 제공하는 네이티브 getElementByClassName의 수행 속도가 현저히 빠르다는 것을 보여주고 있다


getElementsByClassName 은 현재 IE8(이하) 를 제외하고는 대부분의 브라우저에서 지원된다
그러나 이 함수는 HTML5 스펙에 포함되었으며 IE 버전 9 부터는 같이 지원될 예정이다


document.querySelectorAll
CSS Selector 규칙을 그대로 이용할 수 있는 방법이 생겼다
W3C 에서는 보다 유연한 탐색을 지원하기 위해 CSS 규칙을 기반으로 하는 Selectors API 를 표준화 시켰다
querySelectorAll 함수를 통해 CSS 탐색 규칙을 맘껏(?) 적용할 수 있다

페이지에 다음과 같이 div 안에 p 요소가 정의되었다고 가정할 때,
<div id="myDiv">
   <p>First paragraph.</p>
   <p>Second paragraph.</p>
</div>

다음과 같이 CSS 규칙을 이용하여 요소를 쉽게 탐색할 수 있다
var element = document.querySelectorAll("#myDiv p");

for(var i = 0; i < element.length; i++ ) {  
    element[i].style.backgroundColor = "red";
}

또한 querySelector 을 통해 특정 요소를 다음과 같이 탐색할 수 있다
var element = document.querySelector("#myDiv > p:first-child")
alert(element.nodeName);

중요한 것은 CSS 탐색 규칙 즉 CSS Selector 을 이용하여 보다 강력한 탐색이 가능하다는 점이다

참고로 querySelectAll 은 IE8 을 포함한 크롬, 사파리, 오페라, 파이어폭스에서 모두 지원하지만
다른 브라우저가 CSS 3 Selector 까지 지원하는 반면 IE8은 CSS 2.1 Selector 까지만 지원된다

다음의 링크를 통해 CSS Selector 에 대한 자세한 정보를 확인하자
- CSS 2.1 Selector
- CSS 3 Selector
- CSS Selector 상세 브라우저 지원 현황
- CSS 3 selectors explained


Selector 라이브러리를 통한 탐색
근래 웹을 개발하는 거의 모든 사람이 추천하는 jQuery, Prototype 과 같은 자바스크립트 라이브러리에서는 훌륭한 탐색 기능을 제공해 준다. 이들 라이브러리는 브라우저 호환성을 제공하고 빠른 수행 속도가 보장되기 때문에 그 사용이 권장되고 있는 추세이다. 다만 스크립트 해석이 한번 더 랩핑된 형태라 아무래도 브라우저 차원에서 제공되는 네이티브(Native) 보다는 수행속도가 조금 떨어지는 것은 사실이다
그러나 비용 대비 효과면에서는 충분히 수용할 만한 아니 그 이상의 성능을 보여주고 있기 때문에 권장된다
다음 그림은 각각의 탐색 API를 활용할 경우 수행 속도의 차이를 보여준다

출서: FireFox3.5의 DOM selectors API

다음 글은 탐색과 관련한 유용한 정보를 제공해 주니 읽어보기 바란다
참고: FireFox3.5의 DOM selectors API

728x90
HTML5, Canvas 에는 그려진 내용을 URL 문자열로 반환해 주는 함수가 제공된다

Canvas 객체의 toDataURL() 함수를 통해 캔버스에 그린 그림을 문자열 형태로 변환할 수 있는데,
이 문자열에는 이미지 MIME 타입과 인코딩 방법 그리고 인코딩 된 이미지 데이터 문자열이 포함된다

대략 다음과 같은 모습이다
https://t1.daumcdn.net/cfile/tistory/226CDB4956E6D5F802"FONT-FAMILY: Tahoma">그럼, 실제 Canvas 내용이 문자열로 변환된 것을 확인해 보자
아래 그림은 Canvas에 적당히 그림을 그리고 toDataURL() 함수를 이용해 URL문자열을 띄워 본 것이다


toDataURL() 로 반환된 것이 문자열이라는 것은 다음과 같이 타입조사를 해 보면 알 수 있다
alert(typeof canvas.toDataURL()); //string 이 출력됨

이 문자열은 Canvas에 그려진 내용을 Data URL로 변환한 것이기 때문에 그 자체로 이미지 정보가 된다

따라서 이 문자열을 이미지 객체에 바인딩하거나 다른 이미지로 생성할 수 있게 된다

Canvas 에 그린 그림을 이미지로 변환하기
한 가지 간단한 샘플을 만들어 보자.
Canvas 로 그린 내용을 문자열로 변환하여 img 요소의 src 로 사용하는 것이다
Canvas 에 그리기 작업을 수행하는 코드는 이전 글인 [HTML5] Canvas '마무로 데모' 코드를 이용하므로 구현 코드는 생략하도록 한다. 이 글에서는 Canvas 결과를 이미지 소스로 바인딩하는 것을 제시한다

다음 코드와 같이 Canvas와 버턴, 그리고 img 요소를 정의한다
Canvas에 그림을 그리고 버턴을 클릭하면 오른쪽 img 요소에 그 내용이 이미지 소스로 활용되는 예이다

<canvas id="drawCanvas" width="200" height="200" style=" position: relative; border: 1px solid #000;"></canvas>
<button onclick="toDataURL();">이미지로 변환=></button>     
<img id="myImage">
.....
<script type="text/javascript">
function toDataURL(){
  var myImage = document.getElementById('myImage');
  myImage.src = canvas.toDataURL();
}
</script>

데모를 실행하고 캔버스에 적당히 그림을 그린 후 이미지 변환을 클릭하면 오른쪽에 이미지가 표시된다
이렇게 생성된 이미지는 완전한 하나의 이미지 객체 이므로 로컬에 이미지로 저장하는 등의 이미지 작업이 가능하다


참고로 이렇게 생성된 이미지의 HTML 코드는 아래와 같다



Canvas 에 그린 그림을 다른 Canvas 로 복사하기
이번에는 Canvas에 그린 내용을 다른 Canvas로 옮기는 즉 복사하는 예를 살펴보자.
복사 방법이야 여러 가지가 있을 수 있겠지만 여기서는 toDataURL() 함수로 반환된 이미지데이터문자열을 이용해서 복사하는 방법을 알아보자

언뜻 생각하기에 toDataURL() 함수가 있다면 fromDataURL() 함수가 있지 않을까 생각이 든다
다시말해 캔버스 내용을 URL 문자열로 반환해 주는 함수가 있다면 역으로 URL 문자열을 캔버스 내용으로 사용할 수 있는 함수 말이다. 그런데 찾아 보니 그런 함수는 없어 보인다. 아쉬운 부분이다

그렇다면 우리가 직접 fromDataURL 함수를 만들어 보기로 하자
아래 코드와 같이 두 개의 Canvas를 정의하고 왼쪽 캔버스의 내용을 오른쪽 캔버스로 복사하기 위해 toDataURL()로 얻어진 문자열을 이미지 객체의 소스로 바인딩하고 이미지가 로딩될 때 복사 대상 캔버스의 drawImage 함수를 이용해 이미지를 그리는 로직이다.
<canvas id="drawCanvas" width="200" height="200" style=" position: relative; border: 1px solid #000;"></canvas>
<button onclick="fromDataURL();">캔버스 복사=></button>                  
<canvas id="copyCanvas" width="200" height="200" style=" position: relative; border: 1px solid #000;"></canvas>
...
<script type="text/javascript">
function fromDataURL(){       
  var copyCanvas = document.getElementById('copyCanvas');    
  var copyContext = copyCanvas.getContext('2d'); 
 
  var image = new Image();
  image.src = canvas.toDataURL(); 
 
  image.onload = function(){
    copyContext.drawImage(image,0,0);
  } 
}
</script>


데모를 실행한 결과 화면은 아래와 같다


어떻게 보면 fromDataURL() 함수는 끼워 맞춘 듯한 느낌이다
하지만 toDataURL()로 얻어진 이미지데이터문자열을 이런 형태로도 이용할 수 있다는 힌트만 가지면 되겠다

2010.11.24 추가>>
위에서, Canvas 그림을 다른 Canvas로 복사할 때 이미지객체를 생성하는 단계가 있었다
확인 해 보니, 이미지객체를 경유하지 않고 대상 Canvas에 원본 Canvas를 drawImage 해 주면 된다
따라서 단지 복사가 목적이라면 중간 경유로 사용된 이미지객체의 생성은 불필요 하겠다

fromDataURL 함수는 아래와 같이 수정하면 된다
function fromDataURL(){       
  var copyCanvas = document.getElementById('copyCanvas');    
  var copyContext = copyCanvas.getContext('2d'); 
  copyContext.drawImage(canvas,0,0);  
}


Canvas 내용을 문자열로 얻을 수 있다는 것은...
웹에서 다양한 시나리오를 구현할 수 있다는 의미가 된다
글에서 알아본 것과 같이 캔버스 내용을 이미지로 변환하여 로컬 컴퓨터에 저장할 수 있으며
또 다른 예로 캔버스 내용을 서버로 업로드 하여 다른 사람과 공유하거나 관리할 수 있게 된다
또한 캔버스 내용을 쿠키나 localStorage 등에 저장하여 계속 사용할 수 있으며 페이지 통신을 통해 두 페이지간 캔버스 내용을 교환할 수도 있다. 

결론적으로  문자열로 처리 가능한 모든 시나리오에 캔버스를 이용할 수 있다는 의미가 된다
다만 이렇게 생성한 이미지는 일반 이미지 파일과는 달리 브라우저에 캐시되지 않기 때문에
쇼핑몰 이미지 리스트와 같은 많은 이미지를 서버에서 불러와 캐시되는 시나리오에는 적합하지 않을 수 있다

자신만의 다양한 시나리오를 구상해 실현해 보기 바란다

....

참고로 toDataURL() 함수는 두개의 매개변수를 가지는데, 첫번째 인수는 이미지MIME 타입을 지정하는데 이용되며 나머지 인수는 이미지 품질 정도와 같은 추가 이미지 효과를 지정하는데 사용된다
이전 샘플과 같이 매개변수 없이 호출하게 되면 기본적으로 image/png 타입으로 설정된다
만일 jpeg 를 원한다면 다음의 코드가 가능하다

canvas.toDataURL("image/jpeg");

그러나 테스트를 해 보니 브라우저별로 지원되는 부분이 조금씩 다르니 참고하기 바란다

toDataURL 에 대한 더 자세한 내용은 다음의 W3C 스펙 설명을 확인 하자
http://dev.w3.org/html5/canvas-api/canvas-2d-api.html#todataurl-method

W3C, HTML5 도입 이르다?

Posted in 모바일/HTML5 // Posted at 2010. 10. 8. 11:51
728x90

오늘 연속적으로 기사만 두 건 포스팅하네..
W3C가 HTML5 행보에 찬물을 끼얹는 발언을 했구나!
이건 뭐.. 주최측이라고는 하지만.. 달라도 너무 다른거 아닌가...

기사원문: W3C "HTML5, 도입 이르다"... 브라우저 업체와 노선차이

사실 현재시점에 어느 누가 HTML5를 전면 도입 가능하다고 생각하고 있을까?

Mark Pilgrim 이 언급했듯이 HTML5는 한 덩어리의 기술이 아니다
HTML5는 여러 기술 스펙의 조합이며 최신 브라우저에서는 이미 많은 부분 적용되어 있는것이 현실이다

물론 아직 표준화가 완료되지 않아서 브라우저간 조금씩 상이한 구현과 향후 변경 가능성을 내포하고 있어 불완전하다는 측면은 분명 존재한다.

W3C의 발언이 이런 우려를 내비친 보수적인 입장이라는 점은 이해하지만 표준화를 주도하는 입장에서 굳이 이런 발언을 할 필요가 있나 싶다. HTML5 의 가능성과 빠른 표준화를 공표하고 그사이 발생할 수 있는 호환성 문제를 조심스레 제기하는 수준이라면 모를까... 마치 찬물을 끼얹는 듯한 발언에 아쉬움이 든다

기사 중 다음의 글에 공감한다

일부 웹 전문가들은 기술이 표준화되기 이전에 이미 업계에 널리 확산돼 실용성을 검증받는 과정이 자연스러운 수순이라는 입장이다

 

MS 어도비 인수?

Posted in 일상 // Posted at 2010. 10. 8. 10:59
728x90

흥미로운 기사가 떳다. MS의 어도비 인수설이다.
MS와 어도비라... 아직까지는 루머 수준이지만 개인적으로 매우 흥미롭다

전통적으로 그래픽 분야와 거리가 있었던 MS와 그래픽 강자 어도비가 합쳐진다면 낯설긴 해도 꽤 쓸만한 시너지 효과를 얻을 수 있겠다는 생각이 든다

다만 기사에도 언급되었지만, MS가 RIA 시장 진출을 위해 내놓은 실버라이트와 어도비의 제품이 겹치는 상황은 문제가 된다. 그래서 더욱 흥미롭다는 것이다

그러나 한가지 제품의  충돌보다 거시적인 관점에서 스마트폰 시장 석권, 모바일 시장 석권을 위한 행보에 인수가 긍정적이라는 결론이 나온다면 충분히 가능하지 않을까.. 하는 예상도 해 본다

기사원문: MS, 어도비 인수 가능한가?…NYT 보도

'일상' 카테고리의 다른 글

회생하는 플래시?  (0) 2010.10.26
구글, 크롬OS 발표, 기대와 혼란!  (2) 2010.10.18
표준은 결국 (사회적) 동의이다  (0) 2010.09.27
IE9 Beta 1 출시, 향상된 브라우징  (0) 2010.09.16
블로그 실명제 !!  (0) 2010.09.16

자바스크립트 메뉴를 추가하며...

Posted in 모바일/Javascript // Posted at 2010. 10. 7. 18:05
728x90
자바스크립트 메뉴가 '기타 웹 스킬' 로 변경되었습니다

블로그에 자바스크립트 메뉴를 추가할 지 고민이 되었다

이미 많은 메뉴가 있고 그 메뉴의 글에서 적당히 자바스크립트를 다루면 되겟다 싶어서이다
사실 고백하자면, 그간 자바스크립트라는 언어에 대한 가치(?)를 낮게 평가했었다

2000년대 초반 한창 웹 개발을 하던 시절 나름대로 자바스크립트를 자유자재로 구사한다고 착각한 적이 있었다. 그도 그럴 것이 웹 페이지에 동적인 효과를 주기 위한 많은 스크립트를 직접 다루었으며 나름대로 만족할 만한 수준의 결과가 냈기 때문이다

그러나 지금 돌이켜보면 참으로 황당한 착각이다
당시 대부분의 스크립트는 JASKO와 같은 스크립트 소스 제공 사이트나 유사 기능이 구현된 다른 사이트의 소스를 참조하여 개발했다. 물론 그 소스들이 요구하는 기능과 정확히 매칭되지 않았지만 적당한 수준의 수정으로 원하는 기능을 구현할 수 있었다. 당시 이것을 커스터마이징이라 불렀다. 어이 없게시리...

언어에 대한 체계적인 지식없이 소스를 가져와서 적당히 수정하고 몇 차례 테스트하고 완성했다는 자부심을 가지다니.. 10년이 지난 지금 돌이켜보니 참으로 어이가 없다

아마 많은 웹 개발자들이 이와 같은 경험을 했을 것으로 안다. 그리고 나와 유사한 착각도 가졌으리라 본다.
이런식의 스크립트 오용은 버그를 양산할 가능성이 크며 브라우저 호환성을 철저히 무시하는 결과를 자주 보인다. 그리고 잠시나마 스크립트의 동적효과에 매료되어 사용을 난무하게 되고 결국 의도와는 달리 사용자에게 외면받는 결과를 초래하기도 한다. 수 많은 오픈 창과 얼럿창, 이리지러 움직이는 효과들을 상상해 보라... 

그리고 왠지 자바스크립트는 누구나 쉽게 할 수 있는 코드 블럭 쯤으로 생각해서 언어로써의 수준을 낮게 평가했었다. 프로그래머라면 다 알 것이다. 마치 출신 성분을 구분하듯이 프로그래밍 언어별로 조금 씩 서열이 있다는 것을.. (언어 서열 착각은 이 글과는 다른 주제지만 역시 매우 황당한 착각이다. 혹시 누군가 그런 생각이 있다면 집어 치우기 바란다. 요즘 시대에... ㅎ)

그간 등한시(?) 했던 자바스크립트를 본격적으로 그리고 체계적으로 공부하고 싶어졌다
모바일 웹, 표준 웹, HTML5 에 관심을 두게 되면서부터 스크립트의 중요성을 다시 한번 깨닫게 되었고 높은 수준의 웹을 개발하기 위해서는 높은 수준의 스크립트 개발실력이 갖춰져야 한다는 생각이 들었다
블로그에 메뉴를 추가한 이유도 바로 이것이다

이 메뉴에 많은 글을 올리지는 못해도 중요한 몇 가지는 정확히 알고 포스팅 해 볼까 한다

마지막으로 꽤 오래된 기사지만, MSDN에 자바스크립트와 관련한 좋은 글이 있어 링크 걸어 둔다
=> 개체 지향 기술을 이용한 고급 웹 응용 프로그램 만들기

위 MSDN 컬럼의 필자가 언급한 스크립트에 대한 경험이 매우 와 닿아 몇자 옮겨 본다

많은 개발자들이 C/C++/C#에 대해 알고 있거나 프로그래밍 경험이 있다는 이유만으로 자신이 JavaScript에 대해 많은 것을 알고 있다고 착각하곤 합니다. 필자 역시 최근까지 그러했습니다

사실 최근까지도 필자는 JavaScript에 대한 짧은 지식과 MSDN® DHTML 참조, 그리고 C++/C# 경험을 활용하여 필요한 작업을 수행할 수 있었습니다. 필자의 JavaScript 실력이 부족하다는 것을 느끼게 된 것은 현실적인 AJAX 응용 프로그램을 작성하기 시작하면서부터였습니다. 이 신세대 웹 응용 프로그램의 복잡성과 상호 작용성은 JavaScript 코드를 작성하는 데 있어 완전히 다른 방식을 요구하고 있습니다. 이것은 본격적인 JavaScript 응용 프로그램이며 지금까지 스크립트를 작성하던 느슨한 방법으로는 이러한 응용 프로그램을 작성
할 수 없습니다.


필자는 스스로 원해서 JavaScript를 배운 것은 아니었으며 JavaScript를 사용하지 않고 현실적인 AJAX 응용 프로그램을 개발한다는 것이 불가능하다는 것을 깨달은 후에야 배우기 시작했습니다. 처음에는 필자의 프로그래머 수준이 몇 단계가 떨어지는 것이 아닌가 하는 생각도 들었습니다. (JavaScript라니! C++를 사용하는 친구들이 뭐라고 말할까?) 그러나 처음 가지고 있던 거부감을 떨쳐내자 JavaScript가 상당히 강력하고 인상적이며 콤팩트한 언어라는 사실을 깨달았습니다.

728x90
간혹 기술은 변하는데 시각이 변하지 않는 사례를 보곤 한다
지금은 웹을 통한 서비스를 기획하고 창출하는 시각의 변화가 필요한 시점이라 생각한다

현재 그리고 앞으로 다가 올 웹 기술 환경은 과거의 그것과 확연히 구분된다
더 이상 기존 웹 사이트 수준에 머무는 웹을 생각해서는 안된다
기술의 범위가 넓어진만큼 생각의 범위도 키워야 한다

그러기 위해서는 무엇보다 발전하는 웹 기술을 큰 맥락에서 이해해 둘 필요가 있겠다
지금까지 웹 사이트를 개발하고 기획하고 설계하는 범위를 넘어서서 바라보아야 할 것이다

우선, 차세대 웹 표준으로 자리매김 할 HTML5 는 웹을 더 이상 문서가 아닌 응용프로그램이 가능하도록 만들어 준다. 이것은 ASP, PHP 와 같은 서버 측 기술이 아니다

간혹 동적인 웹, 인터렉티브 한 웹 하면 제일 먼저 ASP와 같은 서버 측 기술을 떠올리곤 한다

그리고 멀티미디어 웹 하면 제일 먼저 플래시를 떠올린다

다 맞는 예기다. 하지만 여기에 추가해야 할 중요한 것이 있다.
HTML5, CSS3, SVG 와 같은 차세대 웹 표준 기술이 빠졌다

HTML5 는 단순한 HTML 을 업그레이드 버전으로 생각하면 큰 오산이다
여기에는 2D, 3D 그래픽 표현을 위한 Canvas 와 비디오,오디오 재생을 위한 video, audio 그리고 웹이 응용프로그램화 될 수 있는 멀티 쓰레드 처리(Web Worker), 소켓 통신(Web Socket), 강력한 로컬 저장소(Web SQL Database, Indexed Database), LBS 구현이 가능한 Geolocation 등이 포함되어 있다

이 들의 조합으로 매우 강력한 웹 응용프로그램을 개발할 수 있다

HTML5로 꽤 쓸만한 게임 개발도 가능하다

HTML5에 포함된 그래픽 처리, 멀티 미디어 처리, 백 그라운드 처리, 소켓 통신 등이 이를 가능하게 해 준다
이는 과거 HTML 에서는 상상도 할 수 없는 일이였다

HTML5Games 사이트에서는 HTML5 로 개발된 여러 게임들을 서비스 하고 있다
이 사이트이 게임들만 쭈욱 훓어 봐도 어느 정도 감을 잡을 수 있다

아래 사이트들도 확인해 보기 바란다
HTML5, JavaScript, DHTML 등 웹 기술로만 제작된 게임 데모를 실행해 볼 수 있다
http://www.benjoffe.com/code/demos/canvascape/

http://blog.nihilogic.dk/2008/05/javascript-super-mario-kart.html
http://www.javascriptgaming.com/
http://www.kesiev.com/akihabara/

또한 HTML5는 3D도 지원할 예정이다
WebGL을 이용한 3D 그래픽용 Canvas 스펙이 개발 중이다
Google Web Tookit 팀에서 개발한 퀘이크 동영상도 확인해 보자
=> http://www.youtube.com/watch?v=XhMN0wlITLk 

그리고 모바일 웹을 앱처럼 개발할 수도 있다
흔히 '웹앱' 혹은 '하이브리드 앱'이라고 표현하는데, PhoneGap, Bondi 와 같은 훌륭한 오픈 소스 플랫폼을 활용하면 순수 웹 기술로 스마트 폰에 내장된 네이티브 정보를 활용할 수 있다
=> 모바일 웹, 장치(Device)의 기능을 불러다 쓰다

다음의 웹 앱 마켓과 포털 사이트를 확인해 보기 바란다
=> 모바일 웹 마켓(오픈앱마켓,OPENAPPMKT)
=> http://www.dseffects.com/iphone.php

(위 URL 들 중 데모 실행을 위해서는 크롬, 사파리와 같은 HTML5 지원 브라우저를 이용해야 한다)

이제 이런 말은 조심스럽게 걷어 낼 수도 있겠다

'음.. 웹은 한계가 있어서 그런 서비스를 개발하기는 힘들어요..!@#$@#'

필자 역시 근래 다시 웹에 큰 관심을 두는 이유도 바로 이런 기술의 변화 때문이다
기술의 변화는 서비스를 변화 시킨다. 물론 서비스가 변화하려면 그 서비스를 창출하는 사람들의 의식이 먼저 변해야 한다. 웹을 통한 비즈니스를 하는 그 누구든, 새로운 기술을 큰 틀에서라도 이해하는 것이 매우 중요하다. 그래야 원하는 서비스, 추구하는 목적을 보다 정확히 실현할 수 있기 때문이다
특히 요즘과 같이 급성장하는 모바일 환경, 브라우저 환경에서는 더욱 그러하다 하겠다
.....

경험은 매우 값진 지식이다. 그러나 간혹 과거의 경험이 스스로를 한계 짓는 틀로 작용할 때가 있다.
특히 요즘과 같이 급변하는 세상에서는 경험의 틀에만 의존해서는 곤란하다.
값진 경험과 새로운 환경을 조합한 최적의 준비태세를 갖출 필요가 있겠다

참고로 HTML5를 개괄적으로 소개한 다음의 글을 읽어 보기 바란다
=>
HTML5 개요와 기술적 특징

그리고 다음의 글도 참고 바란다
=> http://m.mkexdev.net/65

JSON (JavaScript Object Notation)

Posted in 모바일/Javascript // Posted at 2010. 10. 6. 11:34
728x90

JSON은 인터넷을 통해 응용프로그램간 데이터를 주고 받는 규칙 즉 데이터 포맷을 일컫는다

'이슨' 이라고 발음하는데 우연찮게도 '13일 밤의 금요일' 의 누군가와 이름이 같다 ㅎㅎ
당연하겠지만, 그 제이슨과는 아무런 연관이 없으며 데이터 포맷을 위한 표기법이 자바스크립트 객체 표기
방식에 근거를 두어
전체 이름이 JavaScript Object Notation 며 그 약자가 JSON 이다

JSON 은 Douglas Crockford 라는 미국의 개발자에 의해 탄생했으며 JSON 을 가장 잘 설명해 놓은 곳은 역시 JSON 공식 웹 사이트이다. 다음의 JSON 사이트에서 JSON의 모든 것을 알 수 있다
=> http://www.json.org/ (한글판: http://json.org/json-ko.html)

그리고 위키백과에도 JSON 을 꽤 적절하게 잘 설명하고 있다
=> http://ko.wikipedia.org/wiki/JSON

인터넷을 통한 원격 통신간 데이터 교환 포맷인, JSON 은 요즘 뜨는 최신 기술이 아니다.
이미 수 년전부터 곳곳에서 이를 이용해 왔으며 나의 경우 3년전인 2007년경에 처음 접하게 되었다
웹의 비동기 통신기법인 Ajax 의 등장시기와 유사한 2005년경에 본격적으로 이름이 알려지기 시작한 것 같으며 현재 트위터와, 오픈 API 와 같은 경량성, 상호연동성, 쉽고 편리한 API를 중시하는 서비스들에 많이 적용되고 있는 추세이다

그리고 JSON 이 비록 자바스크립트 구문형식을 따르기는 하지만 그 자체로 하나의 독립적인 체계로써 특정
언어나 플랫폼에 종속되지 않으며 C#, Java, ASP, PHP, C, C++ 등의 다양한 언어에서 JSON 포맷을 위한 파서들이 제공되고 있다. 


인터넷 데이터 교환 포맷
인터넷 특히 웹을 통한 데이터 교환은 JSON 이전에도 존재했었다.
가장 원시적인 방법이 일반 텍스트를 이용하는 것이었다. 단일 값은 물론 복수의 값도 전달가능 일반 텍스트로 전달하곤 했었는데, 대체로 다음과 같이 구분자를 기준으로 텍스트 포맷을 주고 받는 형태였다

일반 텍스트 포맷: "name=박종명 || email=mkex@naver.com || age=36"
전체 구분자로 '||'를 이용하고 키,값 구분자로 '=' 를 이용하여 데이터를 정의했으며 수신하는 측에서는 구분자를 기준으로 문자열을 분리하여 그 의미를 해석하곤 했다

척박한 당시 상황에서는 일반텍스트 포맷은 꽤 많은 곳에서 이용되었으며 대략 만족하기도 했었다
그러나 구분자 역시 문자이기 때문에 전달하고자 하는 데이터 자체와 충돌할 수 있었고 배열 형태와 같은
복수 집합 자료를 정의하기에는 어울리지 않는 포맷이었다

---

다음으로 각광 받은 포맷이 XML 이다. XML 자체가 데이터 정의에 매우 적합한 언어이기에 아주 훌륭한 포맷이었다. 다음에서 보는바와 같이 각 요소는 정확한 의미의 태그와 연결될 수 있으며 집합자료정의도 쉽게 할 수 있다. 또한 요소의 attribute 를 이용하면 데이터 타입이나 제약사항과 같은 같은 추가 정보도 얼마던지 정의할 수 있어 데이터 정의에 매우 적합한 형태이다
<user>
  <name>박종명</name><email>mkex@naver.com</email>
  <name>홍길동</name><email>xxxxxxx@naver.com</email>
  ...
</user>

이와같이 XML은 데이터에 의미를 부여하기 위해서는 그 어떤 포맷보다 훌륭하지만 매번 열고 닫아야 하는 태그 쌍은 데이터의 크기를 증가시키는 원인이 되기도 하며 XML을 파싱할 때 브라우저 호환성도 신경쓰이 부분이었다
--

이제 JSON의 등장이다. JSON 공식 사이트에서 JSON을 소개하는 문구를 가져와 본다
JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write

JSON은 텍스트 포맷보다 훨씬 효과적으로 데이터를 구조화 할 수 있다
JSON은 XML 포맷보다 가볍다. 그리고 가독성이 좋다
바꿔 말하면, JSON 은 텍스트만큼 가볍고 XML만큼 구조적이다
그리고 JSON 은 자바스크립트에 근간하기 때문에 웹 환경에 더욱 적합하다

Ajax, 웹 Open API 등 웹 환경에 JSON 이 대세인 이유가 조금은 설명되었을 것이다


JSON 사용하기
JSON 은 그 장점에 비해 사용법은 매우 심플하다
기본적으로 알아 둬야 할 것은 JSON은 (규칙이 있는) 텍스트 포맷이며 유니코드 인코딩이란 점이다

그리고 가장 기본적인 형태는 중괄호 안에 정의된 키:값 형태이다.
다수의 객체를 정의하기 위해서는[](대괄호)를 사용하며 배열요소는 ,(꼼마)로 구분한다.
JSON으로 숫자, 문자, 참/거짓, null, 객체, 배열등을 표현할 수 있다

다음의 코드는 id, age, blog 라는 속성을 가진 회원(user) 정보를 JSON 포맷으로 단일 객체와 객체 배열로
정의하고 자바스크립트로 핸들링 하는 예이다

var user = {"id":"mkex", "age":36, "blog":"http://m.mkexdev.net"} 
alert(user.id); // mkex 출력

var objectArray = {
               users: [
                 {"id":"mkex", "age":36, "blog":"http://m.mkexdev.net"},
                 {"id":"mkex2", "age":36, "blog":"http://m.mkexdev.net"}
               ]                 
             }
alert(objectArray.users[1].id); //mkex2 출력



그리고 JSON이 자바스크립트 구문에 근간하기 때문에 다음과 같이 eval 을 통해 일반 문자열을 JSON 객체로 변환할 수 있다. 대부분 시나리오에서 JSON 객체를 문자열로 전송하고 수신측에서는 이를 JSON객체로 변환
하여 사용하게 된다

var userString = '{"id":"mkex", "age":36, "blog":"http://m.mkexdev.net"}'
var userJSON = eval("(" + userString + ")");
alert(userJSON.age); //36 출력

 
마이크로소프트 닷넷과 JSON
여러 언어들에서 JSON 포맷을 지원하기 위한 API들이 제공된다
닷넷을 사랑(?)하는 필자가 가장 먼저 언급할 것 역시 닷넷의 JSON 지원이다
닷넷 프레임워크에서는 System.Runtime.Serialization.Json.DataContractJsonSerializer 라는 클래스를 통해
닷넷 객체를 JSON 객체로 변환하거나 JSON 객체를 닷넷 객체로의 변환을 지원한다


다음의 블로그에서 자세한 정보를 얻을 수 있으니 참고 바란다
http://blog.naver.com/dotnethelper/60103536438

그리고 Json.NET 라이브러리도 있으니 참고 바란다

다양한 언어들을 위한 JSON 파서
JSON이 워낙 유명(?)하기에, 닷넷과 같이 프레임워크 차원에서 JSON 을 지원하는 경우도 있고 Json.NET과
같이 외부 라이브러리로 존재하기도 한다


http://www.json.org 에서는 각종 언어별로 제공되는 JSON 파서의 링크를 제공해 준다
상황에 맞는 라이브러리를 참고하기 바란다

참고로 자바스크립트의 eval 을 통한 변환은 예기치 않은 보안 문제가 발생할 수 있으므로
이들 파서의 사용은 더욱 권장된다

Aptana, HTML5를 지원하는 웹 개발 툴

Posted in 모바일/HTML5 // Posted at 2010. 10. 4. 13:50
728x90

마이크로소프트의 닷넷을 기반으로 웹 응용프로그램을 개발할 땐 비주얼스튜디오만 있으면 된다
개인적으로 MS 진영의 개발툴은 그 어떤 것보다 강력하다고 생각한다
(완벽에 가까운 한글 지원을 포함하여...)

윈도우 응용프로그램, 웹 응용프로그램, 웹 서비스, 라이브러리 등 닷넷과 관련한 모든 개발은 비주얼스튜디오 하나로 다 해결할 수 있다. 물론 ASP.NET 기반의 웹 개발을 위한 도구인 Visual Web Developer 가 존재하지만 이것은 통합 개발환경인 비주얼스튜디오의 서브도구 개념이기 때문에 특수한 경우가 아니라면 비주얼스튜디오만으로도 충분하다.

그리고 과거 ASP나 PHP로 웹 사이트를 개발할 때 특별한 툴을 이용하지는 않았다
한때 asp개발을 위해 비주얼인터데브를 사용한 적이 있으나 프로그래밍 모델이 복잡하지 않은 asp 개발에 오히려 복잡성을 증가시키는 것 같아 Acroedit
와 같은 심플한 텍스트 에디터를 사용했었다
(Acroedit 는 필자가 거의 10년 가까이 사용하고 있는 애착(?)이 가는 무료 에디터이다)
그리고 간혹 웹 디자이너나 퍼블리셔들이 사용하던 드림위버(혹은 나모웹에디터) 라는 툴도 듬성듬성 사용했었다

그러나 요즘 HTML5 기반 응용프로그램을 개발하려다 보니 개발툴의 절실함을 많이 느낀다
Acroedit 는 웹 개발을 위해 FTP 기능, 언어 예약어 하이라이트 기능, 책갈피 기능 등 에디터로써 유용한 기능들이 많이 포함되어 있지만 비주얼스튜디오와 같은 인텔리전스 기능은 가지고 있지 않다

HTML5 개발은 HTML 태그와 더불어 자바스크립트를 사용하는 경우가 많기 때문에 언어 하이라이트는 필수라 할 수 있으며 객체에 정의되어 있는 함수나 속성을 자동으로 띄워주는 인텔리전스 기능이 매우 목마르다. 물론 HTML5 이전의 웹 개발환경에도 자바스크립트의 비중이 적다고는 할 수 없지만 개인적으로 그 당시에는 클라이언트 스크립트를 요즘과 같이 관심있게 들여다 본적이 없었기 때문에 필요성도 덜 느꼈었다.

이번에 소개할 Aptana 는 웹, 특히 자바스크립트나 HTML, CSS와 같은 클라이언트 단 웹 개발을 돕는 개발 툴로 이미 꽤 유명세를 타고 있는 툴인 것 같다

나의 경우 HTML5, CSS3 에 관심을 두기 시작하면서 알게 된 툴이다
툴을 직접 깔아보니 자바 개발툴인 이클립스와 매우 유사한 UI 및 프로세스를 지니고 있다
알고 보니 이클립스를 통해 웹 개발을 돕는 플러그인 형태로 제공되던 툴인데 현재 독립 실행형으로도 배포되고 있는 듯 하다

Aptana Studio 버전 3 부터는 HTML5, CSS3 를 지원하며 현재 베타버전으로 다음의 링크를 통해 다운받을 수 있다 => http://aptana.com/products/studio3



위 그림과 같이 HTML5 태그가 지원되며 브라우저 지원현황도 자동으로 나타내 준다

아직 상세한 기능이나 구체적 사용법은 숙지되지 않은 상태라 더 자세한 정보를 알려 줄수는 없지만 웹 클라이언트 단 개발에 있어 매우 유용한 툴으로 가치가 있어 보인다

언젠가 본격적으로 사용하게 될 도구 목록에 추가해 두기로한다

참고로 Aptana 에 대해 소개한 다음의 블로그를 참고 바란다
http://firejune.com/1205
http://firejune.com/1581

728x90

듣기로 현재(2010.09.30) W3C의 HTML5 표준화 프로세스는 Working Draft 단계에 있는 것으로 알고 있다. 2009년 10월에 WHATWG 에 의해 Last Call이 선언되어 W3C로 사양이 제출되었다
이제 W3C에서도 Last Call 프로세스를 진행하기로 했다는 소식이다

Last Call 은 표준을 위한 권고안이 되기 전에 최종 검토하는 기간이다
ETRI 이원석님의 블로그에 향후 일정이 상세히 설명되어 있으니 참고 바란다
=> W3C, HTML5 표준 초안 Last Call 예정

글에 따르면 2011년 5월에 Last Call 이 종료된다고 한다
이후 권고 후보, 권고안, 권고 과정을 거치면 드디어 표준화가 완성된다

사실 권고안만 되면 거의 게임 끝났다고 볼 수 있다
한 때 HTML5 의 표준화 완성이나 보편화가 최소 10년 후, 먼 미래가 될 것이라는 일부 부정적 시각이 있었으나 현재 분위기로 봐서는 2012년 정도에는 뚜렷한 윤곽이 나오지 않을까 싶다

[HTML5] Web Socket (웹 소켓)

Posted in 모바일/HTML5 // Posted at 2010. 9. 30. 13:44
728x90

실시간 (양방향) 통신을 위한 웹의 노력
개인적인 생각으로 HTML5의 새로운 스펙중에 사용자가 가장 흥미로워 한 것이 Canvas 라면

개발자가 가장 흥미로워 한 것은 바로 웹 소켓(Web Socket)이지 않나 싶다

필자 역시 순수 웹 환경에서 연결 지향 양방향 통신을 지원하는 웹 소켓이 가장 눈에 띄는 것 중 하나였다. 과거 순수 웹 환경에서 채팅과 같은 실시간 응용프로그램을 위한 얼마나 많은 시도들이 있었던가...

이제 박물관(?)에서나 볼 법한 숨긴 frame(or iframe) 을 통한 반복적인 재요청은 당시만 해도 웹에서 실시간 효과를 낼 수 있는 참신한 아이디어로 부상한 적이 있었다

이후 Ajax의 등장으로 비동기로 반복 요청을 할 수 있어 그나마 조금은 개선 되었다
그러나 여전히 클라이언트의 비 효율적인 재요청을 피할 수는 없었다

그리고 이후 Comet 의 등장으로 서버 데이터 수신 후 재 요청이 가능해져 불필요한 반복 요청의 비효율성은 개선되었다.

그러나 이 모든 것은 '폴링(polling)' 방식이다
즉 데이터 수신을 위해 서버가 클라이언트에게 전송해 주는 푸시(push)방식이 아니라 클라이언트가 서버에에게 요청하는 폴링(polling) 방식이었다

비교적 최적의 대안이었던 Comet 역시 무의미한 반복 요청을 피하기 위한 연결유지 기법이 적용되었지만 일정 시간 이후에는 연결을 종료하고 다시 연결해야 한다. 그래서 Comet을 Long-Polling 라 한다

참고: [HTML5] Server-Sent Events

웹의 진정한 실시간 (양방향) 통신, 웹 소켓(Web Socket)의 등장
초기 웹의 탄생 목적은 문서 전달과 하이퍼링크를 통한 문서 연결이었다
웹을 위한 HTTP 프로토콜은 이러한 목적에 매우 부합하는 모델이다
그러나 시대가 변하고 환경이 발전할 수록 웹이 더 이상 문서공유에만 집중할 수 없었다
갈수록 동적인 표현과 뛰어난 상호작용이 요구되었고 이로 인해 여러 새로운 기술이 탄생되었다

플래시(플렉스), 자바애플릿(자바FX), ActiveX , 실버라이트 등을 들 수 있다
하지만 이들은 웹에서 화려한 동작과 뛰어난 상호작용을 보장하지만 순수 웹 환경이 아니라 별도의 런타임을 플러그 인 형태로 브라우저에 설치해야 사용 가능하다

HTML5는 그 주요 목적 중 하나인, 플러그 인 없는 일관되고 표준화된 웹 응용 환경이라는 기치하에 많은 참신한 스펙들이 개발되었다.

그 중 순수 웹 환경에서 실시간 양방향 통신을 위한 스펙이 바로 '웹 소켓(Web Socket)' 이다
웹 소켓은 웹 서버와 웹 브라우저가 지속적으로 연결된 TCP 라인을 통해 실시간으로 데이터를 주고 받을 수 있도록 하는 HTML5의 새로운 사양이다. 따라서 웹 소켓을 이용하면 일반적인 TCP소켓과 같이 연결지향 양방향 전이중 통신이 가능하다

이와 같은 특징으로 웹에서도 채팅이나 게임, 실시간 주식 차트와 같은 실시간이 요구되는 응용프로그램의 개발을 한층 효과적으로 구현할 수 있게 되었다

웹 소켓과 Ajax 속도 비교
한 일본 사이트에서 웹 소켓과 (Ajax의 통신 객체인) XMLHttpRequest 의 속도 비교를 확인할 수 있는 페이지를 제공하고 있어 화제가 되고 있다
=> http://bloga.jp/ws/jq/wakachi/mecab/wakachi.html (크롬 or 사파리에서 실행)


서버에 존재하는 1,981(공백포함) 길이의 일본문자를 132개로 끊어서 가져오는 데모인데, 각각 웹 소켓과 여러개의 Ajax(병렬 Ajax)를 이용해 각각 호출해서 실행 속도를 비교했다

테스트 할 때마다 실행 속도의 차이가 조금씩 나지만 웹 소켓이 대략 50배 이상 좋은 성능을 보이고 있다


물론 이 사이트의 테스트 시나리오에 따르면, 한번에 모든 문자를 가져오는 것이 아니라 132개로 나눠진 단락들을 가져오는 것이다 보니 한번 연결된 통신 라인으로 데이터만 가져오는 웹 소켓에 비해 매번 헤더정보를 실어서 새로 요청 하는 Ajax가 더욱 느리게 느껴질 수 있다

하지만 이것은 '수 차례 송/수신을 하는 시나리오' 를 가정한 만큼 테스트 시나리오에 문제 제기를 할 필요는 없어 보인다. 웹 소켓을 사용하는 환경의 거의 대부분이 이런 시나리오이기 때문에 더욱 그렇다

어쨋던 확실히 실시간 통신환경에서는 Ajax 보다는 웹 소켓이 월등하다는 것을 알 수 있다

웹 소켓이 필요한 다섯가지 징후?
Peter Lubbers 라는 개발자가 'Five Signs You Need HTML5 WebSockets' 이라는 글을 포스팅 했다
HTML5의 웹 소켓을 이용하면 좋을 5가지 경우를 조목조목 설명하고 있다
뭐.. 결론은 웹 소켓 좋다는 거다 ^^ . 글에서 상단의 Summary 만 가져와 본다

  1. Your web application has data that must flow bi-directional simultaneously.
  2. Your web application must scale to large numbers of concurrent users.
  3. Your web application must extend TCP-based protocols to the browser.
  4. Your web application developers need an API that is easy to use.
  5. Your web application must extend SOA over the Web and in the Cloud.

대략 난잡번역 해 보면,
1. 실시간 양방향 데이터 통신이 필요한 경우
2. 많은 수의 동시 접속자를 수용해야 하는 경우
3. 브라우저에서 TCP 기반의 통신으로 확장해야 하는 경우
4. 개발자에게 사용하기 쉬운 API가 필요할 경우
5. 클라우드 환경이나 웹을 넘어 SOA 로 확장해야 하는 경우

그리고 각 경우에 대한 설명이 자세히 나열되어 있으니 스스로 번역해서 음미 바란다
(누가 좀 안해주나 ^^;)


지원되는 브라우저 현황
IE와 오페라를 제외한 사파리,크롬,파이어폭스 최신버전에서 웹 소켓을 지원한다


그림1. 브라우저별 Web Sockeet 지원 현황 (출처: http://caniuse.com/)


웹 소켓 구현하기
웹 소켓 역시 일반적인 TCP 소켓 통신처럼 웹 소켓 역시 서버와 클라이언트간 데이터 교환이 이루어지는 형태이다. 따라서 다른 HTML5 스펙과는 달리 클라이언트 코드만으로 실행 가능한 예를 만들 수는 없다

즉 클라이언트에서는 웹 소켓이 제공하는 자바스크립트 API를 이용해 서버에 연결하고 데이터를 송/수신하는 코드를 구현해야 하며 서버에서는 웹 소켓 프로토콜에 맞는 전용 장치가 구축되어 있어야 한다

웹 소켓 클라이언트
웹 소켓이 제공하는 클라이언트 측 API는 매우 심플하다. 기본적인 서버 연결, 데이터 송신, 데이터 수신만 정의하면 나머지는 일반적인 스크립트 로직일 뿐이다

: 서버연결

웹 소켓이 동작하기 위해서 제일 처음 서버와 연결이 되어야 한다. HTML5가 제공하는 WebSocket 객체를 통해 서버 연결을 수행한다. 일반 통신은 ws, 보안 통신은 wss 프로토콜을 이용한다
기본 포트 역시 http,https와 동일한 80,443을 이용한다
var wSocket = new WebSocket("ws://yourdomain/demo");

: 데이터 송신
서버와 연결이 되면 이제부터 데이터를 주고 받을 수 있게 된다. WebSocket 객체의 send 함수로 데이터를 서버로 송신할 수 있다
wSocket.send("송신 메시지");

: 데이터 수신
서버에서 푸시(전송)하는 데이터를 받으려면 message 이벤트를 구현하면 된다
wSocket.onmessage function(e){ //매개변수 e를 통해 수신된 데이터를 조회할 수 있다 

클라이언트 API는 이 세가지가 핵심이다. 추가로 아래와 같은 이벤트도 제공된다
- open 이벤트: 연결이 설정되면 발생
- close 이벤트: 연결이 끊어지면 발생

웹 소켓을 이용하는 클라이언트 코드의 전체 모습은 대략 다음과 같다

<script>
  var wSocket = new WebSocket("ws:yourdomain/demo");
 
  wSocket.onmessage = function(e){  alert(e.data);  }  

  wSocket.onopen = function(e){ alert("서버 연결 완료"); } 
  wSocket.onclose = function(e){ alert("서버 연결 종료"); }  

  function send(){ //서버로 데이터를 전송하는 메서드
    wSocket.send("Hello");
  }
</script>

보는 바와 같이, 소켓 통신을 위한 클라이언트 측 코드는 매우 심플하며 직관적이다. 하지만 말했듯이 클라이언트 코드 만으로 데모는 실행되지 않는다. 클라이언트와 통신하는 서버가 존재해야 하는데 아래에 계속 이어진다

웹 소켓 서버
웹 소켓은 일반적인 TCP 소켓과는 다른 프로토콜로 설계되었다. 따라서 기존 TCP 서버를 그대로 이용할 수 없고 새로 구현해야 하는데 웹 소켓 서버 사양에 맞도록 구현해야 한다.

웹 소켓 서버를 위한 다양한 오픈소스가 온라인에서 제공되고 있는데,
pywebsocket , phpwebsocket, jWebSocket, web-socket-ruby, Socket.IO-node 와 같은 모듈을 이용하면 웹 소켓 서버를 쉽게 구축할 수 있다

이 글에서는 jWebSocket을 이용해서 웹 소켓 서버를 구축하고 제공되는 데모를 실행해 보도록 하자

jWebSocket 라이브러리는 http://jwebsocket.org/
 사이트를 통해 다운로드 받을 수 있는데
자바로 구현된 웹 소켓 서버모듈인 jWebSocketServer와 자바스크립트로 구현된 웹 소켓 클라이언트 데모인 jWebSocketClient 을 다운받으면 된다. 참고로 jWebSocket 라이브러리의 전체 소스코드는 jWebSocketFullSource를 다운받아 볼 수 있다

jWebSocketServer 구동
우선 웹 소켓 서버를 구동 시켜야 하는데, 아파치 웹서버나 톰켓을 이용하여 구동하거나 Stand-Alone 으로도 구동시킬 수 있다. 이 글에서는 간단한 테스트를 위해 Stand-Alone로 구동시켜 보도록 하자

jWebSocketServer 가 자바로 구현되었기 때문에 자바 가상 머신이 설치되어 있어야 한다
서버에 최소 1.5 버전 이상의 자바런타임을 설치하도록 하자
그리고 기본적인 자바 환경 변수인 JAVA_HOME 과 java.exe를 Path에 등록한다

이제 자바를 위한 기본 설정이 마무리 되었으니 jWebSocketServer를 구동시키면 된다
Stand-Alone로 구동시키기 때문에 별도의 웹 서버는 필요하지 않고 배치파일을 실행하는 것으로 대신할 수 있다. 다운받는 jWebSocketServer을 압축해제 하고 bin 폴더에 있는 jWebSocketServer.bat 파일을 명령프롬프트에서 실행하도록 하자. 배치파일을 실행하면 설정을 위한 일련의 작업들이 진행되고 최종적으로 다음과 같은 모습으로 웹 소켓 서버의 구동이 시작된다


이후 웹 소켓 서버와의 통신로그와 디버그 메세지들이 이 창에 계속 기록된다
배치파일을 실행하는 동안 서버가 구동되는 것이기 때문에 실행창을 닫으면 서버도 종료됨을 기억하자

다음의 퀵스타트를 참고 하자
http://code.google.com/p/jwebsocket/wiki/QuickStart

jWebSocketClient 데모 테스트 하기
서버가 준비되었으니 웹 소켓 통신을 수행하는 클라이언트 데모를 확인해 보자
jWebSocketClient 를 다운받아서 압축해제 하면 다양한 데모가 미리 준비되어 있다
우리는 여기서 채팅데모인 chat.htm 을 실행해 보자

웹 소켓을 지원하는 브라우저를 두 개 띄우고 chat.html을 실행한다. 아래 그림은 크롬 브라우저의 실행 모습이다. 두 개의 브라우저에서 각각 로그인 한 뒤, 채팅하는 모습이다


채팅 외에도 다양한 데모가 있으니 참고 바라며 웹 소켓서버 통신의 기술적 구현을 배우기 위해 코드를 꼼꼼히 살펴보는 것도 좋을 것이다.

참고로 jWebSocket 에서 서버 연결을 위해 다음과 같은 url을 정의하고 있다
var lURL = jws.JWS_SERVER_URL + "/;prot=json,timeout=360000";
...
JWS_SERVER_URL: "ws://" + ( self.location.hostname ? self.location.hostname : "localhost" ) + ":8787"

ws 프토토콜로 localhost, 8787포트로 연결하며 추가로 json 포맷과 타임아웃이 설정되었다

마지막으로 WebSocket 은 다른 HTML5 사양보다 프로그램적인 성격이 강하다.
특히 클라이언트 코드만으로 해결될 수 있는 것이 아니라 좀 더 복잡해 보일 수 있다.
또한 많은 수의 클라이언트를 수용하기 위해서는 소켓 서버의 성능과 가용성이 확보되어야 하기 때문에 보다 신중한 접근이 필요하다 하겠다. 글에서 소개한 웹 소켓 서버 라이브러리를 적절히 이용하거나 오픈 소스를 분석해서 내공을 키우기 바란다

2016.07.15 추가>
- Node.js기반 socket.io 라이브러리를 이용해 간단한 웹 채팅을 구현한 다음 포시팅도 참고하기 바란다.
- [NodeJS] socket.io를 활용한 웹채팅 구현



참고>

Firefox의 웹소켓(WebSocket) 기능
http://code.google.com/p/websocket-sample/
http://dev.w3.org/html5/websockets/
http://www.websockets.org/about.html
http://www.codeproject.com/KB/webservices/c_sharp_web_socket_server.aspx

Code Syntax Highlighter 툴 소개

Posted in 모바일 // Posted at 2010. 9. 30. 12:31
728x90
개발자들은 블로그에 기술 글을 쓸 때 프로그램 코드를 사용하는 경우가 많다
코드를 보여주고 코드 설명을 할 때 주로 사용한다
간혹 코드의 길이가 길거나 복잡할 경우 코드와 설명을 연결하기가 쉽지 않다

지금 소개하는 툴은 프로그램 코드를 블로그와 같은 웹상에 표현할 때 보다 직관적으로 보이기 위해
예약어 색상 변경, 라인 넘버, 들여 쓰기, 코드 접기/펼치기 효과를 주는 HTML코드를 자동으로 생성해 준다. 예약어 색상을 지원하는 언어는 C#, SQL, HTML, VBScript, Java, PHP 등이 지원된다

툴 주소: http://www.stevetrefethen.com/highlighter/default.aspx

- 코드 입력


- 결과


결과로 나온 부분을 그대로 복사해서 사용하면 된다.
그리고 아랫부분에 결과에 대한 HTML코드가 공된다