2012년 2월 20일 월요일

iPhone - NSString 숫자만 , 숫자빼고 제거

NSString* test = @"#+123$@45";

NSLog(@"%@",[[test componentsSeparatedByCharactersInSet:

                            [[NSCharacterSet decimalDigitCharacterSet] invertedSet]] 
                               componentsJoinedByString:@""]);

=> 12345

2012년 2월 14일 화요일

iPhone - NavigationItem UIBarButtonItem ( BarButton 넣기 )

UIBarButtonItem *bbtnSave = [[UIBarButtonItem alloc] initWithTitle:@"저장"
                                                            style:UIBarButtonItemStyleBordered
                                                           target:self
                                                           action:@selector(save)];

self.navigationItem.rightBarButtonItem = bbtnSave;
[bbtnSave release];     
    

- (void)save {

  ....
}

iPhone - NSString Split ( 스플릿 )

NSString* str = @"test1,test2,test3";

NSArray* list = [str componentsSeparatedByString:@","];

2012년 2월 12일 일요일

iPhone WebVeiw - Reading Html ( html 가져오기 )

NSString* html = [webView stringByEvaluatingJavaScriptFromString:@"document.body.innerHTML"];

iPhone WebView Error - uiwebkit error 101 ( 한글, 빈화면, 안뜨는 경우 )

url 에 한글/빈문자 등의 문제로 webview 가 "uiwebkit error 101" 를 뱉어내며
실제 화면에 아무것도 출력이 안된다.

아래와 같이 인코딩을 해주면 해결이 된다.

NSString* url = @"http://www.jmkook77.com?%@"
NSString* param = [@"q=가나다 가나다 가나다" stringByAddingPercentEscapeUsingEncoding:NSUTF8StringEncoding];

NSString* webUrl = [NSString stringWithFormat:@"%@%@", url, param];


[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString: webUrl]]]; 



2012년 2월 9일 목요일

페이스북 유저수 국가별 통계 ( facebook user )

페이스북 한국 유저가 570만이 넘는군요. 국가 순위 28위!!

일본이 670만에 25위!!

곧 따라잡는건가요.

http://www.socialbakers.com/facebook-statistics/


twitter, youtube 등 괜춘한 사이트네요.

2012년 2월 5일 일요일

몽고db ( mongodb ) - 로깅 ( Logging ) , Rotating

1. 커맨드라인 옵션 설정

  1) Rotating

     ./mongod --logpath /log/mongodb/mongod1.log --logappend

     > ls /log/mongodb/
   
     -rw-rw-r-- 1 user user 55020391  2월  6 03:42 mongod1.log
     -rw-rw-r-- 1 user user   9496452  2월  6 02:04 mongod1.log.2012-02-06T02-04-16

    위와 같이 날짜별로 로깅이 됨

  2) 로그 레벨

    --quiet 옵션으로 로그 최소화

    -v 옵션으로 더욱 상세히 -vv 더더욱 상세히 -vvv 더더더욱 상세히 -vvvv....


2. 어드민 콘솔에서 설정

   > use admin
   > db.runCommand("logRotate")
   { "ok" : 1 }

2012년 2월 2일 목요일

몽고db ( mongodb ) 3 - 3 노드 리플리카셋 ( 3 Node Replica Set ) - 레플리카셋,이중화,장애

3 노드 리플라카셋

1. 구성

 1) 세개의  mongodb 프로세스를 가집니다.

 2) 1개의 장애를 허용합니다.

      a,b,c 중 a 가 master 이고 b,c 가 슬레이브라면 b,c 두개 장애 시에는 물론 운영에 영향을 안받겠습니다만. master 인 a 가 먼저 죽으면 b,c 중 우선권이 높은 녀석이 master 가 됩니다.
      다시, 두번째 master 가 죽는다면 답이 없습니다.
      master 는 각 노드의 투표를 통해 과반수가 넘는 표를 받은 우선순위 높은 노드로 선출이 됩니다. 즉, 3 개의 리플리카셋 구성에서는 3 개중 하나가 장애가 발생하여 2개가 남더라도 총 2/3 이라는 과반수가 넘는 표결로 남은 2 개중에서 새로운 master 가 선출될 수 있겠지만, 남은 두개중에서 장애가 발생한다면 1/2  이므로 누가 될지 선출할 수가 없습니다.

    아 헷갈려 ㅋㅋ

 3) 데이터는 세개의 저장소를 가지며 동기화 됩니다.

      테스트로 하므로 제 맥 하나에 세개를 띄울 것이지만.. 운영상에서는 동일한 서버에 이런 구성을 가진다면 io 경합으로 성능이 현저하게 떨어지겠죠.


2. 설치 환경

 1) mac os
 2) mongodb : /app/mongodb
 3) log : /app/mongodb/log
 4) data : /app/mongodb/data1, data2, data3 ( 폴더를 생성해 놓습니다. 권한도 체크 )
 5) port : 40001,40002,40003
 6) replica-set group name : group1 ( group 이라는 말이 이해가 쉬워서 그냥 이렇게 적습니다. )


3. 설치

 1) 구동/중지 스크립트 작성

   # data1
   # start_data1.sh
   /app/mongodb/bin/mongod --replSet group1 --port 40001 --fork --logpath /app/mongodb/log/data1.log --dbpath /app/mongodb/data/data1

   # stop_data1.sh
   ps -ef |grep -v grep |grep data1.log |awk '{print $2}' |xargs kill -2

   # data2
   # start_data2.sh
   /app/mongodb/bin/mongod --replSet group1 --port 40002 --fork --logpath /app/mongodb/log/data2.log --dbpath /app/mongodb/data/data2

   # stop_data2.sh
   ps -ef |grep -v grep |grep data2.log |awk '{print $2}' |xargs kill -2

   # data3
   # start_data3.sh
   /app/mongodb/bin/mongod --replSet group1 --port 40003 --fork --logpath /app/mongodb/log/data3.log --dbpath /app/mongodb/data/data3

   # stop_data2.sh
   ps -ef |grep -v grep |grep data3.log |awk '{print $2}' |xargs kill -2

   # --replSet 에 각 노드들을 묶을 수 있는 이름인 group1 이 들어갑니다.



 2) 리플리카셋 초기화

   각 노드들을 구동합니다.
   ps -ef |grep mongod 로 프로세스가 정상적으로 떠있는지 확인하구요..

   다음과 같이 한 서버에 접속합니다.

   $ ./mongo localhost:40001
   MongoDB shell version: 2.0.1
   connecting to: localhost:40001/test
   
   > config = {_id: 'group1', members: [
            {_id: 0, host: 'localhost:40001'},
            {_id: 1, host: 'localhost:40002'},
                {_id: 2, host: 'localhost:40003'}]
            }

