Installing PyDev into Eclipse on Mountain Lion, Mavericks

i) Install Eclipse and pydev plugins

1. Go to http://www.eclipse.org/downloads/
Screen Shot 2013-12-17 at 6.15.00 PM

 

2. Download Eclipse IDE for Java Developers (Any other version of IDE also) the appropriate directory and Extract.

Screen Shot 2013-12-17 at 6.19.04 PM

 

3. Run the Eclipse and click command link Help > Install New Software.

Screen Shot 2013-12-17 at 6.22.13 PM (2)

 

4. Click Add… button and write a Name as pydev and Location http://pydev.org/updates

Screen Shot 2013-12-17 at 6.22.39 PM (2)

 

5. Select ‘PyDev’ and ‘PyDev Mylyn Integration (optional)’ click Next button

Screen Shot 2013-12-17 at 6.23.11 PM (2)

 

6. Select all and Click Next button

Screen Shot 2013-12-17 at 6.23.22 PM (2)

Screen Shot 2013-12-17 at 6.24.34 PM (2)

Screen Shot 2013-12-17 at 6.24.37 PM (2)

 

7. Check the I accept… and click Finish button

Screen Shot 2013-12-17 at 6.24.41 PM (2)

 

8. Just wait!

Screen Shot 2013-12-17 at 6.24.46 PM (2)

Screen Shot 2013-12-17 at 6.24.48 PM (2)

 

9. Restart Eclipse! But, Eclipse – Preference not show PyDev menu… why? you must set the other preference. See a next step.

Screen Shot 2013-12-18 at 6.33.57 AM

 

ii) Install python 2.7

1. Go to http://www.python.org/download/

Screen Shot 2013-12-17 at 6.33.26 PM

 

2. Download Python 2.7.6 Mac OS X 64-bit/32-bit x86-64/i386 Installer the appropirate directory and double click the python-2.7.6-macosx10.6.dmg

Screen Shot 2013-12-17 at 6.35.22 PM

 

3. Run the Python.mpkg and process install.

Screen Shot 2013-12-17 at 6.35.43 PM

Screen Shot 2013-12-17 at 6.35.48 PM

Screen Shot 2013-12-17 at 6.35.59 PM

Screen Shot 2013-12-17 at 6.36.16 PM

 

iii) Install Java 7

PyDev now must requires Java 7… if you not having Java 7 makes Eclipse-Preference simply not show PyDev!

1. Go to http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html and Click the Java Platform (JDK) 7u45

Screen Shot 2013-12-18 at 6.42.07 AM

 

2. Download jdk-7u45-macosx-x64.dmg the appropirate directory and double click the jdk-7u45-macosx-x64.dmg

Screen Shot 2013-12-18 at 6.42.25 AM

 

3. Run the JDK 7 Update 45.pkg and process install.

Screen Shot 2013-12-17 at 6.48.15 PM

Screen Shot 2013-12-18 at 6.51.01 AM

Screen Shot 2013-12-18 at 6.50.53 AM

Screen Shot 2013-12-18 at 6.51.26 AM

 

4. We’re All ready for using a python on Eclipse Mountain Lion, Mavericks !!! go to next others steps.

 

vi) Set a default pydev preference into Eclipse

1. Run the Eclipse and click command link Eclipse > Preferences.

Screen Shot 2013-12-17 at 6.51.01 PM (2)

 

2. Click the menu PyDev – Interpreters – Python Interpreter and click the Quick Auto-config button

Screen Shot 2013-12-17 at 6.51.33 PM (2)

Screen Shot 2013-12-17 at 6.51.36 PM (2)

 

3. Click the Ok button.

 

v) Start Python Hello Word project!

1. Click command File-New and Click the PyDev Project(if not appeared click the Other…)

Screen Shot 2013-12-17 at 7.05.13 PM (2)

Screen Shot 2013-12-17 at 6.52.18 PM

 

2. Write a Project name

Screen Shot 2013-12-17 at 6.53.02 PM

 

3. Click the Project and click the mouse right button and click the New-PyDev Module

Screen Shot 2013-12-17 at 6.53.52 PM (2)

 

4. write a your module Name and click the finish button

Screen Shot 2013-12-17 at 7.13.15 PM (2)

 

5. Funny coding!

Screen Shot 2013-12-17 at 6.54.18 PM

Screen Shot 2013-12-17 at 7.12.25 PM (2)

Screen Shot 2013-12-17 at 7.12.35 PM (2)

PyDev installation Eclipse Kepler and Mac OS
Getting started with Eclipse and PyDev
Tutorial PyDev Eclipse
Eclipse Install PyDev
맥 이클립스 PyDev 설치하기

Where is Microsoft Translate API for iOS? It’s here!

https://github.com/bitmapdata/MSTranslateVendor

Microsoft Translate iOS API

Microsoft ends free Bing Search API, moves to paid service on Azure Marketplace. Bing translator is deprecated, and it forces developers to use a more complicated way than the previous way using AppID.

The Microsoft Translate new API involves a temporal token, named as access token, which will expire in 10 minutes after you get it. before you get a token, your application must be registered.

Please refer to the steps below.(Microsoft Azure Market Join step is omitted.)

(1) access https://datamarket.azure.com/developer/applications and register the client application (that is, the app using the API), where you can create your own Client ID and Name, and you also have to type in redirect URI which should be a valid URL address (like “http://www…..”);

(2) If you complete the registration, the following screen appears.

For more information: http://msdn.microsoft.com/en-us/library/hh454950.aspx

MSTranslateVendor was constructed based on Microsoft Translator V2 HTTP. and is based on block-based. As much as possible to not have a dependency on another framework is designed Cocoa library only was used.

이 글은 iOS 카테고리로 분류되었고 님에 의해 에 작성됐습니다.

MSCellAccessory

MSCellAccessory is a UITableViewCell accessoryType can easily customize the colors. Many developer really want to customizing UITableViewCell accessoryType color. but, they using a customized png image are solved. but this method is not good. because Unnecessary to create an image file, and each would have to create all colors. and Loading it unnecessarily increases the capacity of the memory. If using a this library is more easily customizing accessoryType and more flexible via Programmatically.

https://github.com/bitmapdata/MSCellAccessory

이 글은 iOS 카테고리로 분류되었고 님에 의해 에 작성됐습니다.

FlasCC + Voronoi

I refer a SampleCode 03_Drawing

FlassCC is a Flash C,C++ Compiler.
C,C++ code compiled with GCC, convert LLVM to AVM2.
you can make a .swf or .swc. is slightly different concept ANE.

visit a this site: http://gaming.adobe.com/technologies/flascc/

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include "VoronoiDiagramGenerator.h"
#include <Flash++.h>
using namespace AS3::ui;
 
flash::display::Stage stage = internal::get_Stage();
void drawVoronoi(void)
{
    myShape = flash::display::Sprite::_new();
 
    int stagewidth, stageheight;
 
    inline_as3(
               "import flash.display.Stage;\n"
               "import flash.display.Graphics;\n"
               "import com.adobe.flascc.CModule;\n"
               "var gfx = CModule.rootSprite.graphics;\n"
               "gfx.clear();\n"
               "gfx.lineStyle(1, Math.random() * 0xffffff);\n"
               "gfx.beginFill(0, 0.0);\n"
               "%0 = CModule.rootSprite.stage.stageWidth;\n"
               "%1 = CModule.rootSprite.stage.stageHeight;\n"
               : "=r"(stagewidth),"=r"(stageheight) :
               );
 
 
    int cellcount = rand() % 3000;
	float xvals[cellcount], yvals[cellcount];
    for(int i=0; i<cellcount; i++)
    {
        xvals[i] = stagewidth * ((float)rand()/(float)RAND_MAX);
        yvals[i] = stageheight * ((float)rand()/(float)RAND_MAX);
    }
 
	VoronoiDiagramGenerator vdg;
	vdg.generateVoronoi(xvals, yvals, cellcount, 0, stagewidth, 0, stageheight, 3);
	vdg.resetIterator();
    float _x1,_y1,_x2,_y2;
    while(vdg.getNext(_x1,_y1,_x2,_y2))
	{
        inline_as3("gfx.moveTo(%0,%1);\n" : : "r"(_x1), "r"(_y1));
        inline_as3("gfx.lineTo(%0,%1);\n" : : "r"(_x2), "r"(_y2));
	}
    inline_as3("gfx.endFill();\n");
 
}
 
var redrawVoronoi(void *arg, var as3Args)
{
    drawVoronoi();
    return internal::_undefined;
}
 
int main(int argc,char **argv)
{
    drawVoronoi();
 
    flash::display::Stage stage = internal::get_Stage();
 
    stage->addEventListener(flash::events::MouseEvent::CLICK,
                               Function::_new(redrawVoronoi, NULL));
 
    AS3_GoAsync();
}

here swf.

