[Java/Javascript]캐리지리턴과 브라우져 비호환성

이번에 회사 업무를 하면서 간단하다고 생각했던 일에 큰 코를 다쳤던 일이 있었습니다.

바로 “캐리지리턴“과 “브라우져 비호환성” 문제였습니다.

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

먼저, “캐리지리턴“은 mysql DB에 저장되어 있던 한글 varchar 데이터를 가져와서

컨트롤러의 ModelMap에 변수에 담아 자바스크립트단의 변수로 쓸 생각이었습니다.

그런데 문제는, 이 변수가 자꾸 define하는 과정에서 “Unexpected token ILLEGAL

에러를 뱉어냈습니다.

debugging을 해봐도 정상적인 데이타가 나와 한참을 삽질하던 도중…

데이타에 “캐리지 리턴“이 포함되어 있는 것을 어렵사리 확인하였습니다 ㅠㅠ

그래서 아래와 같이 서버단에서 “캐리지 리턴“을 replace 처리해서 삽질을 끝냈습니다.

  String data = data.replaceAll("\r","");

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

두번째로, 서버단에서 받아온 ModelMap변수를 자바스크립트단에서 구분자로 나눠

textarea에 각 배열요소를 넣고 끝에 “엔터키”를 삽입하도록 했습니다.

<html>
<head>
<script language="javascript">
var a = [서버단 ModelMap 변수];
var arrList = a.split("|");

for(var i=0; i<arrList.length; i++) {
    if(navigator.appName == "Microsoft Internet Explorer") {  //IE
        $("#box").append(arrList[i]+"\r");
    }else{  //Crome, Mozilla, Etc..
        $("#box").append(arrList[i]+"\n");
    }
}
</script>
</head>
<body>
    <textarea id="box" name="issueHashTag" rows=20 cols=30></textarea>
</body>
</html>

위 소스에서 보이는 바와 같이, 브라우져 별로 “엔터키”를 삽입할 때도 “IE”는

캐리지리턴(“\r”)을 사용하고 그 외의 브라우져는 라인피드(“\n”)를 사용합니다.

만약, IE에서 라인피드(“\n”)를 사용했다면 현재 위치에서 아래로 한줄 내리는 기능은

동작하지만 커서위치가 한칸 띄어지는 현상을 발견할 수 있습니다.

그러므로 캐리지리턴(“\r”)을 사용해야 다음줄의 첫 위치로 커서를 옮길 수 있습니다.

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

마지막으로,  위 소스에서 Textarea에 값을 넣어놓고 해당 값을 삭제하는 순간 크롬에서

아래와 같은 경고메세지가 나오더군요.

event.layerX and event.layerY are broken and deprecated in WebKit. They will be removed from the engine in the near future.

‘이건 또 모야…’ 하고 구글링을 해보니 jquery를 1.7로 업데이트 했더니 해당 문제를

고칠 수 있었다고 나와있어 그것도 시도해 보았지만 Textarea에 액션이 들어가는 순간,

저 메세지는 변함없이 발생하였습니다.

그리고 Textarea에 기존에 세팅되어 있던 값을 건드리지 않고 새로운 값을 넣었을 때

즉, 데이타를 append 할때는 들어갔지만 역시나  Textarea에 액션을 가하면 여지없이

위의 경고메세지가 출력되며 정상작동하지 않는 문제가 있었습니다.

파폭도 동일하게 정상작동하지 않는 문제가 발생했습니다

여기서 중요한건!!!!

“IE에선 이상없이 잘 동작한다는 것입니다! 오잉~~~ ㅋㅋ” 

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

클라이언트 개발이 어렵다는 사실을 새삼 실감하고 공부가 많이 필요하겠구나 느낀

요 며칠이었습니다.

참고로, jquery 버전은 1.6.1과 1.7.1을 번갈아 사용했습니다.

혹시나 해결책을 알고 계신 분은 댓글 꼭 부탁드릴께요^^

*참고 url

[javascript]object 코딩 실습

제가 대학다닐 때, 그러니까 1999년부터 2006년 사이에는

자바스크립트“하면 저는 그저 인터넷에 돌아다니는 몇몇 스크립트 긁어다가 붙여 쓰는게

다였습니다. 그 만큼 개념이 없었죠. ㅡㅡ;

하지만 지금은 그 중요성이 날로 증대되고 있는 상황이니 참 짧은 시간이지만

