Docker file 내부에 아래와 같이 명시



# Change Apt-get URL

RUN cat /etc/apt/sources.list $i | sed -e "s/archive\.ubuntu\.com/ftp\.daumkakao\.com/g" > a.txt

RUN mv a.txt /etc/apt/sources.list



AWS  환경 아래에 ELB 뒷단에 apache가 80 포트로만 동작중일경우

ELB에 인증서를등록하고 80 과 443을 아파치의 80으로 포워딩 할경우




httpd.conf


RewriteEngine On

RewriteCond %{HTTP:X-Forwarded-Proto} !https

RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI}



 

모든 http 호출에 대해서 https 로 변경하는 설정.



RewriteCond %{HTTP:X-Forwarded-Proto} !https

> 설명

Apache에서 X-Forwarede-Proto 헤더 벨류의 값이 https가 아니면 




aws ec2 상에서 timezone이 kst로 설정되어 있지 않다 ..



sudo vi /etc/profile


하단부에 아래 항목 추가


TZ=Asia/Seoul

export TZ




source /etc/profile


date




이후 Tomcat Restart


는 정상적인 시간이 설정됨을 확인할수 있다.


Tutorial Link : https://www.elastic.co/guide/en/logstash/current/getting-started-with-logstash.html#_storing_logs_with_elasticsearch




설치


테스트 환경 :  Virtual Box - Ubuntu Server x64


1 CPU, 2GB RAM, 8GB HDD



https://www.elastic.co


Tar.gz 다운로드

elasticsearch-1.6.0

kibana-4.1.1-linux-x64

logstash-1.5.2








#. LogStash


설치 경로에서


bin/logstash -e 'input { stdin { } } output { stdout {} }'


위 명령어를 이용해서 Echo 로 동작 가능.


bin/logstash -e 'input { stdin { } } output { stdout { codec => rubydebug } }'


위 명령어를 이용하여 


rubydebug라는 code형태로 출력가능..


EX : 


good night moon

{

       "message" => "good night moon",

      "@version" => "1",

    "@timestamp" => "2015-07-08T07:28:10.873Z",

          "host" => "ubuntu"

}


형태로 출력됨.






Elastic Search 경로로 이동하여

./bin/elasticsearch

기본으로 9200 포트로 동작...

Logstash 구동!

bin/logstash -e 'input { stdin { } } output { elasticsearch { host => localhost } }'

위 명령어를 이용해서 elasticsearch로 결과물을 전달.

Logstash 에서 뭔가를 입력하고 일정 시간 경과후

curl 'http://localhost:9200/_search?pretty'

를 이용 해서 확인하면

내가 입력한 결과물이 Elastic Search에 입력되있는것을 확인할 수 있다..




bin/logstash -e 'input { stdin { } } output { elasticsearch { host => localhost } stdout { } }'

이런 형태로 Multiple output 도 가능.





















N By N 배열의 숫자가 빙빙 돌아가며 찍히는 형태로 출력하는것..


점심시간에 잠깐 짬내서 날 코딩 ㄱㄱ...


  1 16 15 14 13

  2 17 24 23 12

  3 18 25 22 11

  4 19 20 21 10

  5  6  7  8  9



위와 같은 형태로 출력되면 성공.......



아래는 코드 . 전문..


public class Snail {


public void run(int size) {


int[][] matrix = new int[size][size];


boolean xToRight = false;

boolean yToDown = true;


// first line (x 로 기록)

for (int x = 1; x <= size; x++) {

matrix[x - 1][0] = x;


}

int leftSize = size + 1;

int loopCount = 0;


int lastValue = size + 1;


int xPos = size;

int yPos = 1;


while (leftSize-- > 0) {

loopCount++;


// Y 방향 값

for (int innerLoop = 0; innerLoop < (size - loopCount); innerLoop++) {

if (yToDown)

yPos++;

else

yPos--;

matrix[xPos - 1][yPos - 1] = lastValue++;


}

yToDown = !yToDown;

// X 방향 값

for (int innerLoop = 0; innerLoop < (size - loopCount); innerLoop++) {

if (xToRight)

xPos++;

else

xPos--;

matrix[xPos - 1][yPos - 1] = lastValue++;


}

xToRight = !xToRight;

}


for (int i = 0; i < size; i++) {

for (int j = 0; j < size; j++) {

System.out.printf("%3d", matrix[i][j]);

}

System.out.println();

}

System.out.println();


}


public static void main(String[] args) {


Snail s = new Snail();

s.run(5);


}


}



초기 1렬을 그대로 출력하고


x축 끝에서 만날시 방향 전환

y축 끝에서 만날시 방향 전환


대충 이런 느낌으로 작성하였습니다.



머리가 굳어가는 느낌에 가끔 기름칠.


  1 32 31 30 29 28 27 26 25

  2 33 56 55 54 53 52 51 24

  3 34 57 72 71 70 69 50 23

  4 35 58 73 80 79 68 49 22

  5 36 59 74 81 78 67 48 21

  6 37 60 75 76 77 66 47 20

  7 38 61 62 63 64 65 46 19

  8 39 40 41 42 43 44 45 18

  9 10 11 12 13 14 15 16 17


9에 대한 출력값...






조건 


 Url에서 특정 패턴을 추출해서 시스템 브라우저를 호출한다. 



Webview에  WebViewClient 를 설정하고


webView.setWebViewClient(new TestWebViewClient());



해당 패턴이 포함되어 있을경우 시스템 브라우저를 호출한다.