click a screen, redraw voronoi. I tested Pure AS 3.0 Voronoi Algorithm. I knew incredibly fast.

Fast Comparison AsciiString Category

In general, when comparing the ascii String, using following category faster then Cocoa.

I tested following.

//2000% faster
- (void)testString1
{
    NSString *string = @"apple_cocoa";
    NSDate *startDate = [NSDate date];
    for (int i = 0; i<1000000; i++)
    {
        [[string lowercaseString] isEqualToString:@"AppLe_CocoA"];
    }
    NSDate *endDate = [NSDate date];
    NSTimeInterval timeInterval = [endDate timeIntervalSinceDate:startDate];
    NSLog(@"*** first-loop sec : %f", timeInterval);
    startDate = [NSDate date];
    for (int i = 0; i<1000000; i++)
    {
        [string isEqualToCaselessAsciiString:@"AppLe_CocoA"];
    }
    endDate = [NSDate date];
    timeInterval = [endDate timeIntervalSinceDate:startDate];
    NSLog(@"*** second-loop sec : %f", timeInterval);
}
//150% faster
- (void)testString2
{
    NSString *string = @"AP.PLE~!@#$%^&*()BBC_Ko";
    NSDate *startDate = [NSDate date];
    for (int i = 0; i<1000000; i++)
    {
        [string lowercaseString];
    }
    NSDate *endDate = [NSDate date];
    NSTimeInterval timeInterval = [endDate timeIntervalSinceDate:startDate];
    NSLog(@"*** first-loop sec : %f", timeInterval);
    NSLog(@"string1:%@", [string lowercaseString]);
    startDate = [NSDate date];
    for (int i = 0; i<1000000; i++)
    {
        [string lowercaseAsciiString];
    }
    NSLog(@"string2:%@", [string lowercaseAsciiString]);
    endDate = [NSDate date];
    timeInterval = [endDate timeIntervalSinceDate:startDate];
    NSLog(@"*** second-loop sec : %f", timeInterval);
}

NSString + AsciiExtend.h

@interface NSString (AsciiExtend)
 
- (BOOL)isEqualToAsciiString:(NSString *)asciiString;
 
- (BOOL)isEqualToCaselessAsciiString:(NSString *)asciiString;
 
- (NSString *)lowercaseAsciiString;
 
- (NSString *)uppercaseAsciiString;
 
@end

======================================================

NSString + AsciiExtend.m

 
@implementation NSString (AsciiExtend)
 
- (BOOL)isEqualToAsciiString:(NSString *)asciiString
{
    int returnValue;
 
    const char *str1 = [self cStringUsingEncoding:[NSString defaultCStringEncoding]];
 
    const char *str2 = [asciiString cStringUsingEncoding:[NSString defaultCStringEncoding]];
 
    returnValue = strcmp(str1, str2);
 
    return (returnValue==0)?YES:NO;
}
 
- (BOOL)isEqualToCaselessAsciiString:(NSString *)asciiString
{
    int returnValue;
 
    const char *str1 = [self cStringUsingEncoding:[NSString defaultCStringEncoding]];
 
    const char *str2 = [asciiString cStringUsingEncoding:[NSString defaultCStringEncoding]];
 
    returnValue = strcasecmp(str1, str2);
 
    return (returnValue==0)?YES:NO;
}
 
- (NSString *)lowercaseAsciiString
{
    NSUInteger len = [self length]+1;
 
    char a[len];
 
    [self getCString:a maxLength:len encoding:[NSString defaultCStringEncoding]];
 
    int i =0;
 
    while((a[i] = tolower(a[i])))
 
        ++i;
 
    return [NSString stringWithCString:a encoding:[NSString defaultCStringEncoding]];
}
 
- (NSString *)uppercaseAsciiString
{
    NSUInteger len = [self length]+1;
 
    char a[len];
 
    [self getCString:a maxLength:len encoding:[NSString defaultCStringEncoding]];
 
    int i =0;
 
    while((a[i] = toupper(a[i])))
 
        ++i;
 
    return [NSString stringWithCString:a encoding:[NSString defaultCStringEncoding]];
}
 
@end

부드러운 이동

<script type="text/javascript">
 
function moveToLoc(nLoc)
{
    // 원하는 위치로 이동
    location.hash=nLoc;
}
function currentYPosition() 
{
    // 파이어폭스, 오페라, 사파리, 크롬
    if (self.pageYOffset) return self.pageYOffset;
    // 인터넷익스플로러6 StandardMode
    if (document.documentElement && document.documentElement.scrollTop)
        return document.documentElement.scrollTop;
    // 인터넷익스플로러6,7,8(9은 테스트 안해봄)
    if (document.body.scrollTop) return document.body.scrollTop;
    return 0;
}
function elmYPosition(eID) 
{
    var elm = document.getElementById(eID);
    var y = elm.offsetTop;
    var node = elm;
    while (node.offsetParent && node.offsetParent != document.body)
    {
        node = node.offsetParent;
        y += node.offsetTop;
    } 
    return y;
}
function smoothScroll(eID) 
{
    var startY = currentYPosition();
    var stopY = elmYPosition(eID);
    var distance = stopY > startY ? stopY - startY : startY - stopY;
    if (distance < 100) 
    {
        scrollTo(0, stopY); return;
    }
    var speed = Math.round(distance / 1000);
    if (speed >= 20) speed = 20;
    var step = Math.round(distance / 25);
    var leapY = stopY > startY ? startY + step : startY - step;
    var timer = 0;
    if (stopY > startY) 
    {
        for ( var i=startY; i<stopY; i+=step ) 
        {
            setTimeout("window.scrollTo(0, "+leapY+")", timer * speed);
            leapY += step; if (leapY > stopY) leapY = stopY; timer++;
        } 
       return;
    }
    for ( var i=startY; i>stopY; i-=step ) 
    {
        setTimeout("window.scrollTo(0, "+leapY+")", timer * speed);
        leapY -= step; if (leapY < stopY) leapY = stopY; timer++;
    }
}

사용방법:

아래와 같은 html코드를 작성한 후…

<p class=”myClass” id=1>테스트1</p>
<p class=”myClass” id=2>테스트2</p>
<p class=”myClass” id=3>테스트3</p>
<p class=”myClass” id=4>테스트4</p>

moveToLoc(원하는 id 호출); 좌측과 같이 사용하면 HTML페이지 내의 id위치로 부드럽게 이동함.

OpenKinect + Actionscript 3.0

히밤 avi파일 임베디드 버그 떠서 swf파일로 올림 -_- 플리커에도 안올라가지고 -_-…

어쨌든 대충 테스트용으로…

금요일까지 샘플작업을 만들게 있어서 -_-;;

뎁스 조정하는거 진짜 라이브러리 뒤져도 안나와서 질문글을 as3kinect.org에 올렸는데

http://www.as3kinect.org/forum/?mingleforumaction=viewtopic&t=18

답변이 계속 소켓하고 라이브러리는 버전업이 될것이고,

조만간에 플래시 내부적으로 뎁스조정을 할 수 있게끔 메서드를 추가 시켜 준다고 답변이 달렸음.

근데… 나는 그때까지 기다리기 힘들어서 C코드 수정 해서 소켓을 다시 생성했음…

as3kinect.org에 올라온 파일은 기본 소켓파일(as3-server.exe)이고,

직접 C로 컴파일 해서 자기가 튜닝해서소켓을 다시 만들어야함…

처음에 솔직히 플래시자체적으로 뎁스 조정할 수 있는지 알았는데…

다음버젼에는 조정 할 수 있도록 메서드 추가해준다고 답변이 달렸으니…

조만간 OpenNI랑 NUI도 테스트를 해야 하기 때문에…

난 기다릴수가 없었음…

아래 영상은 OpenNI를 이용한 충격적인 영상임 ㄷㄷㄷ

OpenNI + MikuMikuDance
http://www.youtube.com/watch?v=bQREhd9iT38

댓글 거의 500개… ㄷㄷㄷ 일본 오타쿠가 만든건데… -_- 대단함…

mikumikudance는 무료 3D 에니메이션 제작 툴인데… 이것도 일본사람이 만든거긴 한데…

현재까지 공개된 영상중에서 이 영상이 최고…

확실히 이런쪽은 일본을 따라잡기가 힘들 듯…

지금은 한물갔긴했지만, FLARToolkit도 일본에서 처음 만든거고…

그리고 쓰러져가는 어도비를 살린 스파클 프로젝트 팀도 일본이고…

정말 최고는 일본의 액션3.0 원서임… 요새 일본어를 게을리해서 해석하는데 시간이 엄청나게 걸리긴하지만 -_-…

설명을 진짜 기가 막히게 적어놨음… 일본원서를 볼때마다 감탄의 감탄…

이 글은 lab 카테고리로 분류되었고 님에 의해 에 작성됐습니다.

수치해석(1) CatmullRom Spline

