Starling performance test

Project/Programming 2012. 1. 10. 21:58

package {
	import starling.events.Event;
	import starling.core.Starling;
	import starling.display.Sprite;
	import starling.display.Button;
	import starling.textures.Texture;
	import starling.display.DisplayObject;
	import starling.display.Image;
	import starling.utils.deg2rad;
	import flash.display.Bitmap;


	public class Demo extends Sprite {

		[Embed(source = "f60.png")]
		private var MyBitmap:Class;
		
		private var _myTexture:Texture;
		private var _arrButterflys:Vector.<Butterfly>;

		public function Demo() {
			// addedToStage 이벤트에 대한 리스너 추가
			addEventListener( Event.ADDED_TO_STAGE , onAddedToStage);
		}


		private function onAddedToStage(e:Event):void {
			var myBitmap:Bitmap = new MyBitmap() as Bitmap;
			_myTexture = Texture.fromBitmap(myBitmap);

			var len:int = 800;
			
			_arrButterflys = new Vector.<Butterfly>(len, false);
			
			for (var i:int = 0; i<len; i++) {
				var fly:Butterfly = new Butterfly(_myTexture);
				
				fly.alpha = Math.random();
				fly.destX = Math.random()*stage.stageWidth;
				fly.destY = Math.random()*stage.stageHeight;
				
				fly.setVertexColor(0, Math.random()*0xFFFFFF);
				fly.setVertexColor(1, Math.random()*0xFFFFFF);
				fly.setVertexColor(2, Math.random()*0xFFFFFF);
				fly.setVertexColor(3, Math.random()*0xFFFFFF);
				
				fly.x = Math.random()*stage.stageWidth;
				fly.y = Math.random()*stage.stageHeight;
				fly.rotation = deg2rad(Math.random()*360);
				
				fly.pivotX = fly.width >> 1;
				fly.pivotY = fly.height >> 1;
				
				_arrButterflys[i] = fly;
				addChild(fly);
			}

			stage.addEventListener(Event.ENTER_FRAME, onFrame);
		}
		
		private function onFrame(e:Event):void{

			var len:uint = _arrButterflys.length;

			for (var i:int = 0; i < len; i++){

				// move the sausages around
				var fly:Butterfly = _arrButterflys[i];
				
				fly.x -= ( fly.x - fly.destX ) * .1;
				fly.y -= ( fly.y - fly.destY ) * .1;

				if (Math.abs(fly.x - fly.destX)<1 && Math.abs(fly.y-fly.destY) < 1){
					fly.destX = Math.random()*stage.stageWidth;
					fly.destY = Math.random()*stage.stageHeight;
					fly.rotation = deg2rad(Math.random()*360);
				}
			}
		}

		public override function dispose():void {
			removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
			_myTexture.dispose();
			super.dispose();
		}
	}
}

import starling.display.Image;
import starling.textures.Texture;

class Butterfly extends Image{
	
	public var destX:Number = 0;
	public var destY:Number = 0;
	
	public function Butterfly(inTexture:Texture):void{
		super(inTexture);
	}
}

    

설정

트랙백

댓글

[Starling-05] Tween 클래스를 이용한 애니메이션

Programming/Framework 2012. 1. 8. 02:57
이전 포스트에서 EnterFrame 이벤트를 사용하여 애니메이션을 구현하는 방법을 소개했다. 이번에는 Tween 클래스를 사용하는 방법이다. Tween을 사용한 경우의 특징 중 하나는 애니메이션의 시간을 초 단위로 지정하는 것이다. Tween은 지정된 시간이 지나는 과정에서 표시 객체의 속성 값, 예를 들어 x좌표를 최종 값에 도달하기까지 순차적으로 변화시킨다.

코드는 다음과 같다. 먼저 Tween 생성자에서 대상 객체와 시간을 지정하여 다음 animate() 메소드를 사용하여 변화하는 속성의 이름과 마지막 값을 설정한다. 여러 특성을 변화시키는 경우 animate()를 계속해서 부르면 된다. 

// myObject을 2 초 걸쳐 가로 50px, 세로 80px 이동하는 애니메이션 지정
var myTween:Tween = New Tween(myObject, 2.0); 
myTween.animate( "x", myObject.x + 50); 
myTween.animate( "y", myObject.y + 80); 


아래 예제는 onAddedToStage() 리스너 함수에 적용한 것이다. 사각형을 4초에 걸쳐 (0,0)에서 (220, 380) 좌표로 이동시키는 것이다.

package {
	import starling.animation.Tween;
	import starling.core.Starling;
	import starling.display.Quad;
	import starling.events.Event;

	private function onAddedToStage(e:Event):void {
		myQuad = new Quad(100,100);
		myQuad.color = 0x00FF00;

		// Tween 객체의 생성
		var myTween:Tween = new Tween(myQuad,4.0);

		// 변화시키는 속성 지정
		myTween.moveTo(220, 380);

		// Juggler에 Tween 객체를 추가하려면
		Starling.juggler.add(myTween);
	}
}


이 샘플에서는 animate() 메소드 대신 moveTo() 메소드를 사용했다. moveTo()는 x좌표와 y좌표를 동시에 이동 시킬 때 유용한 방법이다. 그 외에도 비슷한 방법으로 비율을 바꾸는 scaleTo()와 alpha를 바꾸는 fadeTo() 등이 제공되고 있다. 각도를 바꾸는 방법은 아직 없기 때문에 회전할 때는 animate()를 사용한다.

import starling.utils.deg2rad;
 
var myTween:Tween = new Tween (object, 2.0);
myTween.scaleTo(2);
myTween.fadeTo(0);
myTween.animate( "rotation", deg2rad (45));
Starling.juggler.add(myTween);

위 예제에서 사용한 deg2rad()는 각도를 라디안으로 변환하는 함수다. Starling 프레임워크에서 지원. Juggler 클래스 위 예제에서 살펴보면 Tween 인스턴스에 필요한 설정을 한 후, Tween 인스턴스를 Starling의 juggler이라는 속성에 추가했다. 이는 애니메이션의 시작을 알리는 신호라고 보면 된다. Juggler은 객체의 "시간을 진행하는" 클래스다.
그러나 IAnimatable이라는 인터페이스를 상속하는 객체에만 적용이 된다. Tween은 IAnimatable을 상속하고 있다. Juggler는 객체를 전달하면 해당 객체의 시간을 진행한다. 그리고 객체에 대해 지정된 시간이 지나면 객체에 대한 참조를 자동으로 해제한다. 그런데 Juggler는 delayCall()이라는 메소드가 있다. 이 것은 임의의 함수를 지정한 시간이 지나면 호출하도록 Juggler에게 지시하는 것이다. 호출 함수에 인수를 전달할 수도 있다.
아래는 1초 후에 myFunc()함수를 호출하면서 "Hello"라는 인수를 전달하는 예제다.

Starling.juggler.delayCall (myFunc, 1.0, "Hello");
 
private function myFunc (message:String):void{
  trace (message);
}

애니메이션의 시간과 함수의 실행 시점을 같은 Juggler을 통해서 관리함으로써 양자를 완벽하게 동기화시킬 수 있어 편리하다. Juggler 객체는 Starling 클래스를 제공하기 위해 일반적으로 이 것을 사용하여 애니메이션을 시작하면 충분하다. 단, 애니메이션을 개별적으로 제어하고 싶은 경우에는 Juggler 객체를 생성하는 것이 유용할 수 있겠다.
Juggler 객체를 직접 관리하는 경우 EnterFrame 이벤트에 대한 advanceTime() 메소드를 호출하도록 한다. 또한 dispose()에서 리소스 해제 처리가 필요할지도 모른다. easing 함수 지정 Tween에는 여분의 함수를 지정할 수 있다. easing 함수의 종류는 생성자의 3 번째 인수로 전달한다. 기본 값은 linear다. 생성자에서 설정한 easing 함수는 애니메이션이 시작한 이후에는 변경할 수 없다. Tween 객체의 transition 속성에서 값을 참조만 가능하다.

import starling.animation.Transitions;
var myTween:Tween = new Tween (myQuad, 4, Transitions.EASE_OUT_BOUNCE );
위 예제에서는 easing 함수 easeOutBounce를 지정하고 있다. 여기에 지정 가능한 값은 Transitions 플래스에 정의되어 있다.
아래는 Starling 저자의 사이트에 게재되어 있는 easing 함수의 동작 그래프다. 참고.



섬세한 조정은 허용하지 않는다. 이 점은 Edge 및 Flex와 같다. Tween 진행 상태 알림 Tween은 애니메이션의 시작, 진행, 종료를 알리는 함수를 설정할 수 있다. AS2의 이벤트 핸들러와 비슷하게 사용한다. 구체적인 함수 이름은 각각 onStart(), onUpdate(), onComplete()다. onStart()와 onComplete()는 한 번씩, onUpdate()는 업데이트 프레임 수만큼 실행한다. 아래는 3개의 함수를 설정한 예다.

private function onAddedToStage(e:Event):void {
		myQuad = new Quad(100,100);
		myQuad.color = 0x00FF00;

		var myTween:Tween = new Tween(myQuad,4,Transitions.EASE_OUT_BOUNCE);
		myTween.moveTo(220, 380);
		Starling.juggler.add(myTween);

		myTween.onStart = onStart;
		myTween.onUpdate = onProgress;
		myTween.onComplete = onComplete;

		addChild(myQuad);
	}

	private function onStart():void {
		trace("트윈이 시작되었습니다");
	}
	private function onProgress():void {
		trace("트윈 실행 중");
	}
	private function onComplete():void {
		trace("트윈이 완료되었습니다");
	}

애니메이션의 전처리와 후처리를 실시하고 싶은 경우에는 도움이 될 것이다. 다음에는 Starling의 텍스처의 사용법을 소개한다.

원문 : http://cuaoar.jp/2011/12/tween-starling.html



package {
	import starling.events.Event;
	import starling.core.Starling;
	import starling.display.Quad;
	import starling.utils.deg2rad;
	import starling.display.Sprite;
	import starling.animation.Tween;
	import starling.animation.Transitions;

	public class Demo extends Sprite {
		private var myQuad:Quad;

		public function Demo() {
			// addedToStage 이벤트에 대한 리스너 추가
			addEventListener( Event.ADDED_TO_STAGE , onAddedToStage);
		}
		private function onAddedToStage(e:Event):void {

			myQuad = new Quad(100,100);
			myQuad.setVertexColor(0, 0xFFFF00);
			myQuad.setVertexColor(1, 0xFF0000);
			myQuad.setVertexColor(2, 0x00FF00);
			myQuad.setVertexColor(3, 0x0000FF);
			
			myQuad.pivotX = myQuad.width >> 1;
			myQuad.pivotY = myQuad.height >> 1;

			// Tween 객체의 생성
			var myTween:Tween = new Tween(myQuad, 2.0, Transitions.EASE_IN_OUT);

			// 변화시키는 속성 지정
			myTween.moveTo(stage.stageWidth >> 1, stage.stageHeight >> 1);

			// Juggler에 Tween 객체를 추가하려면
			Starling.juggler.add(myTween);
			Starling.juggler.delayCall(myFunc, 2.0);


			addChild(myQuad);

		}	
		
		private function myFunc():void{
			var myTween:Tween = new Tween(myQuad,4.0, Transitions.EASE_OUT_ELASTIC);
			myTween.animate( "rotation", myQuad.rotation+deg2rad(90));
			myTween.onStart = onStartHandler;
			myTween.onUpdate = onUpdateHandler;
			myTween.onComplete = onCompleteHandler;
			Starling.juggler.add(myTween);
		}

		private function onStartHandler():void{
			var myTween:Tween = new Tween(myQuad,4.0, Transitions.EASE_OUT_ELASTIC);
			if(myQuad.scaleX == 2.0){
				myTween.scaleTo(1);
			}else{
				myTween.scaleTo(2);
			}
			
			Starling.juggler.add(myTween);
		}
		
		private function onUpdateHandler():void{
			trace("트윈 실행 중");
		}
		
		private function onCompleteHandler():void{
			myFunc();
		}

		public override function dispose():void {
			removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
			super.dispose();
		}
	}
}

    

설정

트랙백

댓글

[Starling-03] Flash 컨텐츠 표시의 기본

Programming/Framework 2012. 1. 5. 01:50
Starling은 Stage3D를 이용한 빠른 2D 드로잉을 실현하기 위해 설계된 framework이다. 이전 기사에서 개요와 간단한 사용법을 소개했다. Starling에서는 3가지 방법으로 애니메이션을 사용할 수 있다. 이 방법을 여러 번에 나눠서 소개한다. 기존의 애니메이션 방법과 비교해 보자.

개발 환경 준비
Starling의 개발 환경은 Flash Player 11과 AIR 3가 필요하다. 툴은 Flash Builer 4.6을 권장한다. Flash Professional CS5 또는 CS5.5를 사용하는 경우 다음 문서에서 소개하는 기능확장이 편리하다.
Flash Professional CS5 or CS5.5에 Flash Player 11 설정 MXP

그리고 Starling framework는 github에서 구할 수 있다.
PrimaryFeather / Starling - Framework / zipball

위 링크에서 다운로드한 zip에 포함되어 있는 SWC 파일을 경로에 추가하면 Starling 애플리케이션을 개발 할 수 있다. 또한 혼합 모드에 direct를 지정하지 않으면 제작에 성공해도 화면에 표시할 수 없다. 따라서 SWF 경우 wmode = direct를, AIR일 경우 <renderMode> direct </renderMode> 로 지정하는 것을 잊지 말아야한다.

Starling 인스턴스 생성
Starling로 렌더링하려면 먼저 Starling의 인스턴스를 생성한 다음 start() 메소드를 호출한다. 이 부분은 어떤 Starling을 개발에도 그대로 사용할 수 있다. 아래가 가장 간단한 예제이므로 사용해보자. fla 파일에서 document class로 사용하는 것이 편하다.

package{
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import starling.core.Starling;

        public class StartStarling extends Sprite{
		private var myStarling:Starling;

		public function StartStarling(){
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;

			// Starling의 인스턴스를 생성
			myStarling = new Starling(MyStarlingSprite,stage);
			// 그리기 작업을 시작
			myStarling.start();
		}
	}
}

Starling의 생성자 첫 번째 인수는 Starling의 Sprite다. 이 Sprite의 내용이 실제 화면 그리기에 사용된다. 그리기 정보는 Flash Player의 Sprite와 마찬가지로 자식 객체의 목록 구조와 같이 유지된다. 두 번째 인수는 표기 객체의 그리기 stage다. Starling 생성자는 5개의 인수를 가지지만 3 번째 이후 인수는 기본값을 가지고 있기 때문에 일반적으로 지정할 필요가 없다. 명시적으로 소프트웨어에서 3D 렌더링을 사용하려는 경우에는 5개의 인수를 작성할 수 있다. 마지막 인수가 혼합 모드를 지정한다.

// 5 번째 째의 인수로 그리기 모드를 지정 myStarling = new Starling (Game, stage, null, null, Context3DRenderMode.SOFTWARE );