격세지감을 느낍니다.

저도 요즘 “ppk 자바스크립트“를 출근길에 보면서, “내가 자바스크립트 공부도 하는구나~!”

라는 사실이 가끔씩 새롭게 느껴질 때가 있습니다.

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

각설하고, 잠깐 책에 나온 “자바스크립트 코어“부분에 나온 “객체“에 소개된 부분을

토대로 예제코드를 만들어 보았습니다.


<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script><script type="text/javascript" language="javascript">// <![CDATA[
var test = {
	a : 2,
	b : '2',
	c : function() {
	    return this.a*this.b;
	}
};

$(document).ready(function() {
    /*
    for(var i in test) {
        alert(test[i]);
    }
    */

    //document.write(test['c']());
    document.write(test.c());
});
// ]]></script>

결과는 예상하신대로, “4”가 브라우져에 출력되게 됩니다.

test 객체의 b 프로퍼티의 값은 c메서드에서 숫자로 자동인식하여 2*2=4의 결과를

만들어내게 됩니다.

위 예제에서 for문의 주석을 풀고 결과를 확인하시면 test 객체의 각 프로퍼티와 메서드가

출력됩니다.  c메서드는 본문 전체가 나오게 됩니다.

그리고 마지막에 test객체의 c메서드를 호출할때, “연관배열“을 사용할 수도 있습니다.

연관배열“의 정의를 책에서 빌려오면

  • 어떤 값의 이름 문자열을 사용해 그 값을 찾을 수 있게 해주는 배열

이라고 소개되어 있습니다. a프로퍼티는 test[‘a’] 저런식으로 가져오면 되겠죠.

자바스크립트에도 자바와 동일하게 try-catch-finally가 있어 헷갈리던 시절…

이제 자바스크립트도 자바처럼 “객체지향적“으로 “멋지게” 코딩할 수 있는 날이

어서 왔으면 좋겠네요. 많은 단련을 해야겠습니다. ^^

[Search]업무나 기타 공부에 참고했던 블로그글 리스트

오늘 업무를 하다 문득,

업무나 공부를 하며 무의식적으로 구글링을 통해 유용하게 사용했던 글들을 놓쳐버려

다음에 동일한 것을 또 찾고 있는게 아닌가라는 생각이 들었습니다.

그래서, 간단하게나마 리스팅을 하는게 나을 것 같아 오늘부터 리스팅을 시작합니다.

데이타가 많이 쌓이면 앞으로 이 포스트에서 검색할 수 있는 날이 올 수도 있겠네요 ^___^

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

[Android]”스타크래프트 프로리그” 업데이트/게시 완료!

          

기존에 “신한은행 프로리그 10-11“앱 업데이트를 드뎌 오늘 끝냈습니다.

저번 포스팅에서 업데이트의 주요관점으로 다뤘던 내용은

  • 프로리그/팀/개인리그 결과 잘못나오는 버그패치(O)
  • 버전업데이트 액티비티 추가(X)
  • admob 달기(X)
  • minor 버그패치/성능개선(O)

인데, 실수로 “신한은행 프로리그 10-11“의 키스토어 파일을 잃어버려서(ㅠ.ㅠ)

할 수 없이 업데이트를 하고 리패키징을 하고 앱 이름을 수정해서 신규버전으로

다시 안드로이드 마켓에 올렸습니다.

  • 스타크래프트 프로리그 안드로이드 마켓URL : http://bit.ly/x8t5ZX

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

이번 업데이트 버전의 주요사항은 아래와 같습니다.

  • 전체적으로 프로리그 경기결과,랭킹보기등의 처리속도 개선
  • 개인랭킹을 상위 100위까지 볼 수 있도록 함
  • 프로리그에서 현재 검색된 날짜를 노란색으로 표시함
  • 기존에 있던 마이너버그 수정

기술적인 부분에서 달라진 점을 말씀드리면,

  • 기존 html 파서를 Jericho에서 Jsoup으로 변경(DOM, CSS, jquery에 최적이라고 함)
  • json 라이브러리를 안드로이드 내장라이브러리에서 gson으로 변경(코드량 확 줄임!)
  • 파일/이벤트 관련 부분을 독립적인 클래스로 분리(관심대상을 별도의 클래스로 분리함)

저 정도 입니다. 특히나 gson을 사용할 때는 기존 안드로이드 내장 라이브러리를 사용할때