{
"_id" : "group1",
"members" : [
{
"_id" : 0,
"host" : "localhost:40001"
},
{
"_id" : 1,
"host" : "localhost:40002"
},
{
"_id" : 2,
"host" : "localhost:40002"
}
]
}

   > rs.initiate(config);



{
"info" : "Config now saved locally.  Should come online in about a minute.",
"ok" : 1
}

  
  3) 확인

      일단, 기본적인 시간이 들어가므로. 몇분정도 뒤에 확인을 하도록 합니다.

$ ./mongo localhost:40001
MongoDB shell version: 2.0.1
connecting to: localhost:40001/test

      우선, 해당 서버가 PRIMARY 즉, master 로 설정된 것을 확인할 수 있습니다.

PRIMARY> rs.status()

{
"set" : "group1",
"date" : ISODate("2012-02-03T06:52:12Z"),
"myState" : 1,
"members" : [
{
"_id" : 0,
"name" : "localhost:40001",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"optime" : {
"t" : 1328251739000,
"i" : 1
},
"optimeDate" : ISODate("2012-02-03T06:48:59Z"),
"self" : true
},
{
"_id" : 1,
"name" : "localhost:40002",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 180,
"optime" : {
"t" : 1328251739000,
"i" : 1
},
"optimeDate" : ISODate("2012-02-03T06:48:59Z"),
"lastHeartbeat" : ISODate("2012-02-03T06:52:10Z"),
"pingMs" : 0
},
{
"_id" : 2,
"name" : "localhost:40003",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 178,
"optime" : {
"t" : 1328251739000,
"i" : 1
},
"optimeDate" : ISODate("2012-02-03T06:48:59Z"),
"lastHeartbeat" : ISODate("2012-02-03T06:52:10Z"),
"pingMs" : 0
}
],
"ok" : 1
}

     data2,3 가 SECONDARY 로 설정되어있는것을 확인할 수 있습니다.


 4) 장애확인

   현재 master 인 data1 을 stop_data1.sh 로 내립니다.

$ ./mongo localhost:40001

MongoDB shell version: 2.0.1
connecting to: localhost:40001/test
Fri Feb  3 15:54:16 Error: couldn't connect to server localhost:40001 shell/mongo.js:86
exception: connect failed

   물론, 접속이 안됩니다. data2로 접속을 합니다.

$ ./mongo localhost:40002
MongoDB shell version: 2.0.1
connecting to: localhost:40002/test
PRIMARY> rs.status()

{
"set" : "group1",
"date" : ISODate("2012-02-03T06:55:18Z"),
"myState" : 1,
"syncingTo" : "localhost:40001",
"members" : [
{
"_id" : 0,
"name" : "localhost:40001",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
"optime" : {
"t" : 1328251739000,
"i" : 1
},
"optimeDate" : ISODate("2012-02-03T06:48:59Z"),
"lastHeartbeat" : ISODate("2012-02-03T06:54:08Z"),
"pingMs" : 0,
"errmsg" : "socket exception"
},
{
"_id" : 1,
"name" : "localhost:40002",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"optime" : {
"t" : 1328251739000,
"i" : 1
},
"optimeDate" : ISODate("2012-02-03T06:48:59Z"),
"self" : true
},
{
"_id" : 2,
"name" : "localhost:40003",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 364,
"optime" : {
"t" : 1328251739000,
"i" : 1
},
"optimeDate" : ISODate("2012-02-03T06:48:59Z"),
"lastHeartbeat" : ISODate("2012-02-03T06:55:18Z"),
"pingMs" : 0
}
],
"ok" : 1
}

    위와 같이 data1 은 응답없는 상태, data2 는 새로운 master (PRIMARY)로 선출된 것을 확인할 수 있습니다.

    이제 data2 를 stop_data2.sh 를 통해 내립니다.
    남은 data3 로 접속을 합니다.

$ ./mongo localhost:40003
MongoDB shell version: 2.0.1
connecting to: localhost:40003/test
SECONDARY> rs.status()
{
"set" : "group1",
"date" : ISODate("2012-02-03T06:58:44Z"),
"myState" : 2,
"members" : [
{
"_id" : 0,
"name" : "localhost:40001",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
"optime" : {
"t" : 1328251739000,
"i" : 1
},
"optimeDate" : ISODate("2012-02-03T06:48:59Z"),
"lastHeartbeat" : ISODate("2012-02-03T06:54:07Z"),
"pingMs" : 0,
"errmsg" : "socket exception"
},
{
"_id" : 1,
"name" : "localhost:40002",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
"optime" : {
"t" : 1328251739000,
"i" : 1
},
"optimeDate" : ISODate("2012-02-03T06:48:59Z"),
"lastHeartbeat" : ISODate("2012-02-03T06:58:26Z"),
"pingMs" : 0,
"errmsg" : "socket exception"
},
{
"_id" : 2,
"name" : "localhost:40003",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"optime" : {
"t" : 1328251739000,
"i" : 1
},
"optimeDate" : ISODate("2012-02-03T06:48:59Z"),
"self" : true
}
],
"ok" : 1
}

    data1,data2 가 응답없는 상태입니다. 한대가 살아있지만 여전히 SECONDARY 로 남아있는것을 확인할 수 있습니다. 표수가 1개 밖에 없기 때문에 master 를 선출할 수 없기 때문입니다.