일전에도 설명했던 보간법중에서

현재 가장 많이 쓰이고 있고, 가장 정확한 보간법이 CatmullRom Spline이다.

CatmullRom Spline이 나오기전에 에르미트 보간법이 있었지만, 지금은 CatmullRom 보간법이 주로 쓰이고 있다.

아래는 CatumullRom Spline에 관해서 C언어로 작성해 놓은 사이트…
http://www.lighthouse3d.com/opengl/maths/index.php?catmullrom

아래는 너무나도 유명한 ActionSnippet.com 사이트의 CatmullRom Spline 소스코드모음이다.
http://actionsnippet.com/?s=spline&searchsubmit=Search
하지만… CatmullRom Spline의 원론적인 이해가 없으면 보기가 거북할 수도 있다.

CatmullRom Spline에 관한 설명이다… 꼭 한번 읽어보기를… 번역기를 돌려서 -_-
http://en.wikipedia.org/wiki/Cubic_Hermite_spline

필자는 아래의 공식을 이용하였다…

import flash.geom.Point;
import flash.display.Sprite;
import flash.events.MouseEvent;
 
var total:int = 8;
var points:Vector.<Point> = new Vector.<Point>();
for(var i:int = 0; i<total; i++)
{
	var pt:Point = new Point();
	pt.x = 50 + 100 * i;
	if(i == 0 || i == total-1)
	{
		pt.y = 200;
	}
	else
	{
		pt.y = int(100 + 150 * Math.random());
	}
 
	points.push(pt);
 
	trace(points[i]);
}
 
for(var j:int = 0; j<points.length; j++)
{
	var sp:Sprite = new Sprite();
 
	addChild(sp);
 
	sp.x = points[j].x;
	sp.y = points[j].y;
 
	sp.graphics.beginFill(0xff0000,1);
 
	sp.graphics.drawCircle(0,0,5);
 
	sp.name = "" + j;
 
	sp.graphics.endFill();
 
	sp.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
	stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
}
 
var downSprite:Sprite;
function onDown(e:MouseEvent):void
{
	var temp:Sprite = e.currentTarget as Sprite;
 
	downSprite = temp;
 
	temp.startDrag();
 
	stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
}
 
function onUp(e:MouseEvent):void
{
	downSprite.stopDrag();
 
	stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMove);
}
 
function onMove(e:MouseEvent):void
{
 
	points[downSprite.name].x = downSprite.x;
	points[downSprite.name].y = downSprite.y;
 
	graphics.clear();
	drawSpline(points,0.1);
	e.updateAfterEvent();
}
 
 
var point:Point;
function drawSpline(pt:Vector.<Point>,res:Number=0.25):void
{
	var length:uint = pt.length;
	var i:Number = 0;
 
	for(i = 0; i<1; i+= res)
	{
		point = new Point();
 
		point.x = pt[0].x * ( -0.5*i*i*i + i*i - 0.5*i ) +
				  pt[0].x * ( 1.5*i*i*i + -2.5*i*i + 1) +
			 	  pt[1].x * ( -1.5*i*i*i + 2.0*i*i + 0.5*i) +
				  pt[2].x * ( 0.5*i*i*i - 0.5*i*i);
 
		point.y = pt[0].y * ( -0.5*i*i*i + i*i - 0.5*i ) +
				  pt[0].y * ( 1.5*i*i*i + -2.5*i*i + 1) +
				  pt[1].y * ( -1.5*i*i*i + 2.0*i*i + 0.5*i) +
				  pt[2].y * ( 0.5*i*i*i - 0.5*i*i);
 
		if(i>0&&i<1-res)
		{
			graphics.beginFill(0x00ff00,1);
 
			graphics.drawCircle(point.x,point.y,1);
 
			graphics.endFill();
		}
	}
 
	for(var h:int = 0; h<length-3; h++)
	{
		for(i = 0; i<1; i+= res)
		{
			point = new Point();
 
			point.x = pt[h].x * ( -0.5*i*i*i + i*i - 0.5*i ) +
					  pt[h+1].x * ( 1.5*i*i*i + -2.5*i*i + 1) +
					  pt[h+2].x * ( -1.5*i*i*i + 2.0*i*i + 0.5*i) +
					  pt[h+3].x * ( 0.5*i*i*i - 0.5*i*i);
 
			point.y = pt[h].y * ( -0.5*i*i*i + i*i - 0.5*i ) +
					  pt[h+1].y * ( 1.5*i*i*i + -2.5*i*i + 1) +
					  pt[h+2].y * ( -1.5*i*i*i + 2.0*i*i + 0.5*i) +
					  pt[h+3].y * ( 0.5*i*i*i - 0.5*i*i);
 
			if(i>0&&i<1-res)
			{
				graphics.beginFill(0x00ff00,1);
 
				graphics.drawCircle(point.x,point.y,1);
 
				graphics.endFill();
			}
		}
	}
 
	for(i = 0; i<1; i+= res)
	{
		point = new Point();
 
		point.x = pt[length-3].x * ( -0.5*i*i*i + i*i - 0.5*i ) +
				  pt[length-2].x * ( 1.5*i*i*i + -2.5*i*i + 1) +
			 	  pt[length-1].x * ( -1.5*i*i*i + 2.0*i*i + 0.5*i) +
				  pt[length-1].x * ( 0.5*i*i*i - 0.5*i*i);
 
		point.y = pt[length-3].y * ( -0.5*i*i*i + i*i - 0.5*i ) +
				  pt[length-2].y * ( 1.5*i*i*i + -2.5*i*i + 1) +
				  pt[length-1].y * ( -1.5*i*i*i + 2.0*i*i + 0.5*i) +
				  pt[length-1].y * ( 0.5*i*i*i - 0.5*i*i);
 
		if(i>0&&i<1-res)
		{
			graphics.beginFill(0x00ff00,1);
 
			graphics.drawCircle(point.x,point.y,1);
 
			graphics.endFill();
		}
	}
}
 
drawSpline(points,0.1);

오픈 API 초보도 할 수 있다!

오픈 API는 대표적으로 제공해주는 사이트는

네이버, 야후, 구글, 트위터, 페이스북, 플리커, 유투브…등등이 있습니다.

그 중에서도 네이버에서 제공해주는 오픈 API를 이용해서 간단한 도서검색 프로그램을 만드는 법을

올리겠습니다 ^^;

네이버 API 키 발급받기

네이버 API 키는 네이버 서버는 아무나 접근할 수 없겠죠?

그래서 내부에 있는 데이터에 접근하려면, 따로 키를 발급받아서 접근해야 합니다.

1. http://dev.naver.com/ 에 접속한다.

2. 오픈 API-> 키 등록/수정으로 들어간다.

3. 약관에 동의하고 확인을 누른다.

4. 아래와 같이 자신의 고유 Key가 발급된다. 이 Key가 없으면 네이버 API를 이용할 수가 없다.

도서검색 API 만들기

1. 오픈API -> 데이터API -> 책을 클릭한다.

2. 테스트 URL을 보면 아래와 같이 나와있는데.
key=test에 해당하는 부분에 자신이 발급받은 key를 붙여넣기 한다.
나의 key는 c10aef70d14e9851bf319fdda6835d46 이므로 아래를 다음과 같이 바꾼다.

테스트URL:

http://openapi.naver.com/search?key=test&query=%EC%82%BC%EA%B5%AD%EC%A7%80&display=10&start=1&target=book

실제URL:

http://openapi.naver.com/search?key=c10aef70d14e9851bf319fdda6835d46&query=%EC%82%BC%EA%B5%AD%EC%A7%80&display=10&start=1&target=book

실제 URL을 테스트할때에는 크롬이나 파이어폭스가 아닌 IE7이상에서 실행하기를 권장한다.
크롬이나 파이어폭스에서 테스트할 경우는 제대로 나오지가 않는다!!!

3. URL을 입력하면 아래와 같이 화면이 나온다 ( 반드시 IE7이상!!! )

4. 마우스 오른쪽 버튼을 누르고 소스보기를 클릭한다.

5. 아래와 같은 메모장이 하나 나오게 된다.

6. 위의 내용을 깔끔하게 정리하면 아래와 같은 XML문서가 보이게 된다. ( 필자는 EditPlus를 이용하였고, 보기쉽게 .xml로 저장하였다.)

( 중간생략…)

7. 위의 XML의 의미는 다음과 같다.

8. 플래시와의 연동

연동에 앞서, API는 누가 더 잘만드냐가 아니고 누가 아이디어를 잘 짜느냐가 중요하다.
똑같은 API를 이용하더라도 아웃풋은 천지차이가 될 수도 있다는것을 명심하자.
여기에서는 핵심적인 내용만 설명하고 디테일한 부분은 설명하지 않겠다.
아주 기본적인 부분만 설명하도록 하겠다.
디테일한 부분은 개개인이 직접 해보면서 부딪혀보기를 바란다.

