구글와이드(336x280)_상단 2개


(펌)AJAX Basics and Development Tools AJAX

본론

  1. Rich User Experience란 무엇인가?
    • Rich User Experience
      • 스프레드쉬트와 같은 전형적인 데스크탑 애플리케이션을 한번 보자.
      • 이런 프로그램들은 직관적이고 빠르게 반응한다.
      • 이런 프로그램들은 사용자에게 의미있는 피드백을 즉각적으로 제공한다.
        > 셀 위에 마우스를 올리면 색깔이 변한다.
        > 아이콘 위에 마우스를 올리면 밝아진다.
      • 아주 자연스럽다.
        > 이벤트를 발생시키기 위해 버튼이나 링크를 클릭할 필요가 없다.
    • 전통적인 웹 애플리케이션 특징
      • 사용자와의 상호 작용이 클릭, 대기, 리프레쉬라고 말할 수 있다.
      • 모든 이벤트, 데이터 전송, 탐색에 서버로부터의 페이지 리프레쉬가 필요하다.
      • 사용자는 반응을 기다려야 한다.
      • 동기적 요청/응답 커뮤니케이션 모델
      • 페이지 드리븐: 워크 플로우가 페이지에 근간을 이루고 있다.
      • 페이지 탐색 로직이 서버에 의해 결정된다.
    • 전통적인 웹 애플리케이션에 대한 이슈사항
      • 느린 반응
      • 리프레쉬를 하고 나면 당시의 컨텍스트를 잃어 버린다.
        > 페이지가 리프레쉬 되면 여러분의 뇌는 처음부터 다시 페이지가 뭔지 살펴 봐야 한다.
        > 스크롤을 한 후에 페이지가 리프레쉬 되었다면, 여러분은 다시 아까 본 지점으로 스크롤을 해야 한다.
      • 이러한 이슈사항 때문에 RIA 기술이 탄생하게 되었다.
  2. Rich Internet Application(RIA) 기술
    • RIA 기술
      • Applet
        > 코드 다운로딩 시간이 길다는게 단점
      • Macromedia Flash
        > 구현예: Laszlo suite(오픈소스)
        > 벡터 그래픽을 사용하는게 장점
        > 플러그인을 설치해야 하고, 액션스크립트가 한 회사 소유(proprietary)라는 단점이 있다.
      • Java WebStart
        > 이 기술은 애플릿과 데스크탑 애플리케이션의 단점들을 둘다 보완했다고 볼수 있다.
        즉, 애플릿의 강점은 사용자가 항상 최신 코드를 가질 수 있다는 것인 반면, 네트워크가 연결되어 있어야 한다는 제약 사항이 있다.
        반대로 데스크탑의 경우는 네트워크가 연결이 안 되어 있어도 사용하는데는 전혀 문제가 없지만, 일일이 설치를 해야 한다는 것이다.
        웹스타트는 처음에 설치가 되면 마치 데스크탑처럼 네트워크와 상관없이 사용 가능하고, 더불어 애플릿처럼 자동적으로 최신 버전이 있는지 확인한다. 만약 수정된 부분이 있으면 그것만 업데이트(incremental redeployment)를 한다.
      • DHTML
        > DHTML = JavaScript + DOM + CSS
        > 상호작용이 가능한 애플리케이션을 가능하게 했다.
        > 그러나, 비동기를 지원하지 않기 때문에 전체 페이지 리프레쉬가 여전히 필요하고, 이러한 연유로 반쪽 성공밖에 할 수 없었다고 본다.
      • DHTML with Hidden IFrame
        > IFrame을 사용함으로써 웹페이지에 프로그램을 통해 가능한 레이아웃을 추가할 수 있게 됐다.
        IFrame은 DOM 트리의 엘리먼트가 되며, 페이지가 보인 상태에서 IFrame을 이동, 리사이즈, 또는 감추는게 가능하다.
        > 보이지 않는 IFrame을 통해 비동기적인 요소를 추가할 수 있다. 이때 사용자와 웹페이지의 컨텍스트는 방해 받지 않는다.
        > 이 기술은 여전히 우수하다.(hack, 역자주: 해커도 대단하지 않은가. 같은 맥락의 의미로 파악하면 될듯 싶다.)
        > 단점이라면 IFrame이 원래 디자인된 의도와 다르게 사용되면서 발생하는 부작용과, AJAX와 비교해서 몇가지 제약 요소가 있다.
      • 드디어, AJAX
        > 한 마디로 DHTML 요소에 XMLHttpRequest를 통해 비동기 통신이 가능하게 한 기술이라고 말할 수 있다.
        > 여러 툴킷과 프레임워크가 출현하고 있으며, 코드를 다운로드하거나 플러그인을 설치할 필요가 없다.
        > 단점으로는 여전히 브라우저 호환성에 문제가 있으며, 자바스크립트가 유지보수하고 디버깅하기가 어렵다는 점이 있다.
        > AJAX기술이 가미된 JSF 컴포넌트가 나온다면, 이러한 단점들이 많이 보완되리라 본다.
  3. AJAX: 실례 및 사용 케이스
    • 현재 AJAX로 구현된 것들
      • Google maps
      • Google Suggest
        > auto-completion
      • Gmail
      • Yahoo Maps(new)
        > 야후도 AJAX를 이용해 사이트를 재구축 중이다.
    • Google maps의 핵심
      • 클릭이 아닌 마우스 드래그로 전체 지도를 본다. 즉, 새로운 지도 데이터에 대한 다운로드가 링크를 클릭하는 것이 아니라 지도를 이리저리 움직임으로 가능하게 된 것이다.
      • 물밑에선 AJAX가 사용되고 있다. 웹페이지 다른 부분은 가만히 있는 상태에서 비동기적으로 지도 데이터를 요청하고 다운로드 받고 있다. (No loss of operational context)
    • AJAX 사용 케이스
      • 실시간 서버측 입력 폼 데어터 유효성체크
        > 사용자 ID, 시리얼 번호, 우편번호에 대한 유효성체크가 지금까지는 클라이언트 측(사용자와 반응해야 하는 필요성)과 서버 측(보안, 벡엔드 데이터를 사용해야 하는 것과 같은 다른 이유들) 두 부분 모두에서 일어나야 함으로써 유지보수가 어렵게 되었다.
        > 자동 완성 기능: 이메일 주소, 이름, 도시 이름 등이 사용자가 몇개만 입력하면 자동 완성된다.
        > 개요-상세 오퍼레이션(Master/Detail operation): 사용자 선택에 기반해서 상세 정보를 가져와 뿌려 준다.
        > 진일보한 GUI 위젯과 콘트롤: tree controls, menus, progree bars(페이지 리프레쉬가 필요없음)
        > 데이터 리프레슁: 스코어, 주식시세, 날씨와 같은 실시간 정보를 가져 온다.
        > 서버측 알림에 대한 시뮬레이션: 서버측이 메세지, 페이지 데이터 리프레쉬, 다른 페이지로의 이동과 같이 클라이언트에게 무언가 알려야 하는 이벤트를 처리
    • AJAX 샘플 애플리케이션 데모
      • NetBeans IDE에 포함된 샘플 AJAX 애플리케이션(자동완성, 데이터유효성체크, progress bar)을 실행해 본다.
  4. AJAX란 무엇이며, 왜 AJAX이어야 하는가?
    • Why AJAX?
      • 직관적이고 자연스러운 사용자와의 상호작용
      • 부분적인 스크린 업데이트가 "click-wait-refresh"를 대신한다.
      • 데이터 드리븐(페이지 드리븐에 상반되게)
        > 성능, bandwidth의 감소, 서버측 부하 경감, 향상된 사용자 조작이 가능하게 되었다.
      • 비동기 통신방식
        > 2차 오픈 소스 스터디 > AJAX 기본 > 1. Ajax란? 참조
        > 두번째 그림에서 Ajax engine을 XMLHttpRequest로 보면 된다.
  5. AJAX에 사용된 기술
    • AJAX에 사용된 기술
      • JavaScript
        > 느슨한 타입의 스크립트 언어
        > 자바스크립트 함수는 페이지에 이벤트가 발생할 때 호출된다.
        > 전체 AJAX 오퍼레이션에 대한 접착제 역할
      • DOM
        > 구조화된 문서에 접근하고 조작하는 작업들에 대한 API
        > XML, HTML 문서 구조
      • CSS
        > 스타일과 내용을 분리한다는 의미가 있으며, 자바스크립트를 사용해 프로그램적으로 변경시킬 수도 있다.
      • HTTP
        > HTTP의 요청/응답 모델(GET, PUT 방식)을 이해할 필요가 있다.
      • XMLHttpRequest
        > 자바스크립트 오브젝트, 따라서 자바스크립트 코드 안에서 생성 가능하다.
        > 요즘 브라우저(Mozilla™, Firefox, Safari, and Opera)에서 지원된다.
        > 서버와 표준 HTTP GET/POST 방식으로 통신한다.
        > 백그라운드에서 벡엔드 서버와 비동기 통신 수행
    • Server-Side AJAX Request Processing
  6. 해부: 데이터 유효성 체크 예제를 통해 AJAX 수행 메커니즘 이해
    • AJAX 오퍼레이션 수행 단계

      5번을 제외한 나머지 6개가 클라이언트에서 수행되고 있다.
      • 클라이언트 이벤트 발생(1)
        <input type="text"        size="20"          id="userid"        name="id"     omkeyup="validateUserId();">
        
        > 이벤트의 결과로 자바스크립트 함수가 호출된다.
        > 한 예로 validateUserId()라는 자바스크립트 함수가 "userid"란 id를 가진 입력 폼 필드에 onkeyup 이벤트 핸들러로 매핑되어 있는 부분이다.
      • XMLHttpRequest 오브젝트 생성(2)
        var req; function initRequest() {     if (window.XMLHttpRequest) {         try {             req = new ActiveXObject("Msxml2.XMLHTTP"); // IE6.0 이상 MS의 새로운 버젼의 XMLHTTP객체         } catch(e) {             req = new ActiveXObject("Microsoft.XMLHTTP"); //IE4.0~5.5 SP2
                }
            } else if (window.XMLHttpRequest) {         isIE = true;         req = new XMLHttpRequest();
            }
        }
        
        function validateUserId() {
            initRequest();
            req.onreadystatechange = processRequest;
            if (!target) target = document.getElementById("userid");     var url = "validate?id=" + escape(target.value);     req.open("GET", url, true);     req.send(null); }
        
        > validateUserId() 이벤트 핸들러에서 보면 이 예제에서는 initRequest()란 함수를 통해 XMLHttpRequest 오브젝트를 생성한다. 여기서 마이크로소프트 인터넷 익스플로러와 모질라 타입 브라우저가 서로 다른 XMLHttpRequest 생성 방법을 가지고 있다. 모질라에서는 단순히 자바 오브젝트 생성처럼 "new XMLHttpRequest()"만 하면 되지만, 인터넷 익스플로러에서는 ActiveX 오브젝트를 생성해야 한다. 이 점은 여전히 존재하는 브라우저간 비호환성의 하나라고 볼수 있다. 또한 MS의 ActiveX객체또한 최신 버젼의 IE와 과거 IE간의 객체를 다르게 생성하여야 하는데 try{}문으로 먼저 최신버전의 객체가 있으면 그것을 생성하고 사용자의 IE가 과거 버젼일 경우 이전의 객체를 생성 할 수 있도록 catch{}문으로 묶어 준다.
      • XMLHttpRequest 콜백 함수 설정(3)
        > XMLHttpRequest가 생성된 다음에는 XMLHttpRequest의 onreadystatechange property를 콜백 함수로 설정한다. 이 콜백 함수는 XMLHttpRequest에 상태 변화가 발생할 때마다 비동기적으로 호출된다. 이 예제에서는 콜백 함수를 processRequest로 이름 지었다.
      • XMLHttpRequest 오브젝트 비동기 호출 실시(4)
        > 다음 번으로는 XMLHttpRequest의 open 메소드를 호출한다. 이 메소드는 세 개의 파라메타가 필요한데, 첫번째 것은 HTTP 방식, 즉 GET인지, POST인지를 결정한다. 두번째는 XMLHttpRequest와 상호작용할 서버측 컴포넌트의 URL, 마지막으로 세번째는 이 요청이 비동기적으로 일어날지에 대한 boolean 값이다. true면 비동기다.
      • 서버측 ValidateServlet이 결과를 담은 xml 리턴(5)
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {     String targetId = request.getParameter("id");     if ((targetId != null) && !accounts.containsKey(targetId.trim())) {
                response.setContentType("text/xml ");
                response.setHeader("Cache-Control", "no-cache");
                response.getWriter().write("<valid>true</valid>");     } else {
                response.setContentType("text/xml ");
                response.setHeader("Cache-Control", "no-cache");
                response.getWriter().write("<valid>false</valid>");
            }
        }
        
        > 이제 HTTP 응답을 만들 차례이다. 첫번째로 Content-Type을 text/xml로 세팅하고, Cache-Control은 no-cache로 설정한다. 즉 브라우저가 로컬에 있는 응답 객체를 사용 못하도록 할 것이다. 마지막으로 true 혹은 false라는 내용의 XML 요소(fragment)를 리턴한다.
      • XMLHttpRequest 콜백 함수 호출하여 결과값을 처리(6)
        function processRequest() {     if (req.readyState == 4) {         if (req.status == 200) {             var message = ...; ...
        
        > 다시 컨트롤은 클라이언트로 넘어 왔다. 앞서 3단계에서 processRequest 함수를 XMLHttpRequest 객체의 readyState field에 상태 변화가 발생할 때마다 호출되는 콜백 함수로 등록했었다. 위 코드는 XMLHttpRequest의 readyState 값이 4이고 status 값이 200일때, 즉 서버로부터 데이터가 성공적으로 리턴되었을 때 뭔가를 실행한다는 걸 말하고 있다.
      • HTML DOM 업데이트(7)
        > 자바스크립트에서는 DOM API를 이용해서 페이지 내 어떤 엘리먼트도 참조 가능하다.
        > 추천할 만한 참조방법은 document.getElementById("userIdMessage") 이런식이다.
        > 자바스크립트에서는 엘리먼트의 속성이나 스타일, 또는 child 엘리먼트를 추가, 삭제, 변경할 수 있다.

        > id를 이용해서 document 객체에 있는 div 엘리먼트를 id를 사용해서 참조값을 얻어 온다. 서버로부터 온 값이 true인지 false인지에 따라 messageText 변수에 그에 알맞는 값을 세팅하고 userIdMessage 엘리먼트에 child node로 추가한다. 결국, 이렇게 해서 이 페이지 중 userIdMessage 부분만 업데이트하게 된다.
  7. XMLHttpRequest Methods & Properties
    • XMLHttpRequest Methods
      > open과 send가 중요, 나머지 중 아래 3개는 요청 또는 응답 메세지의 헤더 정보에 관한 것들이다.
      • open("HTTP method", "URL", syn/asyn)
      • send(content)
      • abort()
      • getAllResponseHeaders()
      • getResponseHeader("header")
      • setRequestHeader("label","value")
    • XMLHttpRequest Properties
      • onreadystatechange
        > 자바스크립트 이벤트 핸들러와 함께 세팅하는데, 실제 상태는 readyState property에서 알 수 있다. onreadystatechange property와 함께 세팅된 콜백 이벤트 핸들러는 readyState에 값이 바뀔 때마다 호출된다.
      • readyState - 요청의 현재 상태
        > 0 = uninitialized
        > 1 = loading
        > 2 = loaded
        > 3 = interactive (some data has been returned)
        > 4 = complete (가장 중요한 값인데, 이는 서버와의 상호작용이 완결되었음을 의미한다)
      • status
        > HTTP 상태를 반영하는데, 200이라는 값은 성공적인 응답이 왔음을 의미한다.
      • responseText
        > 서버로부터 리턴된 데이터의 스트링 버전
      • responseXML
        > 서버로부터 리턴된 데이터에 대한 XML 문서
      • statusText
        > 서버로부터 리턴된 상태를 나타내는 텍스트
  8. DOM APIs & InnerHTML
    • 브라우저와 DOM
      • 브라우저는 디스플레이되는 HTML 문서를 객체의 형태로 관리하는데, 이 객체는 Document Object Model(DOM) 형태를 하고 있다. 자바스크립트에서 document라는 이름의 객체로 사용 가능하다.
      • 자바스크립트 코드로 DOM을 프로그램적으로 수정 가능하게 하는 API를 제공한다.
    • DOM APIs vs. InnerHTML
      • DOM APIs는 페이지에 있는 내용들을 탐색하고 수정 가능하게 해 준다.
        var messageBody = document.createTextNode(messageText); if (userMessageElement.childNodes[0]) {
            userMessageElement.replaceChild(messageBody,
            userMessageElement.childNodes[0]);
        } else {
            userMessageElement.appendChild(messageBody);
        }
        
      • InnerHTML 사용법은 더 쉽다. 해당 오브젝트의 시작 태그와 종료 태그 사이의 HTML을 세팅하거나 읽는다.
        userMessageElement.innerHTML = messageText;
        
  9. AJAX 보안
    • 서버측
      • AJAX 기반 웹 애플리케이션 또한 일반 웹 애플리케이션과 같은 서버측 보안 정책을 사용한다. 즉 web.xml에 선언적으로authentication, authorization, 및 데이터 보호를 위한 요구사항을 설정하거나 프로그램적으로 처리한다.
      • AJAX 기반 웹 애플리케이션 또한 일반 웹 애플리케이션과 같은 위험(cross-site scripting, injection flaw)에 노출되어 있다.
    • 클라이언트측
      • 자바스크립트 코드는 사용자 또는 해커에 노출되어 있다. 즉 해커는 서버측 약점을 알아내기 위해 자바스크립트 코드를 사용할 수 있다.
      • 자바스크립트는 서버로부터 다운로드된 후에 나쁜 의도의 코드가 실행됨으로 클라이언트를 손상시킬 수 있다.
      • 다운로드된 자바스크립트 코드는 sand-box 보안 모델에 의해 제약을 받지만 허용된(signed) 자바스크립트에 대해서는 보안이 느슨해질 여지가 있다.
  10. 자바스크립트 디버깅 툴
    • NetBeans IDE 플러그인
      • NetBeans 상에서의 AJAX 애플리케이션 개발은 다른 일반적인 웹 애플리케이션을 NetBeans에서 구축할 때와 대동소이하다.
      • NetBeans 상에서 실행 가능한 자바스크립트 에디터 플러그인을 http://www.liguorien.com/jseditor/에서 구할수 있다.
    • 모질러 브라우저 상의 개발툴
      • Mozilla FireBug debugger (add-on)
        > 소스 코드 레벨로 한줄한줄 디버깅이 가능하다.
        > 상태바를 통해 페이지에 에러가 있는지 알수 있다.
        > 콘솔에서는 자바스크립트와 CSS 상의 문법 에러를 볼 수 있다.
        > 로그 메세지를 콘솔에서 보는게 가능하다. 즉, alert를 통한 디버깅이 필요 없어진다.
        > 자바 스크립트 커맨드 라인(주소란에 더이상 javascript:를 안 써도 된다)
        > XMLHttpRequest 트래픽을 훔쳐 볼수 있다. 또한 HTML 소스, 스타일, 이벤트, 레이아웃, DOM을 볼수도 있다.
      • Mozilla JavaScript console
        > build-in
      • Mozilla DOM inspector (comes with Firefox package)
        > Firefox를 설치할 때 custom을 선택하면 추가로 DOM inspector를 설치 가능하다.
      • Mozilla Venkman JavaScript debugger (add-on)
        > 소스 코드 레벨의 디버깅 가능
      • Mozilla LiveHTTPHeaders HTTP monitor (NetBeans HTTP monitor과 비슷함)
        > 만약 NetBeans을 사용하지 않는다면 HTTP 트래픽을 잡는 용도로 이용 가능하다.
  11. AJAX의 현재 이슈와 미래
    • AJAX 현재 이슈
      • 복잡도의 증가: 서버측 로직 뿐만 아니라 HTML 클라이언트 페이지에서도 프리젠테이션 로직이 필요하게 되었다.
      • AJAX 기반 애플리케이션은 디버깅, 테스트, 유지보수가 어렵다.
        > 자바스크립트는 테스트의 자동화를 실현하기 힘들다.
        > 자바스크립트는 모듈화하기 어렵다.
        > 디자인 패턴과 베스트 프랙티스가 여전히 모자라는 실정이다.
      • 많은 툴킷과 프레임워크가 있지만 아직 성숙단계가 아니다.
      • XMLHttpRequest에 표준이 없으며, 예전 브라우저에서는 지원하지 않는다.
      • 자바스크립트 기술에 의존적이며 브라우저간 incompatibility가 여전히 있다.
      • 자바스크립트가 해커에게 노출됨으로 해서 보안의 위험이 있다.
    • XMLHttpRequest를 지원하는 브라우저
      • Mozilla Firefox 1.0 and above
      • Netscape version 7.1 and above
      • Apple Safari 1.2 and above.
      • Microsoft Internet Exporer 5 and above
      • Konqueror
      • Opera 7.6 and above
    • AJAX 미래
      • AJAX-enabled JSF components가 개발됨으로써 최소한의 개발 노력으로 AJAX 행동패턴을 가진 웹 애플리케이션을 구축할 수 있게 될 것이다.
      • XMLHttpRequest 생성 방법이 표준화 될 것이다.
      • 다음 세대 브라우저는 더욱 AJAX 친화적이 될 것이다.
      • 프레임워크 지원이 더욱 활발해지며, 디자인패턴과 베스트 프랙티스도 알아내고 공유될 것이다.

실습과 숙제

실습0: Mozilla Firefox browser 환경설정 (10 분)
실습1: Build, run, and debug "Data Validation with AJAX" 샘플 어플리케이션 (45 분)
실습2: "Venkman" JavaScript Debugger 사용하기, DOM Inspector (15 분) - 옵션
실습3: "FireBug" Debugger 사용하기(30 minutes)
실습4: Build, 두개의 다른 AJAX 샘플 어플리케이션 실행하기(15분)
실습5: 인라인 컨텐츠 셋팅을 위해 innerHTML 사용하기(장황한 DOM APIs 대신) (15 분)
실습6: Build, run various AJAX sample applications from "Foundations of AJAX" book (30 분)
실습7: Browse sample AJAX application code from "Pragmatic AJAX" book (20 분) - 옵션
숙제 실습 (상신의 "Ajax online course"를 수강하고 있는 학생을 위한)

의문점

  1. 전통적인 웹 애플리케이션에서는 페이지 탐색 로직이 서버에 의해 결정된다고 했다. 그럼 AJAX를 사용하면 클라이언트에서 결정이 되는 것인가? 잘 그림이 안 그려진다.
    • 전통적인 방식에서는 우리가 어떤 하나의 화면을 보고 있고 다음에 어떤 페이지로 이동할지 결정한 후 링크 또는 버튼을 누르면 화면이 새로고침 되면서 서버로부터 다음 페이지에 대한 정보를 가져오잖아요..서버에서 그 두번째 페이지에 대한 정보를 내려주어야만 두번째 페이지에서 세번째는 어디로 이동할지 알 수가 있구요..그걸 page-driven이라고 한게 아닐까..이와 다른 의미로 AJAX는 data-driven방식이라고 설명하고 있는데 서버로부터 데이터를 내려받고 있는 순간에도 화면이 새로고침 되는 게 아니니까 사용자가 다른 화면이나 데이터를 보고 싶다면 얼마든지 이동이 가능하다는.. - 배소희
  2. 이미 있는 위키페이지에 링크가 안 걸리네요. 비동기방식 설명 그림이 2차스터디 위키페이지에 있어서 그 곳에 링크를 걸고 싶은데 안 됩니다.

참고문헌

문서에 대하여

최초작성자 : [김민재]
최초작성일 : 2006년 8월 6일
버전 : 0.9
문서이력 :
  • 2006년 8월 6일 김민재 문서 최초 생성
  • 2006년 8월 11일 김계옥 실습과 숙제 추가
  • 2006년 8월 22일 김민재 전체 내용 일차 검토 완료
(출처: http://wiki.javajigi.net/display/WEB20/AJAX+Basics+and+Development+Tools )

null



바보들의 영문법 카페(클릭!!)

오늘의 메모....

시사평론-정론직필 다음 카페
http://cafe.daum.net/sisa-1

바보들의 영문법 다음 카페
http://cafe.daum.net/babo-edu/

티스토리 내 블로그
http://earthly.tistory.com/

내 블로그에 있는 모든 글들과 자료에 대한 펌과 링크는 무제한 허용됩니다.
(단, 내 블로그에 덧글쓰기가 차단된 자들에게는 펌, 트랙백, 핑백 등이 일체 허용되지 않음.)

그리고 내 블로그 최근글 목록을 제목별로 보시려면....
바로 아래에 있는 이전글 목록의 최근달을 클릭하시면 됩니다.
그러면 제목을 보고 편하게 글을 골라 보실 수 있습니다.

그리고 내 블로그내 글을 검색하시려면 아래 검색버튼을 이용하시면 됩니다.


가가챗창

flag_Visitors

free counters