SECONDARY> show collections
Fri Feb  3 16:02:05 uncaught exception: error: { "$err" : "not master and slaveok=false", "code" : 13435 }

    정상동작하지 않는것을 확인할 수 있습니다.


 4) 자동 복구 

   다시 data1 을 구동합니다.
   그리고 data3 로 다시 접속을 합니다.

$ ./mongo localhost:40003
MongoDB shell version: 2.0.1
connecting to: localhost:40003/test
PRIMARY> rs.status()
....

   master 로 선출이 된것을 확인할 수 있습니다. data1 은  SECONDARY 로 설정이 되었을것입니다.

이것으로 3 Node ReplicaSet 의 기초적인 테스트를 완료합니다.


  

아이폰 (iPhone) Xcode4 OTA (Over the Air) : 애드혹 ( Adhoc ) URL 배포

1. Menu / Product / Archive

2. iOS App Store Package (.Ipa ) -> Next



3. 배포될 Full URL 입력 및 파일명 일치



4. 저장하면 다음의 파일 생성됨

    test.ipa
    test.plist

5. 배포될 URL 로 업로드

6. 다음의 html 작성

...

<a href="itms-services://?action=download-manifest&url=http://URL/test.plist">Test Adhoc</a>

...

2012년 2월 1일 수요일

아이폰 세션 유지 iphone keep session

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    [[NSHTTPCookieStorage sharedHTTPCookieStorage] 
       setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];

    ...
    
    return YES;
}




2012년 1월 25일 수요일

신조어 모음 2



낚다
  다른 사람을 속임. 어떤 게시물에(그리 중요한 내용도 아닌데) 제목만 보고 호기심으로 들렀을 경우.

낚시글
  자신의 글이나 홈피 등에 사람들을 유인하기 위해 흥미있는 내용의 제목으로 올린 글.

낚이다
  ‘낚다’의 피동형. 인터넷 사이트에 들어갔는데 예상했던 것과 달리 별로 볼 것이 없는 게시물일 때 쓰는 말.

넌씨눈
 넌 ㅆㅂ 눈치도 없냐?

냉무
  인터넷 게시물의 내용이 없음. 답변글을 올릴 때 할 말을 제목에 모두 쓰고 내용이 없을 을 때 씀. 예)감사합니다(냉무)

네가지
 싸가지

넷심
 인터넷 상의 다수의 여론. 또는 여론몰이

놀토
 학교에서 노는 토요일. 토요휴무제를 적용하는 2, 4주째 토요일

눈팅
 게시글에 대해 댓글은 달지 않고 보기만 함

님선
 당신이 먼저. 어떤 일을 하기가 난감할 때 상대에게 먼저하라고 권하는 말

놀키충
 놀래키기 충분하다

넘사벽
 넘을 수 없는 사차원의 벽. 이샠키가 이건 진짜 진리다 이 인간은 못뛰어넘는다 라는 뜻.

노페
 브랜드 노스페이스의 줄임말

눈팅
 인터넷상에서 쓰여진 글만 보고 리플을 달지 않는 등 아무것도 하지 않고 보고만 있는 사람
느님 전지전능함을 모티브로 한 하느님의 준말, 대체로 사람 이름이나 직업 뒤에 붙임.

나꼼수
 나는 꼼수다 라는 팟캐스트의 준말



담샘
 담임선생의 준말

담순이
 여자 담임교사

담탱이
 담임교사

당빠
 당연하다.

돌거
 메신저에서 돌림 쪽지 거부

뒤땅
 뒤에서 욕을 하거나 모함을 함

뒷간
 앞에서는 잘해주는 척하다가 뒤에 가서 험담을 함

득템
 게임에서 좋은 아이템. 공짜로 얻은 좋은 아이템

디비
 DB. 담배

돋네
 소름 돋는다는 말.  쩌네와 비슷

듣보잡
 듣도 보도 못한 잡것

떡실신
  떡이 되서 실신하다. 쓰러지다. 술마시고 널브러진 사람들을 떡실신했다라고 함

닭질
 전통적으로 미련한 동물의 상징으로 흔히 사용되는 ‘닭’과 행동을 뜻하는 ‘질’이 합쳐진 신조어. 불필요한 일 또는 행위를 수차례 반복하거나, 자신이 한일이 쓸모 없이 됐을 때 사용한다. 은어 중 ‘삽질’과 동일한 용도로 활용된다. “아! 비도 안오는데 우산 챙겼네. 완전 닭질했네”

닥본사
 닥치고 본방 사수

닥정
 나꼼수의 김어준이 지은 '닥치고 정치'라는 책의 준말

Linux : change hostname ( 호스트네임 변경 )

> echo "new hostname" > /proc/sys/kernel/hostname

or

> hostname -v "new hostname"

and

re-login

> hostname
"new hostname"





2012년 1월 20일 금요일

아마존 AWS ( Amazon ) CloudFront ( CDN )

Amazon CloudFront

아마존에서는 CDN 으로 CloudFront 를 제공합니다.
이미지에 대한 요청이 많은 어플을 만든다면 굉장히 유용하다고 할 수 있습니다.

하지만, 한국도 되는지는 모르겠네요..
일단, 제가 이걸 사용하게 된 이유는 유럽에서 서비스하는 서버 작업을 하게되서..
그 어플이 이미지를 많이 사용하거든요.

일단, 두가지의 효과를 위해서 사용했습니다.

 1) 이미지를 요청하게 되는 클라이언트 어플에서 빠르게 이미지를 가져오게 하기위해..
      CDN 의 장점이죠. 여러 지역에 이미지가 분산되어 가장 가까운 지역에서 이미지를 가져갑니다.

 2) 이미지 서버 부하에 대한 분산
      이미지 서버에 올라간 이미지들을 모든 클라이언트가 저희 서버에서 가져간다면. 서버에 대한 부하가 어마어마하죠. 또한, 요즘같은 경우 어플 오픈시 몰려드는것을 미리 판단하기도 어렵고.. 또 그에 따라 굉장한 서버를 구축하기도 비용이 만만치 않죠..
   
이런 이유로 인하여 이미지서버를 CloudFront 에 연동하게 되었습니다.