private class TestWebViewClient extends WebViewClient {

@Override

public boolean shouldOverrideUrlLoading(WebView view, String url) {

if(url.indexOf("___target=_blank") > -1){

Intent i = new Intent(Intent.ACTION_VIEW);

i.setData(Uri.parse(url));

context.startActivity(i);

return true;

}

return super.shouldOverrideUrlLoading(view, url);

}

}






Kitkat이전까지 이 방법으로 호출하였으나 문제는 킷캣 ( 4.4 kitkat ) 이상에서는 이 방법이 통하지 않습니다...


4.4부터 구글의 크롬엔진이 변경되어서 그렇다는 글을 검색을 통해서 확인하였고


여기저기 뒤져보다가 해결책을 발견...



webView에 웹 크롬 클라이언트를 설정..


webView.setWebChromeClient(new TestWebChromeClient());




새 창이 열리는 액션을 잡아서  해당 패턴일경우  새창에 띄워줍니다.


private class TestWebChromeClient extends WebChromeClient {

@Override
public boolean onCreateWindow(WebView view, boolean isDialog,
boolean isUserGesture, Message resultMsg) {

// Url 문자열을 가져옴.
WebView.HitTestResult result = view.getHitTestResult();
String url = result.getExtra();

if (url != null && url.indexOf("___target=_blank") > -1) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
context.startActivity(i);
return true;
}
return super.onCreateWindow(view, isDialog, isUserGesture, resultMsg);
}


}



상기 두부분을 그대로 유지를 해둬야 4.4 이상에서도 동작하고 4.4 미만에서도 동작을 합니다.




사용중인 갤럭시 S3 의 개발자 도구가 환경설정에서 사라졌다..


숨김 처리가 되있는 ...


서두는 짧게.


홈화면 -> 메뉴버튼 -> 환경설정 -> 더보기


-> 디바이스 정보 

-> 빌드번호를 터치터치터치... 연속으로 하다보면.   3 2 1 . 하고 떨어지면서 Toast가 노출된다...


개발자도구가 활성화 되었습니다.. 라는 문구가 나오고 


Back 버튼... 


더보기 메뉴 아래에  개발자 도구가 활성화 되어있다..


우야건 Success...






페이스북 생활코딩 그룹에 나온문제중 하나...

https://www.facebook.com/groups/codingeverybody/



"1원, 5원, 10원, 50원, 100원, 500원짜리가 각각 C1, C5, C10, C50, C100, C500개씩 있습니다. 가능한 적은 수의 동적으로 A원을 지불하려면, 몇 개의 동전이 있어야 할까요? 지불 방법은 적어도 1개는 존재한다고 가정합니다."




자바 개발자로서(?) 


낼름 풀어보았다...


public static void main(String[] args) {

int val = 5323; // 입력값


int cv = 1000; // 500 -> 100 -> 50 으로 변할값.

int cx = 0, div = 0; // cx는 동전의 갯수 div는 2 : 5 스위치 값.

do {

div = (div == 2 ? 5 : 2); // 처음에 div 는 0이므로 div는 2가 되고 

cv = cv / div; // cv는 500이된다.

cx += val / cv; // val / cv 는 정수값이므로, cx에 나누기의 몫이 들어가고

val = val % cv; // 나머지 값은 다음턴으로 넘긴다.

} while (cv != 1);    // 1이 아니면 루프... do 아래 2번재 줄에서 cv 가 1이되어도 연산이 되므로 문제가 없다.

System.out.println(cx); // 대상 목적인 코인의 갯수만 출력 >.<.

}


댓글로 작성된 다른 능력자 분들의 코드를 보고 있자니..

아직 멀었구나 하는 생각만든다..( 파이썬 능력자님들 ㅎㄷㄷ  , 스칼라도 배우고 싶다능 ... )

좋아하는것을 하나하나 쌓아가는 2013년이 되었으면 하는 바램으로 간만의 포스팅 끗..

상황 : Spring기반으로 짜여진 서버에서 한 클래스의 데이터를 모니터링 페이지에 띄우고자 합니다.


출력해야하는 클래스는 들고 있는 데이터의 가지수만 최소 5-7개에서 내부필드는 20-30개까지


하나하나 정성스레 포멧팅 해주면 되지만. 귀차니즘이 앞서서 어찌하면 이쁘게 String으로 뽑아낼수 있을까 하여


방법을 찾아보았습니다.








Q : 특정 클래스 A를 Json Format을 가지는 String Type로 출력하고자 합니다.


A.

- 구글에서 제공 하고 있는 GSON Library의 Pretty Format 메소드를 활용하여 출력.


GOOGLE GSON : http://code.google.com/p/google-gson/



#. Test Case

ObjClass.java

 import java.util.ArrayList;

public class ObjClass {
    String name;
    int age;
    String address;
    
    ArrayList<String> newArr;
    
}


Main.java 

 import java.util.ArrayList;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class Main {
    public static void main(String[] args){
        ObjClass oc = new ObjClass();
        oc.address = "123";
        oc.age = 56;
        oc.name ="myname";
        oc.newArr = new ArrayList<String>();
        
        
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        String jsonOutput = gson.toJson(oc);

        System.out.println(jsonOutput);
    }
}


#.Output 

{
  "name": "myname",
  "age": 56,
  "address": "123",
  "newArr": []
}
 




필드의 값이 Null 일 경우에는 아에 출력에서 제외됩니다.





이어서 -


View 딴에 데이터를 전달해서 출력할 계획이기에


Javascript를 이용해서 Json Format에 Hightlight 해주는걸 찾아봐야겠습니다...