9. 레이아웃 구성하기

우선적으로 필요한 것들을 UI로 제작해야 하는데,
검색에 관련된 것이기 때문에, 검색어를 입력할 수 있는 사각형과, 검색버튼 이 두가지는 필수적으로 레이아웃에 부착을 시켜야 한다.

필자는 우선적으로 1000 X 600의 스테이지의 크기로 설정하였고,
searchBar, searchBtn이라는 두개의 UI를 생성하였다.
searchBar 안에는 txt라는 사용자입력 텍스트필드를 만들어서, 검색어를 입력할 수 있도록 하였다.
그리고 상단에는 책의 제목과 저자와 출판사 그리고 가격이 표시되게끔 텍스트필드를 만들었다.
각각의 네임은 titleTxt, authorTxt, publisherTxt, priceTxt이다.

10. 설계하기

우선적으로 어떤 방향으로 작업을 해야할지 구상해 본다.

책 검색 API의 큰 구조는 검색어입력 -> 검색어에 맞는 XML 로드 -> XML 파싱후 알맞게 튜닝 -> 책의 이미지 불러오기, 제목,저자,출판사,가격정보 불러오기

a.검색어 입력
우리는 serachBar에 있는 txt에다가 검색어를 입력해서 검색어와 관련된 정보가 있는 XML주소로 이동해서 XML을 로드하는 형식으로 처리 하도록 하자.

아래의 코드를 보면

path부분은 도서검색 XML 정보가 있는 URL 주소값이다.

그런데 아래를 보면 조금 튜닝을 하였다.

원래의 URL 주소는 다음과 같다.

http://openapi.naver.com/search?key=c10aef70d14e9851bf319fdda6835d46&query=%EC%82%BC%EA%B5%AD%EC%A7%80&display=10&start=1&target=book

이 URL 주소에서 key는 내가 발급받은 키 번호를 입력하는 부분이고 query부분은 입력된 검색어이고, display는 한 화면에 보여질 책의 갯수, start는 화면에 보여질 첫 번째 책 인덱스값, target는 검색할 컨텐츠를 의미한다.

여기서 우리는 query부분과 display부분 start부분을 튜닝을 해서 작업을 하려고 한다.

query부분은 검색어가 들어가는 부분 display부분은 우리가 한 화면에 책 갯수를 몇 개 보이게 할 것인지, start부분은 추후에 prev버튼과 next버튼을 추가시키면 도서목록의 다음페이지 이전페이지로 넘겨줄 부분이다.

b. XML을 불러오는 작업
URLLoader클래스를 이용해서 URL값을 불러오게 되면, XML정보들이 넘어온다.

c. 파싱하는 작업
파싱하는 작업은 뭐가 뭐다 라는 정석이 없다. 자기 입맛에 맛게끔 잘 튜닝하면 될 것 같다.

d. 책의 이미지들을 화면에 뿌리는 작업
책의 이미지들의 주소값도 XML문서에 다 포함되어 있다. 책의 이미지들을 뿌릴 때는 한꺼번에 뿌리던가, 순차적으로 뿌리던가 두가지 방법이 있다.
책의 이미지는 나중에 따로 관리해야 되므로
bitmap으로 불러와서 container에 담고 container는 무비클립으로 생성해서 안쪽을 비워버리도록 하자, container는 또 holder라는 Sprite를 하나 생성해서
관리하도록 한다.
물론 책의 이미지들도 외부자원이니 Loader클래스를 이용하도록한다.

e. 책의 정보를 불러오는 작업
책의 정보들을 미리 파싱해놓은 배열이나 오브젝트에 담겨 있을 것이다. 그 담아놓은 정보들을 불러오면 되는데, 여기서 한가지 짚고 넘어가야 될 부분은
현재 책의 번호들과 파싱해놓은 번호들과 일치하도록 잘 맞추는 작업이 필요하다.

f. 이전페이지/다음페이지 버튼 추가 작업
이 부분은 생각을 좀 해봐야 하는데, 우선적으로 책의 총 갯수는 XML에 담겨있는데,
현재내가 한 화면에 10개의 책들을 보이게 하고 있다면, 총 페이지수는 책의 총 갯 수/ 화면에 보여지는 갯 수 = n/10 이 될 것이다.
일단 레이아웃은 현재페이지/총페이지 형태로 우측 상단에다가 텍스트필드로 만드는 작업을 하고, 페이지 끝까지 가는경우와 맨 처음인 경우
예외처리를 해서 버튼이벤트를 막아주는 작업을 해야한다.
그 다음 생각해야 되는 작업이 페이지를 새로 넘기면 현재 화면에 있는 이미지들을 모두 제거시켜줘야한다. 확실히 가비지컬렉션까지 처리해주도록 하자.

11. 기본적인 변수 생성 및 뼈대 갖추기

아래 코드에서 가장 중요한 부분은

search = encodeURI(searchBar.txt.text);

이 짤막한 코드인데, search라는 부분에는 우리가 검색하는 검색어가 들어가야 하는데, URL주소로는 우리가 직접입력하는 단어가 들어가는 것이 아니라 암호화를 거친 문자들이 들어가게 된다.
encodeURI()라는 메서드는 이러한 암호화되지 않은 정보를 내부적으로 암호화를 시켜주는 메서드이다. 반드시 알아두자!

import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
 
/*
	STEP #01	UI생성 및 화면 구상하기
	STEP #02	변수 생성하기
	STEP #03	기본 구조 생성하기( 여기서 다양한 형태로 변형될 것임 )
*/
 
var searchBar:MovieClip = MovieClip(searchBar);
 
// 검색어
var search:String;
// 한 화면에 보여질 갯수
var display:int = 10;
// 현재 페이지의 첫번째 도서 인덱스번호
var startNum:int = 1;
// XML이 담겨있는 URL주소 query부분에는 검색어가 들어가게 된다.
// 이때 검색어는 암호화를 거쳐서 새로운 문자로 반환되어 들어가야 되는데
// 그때 필요한 메서드가 encodeURI()라는 메서드이다.
var path:String = "http://openapi.naver.com/search?key=c10aef70d14e9851bf319fdda6835d46&query="+ search +"&display="+ display +"&start="+ startNum +"&target=book"
 
var xmlLoader:URLLoader;
var xml:XML;
// 추후에 책의 정보들을 담을 리스트
var bookInfo:XMLList;
// 튜닝해서 여기에 담는다.
var baseInfo:Object;
var item:Object;
 
 
function init():void
{
	searchContent();
}
 
function searchContent():void
{
	// 1. 엔터를 쳤을때, 2.search버튼을 눌렀을때 XML을 불러들인다.
	addEventListener(KeyboardEvent.KEY_DOWN, onKey_Down);
	addEventListener(KeyboardEvent.KEY_UP, onKey_Up);
	searchBtn.addEventListener(MouseEvent.CLICK, onSearch);
 
}
 
function onKey_Down(e:KeyboardEvent):void
{
	if(e.keyCode == Keyboard.ENTER) 
	{
		// 엔터를 치면 xml을 불러온다.
		getPath();
		xmlLoad();
	}
 
}
 
function onKey_Up(e:KeyboardEvent):void
{
 
}
 
function onSearch(e:MouseEvent=null):void
{
	getPath();
	xmlLoad();
}
 
function xmlLoad():void
{
	xmlLoader = new URLLoader();
	xmlLoader.load(new URLRequest(path));
	xmlLoader.addEventListener(Event.COMPLETE, loadedXML);
}
 
function loadedXML(e:Event):void
{
	xml = new XML(e.currentTarget.data);
	//xml = new XML(xmlLoader.data);
 
	trace(xml);
	parseXML();
}
 
function parseXML():void
{
 
}
 
// URL을 새로고침 해주는 함수
function getPath():void
{
	search = encodeURI(searchBar.txt.text);
	path = "http://openapi.naver.com/search?key=c10aef70d14e9851bf319fdda6835d46&query="+ search +"&display="+ display +"&start="+ startNum +"&target=book"
}
 
init();

12. XML 정보들을 파싱해서 자신에 맞게 튜닝한다.
이 부분은 어떤게 가장 깔끔하고 가장 적합한 모델로 코딩을 해야 할 지는 하다보면 느끼게 되는데,
for each 구문 또는 for in 구문을 이용해서 파싱하는 방법도 있고, while문으로 하는 방법, for문으로 하는 방법 등등
뭐가 딱 이거다라고 할 수는 없다. 하지만, 외국사이트들은 대부분 for each구문이나 for in구문으로 파싱을 자주하는것 같다.
그리고 나중에 스스로 느끼겠지만, 내장클래스 URLLoader(), Loader()는 반드시 튜닝을 해야지만 자신에 입맞에 맞게 쓸 수가 있다.
반드시 외부자원을 쓰기 위해서는 이 두개의 클래스를 써야하는데, 반복되는 작업을 하다보면 얼마나 비효율적인지 느끼게 된다.
사용자정의클래스로 XMLLoader() 나 ImageLoader() SWFLoader() 등등… 만들어서 쓰는게 훨씬 효율적이고,
작업시간도 줄어들고 다음에 반복되는 작업이 생기면, 또 쓸데없이 수십줄을 코딩해야 하는 번거로움이 사라질 수가 있다.
공개된 라이브러리도 많으나, 자기가 스스로 만들어보면 도움이 많이 될 것이다… ( 물론… 필자도 그리 많이 만들어보지는 않음… )