이제 등록을 해보도록 하죠..


 1) 매니지먼트 콘솔 상단 가운데 Cloud Front 를 클릭하시고 왼쪽 상단 Create Distribution 을 선택합니다.



 2) 저는 이미지 전송이 목적이므로 Download 를 선택했구요.
      아마존 내부 서버가 아닌 외부에 있는 이미지서버를 연동하는 것이므로 Custom Origin 을 선택하여 다음과 같이 입력하였습니다.



  Origin DNS Name 은 실제 이미지 서버의 주소가 되겠습니다. 가령 http://image.jmkook77.com/images/2012/01/20/test.png 라면 앞의 도메인만 적으면 되겠습니다. HTTP 를 통해 제공되는 것이므로 HTTP Only 및 80 포트는 선택하고 Continue 를 클릭합니다.


 3) 이제 CNAMEs 를 설정합니다.
      이렇게 설정되었다면 위 주소의 이미지는 이제 http://cdn.jmkook77.com/images/2012/01/20/test.png 로 접근이 되겠죠.

      물론, cdn.jmkook77.com 도메인 서버의 CNAMEs 에 아마존에서 제공하는 CloudFront 의 도메인 주소를 설정해야합니다. 도메인 서버를 직접 운영하신다면 설정을 하시면 되구요. 호스팅의 경우도 대부분 도메인 설정에 CNAME 을 추가할 수 있는 메뉴가 있습니다.


   로깅이 필요하다면 Logging : On 으로 설정하시고, 생성후 곧바로 동작하게 한다면 Distribution Status 를 Enabled 로 하시면 되겠습니다.


 4) 설정된 값을 최종적으로 보여줍니다. 확인하시고 Create Distribution 을 클릭합니다.



 5) 아래와 같이 리스트가 추가된 것을 확인할 수 있습니다. 해당 항목을 클릭하면 하단에 상세한 내역이 나옵니다. 물론, 오른쪽 버튼으로 수정이 가능합니다.



 하단에 보시면 아마존에서 제공하는 Domain Name 이 있습니다. 그 도메인 주소를 CNAMEs 에 설정한 도메인에 CNAME 등록을 해주시면 되겠습니다.

 6) CNAME 이 등록된 도메인을 확인해보겠습니다.

  > nslookup
  > Server: 164.xxx.xxx.2
  > Address: 164.xxx.xxx.xxx

  > set q=CNAME
  > cdn.jmkook77.com ( 실제 없는 주소입니다. )

  > ...
  > cdn.jmkook77.com     canonical name = dl3xxxxxx.cloudfront.net.
  > ...
 

 7) 이제 이미지를 image.jmkook77.com 에 추가하고 접속을 하면 내부적으로 다음과 같은 동작을 하겠죠.

   http://cdn.jmkook77.com/images/test.png
   -> http://dl3xxxxxxx.cloudfront.net/images/test.png
   -> http://image.jmkook77.com/images/test.png

   물론, 매번 콜될때마다 이미지서버에서 가져오는건 아닙니다. 그럼 의미가 없죠.

   traceroute 명령어를 통해 접근을 해보면 지역에 따라 어떤 서버에서 이미지를 가져오는지 확인이 가능하겠지만 서도.. 테스트가 어렵군요. ㅎㅎ

   자세한 사항은 http://docs.amazonwebservices.com/AmazonCloudFront/latest/GettingStartedGuide/Welcome.html


끝.

2012년 1월 17일 화요일

몽고db ( mongodb ) 기본명령어 1 - Collection ( 컬렉션 )

Mongodb Collection

 1) 컬렉션 생성

   > use dbName;
   > db.createCollection("test1");

   { "ok" : 1 }

   > show collections;

   system.indexes
   test1

   > # Capped Collection ( 제한사이즈로 설정하며 성능적으로 유리함. 단, 제한사항을 가지므로 http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-UsageandRestrictions 에서 확인 필요 ) 

   > db.createCollection("test1", {capped:true, size:100000, max: 1000});

 { "ok" : 1 }

   > show collections;

   system.indexes
   test1


 2) 컬렉션명 수정

   > db.collectionName.renameCollection("newCollectionName");


   { "ok" : 1 }

   > show collections;

   system.indexes
   test2

 3) 컬렉션 삭제

   > db.test2.drop();

   true

   > show collections;

   system.indexes

 4) 컬렉션 상태 보기

   > db.test3.validate();

{
"ns" : "test.test3",
"capped" : 1,
"max" : 2147483647,
"firstExtent" : "0:25000 ns:test.test3",
"lastExtent" : "0:25000 ns:test.test3",
"extentCount" : 1,
"datasize" : 0,
"nrecords" : 0,
"lastExtentSize" : 102400,
"padding" : 1,
"firstExtentDetails" : {
"loc" : "0:25000",
"xnext" : "null",
"xprev" : "null",
"nsdiag" : "test.test3",
"size" : 102400,
"firstRecord" : "null",
"lastRecord" : "null"
},
"deletedCount" : 2,
"deletedSize" : 102224,
"nIndexes" : 0,
"keysPerIndex" : {
},
"valid" : true,
"errors" : [ ],
"warning" : "Some checks omitted for speed. use {full:true} option to do more thorough scan.",
"ok" : 1
}

   

아마존 AWS ( Amazon ) EC2 서버 등록 - 4 : Security Group ( 방화벽 )

EC2 서버에서 제공되는 서비스를 외부에서 접근하게 하기


1. 환경

 - apache
 - port : 8000

 해당 서버가 올라갔다고 가정하고, 외부에서 누구든 8000 으로 접근이 가능하게 설정합니다.