요즘 이클립스에서 이것저것 NodeJS 학습을 진행중인데


개발 경력 얼마나 되었다고 벌써부터 Code Assist 없으면 개발하기 힘들어집니다... (것보담 타이핑 하기 귀찮아 진다? ... 일이라면 하는데 -_- 공부라 생각하니 더 치기 싫어지는 이유는 뭘까  ..요? )


잡설은 여기까지 줄이겠습니다.


---------------


Eclipse에서 NodeJS를 이용하여 개발하는데 Code Assist 사용하기




준비

1. Eclipse

2. NodeJS

3. Git


시작


1. 

Eclipse -> Menu -> Help -> Install New Software -> 


http://download.eclipse.org/vjet/updates-nightly/


위 URL을 추가하여 플러그인을 설치합니다.


2. https://github.com/ebayopensource/vjet-typelib


Git을 이용하여 위 URL을 다운받습니다..

프로젝트를 첨부하고나면

금일 기준 15개 전후의 프로젝트가 첨부가 됩니다.

프로젝트 명중 TL로 끝나는 애들이 앞으로 Code Assist를 담당하게될 Type Libarary가 됩니다.

프로젝트명 Ex : 




마우스 우클릭 -> Import Projects 이후

필요한 것만 선택하여 Project로 가져옵니다.


3. 2에서 첨부된 프로젝트에서 우클릭 Vjet -> Enable VJET Project Capabilities 를 선택하여 VJET 환경 설정을 활성화 해줍니다.

3-1. 첨부한 프로젝트 만큼 반복해주면 됩니다 ( 노가다 만쉐이~~~ )

4. 개발할 JS 프로젝트 (Node JS 프로젝트역시 동일) 생성이후
 
프로젝트에서 우클릭 -> Properties -> VJET -> VJET Build Path -> Project 탭에 추가된 TL 프로젝트를 추가합니다.



5. 이 작업까지 완료하고 나면

js 파일 내에서 첨부된 TL 항목에 대해서만 Code Assist가 동작하는것을 확인할 수 있습니다 ( 유후~ 만세 만세 ;; )





이래저래 검색해봐도 국문으로 작성된 내용은 확인이 되질 않아 초급개발자분들에게 도움이 되고자 

즐거운 개발에 도움이 되고자 (부족한 내용이지만) 글을 적어보았습니다.



#. 주의 사항?


Github에서 확인해보면 최종 Pushed 된 날짜가 2년전입니다.. (2011 04 ~ 2011 05 가 마지막 업데이트입니다 ( ..) )


Node나 JQuery의 경우 광속 Version Up을 하고 있는데 그 빠름을 따라가지 못하는 듯하여


최신 버전관련된 내용이 노출되지않거나 Deprecated된 내용이 정상적으로 노출될수 있으니 100% 신뢰는 금물입니다.





참조 : http://wiki.eclipse.org/VJET/Importing_VJET_JavaScript_Type_Libraries


Win7에서 Node 개발 환경을 구축하고 개발하다가 Custom Module의 추가가 요구되어 질때가 있다.


npm install 블라블라 


명령어를 이용해서 설치하는 방법이 있지만.


설치를 해도 잡히지가 않고


NODE_HOME 환경변수를 등록해도 이클립스에서 모듈을 못불러온다... 


추가로 


www.nodejs.org  에서 Download를 이용해서 받으면


설치 경로 변경도 못한다.!!! ... (윈도우가 설치된 드라이브는 Win7기준으로 이래저래 제한사항이 몇 걸린다... )


그래서 발견한 해결책... 


http://code.google.com/p/nodejs-win/


Node 설치경로 변경가능


기본 모듈 10여개 미리 설치됨


해당 결로의 루트에서 npm install 명령으로 추가 모듈 설치시 정상적으로


동작 :)




개발을 진행하다보면 Apache - Tomcat 구조로 서버 세팅을 완료하고


이미지를 캐싱한다는 이야기를 들었다..


어찌하나 직접 찾아보기로 해서 직접 아파치 설치를 해서 구현해 보았다..



Apache 설치

http://httpd.apache.org/download.cgi#apache24


Windows 기반으로 설치 진행

2.0.64버전을 설치




아파치 설치 경로\Apache2\conf

httpd.conf  : section 2


 LoadModule expires_module modules/mod_expires.so


위 라인 주석제거



httpd.conf Section2 에 아래 항목 추가


 #

# Apache Server Static Data Caching

#

<IfModule mod_expires.c>

        ExpiresActive On

ExpiresByType image/png "access plus 1 month"

</IfModule>



위 설정까지 적용한후 아파치 Restart를 수행한다.



Test용 이미지 등록

C:\Program Files (x86)\Apache Group\Apache2\htdocs\testProject\resources\images\k.png


Test용 Html 등록

C:\Program Files (x86)\Apache Group\Apache2\htdocs\testProject\a.html


a.html 의 내용은 Test이미지를 화면에 노출하는 단순 구조


이 테스트를 위해서 Fiddler를 사용해서 캐싱되는것을 확인하였다.

http://www.fiddler2.com/fiddler2/




아파치 뒤의 서블릿 컨테이너(톰캣)으로 전달되는것을 방지하기 위해


mod_proxy를 손봐야한다는 정보도 Get하였다.



참고 링크

http://ant103.egloos.com/198165

http://www.javajigi.net/pages/viewpage.action?pageId=287244298

http://system.neulwon.com/xe/?mid=linux_apache&page=2&document_srl=1518



안드로이드 에서 메시지 기반으로 이리저리 통통 기기 제어를 하려 하는데....