import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
 
/*
	STEP #01	UI생성 및 화면 구상하기
	STEP #02	변수 생성하기
	STEP #03	기본 구조 생성하기( 여기서 다양한 형태로 변형될 것임 )
	STEP #04	XML 정보들 가공해서 담아두기
*/
 
var searchBar:MovieClip = MovieClip(searchBar);
 
// 검색어
var search:String;
// 한 화면에 보여질 갯수
var display:int = 10;
// 현재 페이지의 첫번째 도서 인덱스번호
var startNum:int = 1;
// XML이 담겨있는 URL주소 query부분에는 검색어가 들어가게 된다.
// 이때 검색어는 암호화를 거쳐서 새로운 문자로 반환되어 들어가야 되는데
// 그때 필요한 메서드가 encodeURI()라는 메서드이다.
var path:String = "http://openapi.naver.com/search?key=c10aef70d14e9851bf319fdda6835d46&query="+ search +"&display="+ display +"&start="+ startNum +"&target=book"
 
var xmlLoader:URLLoader;
var xml:XML;
// 추후에 책의 정보들을 담을 리스트
var bookInfo:XMLList;
// 튜닝해서 여기에 담는다.
var baseInfo:Object;
var item:Array = [];
//var item:Object;
var itemLength:int;
 
 
function init():void
{
	searchContent();
}
 
function searchContent():void
{
	// 1. 엔터를 쳤을때, 2.search버튼을 눌렀을때 XML을 불러들인다.
	addEventListener(KeyboardEvent.KEY_DOWN, onKey_Down);
	addEventListener(KeyboardEvent.KEY_UP, onKey_Up);
	searchBtn.addEventListener(MouseEvent.CLICK, onSearch);
 
}
 
function onKey_Down(e:KeyboardEvent):void
{
	if(e.keyCode == Keyboard.ENTER) 
	{
		// 엔터를 치면 xml을 불러온다.
		getPath();
		xmlLoad();
	}
 
}
 
function onKey_Up(e:KeyboardEvent):void
{
 
}
 
function onSearch(e:MouseEvent=null):void
{
	getPath();
	xmlLoad();
}
 
function xmlLoad():void
{
	xmlLoader = new URLLoader();
	xmlLoader.load(new URLRequest(path));
	xmlLoader.addEventListener(Event.COMPLETE, loadedXML);
}
 
function loadedXML(e:Event):void
{
	xml = new XML(e.currentTarget.data);
	//xml = new XML(xmlLoader.data);
 
	trace(xml);
	parseXML();
}
 
function parseXML():void
{
 
	itemLength = xml..item.length();
 
	bookInfo = xml.channel
 
	baseInfo 			= new Object();
	baseInfo.total 		= bookInfo.total;
	baseInfo.start 		= bookInfo.start;
	baseInfo.display 	= bookInfo.display;
 
for(var i:int = 0; i<itemLength; i++)
	{
		item[i] 			= [];
		item[i].image		= bookInfo.item[i].image;
		item[i].title		= bookInfo.item[i].title;
		item[i].author		= bookInfo.item[i].author;
		item[i].publisher	= bookInfo.item[i].publisher;
		item[i].price		= bookInfo.item[i].price;
	}
}
 
function getPath():void
{
	search = encodeURI(searchBar.txt.text);
	path = "http://openapi.naver.com/search?key=c10aef70d14e9851bf319fdda6835d46&query="+ search +"&display="+ display +"&start="+ startNum +"&target=book"
}
 
init();
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.display.Loader;
import flash.display.Bitmap;
import flash.display.Sprite;
 
/*
	STEP #01	UI생성 및 화면 구상하기
	STEP #02	변수 생성하기
	STEP #03	기본 구조 생성하기( 여기서 다양한 형태로 변형될 것임 )
	STEP #04	XML 정보들 가공해서 담아두기
	STEP #05	검색후에 화면에 Book Image 뿌리기 ( 여기서는 2번으로 진행 )
							1. 동시에 뿌리거나
							2. 순차적으로 뿌리거나
	STEP #06 	해당 Book Image에 마우스를 오버하면, 책에 대한 정보들 표시
*/
 
var searchBar:MovieClip = MovieClip(searchBar);
 
// 검색어
var search:String;
// 한 화면에 보여질 갯수
var display:int = 10;
// 현재 페이지의 첫번째 도서 인덱스번호
var startNum:int = 1;
// XML이 담겨있는 URL주소 query부분에는 검색어가 들어가게 된다.
// 이때 검색어는 암호화를 거쳐서 새로운 문자로 반환되어 들어가야 되는데
// 그때 필요한 메서드가 encodeURI()라는 메서드이다.
var path:String = "http://openapi.naver.com/search?key=c10aef70d14e9851bf319fdda6835d46&query="+ search +"&display="+ display +"&start="+ startNum +"&target=book"
 
var xmlLoader:URLLoader;
var xml:XML;
var imgLoader:Loader;
var imgRequest:URLRequest;
 
// 추후에 책의 정보들을 담을 리스트
var bookInfo:XMLList;
// 튜닝해서 여기에 담는다.
var baseInfo:Object;
var item:Array = [];
//var item:Object;
var itemLength:int;
 
// 굳이 이렇게 컨테이너에 담아야 하는 이유는
// 추후에 작업하다가 이전페이지, 다음페이지를 추가시키면 새로 화면을 refresh해줘야 하는데,
// 그러기 위해서는 이미지들을 담을 컨테이너와 그 컨테이너들을 다시 관리할 holder가 필요하다.
 
// 가상의 컨테이너 ( 컨테이너를 다시 담을 컨테이너 )
var imgHolder:Sprite = new Sprite();
addChild(imgHolder);
// 라이브러리에 만들어 놓은 컨테이너
var container:MovieClip;
 
 
 
function init():void
{
	searchContent();
	addEvent();
}
 
function searchContent():void
{
	// 1. 엔터를 쳤을때, 2.search버튼을 눌렀을때 XML을 불러들인다.
	addEventListener(KeyboardEvent.KEY_DOWN, onKey_Down);
	addEventListener(KeyboardEvent.KEY_UP, onKey_Up);
	searchBtn.addEventListener(MouseEvent.CLICK, onSearch);
 
}
 
function addEvent():void
{
	addEventListener("파싱완료", loadImg);
}
 
function onKey_Down(e:KeyboardEvent):void
{
	if(e.keyCode == Keyboard.ENTER) 
	{
		// 엔터를 치면 xml을 불러온다.
		getPath();
		xmlLoad();
	}
 
}
 
function onKey_Up(e:KeyboardEvent):void
{
 
}
 
function onSearch(e:MouseEvent=null):void
{
	getPath();
	xmlLoad();
}
 
function xmlLoad():void
{
	xmlLoader = new URLLoader();
	xmlLoader.load(new URLRequest(path));
	xmlLoader.addEventListener(Event.COMPLETE, loadedXML);
}
 
function loadedXML(e:Event):void
{
	xml = new XML(e.currentTarget.data);
	//xml = new XML(xmlLoader.data);
 
	trace(xml);
	parseXML();
}
 
function parseXML():void
{
	//trace(xml..item.length());
 
	itemLength = xml..item.length();
 
	//trace("itemLength:" + itemLength);
 
	bookInfo = xml.channel
 
	baseInfo 			= new Object();
	baseInfo.total 		= bookInfo.total;
	baseInfo.start 		= bookInfo.start;
	baseInfo.display 	= bookInfo.display;
 
	var i:int = 0;
 
	while(i<itemLength)
	{
		item[i] 			= [];
		item[i].image		= bookInfo.item[i].image;
		item[i].title		= bookInfo.item[i].title;
		item[i].author		= bookInfo.item[i].author;
		item[i].publisher	= bookInfo.item[i].publisher;
		item[i].price		= bookInfo.item[i].price;
 
		i++;
	}
 
	/*for(var i:int = 0; i<itemLength; i++)
	{
		item[i] 			= [];
		item[i].image		= bookInfo.item[i].image;
		item[i].title		= bookInfo.item[i].title;
		item[i].author		= bookInfo.item[i].author;
		item[i].publisher	= bookInfo.item[i].publisher;
		item[i].price		= bookInfo.item[i].price;
	}*/
 
	var evt:Event = new Event("파싱완료");
	this.dispatchEvent(evt);
}
 