보다 훨씬 코드량이 줄어드는 것을 체감했습니다. 기존에 노가다로 했던 작업들을

라이브러리에서 모두 가져갔기 때문이죠.

결국, 코드도 기존보다 훨씬 깨끗해졌습니다. 물론 유저들은 못 느끼겠지만요^^

그리고, 또 하나!

파일관련 작업과 버튼을 클릭했을 시 이벤트처리 같은 부분도 본래 경기결과나 랭킹을

보여주는 액티비티 안에 중복으로 코드가 있었는데, 이러한 부분들은 엄밀히 말하자면

주요 액티비티와는 다른 관심대상이었고, 당연히 분리되어야 했으며, 또 하나의 큰

문제는 같은 코드가 여러 액티비티에서 중복되어 작성되었다는 점이었습니다.

이러한 부분들도 과감하게 리팩토링하여 독립적인 클래스로 분리하였습니다.

물론 액티비티에 내용을 표시하는 것 외에, html 파싱하는 부분도 리팩토링하여

독립적인 클래스로 분리할 수 있으나 이 부분은 다음 업데이트때 진행하기로 했습니다.

        

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

솔직히, 이번에 업데이트 하면서

  • 알람기능 추가
  • 앱아이콘 및 UI 개선
  • admob/cauly 광고 달기
  • 사용자게시판 추가
  • 전체 OOP관점에서 설계하고, 모델링, 소스 리펙토링, 단위 테스트 작성

등의 욕심이 있었고, 실제로 리팩토링단위테스트 작성 부분에 있어서는 어느정도

성과가 있었다고 생각합니다.

그리고 남아있는 기능추가와 UI 개선은 앞으로도 계속적으로 도전해야 될 부분이

될 것 같습니다.

많이 부족하지만 지속적으로 업데이트할 계획입니다.

SNS를 하시면 폐북에 링크공유와 트위터의 무한 RT로 홍보도 많이 부탁드립니다.

스타크래프트 프로리그“앱의 업데이트와 기술적인 내용도 계속 포스팅하겠습니다^^

    

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

*참고 url

[javascript]암묵적 전역변수 실습 – 안티패턴

오늘 출근하면서 “ppk 자바스크립트” 5장 코어를 보는 와중에 “var“를 선언하지 않은

변수는 함수 밖이든 안이든 모두 전역변수가 된다는 글을 보았습니다.

제 상식에는 함수 안에서 쓰면 무조건 지역변수가 되야 할 것 같은데 자바스크립트는

명시적으로 변수 앞에 “var“를 붙여주지 않으면 암묵적 전역변수가 된다고 합니다.

그래서, 아래 테스트코드를 만들어 보았습니다

<html>
<head>
<script src="../jquery.1.6.min.js"></script>
<script language="javascript">
$(document).ready(function() {
    globalVariableTest();
    print(x);
});
var print = function(val) {
    document.write("global variable x value : " + val);
}

function globalVariableTest() {
    var y = 4;  //함수내 지역변수
    x = y*2;    //암묵적 전역변수
}

</script>
</head>
<body>
</body>
</html>

결과는 변수 x를 선언하지 않았다는 오류가 나올것 같지만 의외로 아래와 같은 결과가

나옵니다.

globalVariableTest() 함수가 실행되면,  x는 암묵적으로 “전역변수“가 되어  document

body에 x의 값이 찍히는 것입니다.

하지만 이것은 “안티패턴“이라고 하네요.  되도록

  • 전역변수를 최소화하라
  • 변수를 선언할때는 명시적으로 “var“를 쓰고, 단일 var패턴을 사용하라.

저렇게 “자바스크립트 코딩기법과 핵심패턴“에 나와있다고 하네요. 저도 나중에 꼭

읽어볼 책입니다.

단일 var패턴“에 대해 궁금하시면 링크를 참고하세요.

여튼,  결론은

  • 변수는 꼭 “var“를 써서 명시적으로 선언하고,  “단일 var“패턴을 사용하라!

[Java]정규식 사용하여 트위터 해시태그 추출기능 만들기

트위터에 보면 “#” 을 붙여 해시태그를 만듭니다.

그런데, 가만히 해시태그가 되는 규칙을 살펴보면 “#“로 시작해서

특수문자공백이 오면 “#“부터 그 사이를 해시태그로 인식해서 보여줍니다.