Permission Deny 상황이 자꾸 떨어진다.


뭘까 ...


http://www.android-permissions.org/permissionmap.html


오늘 (2012 10 09 ) 까지는 잘 접속되는데 나중에 될진 모르겠다..


중한 내용은 아래 내용... Broadcast Message 로 아래 내역은 허락되지 않는다. 시스템딴에서만 전송 가능하다는 이야기.. 다른 방법으로 메시지 날리는게 정답인듯?!?!?


android.app.action.ENTER_CAR_MODE, android.app.action.ENTER_DESK_MODE, android.app.action.EXIT_CAR_MODE, android.app.action.EXIT_DESK_MODE, android.backup.intent.CLEAR, android.backup.intent.INIT, android.backup.intent.RUN, android.bluetooth.adapter.action.DISCOVERY_FINISHED, android.bluetooth.adapter.action.DISCOVERY_STARTED, android.bluetooth.adapter.action.LOCAL_NAME_CHANGED, android.bluetooth.adapter.action.SCAN_MODE_CHANGED, android.bluetooth.adapter.action.STATE_CHANGED, android.bluetooth.device.action.ACL_CONNECTED, android.bluetooth.device.action.ACL_DISCONNECTED, android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED, android.bluetooth.device.action.BOND_STATE_CHANGED, android.bluetooth.device.action.CLASS_CHANGED, android.bluetooth.device.action.DISAPPEARED, android.bluetooth.device.action.FOUND, android.bluetooth.device.action.NAME_CHANGED, android.bluetooth.device.action.NAME_FAILED, android.bluetooth.device.action.PAIRING_CANCEL, android.bluetooth.device.action.PAIRING_REQUEST, android.intent.action.ACTION_MDN_STATE_CHANGED, android.intent.action.ACTION_POWER_CONNECTED, android.intent.action.ACTION_POWER_DISCONNECTED, android.intent.action.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, android.intent.action.ACTION_SHUTDOWN, android.intent.action.ANY_DATA_STATE, android.intent.action.BATTERY_CHANGED, android.intent.action.BATTERY_LOW, android.intent.action.BATTERY_OKAY, android.intent.action.BOOT_COMPLETED, android.intent.action.CONFIGURATION_CHANGED, android.intent.action.DATA_CONNECTION_FAILED, android.intent.action.DEVICE_STORAGE_LOW, android.intent.action.DEVICE_STORAGE_OK, android.intent.action.DOCK_EVENT, android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED, android.intent.action.LOCALE_CHANGED, android.intent.action.NETWORK_SET_TIME, android.intent.action.NETWORK_SET_TIMEZONE, android.intent.action.NEW_OUTGOING_CALL, android.intent.action.PACKAGE_ADDED, android.intent.action.PACKAGE_CHANGED, android.intent.action.PACKAGE_DATA_CLEARED, android.intent.action.PACKAGE_INSTALL, android.intent.action.PACKAGE_REMOVED, android.intent.action.PACKAGE_REPLACED, android.intent.action.PACKAGE_RESTARTED, android.intent.action.RADIO_TECHNOLOGY, android.intent.action.REBOOT, android.intent.action.SCREEN_OFF, android.intent.action.SCREEN_ON, android.intent.action.SERVICE_STATE, android.intent.action.SIG_STR, android.intent.action.SIM_STATE_CHANGED, android.intent.action.TIMEZONE_CHANGED, android.intent.action.TIME_TICK, android.intent.action.UID_REMOVED, android.intent.action.USER_PRESENT, and android.provider.Telephony.SPN_STRINGS_UPDATED. 





이 글을 Effective Java를 읽고 적는 글임을 미리 밝힌다. ( 서적에 정확하게 기록되어있다. )

---------------------------------------

아래의 간단한 코드를 보자.

String strInputValue = "I Love You";

System.out.println("["+strInputValue+"]");

if(strInputValue.equals("TRUE"))

{

System.out.println("True");

}


흔하디 흔한 String 변수선언 이후 변수를 출력하고  문자열과 비교 후 일치할 시에 True 라는 문구를 출력하는 코드이다..

너무 쉽다? 그렇다. 너무 쉬운 코드라면 코드다.. 

위 코드에서 strInputValue 의 값을 null 로 변환하면 어떤 일이 벌어질까?





String strInputValue = null;

System.out.println("["+strInputValue+"]");

if(strInputValue.equals("TRUE"))

{

    System.out.println("True");

}





결과

[null]

Exception in thread "main" java.lang.NullPointerException

at com.ncf.test.java.TestClass.main(TestClass.java:13)




읭?

출력에서 null은 잘 찍어놓고..

비교 구문에서 오류를?

 
대학 시절에는. 아래와 같은 구문으로 null 값에 대한 처리를 수행했었다.


if(strValue != null && strValue.equals("test"))
{
System.out.println("Success");
}


대충 위와 같은 코드다... 물론 이도 동작은 한다.

좀 더 깔끔한 코드를 원하는것 뿐이다.


String strInputValue = null;

System.out.println("["+strInputValue+"]");

if("TRUE".equals(strInputValue))

{

System.out.println("Pass");

}




그렇다면 이 코드는 어떤가?

에? 위하고 비교했을때 .. 비교값의 위치가 반대인 것이잖아?

그렇다면 결과는 어떨까?



글을 쓰고 있는 이유와 같이. Null pointer Exception 은 발생하지 않는다.

왜일까?

좌변의 값 떄문이다.

자바에서 비교는 일단 좌측의 값을 기반으로 비교를 행하는데.

