WebKit 화면 구성 요소

Dev 2009. 5. 15. 15:02

본 기사는 2008년 12월 버전 (rev. 39476) WebKit win32 port를 기준으로 한다.

http://webkit.org에 존재하는 “WebKit Objective-C Programming Guide” 문서를 보면 다음과 같은 그림이 존재한다.



이 그림에서 aWebFrameView는 폐기됐다 (적어도 windows port에서는…). 지금 현실에 맞게 그림을 재구성하면 다음과 같다.


  • WebView는 WebKit 엔진을 담고 있는 main-window를 나타내는 개념이다.
  • WebFrame은 WebKit이 표시하는 페이지를 나타내는 개념이다.
    • WebView는 1개의 WebFrame을 main-frame 멤버로 갖는다.
    • WebFrame은 0개 또는 여러 개의 WebFrame을 children 멤버로 가질 수 있다 (HTML & 태그 처리…).


화면 구성 요소들에 대한 클래스 다이어그램은 다음과 같다.



언제나처럼 이미지를 클릭하면 원본 크기로 볼 수 있다.

 

Posted by ingeeC
,
이전 기사에서 사용자가 URL을 입력했을 때, WebKit이 해당 페이지를 load 하는 시퀀스를 분석했었다. 이번에는 페이지가 load되어 있는 상태에서 사용자가 웹페이지의 HTML Anchor를 클릭했을 때 WebKit이 새로운 페이지를 load 하는 시퀀스를 정리한다. 서론이 다소 길었다. 사실 다음 시퀀스 다이어그램이 전부다. FrameLoader::loadWithDocumentLoader() 이후의 시퀀스는 이전 기사의 FrameLoader::load(docLoader) 호출 이후의 시퀀스와 동일하다.



이미지를 클릭하면 원본 크기로 볼 수 있다.
Posted by ingeeC
,

WebKit의 핵심 시퀀스를 요약하면 아마 다음과 같을 것이다.
- URL 문서를 loading 하는 시퀀스
- loading한 문서를 parsing 하는 시퀀스
- parsing된 내용의 layout을 결정하는 시퀀스
- 구성한 화면을 출력하는 시퀀스

이들중 "URL 문서를 loading하는 시퀀스"를 분석하게 됐다.
WebKit을 갖고 일하는 개발자들에게 조금이라도 보탬이 되면 좋겠다. 혹시나 분석한 내용에 오류가 있다면, 댓글이나 트랙백으로 가르침 주시기 바란다. 분석에 사용한 WebKit은 작년말(2008년 12월) 버전이며 (rev. 39476), cURL을 사용하는 win32 port를 기준으로 하고 있다.

URL을 load 하는 시퀀스를 분석하면서 WebKit에 존재하는 수 많은 종류의 loader들 때문에 골치 아팠다. 대강의 내용을 정리하면 다음과 같다 (클래스 다이어그램에 메모박스로 주석 달아 놓았다).
- FrameLoader : URL-load 과정을 총괄하는 loader (1개의 frame에는 여러개의 web-page가 load될 수 있다).
- DocumentLoader : 1개의 web-page load를 책임지는 loader.
- MainResourceLoader : base-document (HTML 문서) load를 책임지는 loader.
- ResourceLoader : sub-document (CSS, js, image, ...) load를 책임지는 loader.

분석한 내용을 다음 2장의 UML 다이어그램으로 정리한다. 이미지를 클릭하면 원본 크기로 볼 수 있다.


<<URL load 과정에 참여하는 Class 들>>

 

<<URL load 간단 시퀀스 (HTML 파일 1개로만 이루어진 페이지 load 시퀀스)>>


분석을 위해 다음과 같은 뉴스그룹 기사들을 참고했다. 다른 사람들에게도 참고가 되기를 바라며, 해석 없이 그대로 올린다.