2. Security Grouop

 1) 해당 EC2 서버에 설정된 Security Group 확인


 ( 공교롭게 다른 콘솔에 로그인되어 이쪽에서 캡쳐를 이미 한탓에 그대로 갑니다. 횡설수설.. )

  해당 서버의 Security Groups 을 확인합니다. quick-start-1 이군요.. ㅎㅎㅎ


 2) NETWORK & SECURITY / Security Groups 를 선택하면 다음과 같은 화면이 뜹니다.


    상단 리스트중 quick-start-1 을 선택하면 하단에 해당 그룹에 대한 뷰 및 설정이 가능한 페이지가 뜹니다. 탭중 Inbound 를 클릭하면 해당 그룹에 대하여 외부에서 접근하는 포트를 설정할 수 있습니다. 현재는 22번포트 ( ssh ) 만 외부 어디서든 ( ANY ) 접근이 가능하게 되어있네요.

   즉, quick-start-1 Security Groups 을 사용하는 모든 EC2 서버는 이 룰을 따르게 됩니다.


 3) TCP 8000 포트를 열것이므로 Create new rule 셀렉트 박스에서 Custom TCP rule 을 선택합니다.



 4) Port range 에 8000 을 입력합니다.
     물론, 특정 포트 대역을 범위로 설정이 가능합니다.
   
     어디서든 ( ANY ) 해당 포트로 접속이 가능하게 할 것이므로,
     Source 는 0.0.0.0/0 으로 설정합니다.

     역시, 접속하는 특정 아이피 혹은 아이피 대역으로 제한할 수 있습니다.


   
    설정하였으며, Add Rule 을 클릭합니다.

 5) 8000 이 추가된것을 확인할 수 있습니다.

      실제 적용된 것은 아니므로 왼쪽 하단에 활성화된 Apply Rule Changes 를 클릭합니다.


     삭제 역시 각 룰의 우측 Delete 를 통해 적용이 가능합니다.


 해당 설정은 곧바로 적용이됩니다. 예전에 호스팅할때 요청하고 기다리고 했던 기억이 ...
 
 간혹, 해당 설정이 되도 접속이 안되는 경우가 있습니다.
 일단 서버 종류에 따라 다른 부분이구요.. 리눅스의 경우 iptables 와 같은 서버 내 방화벽을 재 확인 하시기 바랍니다.

끝.

2012년 1월 15일 일요일

신조어 모음 1


간지나다 - 폼 나다. ‘뽀대나다’와 동의어. 어원은 일본말 ‘간지(感)’
갈비        - 볼수록 싫어짐. ‘갈수록 비호감’의 준말.
강추        - 강력하게 추천
갠소        - 개인소장
걍고        - 그냥 하자. 어원은 '그냥 go 하자'
걸조        - 걸어 다니는 조각상. 즉, 꽃미남
격친        - 격렬하게 친하게 지냄
고고싱     - 어디어디?가자. 예) 집으로 고고싱. 16강 고고싱
고친        - 고민을 해결해주는 친구
관광시키다 - 게임에서 상대가 너무 약해서 갖고 놀다.
광클        - 미치도록 클릭함. 메이플 스토리 게임에서 미치도록 클릭하는 것
귀사        - 귀여운 척 사기 치다.
글설리     - 글쓴이를 설레게 하는 좋은 리플
길막        - 길을 막는다
깜지        - 시험 공부 등으로 종이에 빽빽할 정도로 글자를 써놓는 것
꼬댕이   - 공부도 못하고 놀지도 못하는 학생
꼽주다   - 창피하게 하다
공방        - 공개방송
깜놀        - 깜짝 놀라다
갑툭튀   - 갑자기 툭 튀어나오다
근자감  - 근거도 없는 자신감
귀척        - 귀여운 척
긔체        - 안녕하긔. 배고프긔. 같이 ㅇㅇ하기의 끝 글자인 기를 귀여운 척하며 표현한것
개오         개화동 오렌지족의 준말이다. MBC 인기 예능프로그램인 ‘무한도전’에 출연 중인 정형돈이 개화동에서 살기 때문에 생긴 신조어이다. 이 프로그램에서 정형돈의 남다른 패션감각을 지칭하기 위해 개화동에 사는 오렌지족이란 뜻에서 ‘개오’란 단어가 사용됐다. 흔히 미친 존재감의 준말인 ‘미존’을 접두어 형식으로 붙여 ‘미존개오’로 사용한다. 여기서 미친은 뛰어난, 엄청난 등의 의미를 가진다.

개드립  - 심한 어이없는 말이나 행동을 나타낼때 사용
금사빠  - 금방ㅇ 사랑에 빠질것 같음

2012년 1월 14일 토요일

iPhone - UIDatePicker setDate

NSCalendar * gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];


NSDateComponents * components = [[[NSDateComponents alloc] init] autorelease];

[components setYear:2012];
[components setMonth:1];
[components setDay:1];
[components setHour:10];
[components setMinute:5];
[components setSecond:30];

[datePicker setDate:[gregorian dateFromComponents: components]];

아마존 AWS ( Amazon ) EC2 서버 등록 - 3 : Elastic IP

EC2 서버 Elastic IP 할당.

처음에 공인아이피를 어찌 할당하나 약간 헤맸는데요.
Elastic IP 라는 것을 제공합니다. 말 그대로 차~암 탄력적입니다.
서버가 켜진 상태에서도 아이피를 바꿀 수 있으며 바로 적용이 됩니다.

1. Elastic IP 추가

 Network & security 내 Elastic IP 메뉴를 선택하면 아래와 같은 화면이 뜹니다.


 상단에 있는 Allocate New Address 를 클릭하여 IP 를 추가할 수 있습니다.


가볍게 Yes, Allocate 를 클릭하면 아이피가 할당이 됩니다.

2. Elastic IP 서버 할당

 추가된 아이피 항목에서 오른쪽 버튼을 누르면 다음과 같은 메뉴가 뜹니다.


 Associate 를 선택하고 Instance 리스트에서 원하는 서버를 선택한 이후 Yes, Associate 를 클릭하면 곧 할당이 됩니다. 
 Instances 메뉴로 가보면 해당 서버에 할당이 되었다는 것을 확인할 수 있으며, 이후 Connect Info 를 확인하시면 할당된 IP 로 접근을 하라고 표시됩니다. 

3. Elastic IP 할당 해제

 해제시에는 Elastic IP 메뉴에서 해당 IP 리스트에서 오른쪽 버튼을 클릭하여 다음과 같이 해제를 할 수 있습니다.

4. Elastic IP 제거
 해제가 된 상태에서 아이피 리스트에서 오른쪽 버튼을 클릭하여 아래와 같이 해제가 가능합니다.