상단의 코드의 경우 좌측의 값이 null 이다... 고로 비교 자체를 할수가 없다.


아래의 경우는 좌측의 값이 문자열 TRUE다.. 우측의 값이 null 이므로 다른값으로 간주하게 되는것이다.


간단한 트릭? 이지만, SI를 뛰고 있는 개발자 입장에서 유익하게 사용중이니

가벼운 마음으로 익혀두면 두고두고 나쁠일은 없지 않을까?






 
자 이제 몽고 DB를 좀 주물럭 거려보자..

1. 쉘 접속 ( 1회차를 참조하시라 )

2. Data Insert.

입력에 사용되는 데이터 타입은 JSON 타입이다.

JSON을 잘 모르겠다? 하는 사람은 

http://json.org/ 이곳에 접속해서 그림! 을 잘 따라가면!!! 이해할 수 있을것이다.

JSON은 
{ "key" : "value" } 의 형태를 가진 표현 방법이다.

사용가능한 변수 타입은 차후에 기록하는 것으로 미루고 

쉘에다 데이터를 넣어보자.

> var my insert = { "user" : "blahblah" , 
... "type" : "human",
... "age" : 30,
... "tune" : "no"
... };
Fri Jan 20 00:13:29 SyntaxError: missing ; before statement (shell):1
> var myinsert = { "user" : "blahblah" , 
... "type" : "human",
... "age" : 30,
... "tune" : "no"
... };
> db
framework
> db.test.insert(myinsert)



입력을 했더니 서버 로그가 좌르륵 올라간다.!

뭐지 하고 대충 확인해보니

첫 데이터를 입력하니 DB가 생성되었따는 문구 

그래 가서 확인해보는거야..



오호라... DB 명칭이 framework ...

파일명도 framework.* 

그렇군..



조회를 해보자..

> db.test.find()
{ "_id" : ObjectId("4f18334ee18f4804da05227f"), "user" : "blahblah", "type" : "human", "age" : 30, "tune" : "no" }



데이터를 아무거나 하나 더 넣고 조회를 해보자.

> var myinsert2 = { "user" : "blahblah2" , 
... "type" : "alien",
... "age" : 26,
... "tune" : "yes"
... };
> db.test.insert(myinsert2)
> db.test.find()
{ "_id" : ObjectId("4f18334ee18f4804da05227f"), "user" : "blahblah", "type" : "human", "age" : 30, "tune" : "no" }
{ "_id" : ObjectId("4f18344ee18f4804da052280"), "user" : "blahblah2", "type" : "alien", "age" : 26, "tune" : "yes" }



결과물에 추가로 기록된 _id는 차후에 설명하겠다.. 

일단 데이터마다 가지는 Unique Key라고 기억하면 되겠다..

SELECT * FROM USERS WHERE ID = 'human'

뭐 이런건 어찌 조회하나?
 
해보자..

> db.test.find({"user":"blahblah"})
{ "_id" : ObjectId("4f18334ee18f4804da05227f"), "user" : "blahblah", "type" : "human", "age" : 30, "tune" : "no" }
>

 

조회 조건에도 역시 JSON  타입을 사용해서 조회를 해야한다.

find 이외에도 findOne 라는 메소드가 있으니 확인해보자.


수정.
user:blahblah 를 가지는 사용자에 대해

type을 frog로 변경해보자..

> db.test.update(
... {"user":"blahblah"},
... {"$set" : { "type":"frog" } }
... )
> db.test.find()
{ "_id" : ObjectId("4f18334ee18f4804da05227f"), "age" : 30, "tune" : "no", "type" : "frog", "user" : "blahblah" }
{ "_id" : ObjectId("4f18344ee18f4804da052280"), "user" : "blahblah2", "type" : "alien", "age" : 26, "tune" : "yes" }
>

 
update 구문을 보면
첫 파라메타로 검색 조건
다음 파라메타로 제한자($set)와 변경할 값을 설정한다.
 

age 수치의 증가.
 
테스트 하다가 깜짝 놀랬는데.. 놀라고 나서 생각해보니 당연하다..

> db.test.update(
... {"user":"blahblah"},
... {"$inc" : { "age":30 } }
... )
> db.test.find()
{ "_id" : ObjectId("4f18334ee18f4804da05227f"), "age" : 60, "tune" : "no", "type" : "frog", "user" : "blahblah" }
{ "_id" : ObjectId("4f18344ee18f4804da052280"), "user" : "blahblah2", "type" : "alien", "age" : 26, "tune" : "yes" }
> db.test.update(
... {"user":"blahblah"},
... {"$inc" : { "age":1 } }
... )
> db.test.find()
{ "_id" : ObjectId("4f18334ee18f4804da05227f"), "age" : 61, "tune" : "no", "type" : "frog", "user" : "blahblah" }
{ "_id" : ObjectId("4f18344ee18f4804da052280"), "user" : "blahblah2", "type" : "alien", "age" : 26, "tune" : "yes" }



윗줄에서 inc 제한자를 사용하여 30.. 을 설정했는데..

30이 증가되어버렸다.. 원 값인 30을 입력하는건가 하고 생각해서 입력한 값이었는데 60이 되어버렸다 -_- ... 

그래서 다시 1로 테스트 해보니 30 -> 60 -> 61 .. 로 변하는 값을 확인할수 있엇다.


삭제 해보자!