이렇게 할 경우, 어떤 환경에서도 GPU로 렌더링 되지 않고 CPU로 처리하게 된다. 만약 실행 중에 소프트웨어 렌더링으로 대체되어 있는지 확인하고 싶다면 Starling 인스턴스 context.driverInfo 속성을 통해서 확인할 수 있다. 다음은 context3DCreate 이벤트를 사용하여 Stage3D를 초기화 한 후, 소프트웨어 렌더링의 프레임 속도를 절반으로 설정하는 예를 보여준다.

stage.stage3Ds[0].addEventListener (Event.CONTEXT3D_CREATE,onContext3DCreate); private function onContext3DCreate (event : Event) : void { if (Starling.context.driverInfo.toLowerCase() indexOf ( "software ")!=- 1){ Starling.current.nativeStage.frameRate = 30; } }

Starling 런타임 오류 검사를 수행하려는 경우에는 start()를 호출하기 전에 다음 설정을 추가한다.
myStarling.enableErrorChecking = true;

그러나 오류 검사 및 성능에 미치는 영향이 크기 때문에 디버깅 이외에는 설정하지 않는 것이 좋다. 기타 Starling 클래스의 기능은 다음 기회에 소개할 예정이다. 우선 온라인 문서는 이 곳에서 확인할 수 있다. Starling @ Starling Framework Reference

사용자 정의 Sprite 만들기

(참고 : 앞으로 Sprite와 같은 클래스 이름은 설명이 없는 한 모두 Starling 프레임워크에 종속된 클래스다. 익숙해질 때까지 실수에 주의가 필요하다.)

다음은 Starling의 생성자의 첫 번째 인자로 지정하는 Sprite 사용자 정의 클래스를 만든다. 만드는 단계는, 표시 오브젝트를 작성하고 Sprite에 addChild() 메소드를 추가하는 기존의 방식과 비슷하다. Stage3D의 그리기 단위는 삼각형이지만 Starling은 삼각형 2개를 기본으로 한다. 따라서 사각형에 해당하는 Quad 클래스의 인스턴스를 표시하는 방법에서 시작한다. 아래의 샘플은 화면에 사각형을 표시하는 것을 수행한다.