* 주의할 점은 서버 리스타트 시 자동으로 해제되므로, 서버가 올라온 뒤 다시 할당해줘야 합니다.

아마존( Amazon ) AWS 윈도우( Window )에서 접속 - Putty , pem ppk 변환

아마존 서버 생성시 다운받은 pem 파일을 이용하여 ssh/sftp 접속하는 방법

1. putty 를 다운받습니다.

 http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html

 여기에서 putty<version>-installer.exe 를 받으세요.
 혹은, putty.exe, psftp.exe, puttygen.exe, pageant.exe 를 따로 설치하셔도 됩니다.
  puttygen.exe 는 pem 파일을 putty에서 사용가능하게 변경하며
  pageant.exe 는 pem 파일을 통해 putty, psftp 가 서버에 접속 가능하게 해줍니다.

2. pem 파일 변환

 1) puttygen.exe 를 실행하면 아래와 같은 화면이 뜹니다. 상단의 Conversions / Import Key 를 선택합니다.


 2) 해당 서버에 접속하기 위한 pem파일을 선택합니다.



 3) 아래와 같이 정상적으로 로드가 된것을 확인할 수 있습니다.
     이제 하단 우측에 있는 Save private key 를 선택하고 Yes 를 선택합니다.



 4) 원하는 위치에 파일명을 설정하여 ppk 파일을 저장합니다. ppk 파일 생성 완료!!




2. Pageant.exe 를 실행하면 아래와 같이 윈도우 우측 하단에 트레이로 추가된것을 확인할 수 있습니다. 이녀석은 항상 저곳에 있어야만 합니다.


 1) 위 트레이를 더블클릭 하여 아래의 화면에서 Add Key 를 선택합니다. 혹은, 트레이 아이콘에서 오른쪽 버튼으로 Add Key 를 선택합니다.



 2) 위에서 저장한 ppk 파일을 선택해줍니다.



 3) 아래와 같이 정상적으로 추가된것을 확인할수 있습니다. 이제 해당 창을 닫습니다.



3. Putty.exe 를 실행합니다. 

 1) Host Name 에 아마존의 Public DNS ( 혹은 Elastic IP ) 를 입력하고 Open 을 합니다. ( 물론, 트레이에는 Pageant 가 떠있어야 합니다. )



 2) 최초 접속시 해당 얼럿이 뜰겁니다. Yes 를 누릅니다.

  


 3) 계정으로 root 를 입력합니다. 정상접속이 되었습니다. !!



4. Psftp.exe 를 실행합니다. ( 당연히 이놈도 Pageant 가 실행되어있어야 겠죠? )


 역시 계정에 root 를 입력하여 정상 접속되는 것을 확인할 수 있습니다.

 기념으로 이미지하나는 드래그하여 put 해봅니다.



끝!!

아마존 AWS ( Amazon ) EC2 서버 등록 - 2 : 서버 접속

EC2 서버 접속


 이건 머 정리하려고 하니 이미지작업이 더 많이 들어가네요. 가리고 쓰고 ..

 여튼 왼쪽 Instances 를 클릭하면 해당 지역( Tokyo ) 에 등록 혹은 운영? 되고 있는 서버 리스트가 위와 같이 뜹니다.

 Type 이 m1.small 이고 running 중이며 Security Group 은 quicklaunch-1 로 , 그리고 Key Pair 가 jmkook ( 이전에 등록할때 다운받았던 jmkook.pem ) 인걸 알수가 있습니다.

해당 라인에서 오른쪽 버튼을 클릭하면 다음과 같이 컨트롤할 수 있는 메뉴가 뜹니다.


여러가지 제어가 가능하며, 아래 Instance Lifecycle 을 통해 서버를 올리고 내리고 리붓하고 그리고 없앨 수 있습니다. 실제 서버를 없애도 ( Terminate ) 곧바로 사라지지는 않습니다.

목적인 Connect 를 선택하면 아래의 화면이 뜹니다.















 SSH 를 통해 서버에 접근이 가능하며, 다운받았던 pem 파일을 통해 접속을 하라고 나와있습니다. 실제 공인아이피가 지정이 되어있지 않더라고 아마존에서 기본적으로 제공하는 Public DNS 를 통해 외부에서 SSH 접근이 가능합니다.

맥이나 리눅스의 경우 pem 파일에 대하여 위와 같이 chmod 400 jmkook.pem 을 수행한 후 아래 ssh -i jmkook.pem .... 를 복사하여 터미널 창에서 접속을 하면 아래와 같이 정상 접속이 되는것을 확인할 수 있습니다.

...

-r--------@ 1 jmkook  admin  1692 12 16 15:27 jmkook.pem

Jemin-Kook-ui-MacBook-Air:Amazon jmkook$ ssh -i jmkook.pem root@ec2-xxx-34-18-xxx.ap-northeast-1.compute.amazonaws.com

Last login: Wed Jan  4 23:59:56 2012 from xxx.209.xxx.xxx
[root@ip-xx-162-xx-xxx ~]# ls -al


접속하였습니다. !!

윈도우를 사용하는 경우 putty 등의 프로그램을 통해 접근이 가능합니다.
putty 로 아마존 접근시 방법은 다음 링크에서 보시기 바랍니다.
 -> putty 로 EC2 서버 접속


 추가적으로 해당 서버를 선택하면 하단에 자세한 내용이 나오는데요.
 Public(공인) DNS 와 Private(사설) DNS , 그리고 Private IP Address 가 제공되는것이 확인이 됩니다. 해당 DNS 를 통해 외부에서 접근이 가능하죠. 내부 서버간은 Private DNS나 IP 를 통해 접근이 가능합니다.

*이 DNS 들과 및 IP 는 서버가 리스타트 될 때마다 변경된다는것을 꼭 기억해두세요!!

또한, Private IP 를 통해 내부 서버끼리 통신하는 비용은 추가가 되지 않지만 Public 을 통해서 이동되는 모든 데이터에 대해서는 추가 요금이 부과된다는 사항도 잊으면 안됩니다.