다만, 연속적으로 “#“을 사용하면 트위터에선 해시태그로 인식을 하지 않더군요.

예를 들면 “#테스트#테스트1#테스트2″같은 문자열은 각각

“#테스트”, “#테스트1”, “#테스트2” 세개의 해시태그로 인식되어야 할 것 같지만 결과는

아무것도 해시태그로 인식하지 못합니다. 궁금하면 직접 한번 해보세요~*

그래서 회사의 업무와 연관되기도 하여서 해시태그 추출기능 테스트코드를 만들었습니다.

@Test
public void extractHashTagTest() {
    String test ="나는 어딘가에서 #테스트 포를 #가#나다#라라라$ #배$#%@ #443##fefef";
    String test1 ="#아무개가 세미나에 참여했다.";
    String test2 ="#아무개? 이 캐릭터는 누구냐?";
    String test3 ="#작두#망토 어때요?";
    String test4= "말도안돼#니가$정말#그 사람이었다니 말야##이상하군!! 정말";

    Pattern p = Pattern.compile("\\#([0-9a-zA-Z가-힣]*)");
    Matcher m = p.matcher(test4);
    String extractHashTag = null;

    while(m.find()) {
	extractHashTag = sepcialCharacter_replace(m.group());

	if(extractHashTag != null) {
		logger.debug("최종 추출 해시태그 :: {}", extractHashTag);
	}
    }
}

public String sepcialCharacter_replace(String str) {
    str = StringUtils.replaceChars(str, "-_+=!@#$%^&*()[]{}|\\;:'\"<>,.?/~`) ","");

    if(str.length() < 1) {
   	return null;
    }

    return str;
}

test부터 test4까지 테스트를 돌려보면 아래와 같은 결과가 나옵니다.

결과를 보면 아시겠지만,  “#“연속으로 사용한 문자열도 순서적으로 추출할 수 있도록

하였습니다.  “작두“와 “망토“가 결과로 튀어나온거 보면 확인할 수 있죠~

추출된 해시태그에서 “#“는 삭제하였습니다. 순수한 문자열만 추출하기 위해서요.

그래서 한단계를 더 거치게 되는데, 만약 정규식이 최적화되어서 한번에 #을 제외한

문자열을 추출할 수 있다면 더욱 베스트겠죠.

혹시 더 좋은 방법을 알고 계시다면  댓글로 달아주세요~^^

*다른 정규식 예제 포스팅은 아래에서 확인하실 수 있습니다.

[jquery].data() api 실습

jquery api중 “.data()” api가 있습니다.

이 api에 대한 내용은 링크를 참조하시면 됩니다.

대략, api 내용을 보면 .data() api 인자에 key, value를 넣을 수 있고,

key만 넣으면 해당 키에 저장된 값(value)을 넘겨주고 key, value를 함께 지정하면,

해당 key의 value를 지정하게 됩니다.

근데 제가 궁금했던 건,

다른 소스코드를 보던 중 아래와 같은 소스가 뜬금없이 나와서 사용되고 있어서였습니다.

    <div id="test_div" data-id="100" data-specify-name="bluepoet">test</div>

위 html의 div요소를 가져오는 자바스크립트에서는 아래와 같이 사용했습니다.

    var $dataId = $testDiv.data("id");
    var $dataSpecifyName = $testDiv.data("specifyName");

오잉! 먼가 이상하지 않으신가요??

jquery 속성을 가져오는 건 .attr() api를 사용해 풀네임 속성으로 값을 가져오는 것으로

알고 있었는데 갑자기 “data-“가 빠진 “id“만 가지고 오다니요…!

그리고 두번째는 더 심하게 “data-specify-name“이 아닌 “specifyName“만

가져오더군요.

그런데! 여기서 순간! 개발자의 직감으로..

specifyName“을 쓰는 것을 보니 “뭔가 내가 모르는 네이밍규칙이 있구나“라는 생각이

들었습니다. 그래서 찾아봤더니 허무하게도 .data() api에 해당내용이 나와있더군요.

data-*“이 html5의 속성이였습니다. 그리고 이것은 jquery 1.4.3 이상에서는

자동으로 jquery data object로 들어간다고 나와있더라구요 ㅎㅎ

html5의 “data-*”속성에 대한 설명은 링크를 참고하세요.

역시 “등잔밑이 어둡구나“라는 옛말이 또 한번 들어맞는 순간이었습니다.