"문서 load 시퀀스"
from http://osdir.com/ml/opendarwin.webkit.devel/2006-10/msg00041.html
======================================================================

Main resource loaded, started from app via API:

[ WebFrame ] (ObjC, WebKit)
[ FrameLoader ] (C++, WebCore) ---> [ FrameLoaderClient ] (C++ abstract base class, implemented in webkit to deliver delegates)
 [ DocumentLoader ] (C++, WebCore)
[ MainResourceLoader ]  (C++, WebCore)
[ ResourceLoader ] (C++, WebCore)
[ FrameLoader ] (C++, WebCore)

 

Main resource loaded, started from engine via link click or form submission:

[ FrameLoader ] (C++, WebCore) ---> [ FrameLoaderClient ] (C++ abstract base class, implemented in webkit to deliver delegates)
 [ DocumentLoader ] (C++, WebCore)
[ MainResourceLoader ]  (C++, WebCore)
[ ResourceLoader ] (C++, WebCore)
[ FrameLoader ] (C++, WebCore)


Subresource load:

[ DocumentLoader ]  (C++, WebCore)
[ Cache ] (C++, WebCore)
[ FrameLoader ] (C++, WebCore) ---> [ FrameLoaderClient ] (C++ abstract base class, implemented in webkit to deliver delegates)
 [ SubresourceLoader ] (C++, WebCore)
[ ResourceLoader ] (C++, WebCore)
[ Cache ] (C++, WebCore)
[ CachedResource ] (C++ WebCore)

 

"Loader의 종류 및 역할"
from http://www.nabble.com/Role-of-all-loaders-to22115931.html#a22172592
========================================================================

Re: Role of all loaders  
by Darin Adler Feb 24, 2009; 08:28am :: Rate this Message:    (use ratings to moderate[?])

> FrameLoader

Controls the process of loading web pages into a frame. Contains all  
the loading-related functions and data instead of having them all on  
Frame itself. There’s one of these for each frame.

> DocumentLoader

Controls the process of loading one particular web page into a frame.  
When a new page is loaded, the frame loader creates a new document  
loader and then later destroys the old one.

> DocLoader

Part of the caching machinery. Manages the cached loading for a  
particular document. May be merged with DocumentLoader at some point  
in the future, or perhaps renamed.

> MainResourceLoader

FrameLoader and DocumentLoader use ResourceLoader objects to load  
individual resources. The main resource is the HTML file (or SVG file  
or whatever). The ResourceLoader for the main resource is a  
MainResourceLoader.

> Sub resource Loader

The ResourceLoader objects for subresources such as images, scripts,  
and CSS style sheets are SubresourceLoader objects.

     -- Darin

 

"URL loading중 발생하는 frameLoaderClient를 통한 이벤트"
from http://www.nabble.com/FrameLoaderClient-notifications-to16025970.html#a16030339
=====================================================================================
Re: FrameLoaderClient notifications  
by Darin Adler Mar 14, 2008; 02:37am :: Rate this Message:    (use ratings to moderate[?])