// 이미지를 불러오는데 카운트를 증가시키면서 불러온다.
// 차례대로 불러오는 효과
// 카운트를 증가시키지 않고 불러오면 시간차 없이 들어옴
// 카운트를 증가시키지 않고 동시에 불러오는 방법은 for문이나 while문을 이용
var count:int = -1;
var isCounting:Boolean =true;
function loadImg(e:Event=null):void
{
	if(!isCounting) return;
 
	count++;
 
	imgLoader = new Loader();
	imgRequest = new URLRequest();
	imgRequest.url = item[count].image;
	imgLoader.load(imgRequest);
	imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadImg);
 
	if(count==itemLength-1)
	{
		count = -1;
		isCounting = false;
	}
 
	trace(count);
}
 
function onLoadImg(e:Event):void
{
	if(count==itemLength-1) imgLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onLoadImg);
 
	var bmp:Bitmap = e.currentTarget.content;
 
	container = new Container();
 
	container.buttonMode = true;
 
	imgHolder.addChild(container);
 
	container.addChild(bmp);
 
	setContainer(container);
 
	loadImg();
 
}
 
// 불러들인 컨테이너를 배치시키기
var index:int=-1;
function setContainer(target:MovieClip):void
{
	index++;
 
	var i:int =0;
	while(i<itemLength)
	{
		target.x	=  	150 + index % 5 * 150;
		target.y 	= 	150 + int((index/5)) * 150;
		target.no 	= 	index;
		target.addEventListener(MouseEvent.MOUSE_OVER, viewInfoFn);
		target.addEventListener(MouseEvent.MOUSE_OUT, 	viewInfoFn);
 
		i++;
	}
 
	if(index==itemLength-1) index=-1;
 
	/*for( var i:int = 0; i<itemLength; i++)
	{
		target.x	=  	150 + index % 5 * 150;
		target.y 	= 	150 + int((index/5)) * 150;
		target.no 	= 	index;
		target.addEventListener(MouseEvent.MOUSE_OVER, viewInfoFn);
		target.addEventListener(MouseEvent.MOUSE_OUT, 	viewInfoFn);
	}*/
 
}
 
function viewInfoFn(e:MouseEvent):void
{
	if(e.type == "mouseOver") showTxt(item[e.currentTarget.no]);
	else					  refreshTxt();
}
 
function showTxt(arr:Array):void
{
	// htmlText는 태그가 붙어있는 문자열을 html형식으로 바꿔줌...
	titleTxt.htmlText 	= arr.title;
	authorTxt.text		= arr.author;
	publisherTxt.text	= arr.publisher;
	priceTxt.text		= arr.price;
}
 
function refreshTxt():void
{
	titleTxt.text = "";
	authorTxt.text = "";
	publisherTxt.text = "";
	priceTxt.text = "";
}
 
// 검색할때마다 URL이 바뀌는것을 처리.
function getPath():void
{
	search = encodeURI(searchBar.txt.text);
	path = "http://openapi.naver.com/search?key=c10aef70d14e9851bf319fdda6835d46&query="+ search +"&display="+ display +"&start="+ startNum +"&target=book"
}
 
init();
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.display.Loader;
import flash.display.Bitmap;
import flash.display.Sprite;
 
/*
	STEP #01	UI생성 및 화면 구상하기
	STEP #02	변수 생성하기
	STEP #03	기본 구조 생성하기( 여기서 다양한 형태로 변형될 것임 )
	STEP #04	XML 정보들 가공해서 담아두기
	STEP #05	검색후에 화면에 Book Image 뿌리기 ( 여기서는 2번으로 진행 )
							1. 동시에 뿌리거나
							2. 순차적으로 뿌리거나
	STEP #06 	해당 Book Image에 마우스를 오버하면, 책에 대한 정보들 표시
	STEP #07 	이전페이지,다음페이지를 넘기기위한 버튼 추가 및 코딩, 
				현재페이지번호/총페이지번호 표시 추가 코딩
 
	STEP #08 	버그잡기
*/
 
var searchBar:MovieClip = MovieClip(searchBar);
 
// 검색어
var search:String;
// 한 화면에 보여질 갯수
var display:int = 10;
// 현재 페이지의 첫번째 도서 인덱스번호
var startNum:int = 1;
// XML이 담겨있는 URL주소 query부분에는 검색어가 들어가게 된다.
// 이때 검색어는 암호화를 거쳐서 새로운 문자로 반환되어 들어가야 되는데
// 그때 필요한 메서드가 encodeURI()라는 메서드이다.
var path:String = "http://openapi.naver.com/search?key=c10aef70d14e9851bf319fdda6835d46&query="+ search +"&display="+ display +"&start="+ startNum +"&target=book"
 
var xmlLoader:URLLoader;
var xml:XML;
var imgLoader:Loader;
var imgRequest:URLRequest;
 
// 추후에 책의 정보들을 담을 리스트
var bookInfo:XMLList;
// 튜닝해서 여기에 담는다.
var baseInfo:Object;
var item:Array = [];
//var item:Object;
var itemLength:int;
 
// 굳이 이렇게 컨테이너에 담아야 하는 이유는
// 추후에 작업하다가 이전페이지, 다음페이지를 추가시키면 새로 화면을 refresh해줘야 하는데,
// 그러기 위해서는 이미지들을 담을 컨테이너와 그 컨테이너들을 다시 관리할 holder가 필요하다.
 
// 가상의 컨테이너 ( 컨테이너를 다시 담을 컨테이너 )
var imgHolder:Sprite = new Sprite();
addChild(imgHolder);
// 라이브러리에 만들어 놓은 컨테이너
var container:MovieClip;
 
var imgBox:Array = [];
 
function init():void
{
	searchContent();
	addEvent();
}
 
function searchContent():void
{
	// 1. 엔터를 쳤을때, 2.search버튼을 눌렀을때 XML을 불러들인다.
	addEventListener(KeyboardEvent.KEY_DOWN, onKey_Down);
	addEventListener(KeyboardEvent.KEY_UP, onKey_Up);
	searchBtn.addEventListener(MouseEvent.CLICK, onSearch);
 
}
 
function addEvent():void
{
	addEventListener("파싱완료", loadImg);
	prev_Btn.addEventListener(MouseEvent.CLICK, scanFn);
	next_Btn.addEventListener(MouseEvent.CLICK, scanFn);
}
 
var isSearch:Boolean;
function scanFn(e:MouseEvent):void
{
	// 이제 여기서 우리가 수정해야 될 부분은
	// 현재 페이지의 startNum이다.
	// startNum은 초반 설계할때 미리 이런 상황을 예측하고 튜닝해서 빼놓았다.
 
	/* 
	=============================================================================================
											주의사항
 
			1. 	맨 첫 페이지에 오면 prevBtn은 반응하지 않는다, 
			2.	맨 마지막 페이지에 올때는 nextBtn이 반응하지 않는다.
			3. 	페이지를 넘길 때 현재페이지의 이미지를 로딩시키고 있을때도 반응하지 않는다.
 
	=============================================================================================
	*/	
 
	if(isCounting=="searching") return;
 
	if(e.currentTarget.name == "prev_Btn")
	{
		if(startNum == 1) return;
 
		startNum = startNum - display
 
		removeAllChildren();
 
		getPath();
		xmlLoad();
	}
	else
	{
		if(startNum > int(bookInfo.total / display) ) return;
 
		startNum = startNum + display;
 
		removeAllChildren();
 
		getPath();
		xmlLoad();
	}
}
 
function onKey_Down(e:KeyboardEvent):void
{
 
	if(isCounting=="searching") return;
 
	isSearch = true;
 
	if(e.keyCode == Keyboard.ENTER) 
	{
 
		if(isSearch) removeAllChildren();
 
		getPath();
		xmlLoad();
	}
 
}
 
function onKey_Up(e:KeyboardEvent):void
{
 
}
 
function onSearch(e:MouseEvent=null):void
{
 
	if(isCounting=="searching") return;
 
	isSearch = true;
 
	if(isSearch) removeAllChildren();
 
	getPath();
	xmlLoad();
}
 
function xmlLoad():void
{
	xmlLoader = new URLLoader();
	xmlLoader.load(new URLRequest(path));
	xmlLoader.addEventListener(Event.COMPLETE, loadedXML);
}
 
function loadedXML(e:Event):void
{
	xml = new XML(e.currentTarget.data);
	//xml = new XML(xmlLoader.data);
 
	//trace(xml);
	parseXML();
}
 