> db.test.find()
{ "_id" : ObjectId("4f18334ee18f4804da05227f"), "age" : 61, "tune" : "no", "type" : "frog", "user" : "blahblah" }
{ "_id" : ObjectId("4f18344ee18f4804da052280"), "user" : "blahblah2", "type" : "alien", "age" : 26, "tune" : "yes" }
> db.test.remove({"age":61})
> db.test.find()
{ "_id" : ObjectId("4f18344ee18f4804da052280"), "user" : "blahblah2", "type" : "alien", "age" : 26, "tune" : "yes" }
> db.test.remove()
> db.test.find()



사용법은 검색이나, 수정에 사용했던 방법과 유사한거 같다.. 

사용 방법은 위 로그를 참조..




이제 MongoDB가 좀 익숙해 질려한다...




현재 O'REILLY사의 "MongoDB 완벽 가이드"를 보면서

학습식의 글을 작성중인데..

글을 남기는 이유는 강의도 아니고 필요에 의해 검색하기 위함이다.

어려운 질의는 늦게 늦게 답변이 달릴수도 있으니 ! 양해 바랍니다 ㅡ.ㅜ;

 


 
 
 
MongoDB 설치

홈페이지 : http://www.mongodb.org/
 
다운로드 페이지 : http://www.mongodb.org/downloads

Data 폴더 : /data/db

mkdir -p /data/db

다운로드 페이지에서 받은 파일은
/data/mongodb-osx-x86_64-2.0.2
여기에 풀었다..

MongoDB의 실행은

$bin/mongod


db 경로를 설정하려면
 

$bin/mongod --dbpath ~/



자 실행해보자

MongoDB가 설치된 경로

MongoDB 구동



서비스 중인 포트로 접속해보면 1000을 더하면 진단 툴에 접속할수 있을을 알리는 메시지를 노출한다.

진단툴의 모습 주소는 localhost:28017이다.







MongoDB  쉘 실행하기
$bin/mongo

쉘의 기본은 자바 스크립트의 기본을 그대로 사용가능.

변수를 할당한다거나. 수학 연산, 함수 생성등이 가능.



> use framework
switched to db framework
> db
framework


사용할 DB를 설정(use)하고 현재 DB를 확인(db)하는 명령.

글이 길어지니

MongoDB 내에서 CRUD는 2회차로! 미룸!!

 





안드로이드의 가장 큰 문제점이라면

기기별로 해상도가 다르다는점..

 개발사에게는 기기의 다양화를 꾸릴수 있는 거지만


나같은 나약한(?) 개발자에게는 이거 어찌 해야하나.. 하는 탄식이 나오게 하는 큰 문제점이라면 문제점이다.


뭐 오늘도 두어시간 삽질을 통해(?) 수확한 즐거운 꺼리 하나를 투척한다. (얼마만의 블로깅인지 모르겠다.. )


테스트 대상은 가장 널리 퍼져 있는 대표 테스트 단말.

갤럭시 S ( 800 * 480  / hdpi )

갤럭시 탭 7 ( 1024 * 600 / hdpi) - 이하 탭7

갤럭시 탭 10.1 ( 1280 * 800 / mdpi ) - 이하 탭10 / 널리 퍼져 있는 단말은 아닌가? -_- ;;;



1. 전제 조건으로 단일 APK를 뱉어내야할것

2. 갤럭시S기반으로 앱은 개발 되었고

3. 탭7 탭10을 지원해야한다.

4. 이미지 리소스는 확대를 허용한다. 


결론부터 얘기하면 이전 포스팅에서 사용한 방법으로는 구분이 불가하다.

layout
layout-1024x600
layout-1280x800 

요 방법..

이상하게 탭10에서 구동시에는 탭7의 레이아웃을 참조해버린다.. (다른 별도 설정이 있는지는 모르겠다.. )

이래저래 안드로이드 개발자 사이트좀 뒤적거리다가  테스트후에 찾은 결론
(참고 링크 : http://developer.android.com/guide/practices/screens_support.html )


layout
layout-large
layout-xlarge

순서대로 갤S
탭7 탭10을 참조한다.. 짜잔...
갤S랑 갤탭은 해상도가 유사하니 hdpi에 때려넣고 그냥 참조 하여 일부 수정.

탭10은 해상도가 어마어마하게 차이나지만 -_- mdpi 니깐 별도로 이미지를 mdpi폴더에 넣어도 되고

아니면 무식하게 hdpi에 있는 녀석을 복사해서 넣어주면, 그럴싸하게 보여진다.

...... mdpi에 파일이 없으면? 절반 크기 정도로 화면에 노출되는것을 알수 있다.

결과로 뱉어내는 APK 용량이 문제라면 문제지만.. (당연한것이다. 고밀도 이미지와 중밀도 이미지를 복수로 저장하고 있으니.. )

단일 APK로 뱉어내야만 하는 상황이라면

충분 고려해 볼만한 개발방법.. (폴더관리? )

이상 .







 
안드로이드 리소스 사용에 대해

다양한 해상도 및 DPI지원에 대해


layout-1024x600
drawable-hdpi-1024x600

이런식으로 폴더 작성후 레이아웃이나 이미지를 넣어줄시에

해당 사항에 맞는 리소스를 불러들인다..

코드 삽질을 줄여주는 중요한 요소중 하나 :)

 


그렇다면 언어 설정은?

drawable-ko
drawable-en
 
공통요소는 drawable 에 :)




  ------------------

댓글에 욕설(?) 이 없는걸로 보아 참고하신 분이 없는거 같군요. (은근 다행입니다 ;; )

과거 .1024*600 에서 1024x600 으로 오타 수정하였습니다. 


http://gtko.springnote.com/pages/5254593.xhtml