가령, 변경되는 아이피때문에 웹서버에서 DB 서버로 접근시 공인아이피로 접근하게 되면 웹에 접근하는 비용에 웹이 DB 에 접근하는것 역시 비용이 되것죠...

여튼, 고정된 아이피를 할당하기 위해서는 Elastic IP 를 통해 할당이 가능합니다.

추가적으로, EC2 서버를 생성해도 기본적으로 우가 디스크가 자동으로 마운트 되지 않으므로 용량이 무쟈게 적습니다.
해당 부분 처리는 이곳에서 -> 디스크 마운트

2012년 1월 12일 목요일

iPhone - TableViewController Background Image ( 이미지 배경 )

- UITableViewController 이미지 배경

 - (void)viewDidLoad {

     UIImageView* imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"bg.png"]];
    self.tableView.backgroundView = imageView;
    [imageView release];
 }

- UITableViewController 투명한/컬러 배경 (Transparent/Color Background)

  - (void)viewDidLoad {


    self.tableView.backgroundColor = [UIColor clearColor]; // [UIColor blackColor];
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; // 셀 구분 라인 제거
   

 }

JQuery Enter + Javascript Enter ( 엔터 )

* <input name="user_pass" ... />

- JavaScript

 <input name="user_pass" onkeydown="javascript:if( (event.keyCode)&&(event.keyCode==13) ) { alert('enter'); }" />

- JQuery

 $(document).ready(function() {

$('input[name="user_pass"]').keydown(function(evt){
if( (evt.keyCode) && (evt.keyCode==13) ) {
alert('enter');
}
});
});

2012년 1월 11일 수요일

Facebook Card ( us.moo.com ) - 페이스북 타임라인으로 멋진 명함을~

페이스북 타임라인으로 멋진 명함을~

페이스북이 타임라인을 선보인 것은 다들 알고 있을겁니다.
그 타임라인을 이용해 명함으로 만들 수 있는 서비스가 등장했습니다.

http://us.moo.com/products/facebook-cards.html

현재 페이스북과 Moo.com 이라는 프린트 관련회사가 제휴를 맺어 선착순 20만명에게 무료로 명함을
만들어주고 있다고 합니다. 위 링크로 접속해서 명함을 신청할 수 있습니다.
참고로 하루 5천만명씩만 신청 가능하다고 합니다.


                                                                                 이미지 출처 : us.moo.com

보통 블로그의 상단 커버 이미지에 자신의 프로필 사진을 올린 것 밖에 기술적? 디자인적?으로 차이는
없으나 그것을 하나의 또다른 문화처럼 만든 Facebook의 디테일함은 정말 칭찬해 줄만하네요.

 - dragonhong

2012년 1월 3일 화요일

redhat linux ( 레드햇 리눅스 ) - disk mount ( 디스크 마운트 )

- Disk Mount

( root )

$ su - 
$ fdisk -l

...
Disk /dev/xvdj: 1xx.x GB, 19xxxxxxxxxxx320 bytes
255 heads, 63 sectors/track, 2xxx7 cylinders
Units = cylinders of 1xx5 * 5xxx = 8xxxxxx0 bytes

Disk /dev/xvdj doesn't contain a valid partition table

1) ext3 로 포맷 ( 포맷안할경우 skip )

$ mkfs.ext3 /dev/xvdj 

2) /data 로 마운트 할 경우

$ mkdir /data
$ mount /dev/xvdj /data

3) 부팅시 자동 마운트

$ echo "/dev/xvdj /data ext3 noatime 0 1" >> /etc/fstab

* 끝에있는 1 은 디스크 체크 여부. 0으로하면 에러 체크 안함

끝!




몽고db ( mongodb ) 2 - 샤딩 ( sharding )

mongodb 는 대용량의 데이터를 물리적으로 다른 서버에 분산하여 성능을
향상할 수 있도록 샤딩을 지원합니다.

물론, 같은 서버에 다른 포트로 올리는것도 방법이겠지만.. 그다지 좋지는 않겠죠..
테스트해보기 위한게 아니라면 말이죠..

가장 간단한 구조로 샤딩해보겠습니다.

1. 환경

 1) 구성
      mongos1 - config server1 - shard server1
                                              - shard server2

 2) 서버1
    - 설치 서버 : mongos1, config server1, shard server1
    - mongodb 설치 경로 : /app/mongodb
    - log 경로 : /app/mongodb/log
    - data 경로 : /data/config1, /data/shard1
    - mongos1 port : 27777
    - config server1 port : 30000
    - shard server1 port : 28001

 3) 서버2
    - 설치 서버 : shard server2

    - mongodb 설치 경로 : /app/mongodb
    - log 경로 : /app/mongodb/log
    - data 경로 : /data/shard2
    - shard server2 port : 28002