package { import Starling.display.Quad; import Starling.display.Sprite; public class MyStarlingSprite extends Sprite { private var myQuad:Quad; public function MyStarlingSprite() { // Quad의 인스턴스를 생성 myQuad = new Quad(200,200); // 우선 채우기 색상을 지정 myQuad.color = 0xABCDEF; // Sprite에 Quad 인스턴스를 추가 addChild(myQuad); } } }

위 코드를 실행하면 사각형이 화면 왼쪽에 그려진다. 사각형을 화면 중앙에 표시하려면 다음과 같이 Quad의 좌표를 설정한다.

myQuad.x = stage.stageWidth - myQuad.width>> 1; myQuad.y = stage.stageHeight - myQuad.height>> 1;
단, 위의 코드는 stage 속성에 대한 액세스를 포함한다. 따라서 Sprite가 초기화가 끝나기 전에 실행되면 오류가 발생한다. 그래서 addedToStage 이벤트를 이용한다. 이 addedToStage 이벤트는 Starling 이벤트지만, Flash Player의 addedToStage 이벤트 처럼 Stage가 이용 가능하게 된 것을 알려준다.

package { import Starling.events.Event; import Starling.display.Quad; import Starling.display.Sprite; public class MyStarlingSprite extends Sprite { private var myQuad:Quad; public function MyStarlingSprite() { // addedToStage 이벤트에 대한 수신기를 추가 addEventListener( Event.ADDED_TO_STAGE , onAddedToStage); } private function onAddedToStage(e : Event ):void { // Quad의 인스턴스를 생성 myQuad = new Quad(200,200); myQuad.color = 0xABCDEF; myQuad.x = stage.stageWidth - myQuad.width >> 1; myQuad.y = stage.stageHeight - myQuad.height >> 1; // Sprite에 Quad 인스턴스를 추가 addChild(myQuad); } } }

원문 : http://cuaoar.jp/2011/12/starling-flash.html
    

설정

트랙백

댓글

[AS3] 좋은 코드를 작성하기 위한 길

Programming/ActionScript 3.0 2008. 12. 27. 11:30
플래시는 에니메이션 저작툴이라는 디자인적인 탄생 배경을 탈피하고 많은 프로그래머들이 매력을 느끼는 컴퓨터 프로그래밍 언어로 발전하였다. 나는 어린 시절 장래 희망을 물어보면 컴퓨터 프로그래머라고 이야기하던 시절이 있었다.(그때는 5.25인치 디스크 한 장에 게임 하나가 들어가던 시절이었는데 아마도 게임을 하면서 스토리를 내 마음대로 바꾸고 싶었던 것 같다.)

하지만 그런 꿈은 삶의 역경 속에서 잊혀지고 나아가 컴퓨터 프로그래머라는 직업이 돈이 되는 직업은 아니라는 것을 알았을 무렵에는 이내 나의 꿈은 컴퓨터 프로그래머가 아니었다고 부정하였다. 결국 부정하던 장래희망의 굴레에 나를 몰아넣은 것은 플래시라고 할 수 있다. 내가 플래시를 처음 접했을 때는 이런 형태로 발전할지는 꿈에도 몰랐었으니 고로 나는 플래시에게 사기를 당한 것이다. ^^


나는 배우는 과정에 서있다. 항상 플래시의 발전을 따라가느라 정신 없이 허우적거리는 생활을 반복하고 있으니 아마도 내가 플래시라는 툴에서 손을 놓을 때까지 이러한 배움의 길은 끝이 없을 듯싶다.

배우는 과정에서 느꼈던 좋은 코드를 작성하는 방법에 대하여 이야기 해 볼까 한다. 본 내용은 일본 잡지에 실린 연재 코너의 내용을 ActionScript 버전으로 본인의 생각을 덧붙여 작성한 것임을 밝혀둔다.

좋은 코드란?
좋은 코드는 조직이나 프로젝트, 프로젝트 메니저에 따라서 그 정의가 다르게 해석될 수 있다. 하지만 보편적으로 좋은 코드로서 바람직한 방향은 있다.

정확하게 동작하는 것.
정확한 결과값을 도출하는 것은 신뢰할 수 있는 코드다.

빠르고 효율적으로 동작 하는 것.
결과 값을 도출하는 방법은 여러 가지가 있을 수 있다. 좋은 코드는 적절한 퍼포먼스로 동작한다.

방어적으로 버그를 생산하지 않는 것.
방어적 프로그래밍 방법론에 기초하여 정상적인 값이 들어 올 것이라고 가정하지 않고 부정확한 값이 와도 문제가 발생하지 않도록 방어적으로 코드를 작성한다. 이것은 처음에 열거한 정확하게 동작하는 것을 도와준다.

유지보수를 하기 쉬운 것.
프로젝트는 단기간에 수명을 다할 수도 있지만 우리가 상상하는 것보다도 길게 생명을 유지하는 것도 많다. 유지보수성을 높이는 것도 좋은 코드에 있어서 중요하다.

다른 사람이 봐도 이해하기 쉬운 것.
현재 작성한 코드를 미래에 자신이 보는 것과 현재 타인이 보는 것은 비슷하다고 볼 수 있다. 미래에 자신이 봐도 이해할 수 있는 코드는 좋은 코드라 할 수 있다.

쓸데없는 부분이 없는 것.
쓸데없는 코드를 작성하는 개발자는 없을 것이다. 다만 코드의 구현과정에서 기능 추가 및 다른 로직과의 연동 과정에서 불필요하게 파생하는 코드들은 지양할 필요가 있다.


좋은 코드를 작성하면 무엇이 좋은가?
좋은 코드는 프로젝트를 추진하고 성공적으로 이끌기 위한 기본적인 요소가 된다. 프로그래밍의 달인들은 심플하고, 유지보수성이 좋고 안정적인 코드를 빠른 속도로 작성한다. 테스트가 어려운 코드를 테스트가 가능하고 검증할 수 있는 코드로 변경함으로써 품질이나 생산성을 수백 배 높이기도 한다. 이것은 프로젝트의 성공에 있어서 큰 요소이다. 물론, 좋은 코드가 있으면 반드시 프로젝트가 성공하는 것은 아니다. 개발 프로세스나 메니지먼트, 커뮤니케이션등으로 좌우되는 경우가 더 많지만 이런 것들을 제외한다면 개발에 있어서 좋은 코드의 힘은 크다고 볼 수 있다.

프로그래머로서의 평가가 높아진다.
좋은 코드를 작성하는 프로그래머는 대체적으로 프로그래머로서 신뢰한다. 프로그래머로서의 평가가 조직으로서의 실제 평가나 이익에 결합될지는 소속하는 조직의 평가 제도나 프로그램 이외의 일도 포함하여 정해지는 것이 현실이다. 그렇다고 좋은 코드를 쓸 수 있는 것이 마이너스 평가로 이어지지는 않을 것이다.

일에 대한 만족감이나 자신감을 가질 수 있다.
두 번 다시 손대고 싶지 않은, 유지보수가 불가능한 코드를 써본 적이 있을 것이다. 이러한 낮은 퀄리티의 일을 해 놓으면 일에 대한 만족감을 얻을 수 없다. 반면 자신의 의지로 적절히 좋은 코드를 작성함으로써 품질이 높고 안정된 소프트웨어를 개발했을 때는 그에 대한 만족감도 높고 자신감을 갖고 일에 임할 수 있다. 앞으로 오랜 시간을 프로그래머로써 살아갈 것이라고 생각한다면 좋은 코드를 쓸 수 있는 레벨을 목표로 하는 것은 합리적인 일이다.

사실 좋은 코드를 작성하기 위해서는 하루아침에 이룰 수 없다. 그렇다면 좋은 코드를 작성하기 위해 구체적으로 무엇을 어떻게 해야 하는지를 살펴보자.

코드 리딩 - 읽어라, 코드를 읽고, 읽고, 또 읽어라.
음악이나 회화, 건축의 세계에서도 자신만의 발상으로 작품을 완성시키는 예술가는 없다. 다른 사람들의 작품을 보고 영향을 받거나 좋은 곳을 훔치거나 해서 자신의 작품을 만드는 것으로 작품을 낳아 왔다.

프로그래밍도 같다. 좋은 코드를 작성 하려면 좋은 코드이건 나쁜 코드이건 간에 다른 사람이 작성한 코드를 평소에 의식하고 읽는 것이 중요하다. 플래시는 특히 많은 오픈 소스가 인터넷에 열려 있기 때문에 다른 사람이 작성한 좋은 코드를 언제라도 부담 없이 읽을 수 있다. ActionScript 중급 정도의 실력자이지만 구조를 어떻게 만들어야 하는지 막막한 분은 특히 주목할 필요가 있다. 이런 단계에 머물러 있는 분이라면 코드리딩을 통해서 한 단계 발전한 자신을 발견할 수 있을 것이다.

코드리딩의 좋은 점은 알아도 코드를 읽는 방법을 모른다면 시작하기 힘든 일이다. 아래의 간단한 코드를 보면서 이야기 해보자.

package classes.data{

    import flash.events.Event;
    import classes.data.*;
    import classes.net.SimpleXMLLoader;
   
    public class DProvider extends SimpleXMLLoader{ // [1] 여기부터
           
        private var _xmlUrl:String;   
        private var _keywords:Array;
       
        public function DProvider(inUrl:String):void { // [2] 여기부터
            _xmlUrl = inUrl;
            addEventListener(Event.COMPLETE, onLoadedXmlHandler);
            loadXML(_xmlUrl);
        }    // [2] 여기까지

        private function onLoadedXmlHandler(e:Event):void { // [3] 여기부터
            var xml:XML = XML(data);
            _keywords = [];
           
            var len:int = xml.item.length();
            for (var i:int = 0; i < len; i++)
            {
                // [4] 여기부터
                _keywords.push(createKeyword(xml.item[i]));
            }
        }    // [3] 여기까지
       
        private function createKeyword(inKeywordNode:XML):KeywordBase
        {
            var keyword:KeywordBase;
            switch(int(inKeywordNode.level)) {
                case 1: keyword = new Keyword1(inKeywordNode);
                break;
                case 2: keyword = new Keyword2(inKeywordNode);
                break;
                case 3: keyword = new Keyword3(inKeywordNode);
                break;
                case 4: keyword = new Keyword4(inKeywordNode);
                break;
            }
            return keyword;
        } // [4] 여기까지
       
        public function get keywords():Array { return _keywords.concat(); } // [5]
    } // [1] 여기까지
}

위 클래스는 본인이 실무에서 작업했던 태그클라우드에서 사용했던 코드이다. 클래스의 기능은 xml데이터를 불러들여 level 노드 값에 따라서 해당 클래스들을 배열로 생성하여 제공한다.

위 클래스 외적으로 사용된 클래스는 다음과 같은 기능을 포함한다.
SimpleXMLLoader : 단순히 xml 데이터를 불러오는 기능을 한다. loadXML 메소드가 포함되어 있다.
KeywordBase : 키워드 무비클립의 기본이 되는 기능을 제공한다. (마우스 다운, 오버, 아웃등)
Keyword1 ~ Keyword4 : KeywordBase 를 상속하는 각 레벨에 따라 디자인이 서로 다른 클래스들

코드리딩을 할 때는 기본적으로 nest 단위로 읽어 내려가면 된다. 중간에 나타나는 다른 클래스들은 현재 블록을 전체적으로 훑어 보면서 유추하도록 하자. 중간에 다른 파일을 열어 읽게 되면 현재 읽고 있는 흐름을 놓칠 수 있기 때문이다.

50줄도 안 되는 코드지만 이 코드만 가지고도 작업된 클래스들의 절반 이상은 이해할 수 있다. 복잡한 기능을 하는 클래스는 아니기 때문에 읽으면서 구조적으로 어떻게 작성이 되었는지 알 수 있을 것이라 믿는다. 이런 훈련을 반복 하다 보면 현재 읽고 있는 클래스 이외의 다른 클래스들도 머리 속으로 그리는 과정을 얻게 된다. 이를 통해서 하나를 보면 열을 알게 되는 경지에 다다를 수 있을 것이다. ^^

구글에서 코드 검색엔진을 통해서 웹에 있는 원시 코드들을 검색할 수 있는 서비스를 제공하고 있다. 자신이 원하는 기능의 클래스명이나 메소드명으로 검색해서 코드리딩 연습을 하는 것도 좋은 방법이다. 또한 많이 알려진 클래스나 패키지들은 구조적으로 잘 설계된 것들이 많이 있다. 구조적인 관점에서는 그런 것들을 분석해 보는 것도 큰 도움이 된다.

http://www.google.com/codesearch
인터넷상에 공개되어있는 Subversion(repository)나 archive파일 등을 기계적으로 빠르게 검색 할 수 있다.

좋은 이름을 붙이자.
우리가 프로그래밍을 하고 있을 때 가장 막히는 부분은 변수명, 메소드명, 클래스명 이름을 붙이는 것이다. 그만큼 좋은 이름을 붙이는 것은 중요하다. 좋은 이름을 붙이는 것이 중요한 이유는 위에서 언급했던 코드리딩에서도 느낄 수 있듯이 관련 기능에 부합하는 좋은 이름을 붙이지 않으면 코드를 읽기가 어려워진다.(생각해보니 위에서 예로 든 코드에서도 어려움을 느낀 분들이 있을 것 같다 ^^;)

그렇다면 좋은 이름의 조건이 있을 법하다.

좋은 변수명, 메소드명, 클래스명은 이름이 그 코드의 내용을 올바르게 나타내고 있다. 그러한 이름은 이름을 보는 것만으로도 코멘트를 읽을 필요도 없이 그 역할을 이해할 수 있다. 좋은 이름은 코드의 이해를 돕지만 나쁜 이름은 읽는 사람을 혼란 시키고 착각을 낳아 버그 발생을 조장한다.

위 코드를 예로 들면 onLoadedXmlHandler 메소드 명을 onComplete로 했을 경우에 어떤 것이 Complete 되었다는 것인지 인지하기 어렵다. 위 클래스의 경우는 단순한 클래스이지만 클래스의 내용이 많고 complete 핸들러 함수를 여러 개 포함하고 있을 경우에는 메소드의 중복이 발생할 수도 있다.

public function get keywords():Array { return _keywords.concat(); }
의 경우에는 keyword에 복수를 뜻하는 s를 붙임으로써 전달 받는 keyword가 하나가 아니라 복수이며 배열이라는 것을 유추할 수 있다. 이 밖에도 아래와 같은 방법이 있다.

어두 이외의 모음을 삭제 (image ->img)
강한 소리를 남긴다. (server -> svr)
약어의 이용 (database -> db)

일관성이 있다.
좋은 이름은 코드 전체에서 일관된 흐름을 가져야 한다.

대칭성을 유지하는 것
begin <-> end
write <-> read
on <-> off

단어의 조합의 일관성
scoreAvg
scoreAverage
avgScore
위 이름은 하나의 클래스에서 중복 사용하지 않을 것.

관용어에 따라서
언어, 프로젝트, 회사나 팀 마다 명명에 관한 관용어(관습)가 있다. 예를 들면 Java의 경우는 메소드명은 소문자로 시작하는 것이 관습이며, C#은 대문자, C++은 멤버 변수에 prefix로 m_를 붙이는 것이 일반적이다. 관용어에 따른 명명은 누가 보더라도 알기 쉬운 이름이라고 이야기 할 수 있다.(ActionScript의 경우는 보통 자바와 언어적 문법이 비슷하기 때문에 자바와 같은 명명 관용어를 사용하는 경우가 많지만 개인적인 취향에 따라 다르게 사용하는 경우가 대부분이다.)

코딩 표준에 따라서
위와 같이 좋은 코드의 조건을 채우기 위해서도 코딩 표준이나 명명 규약을 정해 팀 멤버 전원이 맞추는 것이 중요하다. 작업자 1명이 단기적으로 작업하는 프로젝트에서는 본인이 원하는 규칙을 사용하면 되겠으나 조직의 힘을 바탕으로 얻을 수 있는 큰 프로젝트의 경우는 협업의 중요성이 대두되므로 이러한 코딩 표준을 맞추는 것이 장기적으로는 바람직하다고 볼 수 있다.

좋은 이름을 붙이기 위한 습관
항상 좋은 이름을 붙이는 것을 의식한다.
좋은 이름을 붙이려면 우선 의식적으로 노력을 해야 한다. 이것은 A라는 이름이 좋은가? 아니면 B라는 이름이 좋은가를 항상 신중하게 검토해 보고 적절한 이름을 결정하는 프로세스를 반복할 필요가 있다.

코드의 리딩이나 리뷰
자신이 모르는 완전히 새로운 이름을 만드는 것은 코드를 분별없게 만들 가능성이 크다. 본인이 작성한 코드를 스스로 리딩해 보거나 다른 사람에게 리뷰를 함으로써 사용할 수 있는 이름을 조금씩 늘려간다. (본인 같은 경우는 아는 단어의 수준이 메롱이기 때문에 코드작업을 할 때 항상 사전을 열어놓고 작업을 하는 습관이 있다. 이때도 주의할 것은 일회성으로 모르는 단어를 만들어 명명하는 것 보다는 그 단어를 충분히 숙지한 상태에서 이름으로 사용하는 것이 바람직하다 – 간혹 내가 만든 이름을 내가 이해하지 못하는 어처구니 없는 경우가 발생 하기도 한다. 메롱;;)

좋은 변수명
설명적인 변수명
변수에는 값이나 오브젝트가 대입된다. 변수명을 보는 것만으로도 무엇이 어떠한 역할을 하는지 명확한 것이 좋은 이름이라 할 수 있다.

예를 들어
var n:int;                                                 // 무슨 수치?
var languages:Array = [“kr”, “en”];     // 무슨 언어?
var flg:Boolean = false;                      // 무슨 플래그?
var userAgent:UserAgent                  // 무슨 유저 에이전트?

위와 같은 변수명은 나중에 되돌아보면 변수의 역할을 알 수 없다. 아래와 같이 좀더 구체적이고 명확한 이름으로 해 두면 되돌아 보거나 다른 사람이 봐도 이해하기 쉬운 코드가 된다.

var orderCount:int;                                                // 오더수
var availableLanguages:Array = [“kr”, “en”];     // 이용 가능한 언어
var existsSameName:Boolean = false;           // 동성동명이 존재할까?(존재 true)
var unknownUserAgent:UserAgent                  // 미지의 유저 에이전트

다만 변수는 변수의 종류와 그 변수의 스코프(변수의 값을 참조할 수 있는 범위, 변수의 선언으로부터 시작되어 변수의 값을 참조할 수 없게 될 때까지의 범위)에 의해서 좋은 이름의 성질이 다르다. 스코프가 넓으면 다양한 곳으로부터 참조되므로 영향 범위가 크다고 할 수 있다. 따라서 보다 구체적인 이름이 요구된다. 종류별로 보면 아래와 같다.

필드 변수, 클래스 변수
필드 변수는 인스턴스 변수이다. 필드 변수, 클래스 변수는 로컬 변수등과 비교하면 변수의 스코프가 넓기 때문에 특히 그 변수의 의미를 올바르게 표현한 이름이 바람직하다.

메소드의 파라미터
파라미터명은 알기 쉽고 간결한 이름이 좋을 것이다. 파라미터명은 이용자가 API레퍼런스로 참조하거나 Eclipse, FlashDevelop등의 통합 개발 환경으로부터 변수명의 후보로서 이용되므로 극단적으로 짧은 이름을 붙이는 것은 피해야 한다.

로컬 변수
메소드 내에서 일시적으로 선언되는 변수이다. 스코프가 긴 것도 있지만 for문과 같이 짧은 것도 있다. 스코프가 긴 것은 필드 변수와 같이 변수의 의미를 올바르게 표현하는 구체적인 이름을 붙이는 것이 좋다. 스코프가 짧은 것은 아래와 같이 사용구분만 적당히 해주면 된다.

관용어에 따르는 또는 따르지 않는다.
배열의 내용을 순서대로 처리하는 루프 카운터 변수(i,j,k)등과 같이 잘 사용되는 관습적인 변수명은 그대로 관용어에 따르는 편이 알기 쉬운 코드가 된다.
// 루프 카운터의 변수명이 관습적이지 않고 너무 길다 [X]
for (var empCounter:int=0 ; empCounter < employes.size ; empCounter++) {
          var emp:Employee = employees[empCounter];
    ...
}

// 루프 카운터의 이름이 관습적으로 짧고, 가독성이 높다 [O]
for (var i:int=0 ; i<employes.size ; i++) {
         var emp:Employee = employees[i];
    ...
}


다만 예외적인 경우도 있다. 구체적인 이름을 변수명으로 하는 편이 알기 쉬운 경우는 그렇게 사용한다. 예를 들어 좌표계를 취급하는 경우에는 아래와 같이 사용하여 가독성을 높일 수 있다.
// i,j의 어느 쪽이 x좌표, y좌표인지를 모른다 [X]
for (var i:int=0 ; i<width ; i++) {
    for (var j:int=0 ; j<height ; j++) {
        var color:uint = getColor(i, j);
        ...
    }
}

// 변수명을 x,y로 했으므로 알기 쉽다 [O]
for (var x:int=0 ; x<width ; x++) {
    for (var y:int=0 ; y<height ; y++) {
        var color:uint = getColor(x, y);
        ...
    }
}

위 for문의 경우, 중첩되는 var y:int=0 변수 선언은 for문 밖에서 선언해 주는 것이 바람직하다. 중첩된 for문 안에서 x가 카운팅 될 때마다 메모리상에서는 y라는 변수의 어드레스를 매번 push해야 하는 불필요한 리소스 낭비가 발생하기 때문이다. (이 부분에 대한 논쟁 이슈가 있다. 이후에 이야기할 로컬 변수의 스코프 부분에서 로컬 변수의 스코프는 가능한 작게 한다는 변수의 의존성에 따른 대원칙에 위배되는 것이기 때문이다. 이것은 사용하는 상황에 따라 적절히 혼용하는 것이 좋을 것이다.)
var x:int;
var y:int;
for (x=0 ; x<width ; x++) {
    for (y=0 ; y<height ; y+) {
        var color:uint = getColor(x, y);
        ...
    }
}

변수명을 짧게 하는 편이 가독성이 향상되는 경우도 있다.
충분히 인지할 수 있는 범위인 경우로 루프내의 변수나 짧은 메소드 내의 변수처럼 일시적인 변수는 짧게 하는 편이 반대로 가독성이 향상되는 경우도 있다.
// 변수명 siteContactChangelog는 너무 길다 [X]
for (var i:int=0; i<siteContactChangelogs.length ; i++) {
    var siteContactChangelog:SiteContactChangelog = siteContactChangelog[i];
    siteNames[i] = siteContactChangelog.getSiteName();
    siteTitles[i] = siteContactChangelog.getSiteTitle();
    sitePicIds[i] = siteContactChangelog.getPicId();
    sitePicNames[i] = siteContactChangelog.getPicName();
}

// 변수명 log는 충분히 그 의미를 이해할 수 있기 때문에 가독성이 좋다.[O]
for (var i:int=0; i<siteContactChangelogs.length ; i++) {
    var log:SiteContactChangelog = siteContactChangelog[i];
    siteNames[i] = log.getSiteName();
    siteTitles[i] = log.getSiteTitle();
    sitePicIds[i] = log.getPicId();
    sitePicNames[i] = log.getPicName();
}

좋은 메소드명
좋은 메소드명은 이름으로부터 그 기능을 예상할 수 있다. 메소드는 처리를 담당함으로 메소드명은 동사+목적어 형태인 것이 많다. 아래는 자주 사용되는 메소드명의 예이다.
 메소드의 역할                                         메소드명
 값 취득에 관한 메소드                           getXXX
 값 세트에 관한 메소드                           setXXX
 생성에 관한 메소드                                create, build, make, generate
 초기화에 관한 메소드                            initialize, setupXXX
 파기에 관한 메소드                               destroy, dispose
 상태 확인에 관한 메소드                      contains, exists

인스턴스 메소드는 dataFormat.parse와 같이 오브젝트명으로 조합하므로 합쳐졌을 때는 중복 없게 의미가 통하는 이름으로 한다. 메소드와 클래스명도 이와 동일하다.
// parseDateString은 클래스명 DateFormat과
// date라는 이름이 중복되어 약간 장황
var dateFormat:DateFormat = new DateFormat("yyyy-MM-dd");
var startDate:Date = dateFormat.parseDateString("2008-04-01");

// 클래스명 DateFormat과 메소드명 parse로
// 무엇을 처리하는지 충분히 이해할 수 있음.
var dateFormat:DateFormat = new DateFormat("yyyy-MM-dd");
var startDate:Date = dateFormat.parse("2008-04-01");

좋은 클래스명
변수명이나 메소드명과 비교해서 클래스명은 가용 범위가 크기 때문에 적절하고 좋은 클래스명을 붙이는 것이 중요하다. 좋은 클래스명은 이름만으로 무엇을 실시하는 클래스인가를 알 수 있다.

클래스명이 잘 떠오르지 않을 때는 자신이 만들려고 하는 클래스의 역할을 제대로 정리 할 수 있는지 없는지를 판단해 보아야 한다. 1개의 클래스에 복수의 책무를 넣거나 역할이 애매한 기능은 없는지를 생각해보고 해당 클래스에서 해결하고자 하는 문제를 차분히 생각해보고 클래스명을 다시 선택할 필요가 있다.

클래스명의 어휘 설계 능력
이름 명명에 관하여 자신이 모르는 표현, 개념은 쉽게 생각하기 어렵다. 보다 나은 표현을 선택하려면 여러 가지 코드나 서적을 읽거나 실제로 코드를 쓰고 시험하는 것이 중요하다. 그 경험을 통해서 이름에 관한 어휘가 조금씩 늘어난다. 본인 같은 경우는 영어권의 개발자가 작성한 기능과 메소드명을 보면서 의미해석을 한다. 사실 프로그래밍 과정에서 이름을 짓는 것은 생활에서 보편적으로 사용하지 않는 단어들도 많이 존재한다. 하지만 그만큼 자주 사용되는 단어들은 한정되어 있기 때문에 틈나는 대로 기억을 되살려 사용해 보는 것이 중요하다.

좋은 패키지명
ActionScript의 패키지명은 클래스나 자원의 논리적인 그룹을 만들어 계층 구조를 나타낸다 이것은 주로 이름의 충돌을 막기 위해서 사용된다. 패키지명은 그룹의 논리적인 내용을 나타내는 간결한 명사를 선택한다.

간혹 클래스를 만들지 않고 라이브러리에서 특정 무비클립을 동적으로 참조하기 위하여 Linkage에 클래스명만 기입하여 사용하는 경우가 있다. 이럴 경우 클래스가 플래시 컨텐츠전역에 오픈 되기 때문에 팀의 협업에 있어서 클래스명의 충돌을 야기할 수 있다. 이럴 경우 해당 클래스가 없더라도 관련된 패키지명을 명시함으로써 그러한 충돌을 줄일 수 있다. 

처음부터 좋은 이름을 사용할 수 있는 사람은 없다. 좋은 이름에 대해서 의식적으로 사용하려고 노력하는 것이 중요하다. 누구라도 알기 쉽고, 이해하기 쉬운 코드라고 하는 것은 항상 의식하고 노력하다 보면 점차적으로 좋은 이름을 지을 수 있는 요령이 생길 수 있을 것이다.


스코프를 의식한 프로그래밍
사실 모든 프로그래밍에서 스코프는 존재한다. 의식적으로 스코프를 컨트롤 할 수 있으면 보다 좋은 프로그래밍 스타일에 가까워질 것이다. 이번에는 스코프에 대한 이야기를 해보자.

우선 스코프는 Wikipedia에 다음과 같이 정의되어 있다.
프로그래밍에서 스코프란, 어느 변수나 함수가 특정 이름으로 참조되는 범위, 어느 범위의 밖에 있는 변수 등은 통상 그 이름만으로는 참조할 수 없다. 이때 이러한 변수는 스코프 밖에 있어 보이지 않는다 라고 말한다.

스코프는 변수, 메소드, 클래스등이 보이는 범위다. 그렇다면 보인다는 의미는 무슨 뜻일까? 보인다라는 것은 프로그래밍상에 있다는 것이다. 변수이면 변수명을 지정해 값을 읽고 쓰기가 가능하고 메소드는 호출해 사용할 수 있는 범위에 있는 것이다.

사용할 수 있다라는 것은 바꾸어 말하면 그것에 의존한다라고 이야기할 수 있다. 하나의 코드를 변경하고 싶을 뿐인데 수십 곳을 수정할 필요가 있을 수 있다. 이것은 변경하고자 하는 코드가 여러 곳에 의존하고 있으면 이와 같은 변경이 다른 부분에 영향을 준다.

스코프 == 보이는 범위 == 사용할 수 있는 범위 == 의존하는 범위

변수나 메소드의 스코프를 작게 하는 것으로 보이는 범위가 작아져 사용할 수 있는 범위, 의존하는 범위도 작게 할 수 있다. 스코프를 작게 하는 것으로 보다 의존성이 적어 변경이 용이한 프로그램을 작성 할 수 있는 것이다.

기억해 두는 것을 줄이자.
의존이 작아지는 것 이외에도 스코프를 작게 하는 것으로부터 도움이 되는 것이 있다. 프로그래밍은 본질적으로 복잡한 것이다. 복잡함에 대한 대책으로서 문제 영역을 가능한 작고, 이해 가능한 상태로 취급하는 것이 중요하다. 스코프를 의식적으로 작게 하는 것으로 프로그래머가 기억해 두지 않으면 안 되는 것, 주의하지 않으면 안 되는 범위는 작아져서 쉽게 이해할 수 있게 된다. 이것이 스코프를 작게 하는 것의 본질이라고 할 수 있다.

로컬 변수의 스코프
로컬 변수란 메소드 내에서 선언된 일시적인 변수다. Java나 Ruby의 로컬변수는 선언된 장소로부터 스코프가 시작되어 선언된 블록이 끝나면 스코프가 종료된다. ActionScript 2.0 에서도 순차적으로 메모리 할당이 이루어 졌기 때문에 메소드 내에서 상위에 선언된 변수와 하위에서 선언된 변수가 서로 다른 영역 범위의 스코프를 갖기 때문에 컴파일 시에 충돌이 발생하지 않았다.(Java, Ruby와 동일)

반면 ActionScript 3.0에서의 로컬변수는 스코프의 시작은 컴파일러가 블록에 접근했을 때 블록 내의 위치와는 상관없이 미리 메모리 주소가 할당된다. 이는 컴파일 시에 메모리 할당이 한꺼번에 선행되어 스코프가 동일하기 때문에 변수명 중복 에러 메시지를 출력하는 것이다.

하지만 일반적인 프로그래밍 언어에서는 변수의 의존도를 최소화하여 프로그램의 변경이 쉽게 하기 위하여 [로컬변수의 스코프는 가능한 작게 한다.] 라는 것이 대원칙이다.

필드 변수의 스코프
필드 변수는 인스턴스 변수다. 필드 변수의 스코프는 private / public 등과 같은 키워드를 통해서 정해진다. ActionScript의 경우 필드 변수에 대한 가시성은 스코프가 작은 순서로 4개가 지원된다.
private    : 오브젝트 내에서만 변수에 액세스 할 수 있다.
internal    : 같은 패키지 내에서 액세스 할 수 있다.
protected : 오브젝트 내 그리고 하위 클래스로부터 액세스 할 수 있다.
public : 오브젝트 밖에서 액세스 할 수 있다.

필드 변수는 모두 private가 기본 전략이다. 필드 변수에 외부나 하위 클래스로부터 액세스 하고 싶은 경우에는 set/get 등 액세스용 메소드를 따로 만들어 공개하는 것이 캡슐화에 도움을 준다. 하지만 기본 전략이 바람직하다고는 하지만 상속에 따른 장황함을 배제하기 위해서 protected나 public 접근자를 사용하는 경우도 발생한다.

인스턴스 메소드의 스코프
인스턴스 메소드는 인스턴스에 속하는 메소드를 말한다. ActionScript에서 메소드의 스코프 가시성도 필드 변수와 같이 4개이다. 메소드의 접근 제한은 최소인 private로부터 시작하여 점차적으로 internal -> protected -> public으로 나아가는 것이 바람직하다.

메소드 파라미터의 정보량
스코프에서 조금 벗어난 이야기이지만 메소드의 인수로 건네주는 정보량을 어느 정도로 하는 것도 의존성이라는 관점에서 보면 중요한 선택이다.

예를 들면 아래의 두 코드는 사원 정보를 취득하는 메소드이지만 1번은 인수가 사원ID이고 2번은 인수가 사원 오브젝트이다. 이 두 개의 코드 중에 어느 쪽이 좋은 코드라고 할 수 있을까?
// [1] 인수가 사원ID인 경우
public function getEmployee(inEmpId:int):Employee {
    return empDao.findById(inEmpId);
}

// [2] 인수가 사원 오브젝트의 경우
public function getEmployee(inEmp:Employee):Employee {
    return empDao.findById(inEmp.getId());
}

일반적으로 1번이 인수의 정보량이 적기 때문에 의존이 적고 좋은 코드라고 할 수 있다. 반면 2번은 사원 오브젝트가 가지는 모든 정보로 액세스가 가능하기 때문에 의존이 커지게 된다. 필요한 것은 사원의 ID이므로 그것에만 의존하여 코드를 작성하는 것이 바람직하다.

메소드를 이용하는 측면에서 사원 ID만으로 메소드를 이용할 수 있는 것과 사원 오브젝트가 필요한 것은 전혀 다르다. 더욱이 2번 메소드 내에서 구체적인 처리는 사원 오브젝트의 사원 ID만을 사용해 사원 정보를 검색하고 있다. 이것이 문서화 되어 있지 않을 경우, 코드를 읽지 않으면 그 사실을 알지 못한다. 인수에 불필요한 정보가 포함되어 있으면 사원 ID가 포함된 사원 오브젝트를 건네주어야 한다는 암묵적인 요구가 발생하기 쉽다.

위와 같은 문제 때문에 메소드의 인수는 필요 최저한의 정보를 가지는 것이 의존성이 적고 좋은 코드라고 말할 수 있다.

다만 인수가 너무 많아지는 경우는 인수를 오브젝트로 변경하는 편이 좋다. 기준으로서 인수의 개수가 5개를 넘는 메소드는 인수를 오브젝트로 변경하는 것을 검토할 필요가 있다.

static 메소드
static메소드(클래스 메소드)는 클래스에 속하는 메소드이다. ActionScript에서는 static 키워드를 붙여서 선언한다. static 메소드의 가시성은 인스턴스 메소드의 가시성과 같다. 반면 다른 점은 static 메소드는 필드 변수에 액세스 할 수 없다. static 메소드는 메모리에 미리 할당이 되는 반면 인스턴스 변수는 오브젝트가 인스턴스화 된 시점에서 메모리 할당이 되기 때문에 static 메소드 내에서 인스턴스 변수를 참조할 방법이 없는 것이다.

필드 변수에서 보면 인스턴스 메소드를 static 메소드로 변경했을 경우, 자신이 영향을 주는 메소드가 줄어 들게 되어 결과적으로 스코프는 작아진다. 필드 변수에 액세스 할 필요가 없고, 오버라이드가 필요하지 않는 메소드는 static 메소드로 하는 편이 좋은 경우가 많다. 물론 무조건 static으로 하는 것이 좋은 것은 아니다. 인스턴스가 생성되지 않은 시점에서 메모리에 할당이 되기 때문에 사용하지 않는 클래스의 static 메소드가 메모리에 상주하는 메모리 차원에서의 단점도 있다.
// 인스턴스 메소드의 경우
private var count:int;                                                           ┓
...                                                                                           |
private function regexGroup(inRegex:String):String { |변수 count의 스코프
    // 필드에 액세스 가능                                                     |
    return "(" + regex + ")";                                                   |
}                                                                                             |
...                                                                                            ┛

//static 메소드로 변경했을 경우
private int count;                                                                  ┓
...                                                                                            ┛변수 count의 스코프
static private function regexGroup(inRegex:String):String {
    // 필드에 액세스 불가
    return "(" + regex + ")";
}
...     ―변수 count의 스코프


코드의 분할
몇 천행이 넘는 메소드로 너무 많은 기능을 포함하고 있거나 메소드를 너무 세세하게 분할하여 흐름을 파악하기 어려운 코드는 좋은 코드라 할 수 없다. 좋은 코드가 되기 위해서는 가독성이 좋고, 유지보수성이 우수한 것이라고 위에서 언급했다. 메소드를 적절한 단위로 분할하는 것은 좋은 코드를 만드는 것에 중요한 역할을 한다.

코드를 분할하면 무엇이 좋은가?

가독성의 향상
메소드 코드의 길이가 100줄을 넘으면 처리의 흐름을 읽는데 어려움이 있다. 반면 30행 이하이면 내용을 이해하는 것이 용이하다.

유지보수성의 향상
분할에 의해 변수의 스코프가 작아지거나 처리 기능이 본래 있어야 할 클래스나 메소드로 이동하는 것으로 의존관계가 정리되어 유지보수성이 향상된다.

재이용성 향상
코드를 분할하면 코드의 중복이 줄어들어 이용 가능한 부품으로서의 메소드나 클래스를 만들 수 있다. 이것은 OOP 언어에서 좋은 방법이다.

캡슐화를 지킬 수 있다.
객체 지향에서는 캡슐화라는 개념이 있다. 메소드나 클래스의 상속에 의한 구체적인 구현이나 오브젝트 상태를 몰라도 메소드를 호출하는 것만으로도 각각의 오브젝트가 처리를 이행해 주는 것이다.

클래스의 관점에서도 비슷한 이득을 얻을 수 있다. ActionScript는 타 언어보다 MVC 페턴을 예로 들면 view에 해당하는 클래스가 Model에 비해 상대적으로 비대하다. 따라서 구조 작업에 있어서 이러한 view 그룹을 어떻게 분할하느냐에 따라서 유지보수성의 성패를 좌우한다고도 볼 수 있다.

위에서 좋은 코드를 위한 방법에 관하여 이야기를 했다. 연재에 실린 내용과 그것을 ActionScript에 맞게 수정하는 관계로 문장이 다소 매끄럽지 않는 점이 있을 것이다. 그런 부분은  이해해 주길 바란다.

사실 플래시는 타 언어에 비해서 버그가 발생할 가능성이 크다. 그 이유는 플래시의 강점인 모션을 항상 고민해야 하는 작업이기 때문이다. 일반적인 언어에서는 어떤 오브젝트가 나타나고 사라지는 사이에 시간이라는 개념을 포함할 필요성을 인식하지 못하지만 플래시는 모션에 따라 그 사이에 시간이 존재할 수 있다. 모션이 있는 사이에 예측하지 않은 사용자 반응이 있을 경우에는 버그가 발생할 수 있다. 플래시 개발자는 항상 이런 부분까지 예상하고 방어적 프로그래밍을 해야 한다.

위에서 이야기한 좋은 코드를 작성하는 것은 플래시의 작업에 많은 도움을 주지만 그런 것이 플래시 개발의 모든 약점을 보완해 주지는 못한다. 때로는 일반적인 좋은 코드로서의 방향에 영향을 주지 않는 범위 내에서 플래시의 장점을 극대화 할 수 있는 방법을 고민 해야 하는 것이다.

간혹 좋은 코드를 작성하는 방법을 물어보시는 분들이 있다. 물론 그것이 모르는 부분을 빨리 이해할 수 있는 좋은 방법일 수 있지만 쉽게 얻은 지식은 지식으로 머물러 지혜로 발전하지 못하는 경우가 많다. 더구나 본인 또한 그 방법을 찾고자 고민하고 배워가는 입장이기 때문에 도움을 주지 못하는 경우도 있다.

또한 플래시의 발전은 지식에 목말라 스스로 지혜를 얻으려 노력했던 선배들의 도움으로 커왔다고 나는 믿고 있기 때문이기도 하다. 위에서 이야기 한 내용은 본인 또한 노력하는 부분이고 이 포스트를 읽는 분들도 지혜를 얻기 위해 노력하다보면 좋은 코드를 생산할 수 있을 것이라 믿는다.



    

설정

트랙백

댓글

ActionScript는 프로그래밍 언어가 아니다.

Programming/Etc 2007. 11. 4. 19:21
인터렉션 UI개발과 그 목적을 위해서 사용하고 있는 ActionScript는 프로그래밍 언어가 아니다. 내 천직으로 생각하고 지금 하고 있는 업무가 그것이지만 ActionScript를 프로그래밍 언어적 차원에서 접근 하는 것에는 한계가 있다고 생각한다.

플래시라는 것은 기술적인 환경이나 배경지식 보다는 아이디어가 중요하다. 이러한 아이디어는 다양한 결과물을 만들어 낼 수 있다. 물론 그 아이디어는 어느 정도의 배경 지식이 있어야 하겠지만 없어도 무방하다. 가령 내가 어떤 비주얼을 보고 머리 속에서 그린 인터렉션을 구현하기 위해 작업에 착수 했다고 하자, 내가 필요로 하는 편리한 기능이 플래시 안에 내제되어 있지 않더라도 자신이 가지고 있는 지식 범위 안에서 찾을 수 있는 길은 있을 것이다. 이것이 플래시를 즐기는 사람들의 즐거움이자 정석이다.

플래시로 작업을 하다 보면 자신도 이 방법이 정석인지 아닌지 알 수 없는 경우가 있다. 그래서 작업이 끝나고도 뒤 끝이 어수선한 경우가 종종 발생하게 되는데, 어찌보면 플래시 작업에서의 정석은 없을 수도 있다. 이미 플래시에 탑재 되어 있는 내장 클래스를 모르더라도 그와 유사한 기능을 하는 것을 만들어 낼 수도 있고 전혀 다른 방법으로 문제를 풀어 낼 수도 있다.

그 과정에서 파생된 또 다른 아이디어는 다시 싹을 틔우고 꽃이 피어나는 결과로 진행 될 수도 있다. 하지만 플래시를 프로그래밍 언어적 개발 마인드로 접근을 하다 보면 정석만이 있으며 그것이 유일한 방법이라는 확신에 사로잡혀서 크리에이티브한 창의를 발휘할 수 있는 여지를 묵살하게 된다.

나는 작업을 하면서 엉뚱하며, 디자인 표현에 맞지 않는 결과물들도 많이 만들어 낸다. 남들 보다 같은 결과물을 얻기 까지 시간이 많이 걸리지만 작업 과정에서 떼 묻은 코드들은 또 다른 나의 아이디어로 언젠가는 도움이 되는 것 같다.

현재 플래시를 공부하고 관심을 갖고 있는 분들은 이러한 즐거움을 느꼈으면 좋겠다. 설계, 개발이라는 단어보다는 디자인이라는 단어가 어울리는 플래시는 프로그래밍 언어가 아니라 크리에이티브 언어이다.

    

설정

트랙백

댓글

[AS3] 웹페이지에 코드를 이쁘게 보여주는 AScodeViewer

Project/Programming 2007. 9. 13. 06:43

AScodeViewer 1.0 Beta

개인적으로 플래시 코드를 웹상에 올릴 때 하이라이트를 적용하여 편하게 보기 위해서 만들었다. 만들다 보니 플래시 코드뿐만 아니라 다른 코드의 경우도 xml 파일을 수정하는 것으로 적용할 수 있다.

기능적인 요소
기능적인 요소로는 swf에 외부 변수값(코드파일url, 라이라이트 xml, 스타일 xml, selectable) 값을 전달하여 불러들인 xml과 코드, 그리고 코드를 선택 및 복사가 가능하도록 할 것인지를 지정하는 sable 값을 전달하게 된다. 이로서 AScodeViewer.swf 파일에서 코드 하이라이트 및 스타일이 적용된 AScodeViewer를 볼 수 있다.

외부 변수 값을 전달할 때 주의할 점은 크로스도메인 정책에 따라 도메인이 다른 url 경로에 있는 코드나 xml를 불러올 수 없다는 것이다. AScodeViewer.swf 파일이 있는 위치와 같은 도메인 상에 있는 파일을 불러들여야 한다.


사용성에 따른 기능적인 요소로는 오른쪽 하단에 보면 FullScreen mode로 전환할 수 있는 버튼이 있다. 클릭을 할 경우 전체 풀사이즈 화면으로 코드를 볼 수 있는 기능이다.

사용 방법
AScodeViewer을 사용하는 방법은 아래 제공하는 파일을 다운 받아서 사용하고자 하는 계정에 업로드를 하고 아래와 같이 코드를 웹페이지 html상에 넣어주면 된다.

<object width="700" height="400" >
<param name="bgcolor" value="#242424" />
<param name="allowFullScreen" value="true" />
<param name="FlashVars" value="code=TintColor.as&format=as3.xml&style=style_dark.xml&sable=true" />
<param name="movie" value="AScodeViewer.swf" />
<embed src=" AScodeViewer.swf"  flashvars="code=TintColor.as&format=as3.xml&style=style_dark.xml&sable=true" type="application/x-shockwave-flash" allowFullScreen="true" width="700" height="400" bgcolor="#242424" /></embed>
</object>

위에서 보이는 바와 같이 FlashVar에 해당하는 부분의 변수들에 각각의 파일 및 설정 값을 넣어주면 된다. 위 코드의 경우는 swf파일이 있는 같은 폴더 안에 code, format, style 에 해당하는 파일들이 있는 것으로 가정한 것이다.

하이라이트 및 스킨 적용 방법
코드 하이라이트는 플래시 스크립트 에디터로 많이 사용하고 있는 FlashDevelop 프로그램의 language폴더에 있는 xml 데이터를 그대로 사용하였다. FlashDevelop 프로그램을 사용하는 분은 아래 경로에서 사용하고 있는 하이라이트 xml 파일을 취득할 수 있다.

C:\Program Files\FlashDevelop\FirstRun\Settings\Languages

위 경로에서 보면 AS3.xml, AS2.xml, Jscript.xml 등을 볼 수 있는데 AScodeViewer 1.0 Beta에서 지원하는 xml 형태는 AS3.xml, AS2.xml, Jscript.xml, HaXe.xml 이다. 다른 C++ 이나 Java 등의 코드 하이라이트를 사용할 경우에는 위 4개의 파일 중에 아무 파일이나 열어서 해당 언어에서 사용하는 하이라이트 단어들을 등록하고 다른 이름으로 저장하여 사용하면 된다.

AScodeViewer의 스킨 적용은 제공하는 Style_dark.xml 파일이나 style_light.xml 파일을 열어서 해당 부분의 RGB 색상을 변경하여 스킨을 바꿀 수 있다. 아래 이미지를 보면 style.xml 파일에서 지정할 수 있는 부분들을 표시해 놓았다.

사용자 삽입 이미지


아래는 파일로 제공하는 두 가지 스킨을 적용한 예이다. Style_dark.xml 이나 style_light.xml 파일을 수정하여 원하는 색상을 만들어 낼 수 있기 때문에 적용하는 페이지상의 디자인에 맞게 수정하여 사용하면 된다.
왼쪽은 style_dark.xml을 적용한 예이고 오른쪽은 style_light.xml을 적용한 예이다. 왼쪽의 경우 코드 선택이 안되도록 sable = false 값을 적용하였다.


아래 파일을 다운로드 하여 위에서 설명한 대로 원하는 페이지에 적용하면 된다. 블로그 서비스에서는 “외부 멀티미디”어 등에서 youtube 동영상을 임베드 하는 형태로 적용하면 된다. 주의할 점은 위에서 언급한 바와 같이 AScodeViewer.swf 파일이 있는 곳과 불러오는 파일들의 도메인이 같아야 한다는 것이다(같은 도메인 내의 폴더 구분은 상관없다.)

앞으로 버전업의 경우도 FlashDevelop의 기능을 적용할 생각이다. 시간이 허락하는 대로 업데이트 버전을 올려 놓도록 하겠다. 사용하다가 문제점이 있거나 버그 발견 시에는 아래에 댓글로 남겨주시면 많은 도움이 될 것 같다.


AScodeViewer1_0Beta.zip

    

설정

트랙백

댓글

[AS3] 1행짜리 Tetris

Programming/ActionScript 3.0 2007. 8. 6. 08:47

[Flash] http://jasu.tistory.com/attachment/cfile9.uf@244FC33F58802128306F6E.swf


게임방법 : [H][L]왼쪽과 오른쪽, [J][K] 회전, [SPACE]는 떨어뜨리기.
게임 화면을 클릭해서 키보드 포커스를 줄 필요가 있다.


* import *를 사용함.
* 정수명이나 이벤트명은 직접적으로 쓰면 import를 생략.
* for문이나 if 의 생략 할 수 있다 {}은 생략.
* const 보다 var를 씀.
* with 사용할 수 있는 곳은 사용.
* true , false 보다 1 ,0
* switch ~case 보다 함수 테이블을 사용.
* new Array() 보다 []
* drawRect()의 endFill()를 생략.
* 인스턴스 변수를 1 행으로 전부 선언하면 var 를 줄일 수 있다.
* 로컬 변수 를 인스턴스 변수로 옮기면 var를 삭제할 수 있다.
* 클래스명과 constructor 이외의 public ,private는 삭제.
* 배열 의 첨자에 사용한 int 형 변수 이외의 「: 형명」은 삭제.
* 변수 이름이나 함수 이름을 1 문자로.
* 개행은 모두 삭제, 연속하는 공백은 하나의 공백으로.
* 연산자 ,{ ,} ,( ,) ,; , 의 전후의 공백은 삭제.
* 「} 」의 직전의 「; 」는 삭제.

이러한 방법으로 외국의 한 ASer가 1872 문자(1.83kb)의 테트리스를 만들어 놓은 것이 있어 올려 놓는다. 0x000000과 같은 것을 0으로 할 수 있겠지만 이미 질려서 여기까지 한다는 제작자의 설명이 있었다. 테트리스는 게임 프로그래밍에 있어서 기초적인 것이지만 프로그래밍의 중요한 구조적 성격을 가지고 있다고 생각된다.

예전 DOS시절에 C언어로 헥사와 테스트리스를 접목한 게임을 만든 적이 있었는데 그때 만들었던 게임의 룰은 테트리스 처럼 가로 행이 채워졌을 때도 삭제하고 대각선과 세로에서도 같은 색이 연속으로 5개 있을 때도 삭제하게 했던 기억이 난다. 도스 시절이었기 때문에 아마도 5.25인치 디스크에 보관을 하다가 잃어버린 것 같다.

Assembly 언어는 대학교 다닐 때 가장 골치 아픈 녀석이었다. 직접 기계어로 작성한다는 매력과 그 속도 면에서 반할만한 언어이기는 했지만 그것을 이해하기에는 나의 두뇌가 너무 아날로그적이었던 기억이다. C언어를 배울 당시에도 point(*) 개념으로 point -> point 까지만 들어가도 그때부터 뇌세포가 사경을 헤맸으니…

그러고 보면 ActionScript는 참 친절한 언어라는 생각이 든다… 나 또한 ActionScript를 향해 좀더 친절해 져야겠다는 생각이 든다.. 쿠쿠



Tetris.as 소스

package{import flash.display.*;import flash.text.*;public class Tetris extends Sprite{var W=10,H=20,T=16,C=[0x000000,0x00FFFF,0xFFFF00,0x22FF22,0xFF2222,0x4444FF,0xFF8844,0xFF22FF],P=[[[1,1,1,1]],[[0,2,0],[2,2,2]],[[3,3,0],[0,3,3]],[[0,4,4],[4,4,0]],[[5,5],[5,0],[5,0]],[[6,6],[0,6],[0,6]],[[7,7],[7,7]]],s=[30,20,10,5],b=[],p,r,t=new TextField(),f=[],l=0,c=0,g,j:int,i:int,v:int,u:int;public function Tetris(){t.x=W*T;t.autoSize="left";t.text="Next:";addChild(t);for(j=0;j<H;++j){b[j]=[];for(i=0;i<W;++i)b[j][i]=0}f[72]=function(){v-=w(v-1,u,p)};f[74]=function(){m(1)};f[75]=function(){m(0)};f[76]=function(){v+=w(v+1,u,p)};f[32]=function(){d();h()};stage.addEventListener("keyDown",function(e){if(f[e.keyCode]){f[e.keyCode]();n()}});h();h();addEventListener("enterFrame",function(e){if(--c<0){c=s[int(l/10)];if(w(v,u+1,p)){++u;n()}else{d();h()}}})}function m(o){var q=new Array(p[0].length);for(j=0;j<q.length;++j)q[j]=[];for(j=0;j<p.length;++j)for(i=0;i<q.length;++i)if(o)q[i][p.length-1-j]=p[j][i];else q[q.length-1-i][j]=p[j][i];if(w(v,u,q))p=q}function n(){with(graphics){clear();for(j=0;j<H;++j)for(i=0;i<W;++i){g=0;if(u<=j&&j<(u+p.length)&&v<=i&&i<(v+p[0].length))g=p[j-u][i-v];if(!g)g=b[j][i];beginFill(C[g]);drawRect(i*T,j*T,T,T)}for(j=0;j<r.length;++j)for(i=0;i<r[j].length;++i){beginFill(C[r[j][i]]);drawRect((i+W+1)*T,(j+2)*T,T,T)}}}function w(x:int,y:int,p){for(j=0;j<p.length;++j){if(0>(y+j)||(y+j)>=H)return 0;for(i=0;i<p[j].length;++i){if(0>(x+i)||(x+i)>=W)return 0;if(p[j][i]&&b[y+j][x+i])return 0}}return 1}function d(){for(;w(v,u+1,p);u++);for(j=0;j<p.length;++j)for(i=0;i<p[j].length;++i)if(p[j][i])b[u+j][v+i]=p[j][i];for(j=0;j<H;++j)if(b[j].indexOf(0)<0){b.splice(j,1);b.unshift([]);for(i=0;i<W;++i)b[0][i]=0}l++;if(l/10>=s.length)l=0}function h(){p=r;if(p){v=(W-p[0].length)/2;u=0;if(!w(v,u,p))t.text="GAME OVER"}r=P[int(Math.random()*P.length)]}}}

*위 소스를 Tetris.as 파일로 생성하여 Flash CS3에서 Document class에 등록하고 퍼블리시 하면 된다.

    

설정

트랙백

댓글

Flickr Searcher 1.8 업로드

Project/Programming 2007. 5. 13. 13:49

사용자 삽입 이미지


사용자 삽입 이미지

사용자 삽입 이미지


Flickr의 Open API를 이용한 사진 검색 어플리케이션 'FlickrSearcher'
version 1.8

http://dicaland.cafe24.com/flickr/FlickrSearcher1_8.swf
====================================================================================================

FlickrSearcher1_8.exe

Version 1.8  Release date : 2007/05/13
Change log
1. photo 썸네일 클릭시에 나타나는 왼쪽 중앙에 있는 information 버튼의 가독성을 위하여 색 변경
2. Search history 기능 추가 : 특정 모드(tags, name, email, nsid)를 통해 검색한 history를 저장할 수 있도록 함.
(최근 검색한 검색어와 페이지 수를 통해서 되돌아 갈 수 있도록 함)
====================================================================================================


    

설정

트랙백

댓글

Flickr Searcher 1.7 업로드

Project/Programming 2007. 5. 10. 11:45
사용자 삽입 이미지
사용자 삽입 이미지
사용자 삽입 이미지
사용자 삽입 이미지

Flickr의 Open API를 이용한 사진 검색 어플리케이션 'FlickrSearcher'
version 1.7

====================================================================================================
Version 1.7  Release date : 2007/05/10
Change log
1. 1.6에서 'VIEW AUTHOR PHOTOS'로 검색을 할때 search mode 'name'으로 이동하면서 textField 길이가 불규칙하게 변했던 버그 수정.
2. 정보 TextField를 선택가능 하도록 변경.
3. Photo Information에서 이미지의 exif 정보를 볼 수 있도록 기능 추가.
====================================================================================================
    

설정

트랙백

댓글

Flickr의 Open API를 이용한 사진 검색 어플리케이션

Project/Programming 2007. 5. 9. 09:23



Flickr의 Open API를 이용한 사진 검색 어플리케이션 'FlickrSearcher'


사용자 삽입 이미지
사용자 삽입 이미지

====================================================================================================
Version 1.6  Release date : 2007/05/08
Change log
1.    search mode를 tag, name, email, nsid와 같이 4개 모드로 검색 가능하도록 기능 추가.
2.    tag로 검색할 경우에는 ‘,’ 구분자를 통해 복수 tag 검색 가능 추가. ex) quality, blue, yellow
3.    author & photo information 확인 가능.
4.    author의 정보에 있는 “VIEW AUTHOR PHOTOS” 버튼을 통해 author의 사진들을 볼 수 있는 기능 추가.
5.    photo information에서 이미지의 크기별로 view가 가능하며 해당 이미지를 download하는 기능 추가.
6.    license 적용(크리에이티브 커먼즈의 저작권 규약 표시)
7.    author의 icon 이미지 표시(이미지에 대한 모든 정보를 사전에 습득할 시, 속도 문제를 감안하여 해당 이미지를 클릭한 이후 적용됨).
8.    편의성을 고려하여 1.0버전에 있던 fullscreen 모드 삭제,
9.    기타 1.0버전에 없는 다수 기능 추가.
====================================================================================================
Version 1.0  Release date : 2007/05/03
Change log
최신 버전 업데이트시 자동 알림 기능 추가 ====================================================================================================

    

설정

트랙백

댓글

trace 예찬론

Programming/Etc 2007. 3. 9. 00:48
action script를 코딩하다 보면 중간 중간 내가 작성하는 코드가 syntax error가 없는지 수시로 체크를 하게 되는데 그 단위는 코드 100줄을 넘지 못한다. 코딩을 하면서 중간에 딴 생각을 하다가 엉뚱한 방향으로 흐르는 경우도 있고 손가락의 강약 조절과 위치 파악을 제대로 하지 못한 손가락의 잘못도 있다.(결코 내 잘못 아니란다 쿠쿠)

대부분 syntax error로 수정이 가능한 것들이나 가끔은 overflow의 문제로 한참을 헤매는 경우도 종종 있다. Overflow의 경우는 컴파일러가 정확히 어느 위치에서 overflow가 발생했는지를 알려주지 않는 과계로 중간 체크를 하지 않고 코드를 길게 늘리다 보면 쉽게 문제가 되는 부분을 찾기가 어려울 경우가 있다.

더군다나 overflow가 발생했다는(플래시는 255번 이상 스택이 쌓이면 overflow가 발생한다.) 것을 output 패널 창에 보여주면 그나마 다행이지만 컴파일러가 한참을 계산하고서야 문제를 알려줄 때면 가뜩이나 바쁜 와중에 뒷골이 땡긴다.

이런 문제는 반복문에서의 조건문이 무한하거나 undefined일 경우 흔히 발생하게 된다. 가끔 사이트를 돌아다니다 보면 이런 문제로 브라우저를 종료해야 되는 경우가 종종 보이는데 외부에서 xml 데이터를 받아와서 처리해야하는 구문이 있다면 xml이 로드된 시점에서 처리해야 하는데 그것을 간과한 듯 하다.

이런 문제를 미연에 방지하기 위해서는 수시로 단위별로 체크를 해야 한다. 어느 언어나 기본적으로 특정 값을 확인 할 수 있도록 print 내장 메소드를 제공하는데 플래시도 trace라는 구문을 제공한다. 언제나 감사함을 느끼는 놈이다.

개인적으로 생각해 볼 때 논리적인 error를 잡아내는 데는 trace 하나면 충분하다. 중간 중간 확인을 하고 진행한 코드라고 했을 때 문제가 발생하지 않은 시점과 문제가 발생한 시점을 파악하고 그 문제가 발생했던 부분을 훑어봐도 어디가 문제인지를 모를 때는 최초 문제가 발생한 부분의 상위부터 단계별로 trace로 문제가 될만한 변수들을 확인하고 넘어가면 어느 시점에서는 문제의 변수를 잡아낼 수 있다.

가끔 프로그래밍에 발을 들여놓은 분들을 보면 이러한 확인 절차 없이 무턱대고 코드를 작성하고 한꺼번에 컴파일을 하는 경향이 있는데, 이럴 경우에는 문제가 발생할 만한 곳을 찾기란 쉽지가 않다. 문제가 없는 부분과 문제가 발생한 부분을 쉽게 파악하지 못하기 때문이다.

물론 oop 개념의 프로그래밍을 한다면 이러한 문제를 파악하는데도 많은 도움을 받게 된다. 하나의 독립된 class로 문제를 최대한 잘게 쪼개놓으면 문제가 된 class를 쉽게 알아 낼 수가 있기 때문이다. 플래시 액션스크립트도 2.0으로 넘어오면서 어느 정도 oop개념을 도입했지만 실무에서 완벽한 oop 프로그래밍을 하기에는 쉽지가 않다. Oop 개념을 완전하게 이해하지 못한 이유도 있지만 큰 프로젝트가 아닌 경우에는 사실 그러한 개발 노력보다 시간이 더 중요한 경우가 허다하게 발생하기 때문이기도 하다.

그래서 나 또한 실무에서는 oop반 막무가내 코드 반을 섞어서 사용하고 있고 개인적인 놀이나 작업을 할 때는 되도록 oop에 신경을 쓴다. 물론 개인적인 놀이에서 그러한 것을 하다 보면 실무의 실질적인 프로젝트에서도 기억을 되살려 사용하기도 하니 그러한 놀이를 통해서 점점 oop의 필요성과 유용성을 인정하게 된다.

이야기를 하다 보니 이야기가 엉뚱하게 흐르고 있다. 이쯤에서 trace 한번 찍어보자.

var 엉뚱한변수:String = “#@$#@$@#@$#”;
trace(“엉뚱하게 이야기가 흐른 변수 = ” + 엉뚱한변수);

액션 스크립트를 떠나 존재하는 모든 프로그래밍 언어에서 print 구문이 없었다면 아마도 지금도 어셈블리어로 코딩을 하고 있을지도 모르겠다. 생각해 보니 프로그래밍도 커뮤니케이션이다.

trace(“나 여깄어…너 거기있니”);
trace(“나 여기있고 너 거기있구나”);

trace를 사랑합시다. ^^
    

설정

트랙백

댓글

ImagePuzzle Game Project

Project/Programming 2007. 3. 3. 02:13
*  대학교 시절 졸업년도에 만들었던 게임이다. 퍼즐 게임에 대한 어떠한 자료도 없이 그냥 퍼즐게임을 해보고 초등학교 문방구에서 파는 퍼즐 놀이기구(?!)를 사다가 로직을 어떻게 설계할 것인가를 고민하며 만들었던 것이라 많은 애착이 있는 자료다.

어 플리케이션으로서 그럴듯 하게 디자인도 해서 넣어보고 게임의 순위도 사용자 컴퓨터에 저장할 수 있도록 하였고, 무엇보다도 이미지는 프로그램상에 존재하는 것이 아니라 사용자 컴퓨터에서 이미지를 검색하여 그 이미지를 사용하여 게임을 진행할 수 있도록 한 점이 특징이다, 이때 이미지만을 축출하여 리스트로 표현하는 로직을 구현할 때 재귀함수를 사용하여 하위 디렉토리를 탐색하는 방식을 사용했는데 그때 아마도 재귀함수의 짧은 코드로서의 단순성에 반해 엄청난 결과를 창출한다는 것을 알게 되었는데 속도 면에서는 영 마음에 들지 않았던 기억이다.

아무튼 이 게임 하나 만든다고 학과 컴퓨터실에서 알바를 하며 밤 늦게까지 혼자만의 재미에 푹 빠져 살았던 시절이 그립기도 하다. 물론 지금도 그런 놀이속에 살고는 있지만...

뭐.. 누가 그랬던가 돈이 있어도 지하철을 타는 것과 돈이 없어서 지하철을 타는 것은 모두 지하철을 탄다는 것은 같으나 그 마음은 다르다고.... 아마도 그 재미는 비슷하나 그때의 젊음속에서 느꼈던 것과는 다른 것 같은 생각이 든다. 아무래도 돈과 관련이 있는 것과 나이와 관련이 있는, 이 두가지 때문이 아닐까...쿠쿠

사용자 삽입 이미지

invalid-file

프로젝트 프리젠테이션


invalid-file

게임 인스톨 파일


위 프로그램을 실행하기 위해서는 JDK 1.2이상 버전이 설치되어 있어야 합니다.








    

설정

트랙백

댓글

Artificial Intelligence(Max-Min CRI of Fuzzy System)

Project/Programming 2007. 3. 3. 01:44
구현시 느낌점

※ 이 프로그램에서는 결론부에서 6개의 버튼을 일일이 CLICK해 봄으로써 해당 조건부의 Y값으로 결론부의 범위를 자르게 하였습니다. 이유는 처음에는 조건부의 6개의 버튼중, 또는 비 퍼지값을 임의로 넣었을 때 입력값에 의하여 조건부에 그려짐과 동시에 결론부에도 일괄적인 처리를 통해서 그림을 뿌려지게 하려 하였으나 Paint 메소드가 컴퓨터 내에서 스레드의 형태로 화면에 그림을 뿌려주기 때문에 순차적인 접근으로 일괄적으로 결론부의 그림을 화면에 모두 뿌릴수 없었습니다. 그래서 다소 번거롭지만 각각의 조건부에 해당되는 결론부를 처리할 때 해당되는 결론부 버튼을 클릭함으로써 값을 얻게 하였습니다.

※ 결론부의 잘려진 그림을 그릴 때 직선의 방정식을 이용하여 각각의 X 또는 Y 좌표의 포인트를 계산하려 하였으나 컴퓨터 화면상의 픽셀은 세로, 즉 Y 픽셀은 위로 갈수록 값이 작아지기 때문에 직선의 방정식을 그대로 이용하면 원하는 픽셀의 결과를 얻을 수 없었습니다. 그래서 X를 구하기 위한 식 x=( ((x2-x1)/(y2-y1))*(y-y1) )+x1 의 식을 변형하여 y2와 y1의 위치를 변경하여 시도를 해 보았으나 그것 역시도 주어진 y값에 의해서 원하는 x픽셀을 찾지 못하였습니다. 이 과제에서 주어진 조건은 극히 제한적이기 때문에 y값이 0.25,0.5, 0.75, 1.0을 갖을 때를 switch문을 이용해서 x값을 찾도록 하였습니다.

※ 잘려진 결론부의 그림들을 모두 합하여 y좌표의 max값을 통한 x좌표의 회전값을 이용해서 무게중심을 구해야 합니다만 잘려진 각각의 도형들의 선들이 만나는 지점을 찾는 것이 어려웠습니다. 처음부터 직선의 방정식을 이용해서 잘려진 부분의 x값을 찾을 수 있었다면 약간의 조건문과 반복문으로 max 값만의 line을 축출할 수 있었을 텐데 저는 그렇게 하지 못하여 각각의 잘려진 부분의 무게중심들을 구하여 모두를 더한 값을 잘려진 부분이 있는 결론부의 수로 나눈 값을 최종 결과값으로 출력하도록 하였습니다.

※ Max-Min CRI 알고리즘의 개념은 극히 단순하지만 그것을 프로그램으로 구현하는 과정은 어려웠습니다. 특히 수학의 직선의 방정식과 컴퓨터의 픽셀을 연결하는데 연구가 필요하다고 느꼈습니다.




* 대학교 시절 인공지능 시간에 만들었던 퍼지 알고리즘 객체지향 언어의 장점을 활용하지 못하고 무작정 손가락 가는대로 만들었던 것 같다.
사용자 삽입 이미지
<초기 실행시 화면>

사용자 삽입 이미지
<조건부 2의 버튼을 눌렀을 때의 화면>


사용자 삽입 이미지
<비퍼지값 3을 입력 하고 Setting을 누르고 결론부 1부터 6까지 누른 상태 화면>


사용자 삽입 이미지
< Max-Min Result 버튼을 누른 상태 화면>



사용자 삽입 이미지




    

설정

트랙백

댓글

Multipayer Perceptron(EBP 알고리즘 구현 프로그램)

Project/Programming 2007. 3. 3. 01:25
구현 과정
프 로그램 구현 과정에서 처음에는 5 by 5픽셀로 설정을 하여 패턴을 입력한 결과 숫자들이 서로 비슷한 픽셀 안에서 학습을 하기 때문에 학습율이 저조한 편이었습니다. 그래서 픽셀의 수를 7 by 7로 하여 구현해 보았습니다. 앞의 5 by 5 픽셀에 비해서는 좀더 나은 학습율을 보였지만 이것 마저도 학습율은 만족스럽지 못했습니다. 그래서 다음에는 픽셀의 수를 7 by 8로 가로 세로의 픽셀수를 다르게 하여 총 입력 노드수를 56개로 패턴을 결정하고 노이즈 패턴을 입력한 결과 앞의 픽셀보다는 나은 결과치를 얻을 수 있었습니다.
 이 과정에서 한가지 알수 있던 것은 10개의 패턴들이 1로 세팅된 수가 많으면 많은 수록 학습율은 떨어졌으며 0인 부분 즉 패턴에서 색깔이 칠해지지 않은 부분이 많은 10개의 패턴의 학습율은 크게 향상되는 것을 알수 있었습니다.
 그리고 에타의 값과 초기의 가중치값의 변경에서도 학습율이 변동되는 사실을 입증할 수 있었습니다.

프로그램 설명
 EBP 알고리즘으로 구현한 제 프로그램은 패턴의 픽셀 수(가로, 세로)와 히든 노드의 수,에타값, 웨이트을 프로그램 구동 중에 수정할 수 있도록 하였으며 10개의 패턴의 픽셀을 마우스로 클릭하여 임의의 패턴들을 만들어 노이즈패턴을 입력 결과를 확인할수 있도록 하였습니다.

프로그램 버그, 및 문제점
1.)이 프로그램의 입력 노드는 총 56개인대 반하여 패턴의 수가 10개이기 때문에 입력노드의 15% 벗어나는 패턴들을 학습하였기 때문에 학습율이 보다 작은 패턴으로 학습하는 것보다는 저조할 수 있습니다.

2.> 프로그램의 패턴의 픽셀 수를 프로그램 구동중에 수정할 수 있도록 하였으나 자바 언어에서는 배열의 값을 초기 세팅할 때 초기 선언 부분에서만 가능하여 7 by 8의 배열 범위를 넘는 필셀의 수를 입력하였을 경우에는 ArrayIndexOutOfBoundsException에러를 냅니다. 그래서 초기 배열의 값을 넣을 때 뒤에 20개의 공간을 추가하여 사용자가 7 by 8이상의(가로*세로 20이하) 픽셀을 입력하였을 경우에도 프로그램에 에러가 나오지 않도록 보완하였습니다.

3.> EBP 알고리즘의 학습의 끝을 모든 가중치가 0에 가깝거나 가중치의 차이가 거의 없을 때까지 반복 학습을 해야하는데 반하여 제 프로그램의 학습의 끝은 카운트로 설정을 하였습니다. 픽셀의 수를 고정했을 경우에는 차이의 최소 값을 셋팅할 수 있지만 사용자가 임의로 픽셀의 수를 셋팅하게 만들었기 때문에 그 기준에 문제점이 있었습니다.


* 대학교시절 인공지능 수업을 들으면서 실습 과제로 제작했던 EBP 알고리즘 프로그램.
사용자 삽입 이미지

사용자 삽입 이미지

사용자 삽입 이미지



 

    

설정

트랙백

댓글

무결점에 도전하는 아름다운 사람들의 이야기

Programming/Etc 2007. 2. 27. 02:53
 지금의 고등학교에서는 문과와 이과를 구분하여 수업을 듣고 있는지 모르겠으나 나의 고등학교 시절에는 문과와 이과를 나누어 ‘가벼운 수학’과 ‘깊이 있는 수학’으로 구분하여 수업을 들었던 기억이다. 수학이 싫다는 단순한 생각에서 이과가 아닌 문과를 지망하게 되었지만 수학은 여전히 나의 기대에 부합하지 않고 문과에서 날 괴롭혔다.
 
 그러했던 나의 선택에 그나마 스스로에게 최선을 다 하겠다며 수학 시간에 학내 도서관에서 빌린 소설책을 선생님 몰래 보면서 스스로를 위한 하곤 했다…^^; 지금은 직장생활로 인해서 전문서적을 보는 것으로 책 읽기를 대신하고 있으니 평소에 소설을 책 한 권 접하기가 쉬운 일이 아니다.
 
 그래서 얼마동안 이 두 가지 토끼(전문 서적 & 에세이 & 소설)을 잡을 욕심으로 가벼운 프로그래밍 관련 서적을 구입하여 읽었다. 읽다 보니 임백준이라는 저자의 책들을 읽게 되었는데 그 중 4권을 소개해 볼까 한다.
 
 먼저 저자 임백준은 삼성 SDS와 미국 루슨트 테크놀로지에서 소프트웨어 엔지니어로 근무했으며 월간 마이크로소프트웨어에 컴퓨터 칼럼을 연재했고 인터넷 신문 “프레시안”에 시사 칼럼을 쓰고 있는 저자다.
 책은 초판발행일자 기준으로 정리 하였다.

1. 행복한 프로그래밍 – 컴퓨터 프로그래밍 미학 오디세이
사용자 삽입 이미지

: 책 제목에 ‘프로그래밍’이라는 말이 들어가면 사람들은 대개 기술적이거나 전문적인 내용을 다루는 책을 떠올리기 마련이다. 하지만 ‘행복한 프로그래밍’이라는 제목에서 필자가 중점을 둔 부분은 “프로그래밍”이라는 명사가 아니라 “행복한”이라는 형용사다. 다시 말해서 이 책은 특정한 기술이나 전공 지식을 담은 책이 아니라 컴퓨터 프로그래밍 속에 들어 있는 미학을 전달하려는 소프트한 얘기를 담고 있는 책이다. –서문중에서
해바라기 씨앗의 배열을 닮은 피보나치 수열은 매우 아름답지만, 그것을 컴퓨터 프로그램으로 옮기는 것이 별로 어려운 일이 아니라는 사실은 나중에야 알게 됐다. 그 때에는 화면에 나타나는 숫자들을 바라보는 것만으로도 황홀감을 느낄 지경이었다 – “영혼을 녹여서 만드는 아름다운 공식” 중에서…



2. 누워서 읽는 알고리즘 – 생각하는 방법을 알려주는 알고리즘 이야기
사용자 삽입 이미지
: 이 책은 어렵고 복잡한 알고리즘을 ‘쉽게 풀어서’ 설명한 책이 아니다. 오히려 맛있는 읽을거리를 만들기 위해서 알고리즘과 같은 기술적인 내용을 ‘동원한’ 책이다. 나는 새로운 알고리즘 이론을 소개하는 것도, 독자들에게 알고리즘을 ‘강의’ 하는 것도 아니다. 즉 ‘공부’와는 아무런 상관이 없다. 나는 실전 프로그래밍을 업으로 삼고 있는 사람들과 함께 가볍게 ‘수다’를 떨면서 우리가 매일 수행하는 ‘일’이 얼마나 재미있는지, 얼마나 아름다운지 그리고 얼마나 창조적인지 확인하고 싶었다 – 서문 중에서
짧은 시간이 흐르고, 화면에 나타나는 결과를 보았을 때 필자의 가슴은 그만 철렁 내려앉고 말았다. 화면에 나타난 것은 정상적인 페이지가 아니라 페이지 수가 이미 최대 값에 도달했으므로 더 이상의 페이지를 열 수 없다는 오류 메시지였다. 모든 경우에 대해서 완벽하게 동작하는 것처럼 보였던 알고리즘안에 조용히 숨어 있던 버그가 드디어 모습을 들어낸 순간이었다 – ‘재즈로 여는 아침의 향기’ 중에서



3. 나는 프로그래머다 – 무결점에 도전하는 아름다운 사람들의 이야기
사용자 삽입 이미지
: 인생에 있어서 도전이란 결코 입맛에 딱 맞는 방식으로 찾아오지 않는다. 그것은 언제나 두 발을 전부 땅에서 떼서 허공에 몸을 완전히 맡겨야 하는, 따라서 상당한 불편함과 두려움을 수반하는 방식으로 찾아온다. 어렵지만 마음에 쏙 드는 일자리를 만났을 때, 어렵지만 풀어 보고 싶은 문제를 만났을 때, 어렵지만 한 번 걸어 보고 싶은 길을 만났을 때, 어렵지만 한 번쯤 말을 꼭 걸어 보고 싶은 이성을 만났을 때, 필요한 것은 앞뒤를 재고 따지는 ‘계산’이 아니라 최선을 다해서 허공에 몸을 맡기는 ‘용기’다. – 서문 중에서
이 책은 IT 각 분야에서 종사하는 7분이 모여서 만든 책이다. 김용준, 김종호, 원은희, 유영창, 이춘식, 임백준, 허광남, 임백준을 제외한 분들은 책을 많이 써보지 않은 분들이라 그런지 문장이나 형식이 자연스럽지 못하다는 느낌이 많이 들었던 것 같다. 임백준의 글이 가장 읽기 편했다. (길들여 진 것일까..;;)





4. 임백준의 소프트웨어 산책 – 소프트웨어에 대한 새로운 시선 그리고 통찰력
사용자 삽입 이미지
: 이 책은 공부를 목적으로 하는 책이 아니다. 프로그래밍과 조금이라도 관련이 있는 사람이라면 이 책을 한 손에 들고 다른 한 속으로는 새우깡이라도 먹으면서 마치 소설책처럼 읽을 수 있기를 바라면서 글을 썼기 때문이다. 사실 이 책은 소설을 담고 있다는 점에서 실제로 ‘소설책’이기도 하다. 깊이와 짜임새를 향한 결심은 지켜내지 못했지만 독자들이 이 책을 재미있게 읽을 수 있기를 바라는 마음에서 아예 소설을 한 편 쓰기도 했다. 말하자면 프로그래머가 프로그래머를 위해서 프로그래밍을 주제로 쓴 소설인데, 책의 뒤에 실려 있다 – 서문중에서
“어려운 문제를 드디어 풀어냈다는 성급한 기대가 K씨의 심장을 빠르게 뛰게 만들었다. 사실 프로그래머가 이와 같은 ‘유레카’의 순간에 느끼는 순백의 열정은 사랑에 빠진 청춘의 감격과 별로 다를 것이 없다. 적어도 그 순간만큼은 세상의 모든 사물이 그 자리에서 동작을 멈추고 시간이 정지한다. – 프로그래머 K씨의 하루 중에서




 이렇게 4권의 책을 읽게 되었다. 임백준은 프로그래밍에 숨어 있는 미학을 발견하고 프로그래밍을 통해서 세상을 이해하려는 노력을 하고 있다. 현재는 뉴욕 월스트리트에서 금융 소프트웨어를 개발하고 있다고 한다. 책의 서문이나 내용을 보면 알 수 있겠으나 대부분의 책들은 프로그래밍이나 컴퓨터 언어에 대한 해박한 지식을 요구하거나 강요하지 않는다. 그렇다고 프로그래밍과 전혀 관련이 없는 사람들이 읽기에는 공감이 가는 성격의 글이 아니기에 권하고 싶은 마음은 없다.
 
 작년 Macromedia conference MAX 2005 KOREA에서 스피커로 나왔던 Jared Tarbell은  “프로그래밍은 시와 같다”, “프로그래밍은 아트다” 와 같은 이야기를 한 적이 있다. 임백준이 프로그래밍에서 발견한 미학이라는 것이 이런 의미에서의 아름다움이 아닐까 하는 생각이 든다. 나 자신도 구조적으로 잘 짜여진 짧지만 많은 의미를 담고, 아름다울 만큼 창의적인 결과를 표현하는 프로그램을 보면 ‘아름답다’라는 표현이 가장 적절하다는 생각이 든다.
 
 얼마 전에 모 출판사에서 나에게 책을 쓸 것을 권한 적이 있다. 판매금액의 10%를 받는 조건으로 책을 쓰면 어떻겠냐는 이야기였다. 금전적인 문제를 떠나 내가 쓴 책이 일반 서점에서 독자들에게 판매될 수 있다는 것을 생각하니 결정도 내리지 않은 시점인데도 흥분되는 일이 아닐 수 없었다.
 
 며칠 동안 고민하다가 일단 샘플을 하나 만들고 간단한 구조로 내용을 담아 보았다. 그런데 가만히 내가 만든 소스와 내가 쓴 글을 보고 있으니 책으로 세상에 내놓기에는 쓰레기 같아 보였다. 소스는 순전히 개인적인 습관과 입증되지 않은 구조와 알고리즘으로 낙서를 해놓은 것 같은 느낌이 들었다.
 
 임백준의 책 속에 이런 내용이 있다. “자신이 만든 프로그램으로 만든 전투기를 직접 자신이 조정할 수 있는 용기가 있는가” 결코 쉬운 일이 아닌 듯 싶다. 더군다나 인터넷이 아닌 인쇄물로 한번 세상에 내놓으면 수정할 수도, 업데이트 할 수도 없는 책을 출간한다면 잘못된 정보를 통해 위와 같은 질문에 ‘예’라고 대답한 사람들의 사고들을 내가 어찌 감당할 수 있겠는가 싶었다. 그래서 다음날 출판사 담당자에게 기회가 되면 다음에 쓰겠다고 정중히 거절을 했던 일이 있었다. 지금도 나는 그때의 결정을 잘 했다고 생각한다.
 
 프로그래밍이 아름다음을 갖으려면 그것을 만드는 사람의 흥미와 재미, 열정과 인내가 필요한 작업이 아닐까 싶다. 혹시나 나는 인내가 어려워 가벼운 흥미와 재미를 쫓고 그것을 열정이라 자찬하고 있는 것은 아닐런지...;
    

설정

트랙백

댓글

NLP 란 무엇인가

Miscellaneous/Etc 2007. 2. 23. 21:15

NLP(Neuro-Linguistic Programming) 신경-언어 프로그래밍

"NLP는 인간의 마음과 행동이 일어나는원리를 설명하고 어떻게 함으로써 효과적으로 마음과 행동을 변화 시킬 것인지를 다루는 심리전략 프로그램이다"

1. NLP란 인간의 마음 과 행동 에 관한 이론과 기법체계 이다. 인간의 모든 것이 마음에서 비롯된다는
“일체 유심조” 의 논리를 생각한다면 NLP는 인간 삶의 모든 것과 관계된다.

2. NLP는 기본적으로 변화 를 위한 것이다. 변화는 여러 가지 형태로 이루어진다. 치료, 성장, 성공, 발전, 업 그레드 … . NLP는 이 모든 것들을 위해서 활용된다.


N: 신경 (Neuro)을 의미하면서 인간경험의 기초가 되는 5감적 요소의 작용을 말한다.

L: 언어 (Linguistic)을 의미하면서 마음을 구성하고 행동을 일으키는 언어적 작용
(비언어적 요소를 포함하는)을 말한다.

P: 프로그래밍 (Programming)을 의미하면서 인 간의 모든 마음 작용이나 행동은 결국 하나의 체계와
패턴으로 구조화 된다는 것을 말한다.

NLP는 1970년대 중반 미국 산타크루즈 캘리포니아 대학교의 존 그린더(언어학 교수),
리차드 밴들러(심리학 대학원생)에 의해 창시되었다.


NLP의 활용분야

NLP의 기업 및 경영에의 활용
NLP가 적용되는 또 다른 큰 분야는 바로 기업 / 경영 분야이다. 경영에 있어서 가장 중요한 요소 중의 하나는 바로 인간관리일 것이다. 즉 생산을 직접 담당하거나 생산에 있어서 결정적인 역할을 하는 존재가 바로 인간이기 때문에 인간관리 또는 인적관리의 문제는 경영에 있어서 항상 중요한 이슈가 된다. 경영에 있어서 인간관계의 문제와 인적 자원 관리의 중요성의 문제는 일찌기 메이요 교수의 호손연구 이래로 큰 관심을 받아왔다. NLP는 바로 인간과 인간관계, 특히 인간의 내적 자원을 다루는 학문이기에 NLP의 원리는 당연히 경영분야에 활용도가 높다. 그리고 목표설정의 원리인 SMART의 원리는 경영의 모든 면에서 크게 활용될 수 있을 것이다.

인간관계
경영은 인적 조직체에 의해서 움직인다. 그렇기에 조직체 내에서의 인간관계는 대단히 중요하다. 조직의 인간관계는 상사와 부하의 관계, 동료와 관계, 사무직과 생산직의 관계, 노사관계 등 다양하다. 이러한 조직에 있어서의 생산적인 인간관계의 형성과 관리는 큰 관심의 대상이 된다. NLP는 인간관계의 원리와 기법에 있어서 탁월성을 보여주고 있다. 인간관계에서의 핵심은 래포인데 NLP에서는 다양한 래포기법을 제공해주고 있다. 언어적인 차원뿐만 아니라 비언어적인 차원에서의 맞추기, 일치시키기, 거울기법 등은 훌륭한 래포 기법이다. 이 기법들은 말의 내용과 음성, 신체적 요소들 모두에 초점을 두는 것이기 때문에 효과적으로 래포 형성을 하기에 좋다. 그리고 종업원 또는 조직인의 선호표상체계를 파악하여 활용하며 눈동자 움직임을 활용하는 것 또한 래포 형성을 위한 훌륭한 수단이 된다.
 선호표상체계의 이론도 인간관계에 있어서 서로를 이해하고 래포를 형성하며 서로에게 맞추어 감으로써 생산적인 관계를 형성하며 효과적인 영향미치기를 하기 위한 좋은 재료가 된다. 그러나 어떻게 보면 래포 형성의 선행단계는 종업원, 동료, 고객 특성에 대한 진단과 이해라고 할 수 있다. 왜냐하면 상대방의 특성에 따라서 래포형성의 방법이 달라질 수 있기 때문이다. 그러므로 그의 선호표상체계를 파악하고 활용하는 것, 그리고 그의 눈동자 접근 단서도 마찬가지로 서로를 이해하고 맞추기를 할 수 있는 좋은 수단이 된다. 이러한 래포의 원리는 이미 상담과 심리치료부분에서 충분히 설명을 하였기에 여기서는 더 이상의 설명을 생략하겠다.
 한편, 메타모형은 인간관계에 있어서 대화를 보다 효과적으로 진행해 나갈 수 있는 기법이 된다. 아울러 밀턴모형은 상대방에게 영향을 미칠 수 있는 효과적인 방법이 된다. 닻내리기도 효과적인 인간관계를 형성하거나 유지하는 좋은 방법이 된다.

세일즈
세일즈란 고객에게 상품을 판매하는 것이지만 따지고 보면 판매인이 고객에게 인간적으로영향을 미치는 과정이라고 할 수 있을 것이다. 즉 고객의 마음이 움직이지 않으면 고객의 구매행위 또는 판매인의 판매행위가 이루어지기 어렵다고 볼 수 있기에 고객의 마음을 움직이는 것, 그것이 바로 세일즈의 핵심이 아닐까?
 그러나 그렇게 고객에게 영향미치고 마음을 움직이기 위해서는 무엇보다도 먼저 고객과의 래포가 형성되어야 한다. 래포야 말로 영향미치기의 전제조건이 되는 셈이기 때문이다. 래포가 형성되지 않은 상태에서 어떻게 상대방에게 영향을 미치고 그의 마음이 움직여지기를 기대할 수 있겠는가? 그래서 세일즈의 첫 단계는 바로 래포 형성이라고 할 수 있다.
 래포를 형성하기 위해서는 고객에 대한 진단과 이해가 선행되어야 한다.  래포형성을 위한 구체적인 방법으로는 맞추기, 일치시키기, 거울기법 등의 기법을 꼽을 수 있다. 이 기법들은 말의 내용과 음성, 신체적 요소들 모두에 초점을 두는 것이기 때문에 효과적으로 래포 형성을 하기에 좋다. 그러나 어떻게 보면 래포 형성의 선행단계는 고객의 특성에 대한 진단과 이해라고 할 수 있다. 왜냐하면 고객의 특성에 따라서 래포형성의 방법이 달라질 수 있기 때문이다. 그러므로 그의 선호표상체계를 파악하여 활용하며 눈동자접근 단서에 있어서 눈동자 움직임을 활용하는 것 또한 래포 형성을 위한 훌륭한 수단이 된다.
 예를 들어 시각적인 고객은 상품의 디자인이나 색상을 중시할 것이다. 그리고 판매인의 외모나 옷차림에 대해서도 민감할 것이다. 그러므로 시각적인 고객을 대해야 하는 판매인이라면 당연히 외모에 신경을 쓰며 옷차림에도 주의를 기울여야 할 것이다. 그리고 상품을 소개하거나 권할 때 특히 시각적인 차원에서 호감이 가도록 하는데 초점을 두어야 할 것이다.이러한 원리는 다른 선호표상체계를 가진 고객에게는 다른 형식으로 적용될 수 있을 것이다. 표상체계에서 일치가 될 때와 그렇지 않을 때는 고객의 입장에서 상품 구매에 대한 의욕이나 동기수준이 달라질 것은 분명할 것이다. 그러므로 판매인의 입장에서 고객의 선호표상체계를 제대로 파악하고 이해하며 활용할 수 있는 것만 해도 아주 효과적으로 세일즈를 성공시켜 나갈 수 있을 것이다.
 세일즈에서 또 중요한 것은 전략과 관련한 것이다. NLP에서는 전략에 대해서 탁월한 원리와 기법을 제공해주고 있다. 세일즈 상황에서 필요한 전략은 고객의 구매전략의 파악, 판매인의 판매전략의 활용과 같은 것이다. 이 과정에서 판매인이 어떻게 닻내리기를 잘 하느냐라는 문제도 중요하다.
 아울러 고객과의 래포가 형성된 바탕 위에서 판매인이 고객의 구매 결정 행위에 영향을 미쳐야 세일즈는 성공했다고 볼 수 있다. 다시 말해서 판매인은 고객과의 래포를 직접적인 구매결정과 함께 구매행위로 연결될 수 있도록 영향을 미쳐야 할 것이다. 이 과정에서 필요한 것은 밀턴모형과 함께 최면적 언어패턴이다. 이 기법들은 최종적으로 고객에게 긍정적으로 영향을 미쳐서 구매결정과 구매행위를 유도하는데 아주 효과적이다. 그리고 판매인은 최종적으로 판매를 종결짓고 타결을 보는데 필요한 NLP의 타결을 위한 언어적 패턴도 익힐 필요가 있다. 이상의 원리와 기법을 반영하여 NLP 분야에서는 “5단계 세일즈” 과정이란 것도 개발되어 있다.

마케팅과 광고
앞의 세일즈에서와 마찬가지로 마케팅도 결국은 잠재적 고객에 대한 진단과 파악이 우선적으로 이루어져야 할 것이다. 고객 진단에 있어서 가장 기초적인 것은 바로 잠재적 고객의 선호표상체계와 구매전략을 파악하는 것이다. 그리고 그것에 바탕하여 마케팅 전략을 수립할 수 있을 것이다.
마케팅의 방법에 있어서 텔레마케팅이 많이 활용되고 있다. 이것은 잠재적 고객과 목소리에 의존해서 래포를 형성하고 영향미치는 과정이라고 볼 수 있다. 그렇다면 보이지 않는 잠재적 고객의 선호표상체계에 따라서 동일한 언어적 반응이라 하더라도 그에게 미칠 영향력은 다를 것은 분명하다. 그러므로 텔레마케팅 담당자들은 선포표상체계와 그에 따른 언어패턴, 그리고 최면적 언어패턴과 밀턴모형에 대해서 숙달하는 것이 중요하다.
 특히 텔레마케팅에서는 잠재적 고객과 빠른 시간내에 래포를 형성할 수 있는 기술이 필요하다. 서로가 눈에 보이지 않는 상태에서 음성언어에만 의존한 대화를 통하여 어떻게 잠재적 고객의 마음을 끌며 움직일 것인가의 문제는 마케팅의 성패를 결정지을 것이다. 그러므로 NLP의 래포형성의 원리와 언어패턴은 텔레마케팅을 비롯한 마케팅 자체에 있어서 필수적인 것이다.
 한편 광고에 있어서도 마찬가지이다. 요즘 광고를 보면 감각양식을 최대로 활용하는 것을 볼 수 있다. 즉 시각적 차원에서 화려하거나 환상적인 동영상 내지 이미지를 보여주고 청각적인 차원에서 감미로운 음악이나 경쾌한 음악을 들려주거나 또는 음성적 요소를 활용하며, 신체감각적 차원에서는 고객을 대상으로 하여 고객이 직접 참여함으로써 함께 느끼고 공감할 수 있도록 유도하는 전략들이 많이 활용되는 것을 볼 수 있다. 이 모두는 NLP에서 말하는 감각양식 또는 선호표상체계의 원리가 적용되는 예라고 할 수 있다. 잠재적 고객이 주로 어떤 표상체계를 사용하는 사람들인가를 분석하고 파악하는 것은 광고 전략 수립에 있어서 가장 첫 단계로 수행해야 할 과제가 될 것이다. 아무리 많은 광고비를 투자하여 제작한 광고라 하더라고 그것이 잠재적 고객에게 어필하지 않는다면 무용지물이 될 것이기 때문이다.
 광고에 있어서 닻내리기 기법의 적용 범위는 아주 광범하다. 대부분의 자동차 광고에서는 매력적이며 노출이 심한 여성이 등장한다. 그것은 술 광고에서도 마찬가지이다. 자동차와 여인, 이것은 무슨 상관관계가 있을까? 그리고 술에서도 마찬가지이다. 이것은 NLP의 원리를 알면 쉽게 이해된다. 즉 이것은 아름다운 여성에게서 느끼는 매력과 호감도, 이것을 자동차로, 또는 술로 연결시키는 닻내리기의 기법이 적용된 전형적인 예인 것이다. 이러한 예들은 역시 대부분의 인기있는 광고에서 인기 연예인이 등장하는 것도 마찬가지이다. 그것은 기존의 인기 연예인에 대한 호감도를 특정 상품으로 연결시키는 닻내리기의 전략을 활용한 것이다. 최근 2002년 6월의 ‘월드컵 4강 신화’의 주인공인 히딩크 감독을 광고에 활용한 예도 마찬가지일 것이다.
 광고의 카피는 은유법, 최면적 언어패턴, 밀턴모형이 활용되는 전형적인 예이다. 우리 일상에서 NLP의 최면적 언어패턴이 얼마나 광범하게 적용되는지는 다음의 예를 보면 쉽게 알 수 있다:

 “한 시간 빠른 뉴스, SBS뉴스”
 “스피드 011”
 “아름다운 사람들, 아시아나”

 이처럼 NLP의 원리가 광고에 적용될 수 있는 가치는 아주 크다고 하겠다.

선발과 배치
조직과 경영의 성패는 인적관리에 달려있을 것이며 그 인적관리의 핵심은 인재를 적재적소에 배치하는 것이라고 생각된다. 그렇다! 어떤 조직에서든 인적관리 또는 인재관리를 잘 하는 것이 중요한데 그것은 국가조직에서도 마찬가지이다. 아무튼 인재를 적재적소에 배치하기 위해서는 각 개인의 특성에 대한 진단과 파악이 제대로 이루어져야 할 것이다.
 개인 특성 파악을 위해서는 선호표상체계의 원리가 일차적으로 활용될 수 있다. 선호표상체계에 따라서 개인의 사고와 감정 관리, 행동 양식이 달라진다. 뿐만 아니라 취미와 관심분야 또한 달라질 수 있다. 예를 들어서 시각적인 사람은 그림이나 그래픽, 공간예술, 디자인, 건축, 색상과 같은 부분에 관심을 가지고 좋아할 것이다. 그러나 청각적인 사람은 음악이나 음향, 소리, 말하고 듣기, 토론하기 등을 좋아할 것이다. 그리고 신체감각적인 사람은 가만히 자리에 앉아있기 보다는 몸을 움직이거나 활동하는 일, 스포츠, 현장에서의 경험과 같은 것에 관심을 가지고 소질을 보일 것이다. 그렇다면 개인이 이러한 자신의 특성이 제대로 반영되는 일을 하거나 분야에 종사한다면 업무의 능률을 꾀할 수 있겠지만 그렇지 않다면 자기가 하는 업무에 대해서 쉽게 싫증을 내거나 집중하지 못하고 흥미를 느끼지 못할 가능성이 클 것이다. 그리고 그것은 곧 이직으로 쉽게 연결될 수 있을 것이다.
 이처럼 인재를 적재적소에 배치한다는 것은 개인의 생산성과 정신건강, 업무의 능률 뿐만 아니라 조직 자체의 생산성에도 아주 큰 영향을 미친다. 그럼에도 불구하고 과연 조직에서 인재에 대한 적재적소 배치의 원칙이 얼마나 잘 지켜질까? 그런데 적재적소 배치의 원칙보다 더 중요한 것이 있다면 선발의 문제일 것이다. 다시 말해서 조직에 꼭 필요한 적절한 인재를 선발하는 것은 적재적소에 배치하는 문제 이전의 문제이다. 아무리 많은 능력을 가진 사람이 있다고 하더라도 그가 조직에서 꼭 필요로 하고 요구하는 스타일의 사람이 아니라면 별로 의미가 없을 것이다.
 그렇다면 조직에 꼭 필요한 인재를 어떻게 선발하고 배치할 것인가? 이에 대해서는 NLP에서 아주 지혜로운 대답을 해주고 있다. 이 분야에서는 기본적으로 선호표상체계의 원리가 적용될 수 있겠지만 메타프로그램이 아주 효과적인 수단이 될 수 있다. 이 메타프로그램은 아주 빠른 시간, 즉 10분 정도의 시간 정도만에 무려 20여 가지 차원에서 인간을 진단하고 파악할 수 있는 지혜를 제공해주고 있다. 이 메타프로그램은 개인의 성격이나 행동성향, 취미, 관심사, 시간감각, 인간관계양식, 일에 대한 태도, 조직에 대한 태도 등 광범위한 분야에서 개인의 성향과 특성을 진단하고 분류해준다. 그러므로 이 NLP 메타프로그램을 제대로 활용한다면 인재의 선발뿐만 아니라 적재적소에의 배치 문제는 아주 효과적으로 해결될 수 있을 것이다 (이 부분은 매스터 프랙티셔너 과정에서 다루어진다).
 
인사관리
관리자의 부하관리를 비롯하여 노사관계 차원에서 인사관리의 문제는 대단히 중요하다. 인사관리의 성패 여부에 따라서 기업이나 조직의 존폐여부가 영향을 받을 정도로 인사관리의 문제는 중요하다.
 인사관리의 핵심은 인간관계일 것이다. 생산적이며 효과적인 인사관리를 하는 것은 관리자가 부하관리를, 경영자가 종업원 관리를 인간관계 차원에서 얼마나 잘 하느냐의 문제와 직결된다고 본다면 앞의 1번 항에서 살펴본 NLP 인간관계의 원리와 기법이 여기서도 그대로 적용될 것이다.
 그리고 인원의 선발과 배치의 문제도 인사관리의 중요한 부분이 될 수 있는데, 이와 관련해서도 앞의 4번에서 충분히 설명을 하였기에 더 이상의 설명을 생략하고자 한다.

기타
NLP가 적용될 수 있는 기타 경영분야의 예로서 협상과 회의 상황을  들 수 있다. 앞에서 설명한 대부분의 기법들은 협상과 회의 장면에서도 적용될 가치와 가능성이 충분히 있다. 특히 협상의 장은 래포와 영향미치기 기법이 직접적으로 적용되어야 하는 분야이다. 그리고 메타모형과 밀턴모형, 최면적 언어패턴도 중요한 수단이 될 수 있다. 그것은 회의에서도 마찬가지이다. 당신이 만약 회의를 주재하는 입장이라면 특히 집단래포에 주의를 기울일 필요가 있다. 그리고 닻내리기도 마찬가지로 적용될 수 있다.
 한편 프리젠테이션 상황에서도 앞에서 소개한 대부분의 NLP의 원리와 기법이 적용된다. 특히 선호표상체계의 원리는 프리젠테이션 상황에서 아주 효과적으로 적용될 수 있다. 그리고 닻내리기 또한 중요한 기법이 된다.
 고객관리 차원에서도 NLP는 아주 유용하다. 특히 닻내리기의 원리는 고객관리에 있어서 도움이 크게 된다. 일정한 기간마다, 또는 특별한 이벤트나 기념일에 맞추어서 고객에게 기념이 되거나 좋은 기억을 상기시켜줄 닻내리기를 시도하는 것은 아주 효과적인 고객관리의 방법이 된다. 이 과정에서 밀턴모형을 활용하는 것도 도움이 된다. 특히 고객의 선호표상체계에 따라서 닻내리기의 방법이 다양화될 수 있을 것이다.


NLP와 성공학
NLP는 대표적인 성공학이라고 할 수 있다. 현대 성공학 분야의 스타로 꼽히고 있는 미국의 안토니 로빈스는 한때 자살 직전에 이르는 좌절과 절망상태까지 간 적이 있었다. 그러나 다행히 그는 NLP를 통하여 삶의 의욕과 용기를 찾았을 뿐만 아니라 새로운 차원의 성공적인 삶을 살 수 있게 되었다. 그는 “무한능력”이란 책과 “네 안에 잠든 거인을 깨워라”와 같은 베스트셀러를 펴내면서 그의 이름을 이 분야 최고의 전문가로 인정받게 하였다. 그는 국제적으로 최고의 모티베이션 서피커, 최고의 성공학 강사 및 전문가로 인정받고 있으며 그것으로 인해 최고의 재벌로도 부상하였다. 그는 자가용 헬기를 타고 강연을 다니고 있으며 태평양에 자기 소유의 섬을 갖고 있을 정도가 되었다. 무엇이 그로 하여금 그러한 탁월한 성공인이 되게 했을까? 그것은 바로 NLP요, NLP를 실천한 그의 인생경험이요 또한 NLP에 기반한 그의 독특하고 파워풀한 성공학이라고 할 수 있다.

사용자 삽입 이미지

 NLP의 역사에서 볼 수 있듯이 NLP는 인간변화의 탁월한 능력을 발휘하는 심리전문가들을 모델로 삼아서 개발되었다. 그들은 모두가 당대 최고의 성공인이었다. 그러므로 NLP는 그러한 최고의 성공인의 성공의 원리를 모방한 이론이요 기법이기에 NLP야 말로 최고의 성공학이라고 할 수 있겠다. NLP에는 “성공의 4대 원리”라는 것이 있다. 이 원리에서 볼 수 있듯이 NLP는 그것 자체가 바로 성공심리학이요 성공학이라고 할 수 있다.
 “성공하는 사람들의 7가지 습관”을 말하는 7 Habit이 강조하는 것도 결국은 누구라도 성공하는 사람들의 습관을 실천하면 모두가 성공인이 될 수가 있다는 것이며 따라서 그 성공의 원리를 실천하자는 것이리라. NLP도 마찬가지이다. NLP의 전제조건에서는 “탁월성은 모방할 수 있다”고 하였다. 그리고 그렇게 탁월성에 대한 모방이 가능하다면 다른 사람에게 그것을 “가르칠 수도 있다”고 하였다. 이 탁월성이야 말로 바로 성공의 원리요 성공의 지혜인 것이다. NLP는 이 시대 최고의 성공학이라고 할 수 있다. 그러므로 성공을 꿈꾸는 사람들은 누구라도 NLP를 통하여 성공시대를 열어갈 수가 있다.


출처 : 설기문 박사의 Mind Coach(http://www.mindcoach.co.kr)

    

설정

트랙백

댓글