> I suppose the following order of loading events for a page with a  
> single frame (please, correct me, if I'm wrong):
>
> page load started
> main document load started
> title received
> icon received
> * main document load finished
> ** resource load started
> resource load finished
> page load finished
...[show rest of quote]

The the FrameLoaderClient functions about the frame (not the ones that  
take DocumentLoader*) are what you want. They are all about this  
cycle. dispatchDidStartProvisionalLoad is the one that goes first, and  
then there are quite a few others, ending with dispatchDidFinishLoad,  
dispatchDidFailLoad or dispatchDidFailProvisionalLoad.

> OK, I see. Is there any other load process other than provisional?

All loads start provisional.

>> dispatchWillSendRequest will be called repeatedly with different  
>> URLs when a server does redirection. This is normal. How it should  
>> be handled depends on what API you've devised.
>
> Is there any separate notification about redirection, or this method  
> is enough?

There is
dispatchDidReceiveServerRedirectForProvisionalLoad for loads of the  
main resource of a frame, but dispatchWillSendRequest alone is all  
that's needed for arbitrary resource loads.

> One more question: is there any method about starting loading of an  
> external resource? Is it dispatchWillSendRequest?  
> dispatchDidReceiveResponse?

assignIdentifierToInitialRequest and dispatchWillSendRequest

     -- Darin

 

"HTTP 스택은 누가 처리하나?"
from http://www.nabble.com/Complicated-Loaders-to18706606.html#a18724848
========================================================================

The sequence of FrameLoader and DocumentLoader functions is indeed complicated
and overloaded.  This is slowly being improved over time, little by little. 
And no, there is no documentation at this time.


I'm not sure of the exact motivation for your question, but you did end on
a very specific note so this might be of use.  The question of "how WebKit is
invoking the HTTP stack" is much simpler - the ResourceRequest, ResourceHandle,
and ResourceResponse classes are all fairly encapsulated and represent
HTTP connections.

~Brady

Posted by ingeeC
,

UML의 Class Diagram에 관해

Dev 2009. 4. 23. 12:19
UML 하면 떠오르는 다이어그램이 무엇일까?
대부분의 사람들이 Class Diagram을 UML의 대표 다이어그램으로 떠올린다. 그래서 UML을 도구로 S/W를 설계할 때 Class Diagram을 먼저 그리려고 애쓰곤 한다. 그런데, Class Diagram은 UML의 모든 다이어그램들 중에서 abstraction degree (추상화 정도)가 가장 높은 다이어그램이다. 순서로 따지자면 S/W 설계시에 가장 마지막에 그려야 할 다이어그램이다.

웹킷을 가지고 작업하면서 WebKit 코어를 헤집어보게 됐다. 분석한 결과를 블로그에 꾸준이 올리려고 한다. 그러기에 앞서 분석을 설명하는 "언어"에 대해 일러두려 한다. UML은 소프트웨어 형상에 관한 자신의 생각을 표현하는 "언어"다. 클래스 다이어그램을 그리는 많은 기법들이 존재하는데, 일러두려고 하는 것은 클래스와 클래스 사이의 association (연관관계) 표기에 관한 것이다.


앞으로 블로그에 올리는 클래스 다이어그램에서는 클래스와 클래스 사이의 관계를 가능한 association-line과 role-name 만으로 표현하려고 한다. 하얀 다이아몬드와 검은 다이아몬드 같은 예쁜 기호는 가능한 사용하지 않으려고 한다. 사용하는 어휘가 많아질수록 오해의 여지가 높아지기 때문이다. 위의 그림에서 표기한 ClassA와 ClassB 사이의 관계를 문장으로 옮기면 "ClassA is role-A of ClassB", "ClassB is role-B of ClassA"와 같다. 이와 같은 표기법은 당연(?)하게도 내 생각이 아니다 (분하다...). 훌륭한 선배 개발자의 경험에서 우러난 가이드이다 (클래스 다이어그램 그리는 법에 관한 책을 통해 배운 방법이다. 그 책의 저자는 임베디드 분야에서 무척 많은 경험을 쌓은 훌륭한 S/W 엔지니어였다).
Posted by ingeeC
,
웹킷 뉴스 그룹은 작업 정보의 보고다.
일이 막힐 때, 머리를 비우고 아래 사이트에서 검색어를 입력한 다음 일년치 정도의 기사를 정독하면 문제 해결의 실마리를 잡을 수 있을 것이다.

http://www.nabble.com/Webkit-f14949.html
Posted by ingeeC
,

WebKit 포팅에 관해

Dev 2009. 3. 31. 12:42
단말 엔지니어에게 포팅이란,
HAL API를 타겟 플랫폼에 맞게 구현해주는 작업이다. WIPI를 비롯한 기타 단말 솔루션들은 HAL API set 이 분명하게 정의되어 있다. 정해진 C함수들을 정해진 규격대로 구현하면 포팅이 끝난다. 근데 WebKit 은 이게 모호하다. 플랫폼에 dependent 한 포팅 레이어가 소스 트리 여러 곳에 산재해 있다. 기존 WIPI 포팅에 익숙한 한국의 단말엔지니어에게는 난감한 구조다. 하지만 여기에도 WebKit 나름의 규칙과 일관성이 있다. 익숙해지면 그럴만 하다고 동의할 수 있는 문제다.

WebKit port 의 특징은 포팅 타겟을 OS 로 한정하지 않는다는 점이다.
WebKit의 포팅 타겟은 Windows 나 Linux 같은 OS가 아니라, CoreGraphics, Cairo 같은 그래픽 툴킷, CFNetwork, CURL 같은 네트웍 툴킷이다. Cairo 가 올라간 OS 면 Windows 든 Linux 든 WebKit Cairo port 가 화면을 출력할 수 있다. 마찬가지로 CURL 이 올라간 OS 면 Windows 든 Linux 든 WebKit CURL port 가 네트웍을 이용할 수 있다.

WebKit 이 요구하는 툴킷들을 나열하면 대략 다음과 같다.
* 그래픽 툴킷 : CoreGraphics 또는 Cairo
* 네트웍 툴킷 : CFNetwork 또는 CUrl
* 이미지 디코더 : giflib, jpeglib, libpng ...
* XML 파서 : libxml, libxslt
* DB 라이브러리 : SQLite

WebKit 포팅 절차를 요약하자면 다음과 같다.
1. 사용할 툴킷 set 을 선택한다.
2. 선택한 툴킷을 타겟 OS 또는 타겟 device 에 포팅한다.
3. WebKit 을 올린다.

간단하다.
하지만 언제나 그렇듯, 간단함에도 불구하고 일이 되려면 개발자의 눈물겨운 노력이 있어야 한다.
Posted by ingeeC
,

StarUML

Dev 2009. 1. 13. 18:56

StarUML은 UML을 그리는 도구다.
한 10년 전에는 상용으로 판매됐던 도구인데, 현재는 무료 오픈 소스 프로젝트로 전환됐다. 비싸기로 유명한 Rational Rose를 비롯해서 여러개의 UML 도구를 써봤는데, StarUML이 최고였다. UML이 필요하다면 고민하지 말고 가져다 쓸 것을 권한다. 중요하진 않지만, 자랑스럽게도 우리나라에서 만든 툴이다. 그래서 '한국어'로 된 매뉴얼이 존재한다 (이건 중요하다).

http://staruml.sourceforge.net/ko/index.php

Posted by ingeeC
,
XP에서 WebKit을 빌드하고 나서, WebKit의 실행 얼게를 분석하고 있다.
웹킷을 엔진으로 이용하는 어플리케이션을 어찌 작성해야 하는지 분석하려면, XP WebKit 프로젝트에 포함된 WinLauncher를 이용해야 한다. 이를 이용하는데도 약간의 노하우가 필요하다. 이에 관한 내용을 다음과 같이 정리한다.

1. Isolated COM Component
WinLauncher는 WebKit.dll 에 COM 콤포넌트 형태로 포함된 다양한 WebKit 모듈들을 호출해가며 동작한다. 내 개발 머신에는 사파리 브라우저가 깔려있고, 사파리 폴더에 WebKit.dll 이 존재한다. 근데, WinLauncher.exe가 실행될 때 사파리 폴더에 존재하는 WebKit.dll 이 아니라, WinLauncher.exe 와 같은 폴더에 있는 WebKit.dll 을 로드하는게 너무 신기했다. 이건 COM DLL인데 말야. 레지스트리에는 분명 사파리 폴더에 있는 WebKit.dll path가 등록되어 있는데? 어찌된거지?
XP 이상의 윈도에서는 어플리케이션 빌드시 manifest 파일을 통해 로드될 COM DLL의 path를 지정할 수 있다고 한다. 이걸 isolated component 라고(맞나?) 부른다고 한다. 그래... 내가 윈도에 관한 공부를 게을리했다. 반성한다.

2. WinLauncher.exe 실행 팁
(
http://aautar.digital-radiation.com/blog/?p=98)

2.1. request->initWithURL() 타임아웃 설정

이젠 웹킷을 철저히 뜯어볼테다 결심하고 WinLauncher를 실행시켰다. 근데, WinLauncher.exe에서 네트웍이 안된다. http://naver.com 등에 접근할 수 없다. 아... WinLauncher는 샘플 코드라 네트웍 코드가 존재하지 않는가보다 하고 의심했다. 근데, 그게 아니었다. http://aautar.digital-radiation.com/blog/?p=98 글을 찾으니 답이 있었다. WebKit 메소드를 호출할때, 타임 아웃 설정이 필요하다고 한다.
WinLauncher 소스의 loadURL() 함수에서 request->initWithURL()를 호출할 때 인자를 다음처럼 설정해줘야 한다.
request->initWithURL(urlBStr, WebURLRequestUseProtocolCachePolicy, 60);

2.2. SafariTheme.resources 폴더 복사
그리고, WinLauncher.exe를 정상적으로 실행시키기 위해서는 사파리 폴더에서 SafariTheme.resources 폴더를 통째로 복사해와야 한다고 한다. 이거 무지하게 결정적인 정보다. 다른 것들은 어찌어찌 고생하면 해결할 수 있었을 것 같은데, 이건 해결 못했을 것 같다.

이런 정보가 존재하는 인터넷이 너무 고맙다. 이런 정보를 아낌 없이 공개하는 개발자들도 고맙고... 인터넷과 구글이 없었다면 개발을 어찌했을까...

WinLauncher 실행이미지를 첨부한다. 에디트 콘트롤에 URL을 입력하면, 해당 페이지로 이동한다.

Posted by ingeeC
,

Qt WebKit 단말 사용기

Dev 2008. 11. 18. 11:31

Qt-WebKit을 Windows Mobile 6.1 단말기에 올렸다.
"자, 이젠 빠른 성능과 아름다운 페이지를 보여줘." 하는 마음으로 실행시켰는데... 결론을 말하자면 실망이다. 아직 모자란 점이 많다. 이건 WebKit의 문제라기 보다는 Qt-WebKit의 문제다. 포팅이 불충분하다. 적어도 Windows Mobile에서는 그렇다.

1. 우선 네트웍에 관한 처리가 미흡하다.
스스로 단말의 네트웍 연결을 초기화시키지 못한다. 백그라운드로 Windows Mobile의 Internet Explorer를 실행시켜서 네트웍을 잡고 실행시키면 그나마 조금 상태가 나아진다. 하지만 한 화면을 구성하는 모든 document 들을 네트웍을 통해 다운로드하지 못한다. 화면 상태로 미루어 추정하자면, base HTML document만 다운로드해서 보여주는 것 같다.

2. 속도가 미흡하다.
난 빠른 속도를 기대했다. 적어도 Mobile IE보다는 빠른 속도를 기대했다. 그런데 체감 속도가 IE에 비해 대등하거나 느리다. 이건 Qt 레이어의 오버헤드 때문일 것 같다.


오른쪽은 Qt WebKit을 실행시키면 처음 뜨는 디폴트 홈페이지. 내가 만들어서 로컬 파일 시스템에 복사한 index.html 파일이다. 왼쪽은 BBC 뉴스 모바일 페이지. HTML만 처리하고, 이후 이미지 파일들을 읽어 들이지 못했다. Qt WebKit의 네트웍 처리가 불충분한 것 같다.




왼쪽 화면을 보면, "링크를 다른 창에서 열기" 컨텍스트 메뉴를 볼 수 있다. HTML 링크에 대고 롱클릭을 하면 뜨는 메뉴다. 웹킷 윈도를 하나 더 만들 수 있다. 이건 감동... 오른쪽 화면은 한글이 깨져보인다. 한글 폰트 처리에 문제가 있다.

완벽한 솔루션이 없어야, 프로그래머가 밥을 먹고 살 수 있는 것 아니겠는가? 웹킷이 또 기회를 주는구나...
이제 웹킷 자체를 분석해볼 참이다. 관련된 일을 하는 사람들이 있다면, 댓글이나 트랙백 등으로 알려주면 좋겠다. 오손도손 사이 좋게 개발할 사람들을 찾는다.

Posted by ingeeC
,


Windows Mobile 단말기가 하나 있다. 이놈 위에 웹킷을 올려보고 싶었다. 이리저리 찾던 중에, Qt WebKit 브라우저가 눈에 들어왔다. 다시 말하지만, 웹킷은 브라우저 엔진일뿐 브라우저가 아니다. 이놈을 브라우저로 동작하게 만들려면 많은 노력이 필요하다. Qt WebKit 프로젝트가 바로 그런 노력을 하고 있는 프로젝트다. 마침 "한.글.로.된." 좋은 블로그 글을 찾아 편안한 마음으로 시도해볼 수 있었다. 자기가 겪은 경험을 글로 정리해서 공개하는 사람들에게 다시 한번 감사하는 마음을 전한다.
http://www.korone.net/bbs/board.php?bo_table=qt_lecture&wr_id=465

하지만, 세상 모든 일이 그렇듯 뭔가 넘기 힘든 고개들이 있었다. 그런 고개들이 있어야 성공했을 때 성취감을 느낄 수 있는 것 아니겠는가? 나 다음 개발자들은 그런 성취감(?)을 느끼지 못하기를 기도하며 몇가지 경험을 정리한다.

처음에는 Cygwin 콘솔창을 열고 작업 했는데, 뭔가 잘 안됐다. 다음의 웹 페이지를 보고 원인을 알게 됐다. Qt WebKit을 Cygwin서 빌드하는 것은 원래 아직 안되는 것이었다 (2008.11.13. 현재). 그래서 WinXP 32bit의 커맨드 콘솔(cmd.exe)에서 작업했다. 커맨드 콘솔에서 작업하려면, 몇가지 GnuWin32 도구들을 설치해줘야 한다. 아래 "빌드 환경" 파트에 관련 내용을 정리했다.
http://trac.webkit.org/wiki/BuildingQtOnWindows

그리고, 빌드할 때 Qt WebKit 소스가 있는 드라이브의 루트 아래에 tmp 폴더를 만들어줘야 한다. 별거 아닌데, 이것 때문에 조금 고생했다.


빌드 환경
- WinXP 32bit
- Qt-wince를 다운로드 받아 빌드 완료한 상태 (참조 URL)
- Qt-WebKit 소스를 다운로드 받은 상태 (E:\Work\QtWebKit에 소스를 다운로드 함)
- 빌드를 위해 필요한 perl 및 GnuWin32 툴들을 설치한 상태 (참조 URL)


빌드 시퀀스

빌드 시퀀스를 순서대로 적으면 다음과 같다.
E:> cd \Work\QtWebKit\webkit
E:\Work\QtWebKit\webkit> mkdir \tmp
E:\Work\QtWebKit\webkit> mkdir WebKitBuild\Release
E:\Work\QtWebKit\webkit> perl WebKitTools\Scripts\build-webkit
... 성공 !!!  


이상이다.
이렇게 빌드한 바이너리를 Windows Mobile 6.1 단말기에 올리고 테스트해보고 있다. 실행화면과 사용 소감은 다음에 올릴 예정이다.
Posted by ingeeC
,