function parseXML():void
{
	//trace(xml..item.length());
 
	itemLength = xml..item.length();
 
	//trace("itemLength:" + itemLength);
 
	bookInfo = xml.channel
 
	baseInfo 			= new Object();
	baseInfo.total 		= bookInfo.total;
	baseInfo.start 		= bookInfo.start;
	baseInfo.display 	= bookInfo.display;
 
	var i:int = 0;
 
	while(i<itemLength)
	{
		item[i] 			= [];
		item[i].image		= bookInfo.item[i].image;
		item[i].title		= bookInfo.item[i].title;
		item[i].author		= bookInfo.item[i].author;
		item[i].publisher	= bookInfo.item[i].publisher;
		item[i].price		= bookInfo.item[i].price;
 
		i++;
	}
 
	/*for(var i:int = 0; i<itemLength; i++)
	{
		item[i] 			= [];
		item[i].image		= bookInfo.item[i].image;
		item[i].title		= bookInfo.item[i].title;
		item[i].author		= bookInfo.item[i].author;
		item[i].publisher	= bookInfo.item[i].publisher;
		item[i].price		= bookInfo.item[i].price;
	}*/
 
	pageInfo();
 
	var evt:Event = new Event("파싱완료");
	this.dispatchEvent(evt);
}
 
// 이미지를 불러오는데 카운트를 증가시키면서 불러온다.
// 차례대로 불러오는 효과
// 카운트를 증가시키지 않고 불러오면 시간차 없이 들어옴
// 카운트를 증가시키지 않고 동시에 불러오는 방법은 for문이나 while문을 이용
var count:int = -1;
var isCounting:String = "ready"
function loadImg(e:Event=null):void
{
 
	count ++;
 
	isCounting = "searching";
 
	imgLoader = new Loader();
	imgRequest = new URLRequest();
	imgRequest.url = item[count].image;
	imgLoader.load(imgRequest);
	imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadImg);
 
	if(count == itemLength-1)
	{
		isCounting = "complete";
		count = -1;
	}
}
 
function onLoadImg(e:Event):void
{
 
	imgLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onLoadImg);
 
	var bmp:Bitmap = e.currentTarget.content;
 
	container = new Container();
 
	container.buttonMode = true;
 
	imgHolder.addChild(container);
 
	imgBox.push(container);
 
	container.addChild(bmp);
 
	setContainer(container);
 
	if( isCounting == "complete") return;
 
	loadImg();
}
 
// 불러들인 컨테이너를 배치시키기
var index:int=-1;
function setContainer(target:MovieClip):void
{
	index++;
 
	var i:int =0;
	while(i<itemLength)
	{
		target.x	=  	150 + index % 5 * 150;
		target.y 	= 	150 + int((index/5)) * 150;
		target.no 	= 	index;
		target.addEventListener(MouseEvent.MOUSE_OVER, viewInfoFn);
		target.addEventListener(MouseEvent.MOUSE_OUT, 	viewInfoFn);
 
		i++;
	}
 
	if(index==itemLength-1) index=-1;
 
	/*for( var i:int = 0; i<itemLength; i++)
	{
		target.x	=  	150 + index % 5 * 150;
		target.y 	= 	150 + int((index/5)) * 150;
		target.no 	= 	index;
		target.addEventListener(MouseEvent.MOUSE_OVER, viewInfoFn);
		target.addEventListener(MouseEvent.MOUSE_OUT, 	viewInfoFn);
	}*/
 
}
 
function viewInfoFn(e:MouseEvent):void
{
	if(e.type == "mouseOver") showTxt(item[e.currentTarget.no]);
	else					  refreshTxt();
}
 
function showTxt(arr:Array):void
{
	// htmlText는 태그가 붙어있는 문자열을 html형식으로 바꿔줌...
	titleTxt.htmlText 	= arr.title;
	authorTxt.text		= arr.author;
	publisherTxt.text	= arr.publisher;
	priceTxt.text		= arr.price;
}
 
function refreshTxt():void
{
	titleTxt.text = "";
	authorTxt.text = "";
	publisherTxt.text = "";
	priceTxt.text = "";
}
 
function pageInfo():void
{
	pageTxt.text = int(digit(startNum).substr(0,String(startNum).length-1)) + 1 + "/" + int(bookInfo.total /display);
}
 
function digit(value:Number):String
{
	var str:String;
 
	if(value<10) str = "0" + value;
	else		 str = "" + value;
 
	return str;
}
 
// 검색할때마다 URL이 바뀌는것을 처리.
function getPath():void
{
	search = encodeURI(searchBar.txt.text);
	path = "http://openapi.naver.com/search?key=c10aef70d14e9851bf319fdda6835d46&query="+ search +"&display="+ display +"&start="+ startNum +"&target=book"
}
 
function removeAllChildren():void
{
	for(var i:uint = 0; i < imgBox.length; i++)
	{
		imgHolder.removeChild(imgBox[i]);
	}
 
	imgBox.length = 0;
}
 
init();

최종완성코드

import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.display.Loader;
import flash.display.Bitmap;
import flash.display.Sprite;
 
import com.greensock.TweenMax;
import com.greensock.easing.*;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
 
/*
=================================================================================================
									도서 검색 API
					http://dev.naver.com/openapi/apis/data/book
 
	제작자  블로그: www.bitmapdata.com 
			이메일: bitmapdata.com@gmail.com 
			메신저: visvim@nate.com
 
	*	네이버에서 제공해주는 책의 총 갯수는 1000개 그 이상은 검색해도 런타임 에러가 난다.
 
	작업을 하면서 얻은점:
 
	while문에서 target.contentLoaderInfo.addEventListener 는 while문에서 반응하지 않는다.
 
	var i:int = 0;
	while( i < 10 )
	{
		testFn();
 
		i++;
	}
 
	testFn() 이 10번 호출
 
	var i:int = 0;
	while( i < 10 )
	{
		target.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
 
		i++;
	}
 
	onComplete() 호출안됨 < 로더에 관한 모든 리스너 마찬가지 >
 
=================================================================================================
 
/*
	STEP #01	UI생성 및 화면 구상하기
	STEP #02	변수 생성하기
	STEP #03	기본 구조 생성하기( 여기서 다양한 형태로 변형될 것임 )
	STEP #04	XML 정보들 가공해서 담아두기
	STEP #05	검색후에 화면에 Book Image 뿌리기 ( 여기서는 2번으로 진행 )
							1. 동시에 뿌리거나
							2. 순차적으로 뿌리거나
	STEP #06 	해당 Book Image에 마우스를 오버하면, 책에 대한 정보들 표시
	STEP #07 	이전페이지,다음페이지를 넘기기위한 버튼 추가 및 코딩, 
				현재페이지번호/총페이지번호 표시 추가 코딩
 
	STEP #08 	버그잡기
	STEP #09	예외처리 하기
	STEP #10	코드최종정리
*/
 
var searchBar			:MovieClip 			= MovieClip(searchBar);
 
// 검색어
var search				:String;
// 한 화면에 보여질 갯수
var display				:int 				= 10;
// 현재 페이지의 첫번째 도서 인덱스번호
var startNum			:int 				= 1;
// XML이 담겨있는 URL주소 query부분에는 검색어가 들어가게 된다.
// 이때 검색어는 암호화를 거쳐서 새로운 문자로 반환되어 들어가야 되는데
// 그때 필요한 메서드가 encodeURI()라는 메서드이다.
var path				:String 			= "http://openapi.naver.com/search?key=c10aef70d14e9851bf319fdda6835d46&query="+ search +"&display="+ display +"&start="+ startNum +"&target=book"
// <이미지 없음> 이미지 URL
var blank				:String 			= "http://static.naver.com/book/image/noimg3.gif";
 
var xmlLoader			:URLLoader;
var xml					:XML;
var imgLoader			:Loader;
var imgRequest			:URLRequest;
 
// 추후에 책의 정보들을 담을 리스트
var bookInfo			:XMLList;
// 튜닝해서 여기에 담는다.
var baseInfo			:Object;
var item				:Array 				= [];
// 현재 화면에 보여지는 책 들의 총 갯수
var itemLength			:int;
 
// 굳이 이렇게 컨테이너에 담아야 하는 이유는
// 추후에 작업하다가 이전페이지, 다음페이지를 추가시키면 새로 화면을 refresh해줘야 하는데,
// 그러기 위해서는 이미지들을 담을 컨테이너와 그 컨테이너들을 다시 관리할 holder가 필요하다.
// 가상의 컨테이너 ( 컨테이너를 다시 담을 컨테이너 )
var imgHolder			:Sprite 			= new Sprite();
addChild(imgHolder);
 
// 라이브러리에 만들어 놓은 컨테이너
var container			:MovieClip;
 
// 페이지 번호
var pageNum				:int 				= 1;
 
// container를 관리할 배열 ( 다음페이지, 이전페이지로 넘어갈 떄 이전의 모든이미지를 지울때 용이함 )
var imgBox				:Array 				= [];
 
// 재검색인지 아닌지 판별
var isSearch			:Boolean;
 
var count				:int 				= -1;
var isCounting			:String 			= "ready"
var index				:int				= -1;
 