2. 세팅

 1) 각 서버의 ip 를 네임 설정합니다.

   $ /etc/hosts
   1.1.1.1  mongodb1
   1.1.1.2  mongodb2

 2) 서버1 configsvr1 실행/중지 쉘

   $ cd /app/mongodb/bin
   $ vi start_configsvr1.sh
   /app/mongodb/bin/mongod --configsvr --port 30000 --fork --logpath /app/mongodb/log/configsvr1.log --dbpath /data/config1
   $ chmod +x start_configsvr1.sh

   $ vi stop_configsvr1.sh
   ps -ef |grep -v grep |grep configsvr1.log |awk '{print $2}' |xargs kill -2
   $ chmod +x stop_configsvr1.sh

 3) 서버1 mongos 실행/중지 쉘

   $ vi start_mongos1.sh
   /app/mongodb/bin/mongos --port 27777 --fork --logpath /app/mongodb/log/mongos1.log --configdb mongodb1:30000
   $ chmod +x start_mongos1.sh

   $ vi stop_mongos1.sh
   ps -ef |grep -v grep |grep mongos1.log |awk '{print $2}' |xargs kill -2
   $ chmod +x stop_mongos1.sh

 4) 서버1 shardsvr1 실행/중지 쉘

   $ vi start_shardsvr1.sh
   /app/mongodb/bin/mongod --shardsvr --port 28001 --fork --logpath /app/mongodb/log/shardsvr1.log --dbpath /data/shard1
   $ chmod +x start_shardsvr1.sh

   $ vi stop_shardsvr1.sh
   ps -ef |grep -v grep |grep shardsvr1.log |awk '{print $2}' |xargs kill -2
   $ chmod +x stop_shardsvr1.sh
   
 5) 서버2 shardsvr2 실행/중지 쉘

   $ vi start_shardsvr2.sh
   /app/mongodb/bin/mongod --shardsvr --port 28002 --fork --logpath /app/mongodb/log/shardsvr2.log --dbpath /data/shard1
   $ chmod +x start_shardsvr2.sh

   $ vi stop_shardsvr2.sh
   ps -ef |grep -v grep |grep shardsvr2.log |awk '{print $2}' |xargs kill -2
   $ chmod +x stop_shardsvr2.sh
   
 6) 모든 프로세스를 실행합니다. 물론, mongos 는 마지막에 실행합니다.

 7) /app/mongodb/bin/mongo mongodb1:27777/admin 를 통해 mongos에 접속합니다.

 8) 다음의 스크립트를 통해 shard 를 등록합니다.
   
   > db.runCommand({addshard:"mongodb1:28001"})
   > db.runCommand({addshard:"mongodb2:28002"})

   > use config
   > db.shards.find()
   
   { "_id" : "shard1", "host" : "mongodb1:28001" }
   { "_id" : "shard2", "host" : "mongodb2:28002" }
   

 9) 이제 특정 데이터베이스의 컬렉션을 샤딩합니다.

  > use admin
  > db.runCommand({"enablesharding":"myDb"})
   
   { "ok" : 1 }

  myDb 가 샤딩이 가능해졌습니다.
  myDb 의 myBook 이라는 컬렉션을 샤딩하겠습니다.

  > db.runCommand({"shardcollection":"myDb.myBook", "key":{"_id":1}})

  여기서 key 는 _id 가 아닌 다른 인덱스로도 선택이 가능합니다.

  샤딩상태는 다음의 명령어로 확인이 가능합니다. 

  > printShardingStatus()


실제 데이터가 분산되서 쌓이는걸 보려면 각 shard 의 데이터 스토어
여기의 경우 /data/shard1 이 되겠네요. 여기를 보면 되는데요.
기본적으로 chunk 사이즈가 32메가인가. 64메가인가 훔.. 머 여튼..
적어도 그 사이즈가 넘어야 다른 쪽으로 분산됩니다.


현재의 구조는 장애발생시 취약한 구조입니다. 
실제로 서비스에는 mongos 는 멀티로, config server 는 3개로, 
각 shard server 는 리플리카셋으로 묶어서 세팅을 합니다.
다음에는 그걸 문서화 해봐야겠네요. 

  

2012년 1월 2일 월요일

아마존 AWS ( Amazon ) EC2 서버 등록 - 1

아마존 AWS EC2 서버 등록

 1. 우선 http://aws.amazon.com 우측에 sign up now !! 를 통해 가입을 합니다.

 2. EC2 서버의 가격 정책은 http://aws.amazon.com/ec2/pricing/ 를 참고하시면 되겠습니다. 저는 large, 레드햇 리눅스, 그리고 지역은 가장 가까운 일본 Tokyo 에 설치합니다.
    가격정책이 지역마다 틀리므로, 꼭 원하는 지역을 선택하시어 가격을 확인해봐야 합니다.

 3. 가입을 하셨으니 아래의 과정을 통해 로그인을 합니다.



 4. 이제 매니지먼트 콘솔에서 상단 EC2 탭 선택 및 좌측 상단 지역을 선택 합니다.


   그리고, 중간에 잇는 Launch Instance 를 클릭합니다.
   이미 Instances 메뉴에 있다면 하단 이미지와 같이 해당 버튼을 클릭하여 추가가 가능합니다.



5. Launch Instance 를 하면 아래와 같이 화면이 뜹니다. 예전에는 좀 더 복잡했는데... 좌측 Quick Launch 를 제공하여 매우 쉽고 빠르게 등록이 가능해졌습니다.


 좌측, QuickLaunch 일 경우 아래의 순서대로 입력을 합니다.

  1) Name your instance 에는 관리를 위한 이름을 설정합니다.
       저는, 일단 jmkookDev1 으로 하였습니다.

   2) Choose a key pair 는 ssh 로 접속시 사용하는 인증서를 설정하는 것으로,
        최초 등록이라면 아직 등록된 것이 없으므로 아래의 Create new key pair 를 통해
        등록을 합니다. 생성을 하면 pem 파일을 다운로드 받게 됩니다.
        이 파일을 통해 이후 ssh 접속을 할 것입니다.
        참고로, 각 인스턴스마다 다른 key pair 를 사용할 수 있습니다. 저는 구차나서 ㅋㅋ

     
   3) Choose a launch configuration 에서 제가 원하는 Red Hat Enterprise Linux , 64bit 를 선택하여 하단의 Continue 를 클릭합니다. 참고로, micro 는 64bit 지원이 안됩니다.


6. 기본적인 세팅이 되었습니다. 아래와 같이 지금까지 기본적으로 설정된 사항이 보여집니다.


 7. 이 화면에서 상세설정이 가능합니다. 저는 Type 만 m1.large 로 변경하고 인스턴스가 생성되고 일단 부팅이 안된상태로 설정하였습니다. 기타 설정은 이후에 하도록 하고 하단의 save details 를 클릭합니다.


8. 그럼 6번 화면으로 다시 돌아가게 되며 변경된 사항을 다시 확인할 수 있습니다. 이제 Launch 를 클릭합니다.



 아고, 이제 설치 완료입니다. 닫힌후 보여지는 Management Console - Instances 에 등록된 서버가 다음과 같이 막 설치중일 겁니다.



9. 기본적인 설치 끝!!!


아.. 이건 머 별 내용을 담지도 않았는데 이미지작업이나 캡쳐하는게 더 일이군요.

다음 진행 내용은 접속 / 추가 디스크 마운트 / 방화벽 등 입니다.