하여튼, 문제를 해결하고 .data() api에 있는 예제를 조금 수정해 “data-*“속성을

테스트해보기로 했습니다.

<!DOCTYPE html>
<html>
<head>
  <style>
  div { margin:5px; background:yellow; }
  button { margin:5px; font-size:14px; }
  p { margin:5px; color:blue; }
  span { color:red; }
  </style>
  <script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
  <div id="test_div" data-id="100" data-specify-name="bluepoet">A div</div>
  <button>Get "blah" from the div</button>
  <button>Set "blah" to "hello"</button>

  <button>Set "blah" to 86</button>
  <button>Remove "blah" from the div</button>
  <p>The "blah" value of this div is <span>?</span></p>
<script>
$(document).ready(function() {
	var $testDiv = $("#test_div");
	var $dataId = $testDiv.data("id");
	var $dataSpecifyName = $testDiv.data("specifyName");

	$("button").click(function(e) {
	  var value;

	  switch ($("button").index(this)) {
	    case 0 :
	      value = $("div").data("blah");
	      $dataId = 1;
	      $dataSpecifyName = "kim";
	      break;
	    case 1 :
	      $("div").data("blah", "hello");
	      value = "Stored!";
	      $dataId = 2;
	      $dataSpecifyName = "lee";
	      break;
	    case 2 :
	      $("div").data("blah", 86);
	      value = "Stored!";
	      $dataId = 3;
	      $dataSpecifyName = "park";
	      break;
	    case 3 :
	      $("div").removeData("blah");
	      value = "Removed!";
	      $dataId = 4;
	      $dataSpecifyName = "choi";
	      break;
	  }

	  $("span").text("" + value+ ", data-id : "+ $dataId + ", data-specify-name : " + $dataSpecifyName);

	});
});

</script>

</body>
</html>

결과는,  위 그림처럼 data-id와 data-specify-name가 버튼을 누를때마다 다른 값이

나오게 됩니다.

[Android]신한은행 프로리그 앱 리뉴얼 1.1 버전 내용

                 

새해 계획 중 하나인 자작앱 스타크래프트 “신한은행 프로리그 10-11“앱을

1.1 버전으로 리뉴얼 하는 세부내용을 세워보았다.

  • 프로리그/팀/개인리그 결과 잘못나오는 버그패치
  • 버전업데이트 액티비티 추가
  • admob 달기
  • minor 버그패치/성능개선

일단 admob사이트에 계정을 만들고, 내가 만든 앱을 연결시키는건 완료!

 

너무 커다란 업데이트 계획을 세워서 하려니 벌써 2월 중순인데도 아직 업데이트를

못하고 있다. 이번주에 달려서 1.1버전 업데이트를 해보자꾸나! ^^

아~ 앱 이름도 바꿔야 함 ㅠㅠ

*안드로이드 마켓  “신한은행 프로리그 10-11

[Java]if-else 리팩토링

오늘 회사에서 업무중에 아무 생각없이 if-else 중첩으로 코딩하고 “기능적으로”  잘

돌아가는 것을 확인한 뒤, 해당 업무를 접으려고 했습니다.

그런데 문득 이런 생각을 해보았습니다.

왜 맨날 분기로직은 if-else로만 짜야할까… 과연 내가 아닌 다른 사람이

내 코드를 유지보수한다면 저걸 얼마나 이해하고 작업할 수 있을까

그래서 과감하게 if-else 로직을 걷어내고 리팩토링 하기로 결정하고 구글링을 통해 그런

사례가 있는지 찾아서 테스트코드를 만들었습니다.

아래 참고 url은 꼭 한번 읽어보시기 바랍니다.

소소코드참고 url에서 다운받아서 인터페이스를 구현한 enum class의 메서드에서

String Object를 리턴하도록 약간 수정하였습니다.

1. 먼저 기존 if-else class입니다.

public class IfThenElse {

    public String invoke(String operationName) {
    	String result = null;

        if (StringUtils.equals(operationName, "operation1")) {
            result = operation1();
        } else if (StringUtils.equals(operationName, "operation2")) {
        	result = operation2();
        } else if (StringUtils.equals(operationName, "operation3")) {
        	result = operation3();
        }

        return result;
    }

    public String operation1() {
    	return "operation_1";
    }

    public String operation2() {
    	return "operation_2";
    }

    public String operation3() {
    	return "operation_3";
    }
}