function init():void
{
	searchContent();
	addEvent();
}
 
function searchContent():void
{
	searchBar.txt.text = "";
 
	// 1. 엔터를 쳤을때, 2.search버튼을 눌렀을때 XML을 불러들인다.
	addEventListener(KeyboardEvent.KEY_DOWN, onKey_Down);
	searchBtn.addEventListener(MouseEvent.CLICK, onSearch);
 
}
 
function addEvent():void
{
	// 파싱이 완료 되면 이미지를 불러온다.
	addEventListener("파싱완료", loadImg);
 
	// 페이지를 넘기는 이벤트
	prev_Btn.addEventListener(MouseEvent.CLICK, scanFn);
	next_Btn.addEventListener(MouseEvent.CLICK, scanFn);
}
 
/* 
=================================================================================================
											주의사항
 
			1. 	맨 첫 페이지에 오면 prevBtn은 반응하지 않는다, 
			2.	맨 마지막 페이지에 올때는 nextBtn이 반응하지 않는다.
			3. 	페이지를 넘길 때 이미지를 로딩시키고 있을때도 반응하지 않는다.
			4.	다시 검색할 때는 1번페이지로 넘어온다.
=================================================================================================
*/	
 
function scanFn(e:MouseEvent):void
{
 
	if(isCounting=="searching" || searchBar.txt.text == "") return;
 
	if(e.currentTarget.name == "prev_Btn")
	{
		if(startNum == 1) return;
 
		pageNum --;
 
		startNum = startNum - display
 
		removeAllChildren();
 
		getPath();
		xmlLoad();
	}
	else
	{
 
		if(startNum >= bookInfo.total - display ) return;
 
		pageNum ++;
 
		startNum = startNum + display;
 
		removeAllChildren();
 
		getPath();
		xmlLoad();
 
		//trace("startNum:", startNum)
		//trace("총갯수:",bookInfo.total);
	}
}
 
// 첫번째 검색은 그대로 진행
function onKey_Down(e:KeyboardEvent):void
{
 
	if(isCounting=="searching" || searchBar.txt.text == "") return;
 
	if(e.keyCode == Keyboard.ENTER) 
	{
		// 재검색 되었으면 이미지를 지운다.
		if(isSearch) removeAllChildren();
 
		startNum = 1;
		getPath();
		xmlLoad();
 
		// 재검색 되었음을 알려줌
		isSearch = true;
	}
 
}
 
// 첫번째 검색은 그대로 진행
function onSearch(e:MouseEvent=null):void
{
 
	if(isCounting=="searching" || searchBar.txt.text == "") return;
 
	// 재검색 되었으면 이미지를 지운다.
	if(isSearch) removeAllChildren();
 
	startNum = 1;
	getPath();
	xmlLoad();
 
	// 재검색 되었음을 알려줌
	isSearch = true;
}
 
/*
====================================================================================================
										XML 연동 부분
====================================================================================================
*/
 
function xmlLoad():void
{
	xmlLoader = new URLLoader();
	xmlLoader.load(new URLRequest(path));
	xmlLoader.addEventListener(Event.COMPLETE, loadedXML);
}
 
function loadedXML(e:Event):void
{
	xml = new XML(e.currentTarget.data);
 
	// XML 파싱
	parseXML();
}
 
function parseXML():void
{
	// 현재 화면에 보여지는 책 들의 총 갯수
	itemLength = xml..item.length();
 
	// 책의 고정정보 ( 페이지가 넘어가도 변하지 않음 )
	bookInfo = xml.channel
 
	baseInfo 			= new Object();
	baseInfo.total 		= bookInfo.total;
	baseInfo.start 		= bookInfo.start;
	baseInfo.display 	= bookInfo.display;
 
	// 책의 유동정보 ( 페이지가 넘어가면 변동 )
	var i:int = 0;
	while(i<itemLength)
	{
		item[i] 			= [];
		item[i].image		= bookInfo.item[i].image;
		item[i].title		= bookInfo.item[i].title;
		item[i].author		= bookInfo.item[i].author;
		item[i].publisher	= bookInfo.item[i].publisher;
		item[i].price		= bookInfo.item[i].price;
 
		i++;
	}
 
	// 파싱이 완료되었다는 이벤트 발생
	var evt:Event = new Event("파싱완료");
	this.dispatchEvent(evt);
 
	// 페이지정보 호출
	pageInfo();
}
 
// 이미지를 불러오는데 카운트를 증가시키면서 불러온다.
function loadImg(e:Event=null):void
{
	// 카운트 증가
	count ++;
 
	// 이미지 로딩 중
	isCounting = "searching";
 
	imgLoader = new Loader();
	imgRequest = new URLRequest();
	imgRequest.url = item[count].image;
	imgLoader.load(imgRequest);
	imgLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, unloadedImg);
	imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadedImg);
 
	// 카운트가 0부터 시작하므로 끝 번호는 책의 갯수 -1
	if(count == itemLength-1)
	{
		// 이미지 로드 완료
		isCounting = "complete";
		count = -1;
	}
}
 
var delay:int = -1;
function onLoadedImg(e:Event):void
{
 
	imgLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onLoadedImg);
 
	var bmp:Bitmap = e.currentTarget.content;
 
	container = new Container();
	container.buttonMode = true;
	container.addChild(bmp);
 
	imgHolder.addChild(container);
	imgBox.push(container);
 
	delay++
 
	addImg(container);
 
	//trace(imgHolder.numChildren);
 
	// 이미지를 다 불러왔으면 이미지 로드는 중단
	if( isCounting == "complete") 
	{
		delay = -1;
		return;
	}
 
	loadImg();
 
}
 
// 이미지를 불러오지 못하는 경우는
// 해당 이미지가 없는 경우이므로
// 따로 URL을 연결해서 <이미지 없음> 이미지를 불러온다.
function unloadedImg(e:IOErrorEvent):void
{
	imgLoader = new Loader();
	imgRequest = new URLRequest();
	imgRequest.url = blank;
	imgLoader.load(imgRequest);
	imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadedImg);
}
 
// 좀 특이한 문장으로 보이나
// index는 	책의 번호
// i는		현재 콜백된 횟수
function addImg(target:MovieClip):void
{
 
	target.x		=  	150 + delay % 5 * 150;
	target.y 		= 	150 + int((delay/5)) * 150;
	target.index 	= 	delay;
	target.addEventListener(MouseEvent.MOUSE_OVER, viewInfoFn);
	target.addEventListener(MouseEvent.MOUSE_OUT, 	viewInfoFn);
 
	//trace("index", index);
 
 
	//if(index==itemLength-1) index=-1;
 
}
 
// 책의 정보들 상단에 표시
function viewInfoFn(e:MouseEvent):void
{
	if(e.type == "mouseOver") showTxt(item[e.currentTarget.index]);
	else					  refreshTxt();
}
 
function showTxt(arr:Array):void
{
	// htmlText는 태그가 붙어있는 문자열을 html형식으로 바꿔줌...
	titleTxt.htmlText 		= arr.title;
	authorTxt.htmlText		= arr.author;
	publisherTxt.htmlText	= arr.publisher;
	priceTxt.text			= arr.price;
 
	if(priceTxt.text =="") priceTxt.text = "품절";
}
 
function refreshTxt():void
{
	titleTxt.text = "";
	authorTxt.text = "";
	publisherTxt.text = "";
	priceTxt.text = "";
}
 
/*
=====================================================================================================
								현재 페이지/ 총 페이지를 구현하는 부분
=====================================================================================================
		XML에서 현재페이지와 총페이지를 알려주는 정보는 없다.
		XML에 있는 정보를 가공해서 변형해야 페이지 정보를 알 수가 있다.
*/
 
function pageInfo():void
{
	var num:String = String((startNum - 1) / display)
 
	pageTxt.text = int(num) + 1 +"/" + int(int((bookInfo.total /display)) + 1);
}
 
function digit(value:Number):String
{
	var str:String;
 
	if(value<10) str = "0" + value;
	else		 str = "" + value;
 
	return str;
}
 
// 검색할때마다 URL이 바뀌는것을 처리.
function getPath():void
{
	search = encodeURI(searchBar.txt.text);
	path = "http://openapi.naver.com/search?key=c10aef70d14e9851bf319fdda6835d46&query="+ search +"&display="+ display +"&start="+ startNum +"&target=book"
}
 
// 자식들을 모두 제거
function removeAllChildren():void
{
	for(var i:uint = 0; i < imgBox.length; i++)
	{
		imgHolder.removeChild(imgBox[i]);
	}
 
	imgBox.length = 0;
}
 
init();

혹시 파일이 필요하신분은 아래 클릭 ↓
웹상에서는 swf파일을 올려도 네이버 보안 때문에 돌아가지를 않습니다.
다운 받으셔서 컴파일 하시면 잘 작동되실겁니다.
http://www.bitmapdata.com/down/book_api.fla