검색중에 솔깃한 URL 발견..

Intent FLAG  정리

TextView 에 URL을 낑궈 넣을수 있는

Linkfy 설정 등.

유용한 기술들이 기록되어있다...



통화

#758353266#646#

입력이후 리붓되고나서

USIM 다운로드가 진행되면 완료 :)






안드로이드에서 제공하는 

스택의 크기는.

8KB..

아 작다 ( --);;; 모바일 환경이니 그러려니.. 하지만서도

Recursive좀 굴리다보면

훌쩍 초과하는게 8kb...


8kb이상을 사용할려면 쓰레드 그룹을 만들어서

최대 스택 크기를 늘리는 방법!

아래 코드 참조 ( --);

Runnable r = new Runnable(){
@Override
public void run() {
// Do SomeThing
}
};
ThreadGroup tGrp1 = new ThreadGroup("ThreadGrp00001");
Thread a = new Thread(tGrp1,r, "Thread Name", 1024*256) ;
a.start();


최대 크기는 256kb.

개발자 포럼에 가보니..

그 이상은 어떻게 사용이 가능하냐는 질의에...

최적화 해라 -_- 라는 아름다운 답변..



그럼 즐 코딩~ 

내가 쓸려는 User 테이블..

Primary Key로 이미 두개의 값이 잡혀있다...

phoneNumber , nickName

타 테이블(대략 10개쯤) 저 값을 참조하고 있어서 

1. ALTER TABLE User ADD idx int(11) NOT NULL AUTO_INCREMENT;
2. ALTER TABLE User ADD idx int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT;

안먹는다 -_-.. 당연하다..

자동 증가값은 KEY가 아니면 안된다.

그렇다면 키를 해제!


ALTER TABLE User DROP PRIMARY KEY;
ALTER TABLE User DROP PRIMARY KEY (nickName,phoneNumber);

안된다 -_- 다른 테이블 참조 다 끊던가.




어쨋든 User에 순번을 추가해야하는 상황..

모로가도 서울로 가면된다.!

Unique Key.. (어디서 들었는데 검색하다 급 눈이 반짝 *.* )


ALTER TABLE User ADD idx int(11) NOT NULL UNIQUE KEY AUTO_INCREMENT;

그래서 이것!..

성공~ .~




PRIMARY KEY와 별개로 설정이 가능하고 중복을 방지해준다.

PRIMARY KEY로 선언할수 없는 상황에서 사용하면 나름 유용할듯하다..




P.S. DB Schema 설계할때,  안쓰더라도 idx는 기본으로 좀 넣어주라 ㅠ.ㅠ. 제발;;(모 님 찔리십니까? )






ALTER TABLE [[[TableName]]] AUTO_INCREMENT = [[[VALUE]]];

Table에서 AutoIncrement 값을 사용하다가 특정 값으로 설정해줄때.
예를들어 
신규 테이블(TblBoardFree) 생성 -> 시작번호를 10001번으로 하고싶으면

ALTER TABLE TblBoardFree AUTO_INCREMENT = 10001;

다음에 신규로 추가한 항목은 10001번의 값을 가지게된다.




P.S. 자주 쓰는데 자꾸 잊어버린다 ㅡ.ㅜ;


요즘 검색해보니 원클릭 루팅이 있더군요..

아래 과정을 한방에(?) 진행해주는 녀석 같습니다.

+ 사용에 대한 책임은 모두 본인이 지고 가는겁니다..


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

간략하고 텍스트 위주의 모토로이 루팅 방법에 대해 기록하겠습니다.

기존 전제조건은

1. 모토로이  USB 드라이버가 설치된 상황 [ 요거 하나; ]



널리고 널린 첨부 파일

다음을 다운받아서 압축을 풀고


1. USB연결
2. 상단 USB 연결 메뉴에서 "모토로라 휴대전화도구" 선택
3. 바탕 -> 메뉴버튼 -> 설정 -> 응용프로그램 -> 알수없는 소스 ON 
4. 3에 이어 개발 메뉴 -> USB 디버깅 ON 켜진상태로 유지 ON
5. 설정 -> Wifi OFF BlueTooth Off
6. 계정및 동기화 -> 백그다운드 데이터 OFF (자동으로 자동 동기화 OFF)

Console 을 열어 (Win + R : cmd [enter] )
adb push Superuser.apk /sdcard/superuser.apk
adb push su /sdcard/su
adb push busybox /sdcard/busybox
adb push exploid /sqlite_stmt_journals/exploid
adb shell

cd sqlite_stmt_journals
chmod 755 exploid
./exploid
rootshell 


여기 rootshell 을 실행하기 까지 여분의 시간이 소요됩니다.(기다렸다가 입력하세요)

패스워드를 묻는 곳에서

secretlol 

cp /sdcard/superuser.apk /system/app/superuser.apk
cp /sdcard/su /system/bin/su
cp /sdcard/busybox /system/bin/busybox
chmod 4775 /system/bin/su
chmod 4775 /system/bin/busybox
rm /system/bin/rootshell

exit
exit

adb shell
su

모토로이 화면에서 Allow 선택
이상루팅끝

기타 설치 추천(?) 어플.

Estrongs File Explorer : 무료 파일 매니저

My Market : 해외 무료 게임 마켓 접근 가능

MilestoneOverclock12 : 오버클러킹 
Launcher Pro : 빠른 홈 런처

Mini Info : 배터리, 내장 매모리, SD 용량  위젯

APNDroid : 3G차단 위젯

Advanced Task Killer : 작업관리자 ( 위젯 강추 )