2. 두번째로 if-else 분기문을 enum 클래스로 리팩토링한 코드입니다.

public class NewIfThenElse {

    private interface IOperation {
        String apply(String name);
    }

    private enum Operation implements IOperation {

        OPERATION_1("operation1") {
            public String apply(String name) {
                return "operation_1";
            }
        },
        OPERATION_2("operation2") {
            public String apply(String name) {
            	return "operation_2";
            }
        },
        OPERATION_3("operation3") {
            public String apply(String name) {
            	return "operation_3";
            }
        };

        private static Map<String, Operation> requestLookup;

        static {
            requestLookup = new HashMap<String, Operation>(3);
            requestLookup.put(OPERATION_1.getName(), OPERATION_1);
            requestLookup.put(OPERATION_2.getName(), OPERATION_2);
            requestLookup.put(OPERATION_3.getName(), OPERATION_3);
        }

        private final String name;

        private Operation(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        @Override
        public String toString() {
            return "Operation{" + "name='" + name + '\'' + '}';
        }

        public static Operation getOperationByName(String name) {
            return requestLookup.get(name);
        }
    }

    public String invoke(String operationName) {
    	String result = null;
        Operation operation = Operation.getOperationByName(operationName);
        if (operation != null) {
            result = operation.apply(operationName);
        }

        return result;
    }
}

3. 마지막으로 저 두개의 클래스를 단위테스트하는 코드입니다.

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * if-else Refactoring 테스트케이스
 *
 * @author bluepoet
 *
 */
public class IfElseRefactoringTest {
	Logger logger = LoggerFactory.getLogger(IfElseRefactoringTest.class);
	private String result;

	@Test
	public void procedural() {
		IfThenElse obj = new IfThenElse();

		result = obj.invoke("operation2");
		logger.debug("결과 : {}", result);
		assertThat(result, is("operation_2"));
	}

	@Test
	public void refactor() {
		NewIfThenElse obj = new NewIfThenElse();
		result = obj.invoke("operation1");

		result = obj.invoke("operation1");
		logger.debug("결과 : {}", result);
		assertThat(result, is("operation_1"));
	}

}

단위테스트 결과는 물론, 녹색막대가 뜨며 두개의 메서드 모두 통과로 나옵니다.

로그도 위와같이 console창에서 출력됩니다.

이번에 리팩토링을 진행하면서 기존의 if-else문 자체를 완벽히 거둬내지는 못했지만,

관심대상을 별도의 클래스로 분리해 독립적으로 구현하는 것에는 일부분 성공했습니다.

OOP적인 부분에서는 절반의 성공은 했다고 생각됩니다.

그리고 기존의 코드를 최대한 안 건드리려고 한 부분도 일부분은 만족스럽게 구현했구요.

이것도 예제의 일부분일 뿐이고, 아마 더 좋은 구현사례가 많이 있을 것입니다.

혹시 좋은 리팩토링 사례가 있다면 댓글 남겨주시구요.

오늘 회사 선배개발자님과 커피를 마시며 한 대화중에 떠오르는 말이 있네요

리팩토링은 새로운 기능을 개발할 때 할 수 있는게 아니라 비교적 여유가 있을 때,

기존의 코드를 고치며 하는 것이 더 바람직하다. 그리고 오히려 그렇게 리팩토링을

하는 것이 실력향상에 더 도움이 된다.

리팩토링의 길은 멀고도 험하지만, 그것을 해냈을 때 프로그래머로써 느끼는 “쾌감“은

다른 무엇과도 비교할 수 없는 달콤한 열매겠죠? ^^

*참고 url

[Eclipse]생산성 향상 – 템플릿 등록하기

이클립스를 사용하다 보면 항상 자주 사용하는 소스코드가 있습니다.

예를 들면, 로거를 가져올때 사용하는 아래와 같은 코드죠.

Logger logger = LoggerFactory.getLogger(Test.class);

이걸 매번 클래스 만들때마다 저 소스를 입력하면 시간낭비겠죠?

이럴때 생산성향상을 위해 사용하는 것이 이클립스의 “템플릿“기능입니다.

템플릿“을 등록하고,  “ctrl+space“로 해당구문을 쉽게 입력하실 수 있습니다.

템플릿을 등록하는 방법은 아래 참고url에서 보시면 됩니다. 잘 설명되어 있습니다.

이제 조금 더 빨리 코드를 만들어보시죠?^^

*참고 url