즐거운 안드로이드 생활이 되시길!

Enjoy!

프로젝트를 진행하던중


수많은 리소스로 골머리가 솔솔 아파왔는데!

어라? 폴더에 폴더 추가해서 쓰면 

그래도 좀 보기는 편하겠네?



.. 일단 결론은 안됩니다...

@drawable/lv2/img블라블라..


값 자체를 

해석하지를 못하는건지 어쩐건지






위 이미지와 같은 구조에 대해 지원을 해주지 않으므로(혹시 가능한 방법을 알고 계시면 알려주세요 ㅠ.ㅠ. )

file명을 잘 지어서 임시로 회피하세요...

뭔가.. 다른곳에 문의를 해봐야겠습니다.




View v;

LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.row, null);

TextView tt = (TextView) v.findViewById(R.id.toptext);
TextView bt = (TextView) v.findViewById(R.id.bottomtext);

return v;


뭔가 미묘하게 문제 스럽지만

중요한 코드들은 다 잘 들어가있는 Layout Inflater...

return v 대신에 setContentView(v)식으로 선언해주면 

Activity내 onCreate에서 바로 화면에 설정도 가능하다는점...

참고하세요 :)






5/7일 실시한 안드로이드펍 개발자 컨퍼런스에 다녀왔습니다.


개발자 팁 위주의 강연이 

꽤나 마음에 들었습니다.


물론 중간에 -_- 거침없는 취침폭풍을 취해서 미친듯이 아쉬운 부분도 있습니다. (이놈의 저질 체력... )




아래는 간략한 설명. + 강의중에 몇 기록한것들


세션1 - 안드로이드 다양한 스크린 디바이스를 위한 UI처리 : 박성서 ( 회색님 )
- Pixel을 사용하지 말아라, DIP를 사용하라.
- Abs Layout을 사용하지 말아라 (1.5부터 Deprecated 되었다고는 하는데 -_- 실제 사용해보면 작동은 하죠? ;; )
- 이미지는 고해상도 이미지를 사용해라 (res/HDPI 경로 이용 )

세션2 - 안드로이드 인터넷 서비스 연동 애플리케이션 개발 ( 강순권 )
 - 인터넷 작업이 들어간 애들은... 전부 
 Cache, Async를 유지하라 + 음영지역에 대한 대비를 하라.


HVGA - 16MB
WVGA - 24MB 의 어플 할당 공간..


NDK 세션에서는 -_-; 빠른 속도를 보장한다는게 주였습니다.
여기서 고민했었던것이...

어플 개발하라고.. SDK가 있는 것인데. 속도를 위해서 NDK로 가야한다그러면.. 전부 NDK로 가야하는것 아닌가?

하는 생각이 들었습니다.

발표자(이제현)님이 말씀하신대로.. 안드로이드 베이스에서 300p이상의 PDF리더는 NDK로 작성한 애들뿐이다.. 라고 말씀하시는게..

앞으로 NDK도 공부좀 해둬야되겠더군요 ㅠ.ㅠ..

+ 강조하신 포인트는...

일반 어플 UI의 구현에..

가속을 받아서 구동해야하는 부분만 NDK로 구현하는 구조로 가야한다고 말씀하시더군요..

좋은 정보 인거 같아 기록에 남깁니다 :) - 다시한번 감사의 말씀 드립니다. 



OK JSP 의 허광남님은... 말투가.. 완전 유쾌하시더군요.

이클립스 사용에 Short Cut위주의 설명이라 ..

쉬운 주제였으나, 알면알수록 개발속도 향상에 큰 도움을 주는 것들?

저역시 단축키 매니아라서;;

저보다 많이 알고 계시더군요 ( --);



세션 6의 AR부분은 SurfaceView 에 대한 설명 부분이 유독 기억에 남는군요.. 
배터리 잡아먹는 귀신! 사용은 해라 그렇지면 UX에 긍정적인 결과를 미치지는 않을것이다.. 라는 놀라운 발언과 함꼐...



이상 대략적인 후기였습니다.


아래는 
컨퍼런스 전리품(?) 응?








내 PC를 서버로 둔 상태에서

안드로이드 에뮬로 작업을 하는도중..



URL targetUrl = new URL("http://127.0.0.1:8888/test.jsp");


이런 URL로 Request 를 날렸더니

접근이 거절되었습니다.

라고 나오길래;


뭔가 문제 인가.. 하고..

뒤적거려보니..

잘 생각해보니..

에뮬 자체로 저 방향(Localhost or 127.0.0.1)이 설정됨을 알수가 있었습니다...

Localhost나 127.0.0.1 같은 녀석은.

안드로이드 AVD자신을 가리키므로..

내 PC의 IP를 직접 기록해주어야


원할한 테스트를 진행할수가 있습니다.




Java에서 오늘 날짜 출력하기..

TimeStampMillis 를 사용해도 되지만..


바로바로 뽑아서써야할 필요가 있을때에

이만한 메소드가 따로 없다;;



public String getDateTime()
    {
     Calendar oCalendar = Calendar.getInstance( );  

        return "" + oCalendar.get(Calendar.YEAR) + "."
        + (oCalendar.get(Calendar.MONTH) + 1) + "."
        + oCalendar.get(Calendar.DAY_OF_MONTH) + " "
        + oCalendar.get(Calendar.HOUR_OF_DAY) + ":"
        + oCalendar.get(Calendar.MINUTE) + ":"
        + oCalendar.get(Calendar.SECOND);
    }



이상 끝...

Coming Soon..


On March 2010.

+ Recent posts