프로그래밍/알고리즘2010. 12. 11. 20:41

길 찾기 알고리즘, A* 알고리즘, A Star라고 발음한다. 상당히 오래 전에 만들어진 알고리즘이다. 게임 제작에서 가장 기본적으로 가르치는 방법이라서 외국 글을 읽어 단순히 번역하지 않고 다시 정리해서 올린다. 유사한 방법에 Dijkstra[다익스트라]라는 사람이 만든 방법이 있다고 한다. 발음법이 특이한 것은 네덜란드 사람이라서 그렇다. 약간 독일어를 닮은 언어다. 아마 A*의 원형일 것이다. 컴퓨터 공학과에선 가르치는 것 같다. 우린 모르지만...

 

 <그림 : 기본 개념>

 

 

먼저 알아야 할 것부터 정리하면 이렇다. 컴퓨터는 봉사에 귀머거리다. 그래서 화면 전체를 볼 수 없다. 비유를 하면 봉사 슈퍼 개미가 빛의 속도로 화면을 돌아다니며 더듬어서 길을 찾는 것이다. 일을 간단하게 만들기 위해서 지도를 바둑판 형태로 나눈다. 이것을 격자(Grid)라고 부른다. 그래서 하나의 사각형, 육각형, 삼각형 안에서 다른 것 안으로 이동하거나 또는 바둑판처럼 하나의 교차점에서 다른 교차점으로 이동하는 형태로 생각한다. 사각형, 육각형, 삼각형은 평면을 알뜰하게 나누어 사용할 수 있는 도형이다. 주로 사각형을 많이 쓰지만 뭐를 써도 가능하다. 그렇게 구역을 나누고 각 구역은 뭔가 기억할 수 있는 능력이 있다고 하자! 즉, 각 바둑판 사각형이나 십자 교차점은 컴퓨터에서 말하는 2차원 배열이 된다. 다시 말하면 길을 찾기 위해 지도에 뭔가 표시할 수 있도록 하는 것이다! 여하튼 움직임은 연속적이지 않고 계단식으로 간격을 두고 움직인다! 그리고 그 지점에 뭔가 표시를 한다. 이런 것을 Node[노우드](마디)라고 부른다. 이 말은 원래 나무 형태의 구조에서 가지가 갈라지는 부분을 부르는 말이다. 이런 이름이 붙은 이유는 바둑판에 표시한 길을 보면 마치 나무 가지 형태를 하게 되기 때문이다. 보통 Node가 나오면 List가 따라 나온다. Linked List(연결 목록)이란 것은 배열이다. 그런데 서로 누가 먼저 누가 나중인지 연결된 정보를 가지고 있다. 그래서 순서를 자유롭게 바꾸고, 삽입과 삭제가 쉽다. 지도에 표시하는 대신 이 Linked List를 사용하여 길을 기억하는데 이 연결 상태를 그려보면 나무(Tree) 모양이 된다. 그래서 Node라고 부른다.(^^) 우리의 봉사 슈퍼 개미는 바로 옆의 8개 점만 검사할 수 있다. 그래서 8방향 탐색이다!(^^) 이 8방향에서 또 각자 다음 주변 8방향으로 물결처럼 퍼져나간다. 그런데 이렇게 무조건 8방향으로 퍼져나가면 좀 문제가 있다. 하나만 선택해서 계속 깊게 나가야 한다. 우린 넓이 우선 탐색을 하는 것이 아니라 깊이 우선 탐색을 하는 것이다. A 스타는 깊이 우선 탐색 + 넓이 우선 탐색이다. 처음엔 계속 가능성이 높은 것 하나를 선택해서 깊게 나간다. 그러다 막히면 나머지 가능성 중에서 하나를 선택해서 넓게 나간다. 그 가능성 높은 방향을 선택하는 방법이 바로 A 스타 알고리즘이다.

 

 <그림 : 유사 방법>

  

<그림 : 진짜 방법>

 

 

 

A*란 8방향을 탐색해야 하며 8방향 중에 어느 하나를 선택하는 방법으로 이미 왔던 거리와 목표까지 예상 거리의 합을 사용해야 하는 것이다. 그렇지 않다면 A*라고 부르기 어렵다. 이 가장 기본적이고 가장 실용적이게 보이는 방법도 문제가 많다.(^^) 아주 긴 장벽을 넘는 것이 어렵게 보인다. 또한 호랑이 입이나 항아리 구조 같은 지형에서도 시간 소모가 많다. 가장 짧은 거리를 선택한다는 것은 말 그대로 Sorting을 한다는 것이고 그러면 시간이 많이 소모된다. 또한 검토할 지점과 이미 검토한 지점을 목록(Linked List)에 잘 저장해서 찾아야 한다. 다만 책에 이름이 자주 거론되니 궁금해서 공부했을 따름이다. 좀 더 간단하고 효과적인 방법이 있다. 이쪽에서 저쪽으로 가는 길을 찾는 것은 복잡하지만 반대로 저쪽에서 이쪽으로 오는 길을 찾는 것은 쉬울 수 있다. 항상 반대로 생각해 봐야 한다. 그래서 양방향 탐색을 한다. 또한 우리가 산 속에서 또는 사막에서 또는 초원에서 또는 바다에서 길을 잃었다고 하자! 그럼 제일 먼저 찾는 것이 뭔가? 산 속에선 계곡의 물줄기다. 따라가면 큰 강이 나온다. 사막이나 초원에선 강을 찾거나 산맥을 찾아야 한다. 바다에선 육지를 찾아야 한다. 모두 경계라는 특징이 있다. 마찬가지로 갈 수 있는 길과 갈 수 없는 장애물 사이의 경계가 바로 따라가야 할 길이다. 장애물이 없다면 무조건 목표 방향을 향해 직진하는 것이 빠르다. 실제 게임에서 Unit들의 움직임을 보면 장애물을 만나기 전까지는 일직선으로 이동한다. 장애물을 만나면 벽을 따라 이동하는 것을 알 수 있다. 물론 이 길을 찾는 방법을 개발해야 하지만 별로 어렵지 않다. 아래 그림을 봐라!

  

<그림 : 기타 방법>

 

 

A*와 유사한 결과를 내지만 더 간단하다. 이 방법은 내가 고민하다가 기억해 낸 것이다. 인터넷에 찾아 보면 우선법/좌선법(우수법/좌수법!? 뭐라고 하든 무슨 상관이냐?)이라는 벽 타기 기법이 유사하다는 것을 느낄 것이다. 미로에서 오른 손이나 왼 손을 벽에 붙이고 계속 가면 출구가 나온다는 그런 이야기다. 이 방법은 계속 벽에 붙어 있기 때문에 벽에서 떨어지는 상황에 대응한 위의 방법과는 다르다. 어느 경험 많은 프로그래머에게서 오래 전에 들은 이야기다. 당시 게임 제작에 대한 막연한 호기심으로 질문을 했었다. 그 사람들 경험으로는 게임 제작은 엄청 골치 아픈 분야라고 한다. 컴퓨터를 생각하도록 만드는 작업은 정말 어렵다. 이런 길 찾기는 아주 쉬운 편에 속한다고 한다. 한 참 후에 세월이 흘러 직접 게임 제작에 관한 글을 쓰다가 궁리 끝에 뭔가 아이디어가 떠올랐는데 알고 보니 옛날에 누군가에게 들은 것이었다.(^^) 진짜 실력이 있는 프로 게임 제작자들은 이미 답을 알고 있었다! 컴퓨터 공학과나 수학과에서 다루는 분야이니까! 컴퓨터는 컴퓨팅(계산)하는 장치이니 수학과와 친하다. 우리 아마추어만 모르고 있었다! 내가 게임 업체의 비밀 알고리즘을 하나 듣게 된 것이었다. 어디 가서 말하지 말라고 했지만 내가 게임 제작자가 될 수도 없는 입장에서 세월은 흘러 이미 늙어 버렸으니 내겐 더 이상 감출 비밀이 아닌 것 같다! 어린 학생들 좋은 꿈 꾸라고 이렇게 글을 올린다. 한국 게임 업체의 비밀은 외국 게임 업체에 비하면 비밀도 아니니까!(^^) 게임 분야는 너무 경쟁이 심하다. 장래 희망이라면 잘 고려해 보길 바란다!

[출처] http://blog.daum.net/jty71/15645104

Posted by 컴투

먼저 그동안 자바의 스트링 포멧에 대한 이해가 부족했었다.
안드로이드를 써서 euc-kr로 되어있는 한글홈페이지를 접근했었는데....
한글이 모두깨져 나왔다.

그래서 주로 c로 개발을 했던나로써는 바이트 문자열에 접근해서 코드체계를 직접 바꾸려는 시도를 하려고했었다.

그러나 나중에 자바의 스트링은 c언어의 문자열과는 차원이 다르게 고차원이라는것을 알았다.

 
new String("문자열","euc-kr"); 
최초 생성할때 이런식으로 인코딩자체를 지정해줄수도있다.

그래서 깨지는 문자열을

byte[] bytes = str.getBytes("euc-kr");
String newStr = new String(bytes,"utf-8");
TextVw.setText(newStr);

이와 같이 utf-8로 복원을 시키면 어떨까 생각하고 시도를 해봤지만 결과는 카오스.... ㅡ.ㅡ;;

무엇이 잘못됐을까 곰곰히 생각해보니 입력받을 당시에도 코드를 지정할수있다는 것을 발견할수있었다.
입력스트림 대상이 파일건 인터넷 http든 결국 inputstream으로 받아오는데...

InputStreamReader(InputStream in, String enc)
Constructs a new InputStreamReader on the InputStream in.

이런게 있다는 사실 발견!!

그렇다 처음부터 잘못받아온걸 다시 수정하려니 그게 문제였던거다.

그래서 스트림에서 받아올 시점에 아래와같이 두번째 인자를 "euc-kr" 로 줘서 해결 해줬다.

BufferedReader br = new BufferedReader(
new InputStreamReader(Httpconn.getInputStream(),"euc-kr"));

Httpconn 의 데이터 형은 HttpURLConnection이다.

-전체 소스-

public static String DownloadHtml(String addr) {
StringBuilder html = new StringBuilder(); 
try {
URL url = new URL(addr);
//HttpURLConnection conn = (HttpURLConnection)url.openConnection();
HttpURLConnection conn = null; 
            
            if (url.getProtocol().toLowerCase().equals("https")) { 
             //   trustAllHosts(); 
             //   HttpsURLConnection https = (HttpsURLConnection) url.openConnection(); 
              //  https.setHostnameVerifier(DO_NOT_VERIFY); 
              //  conn = https; 
            } else { 
             conn = (HttpURLConnection) url.openConnection(); 
            } 
if (conn != null) {
conn.setConnectTimeout(10000);
conn.setUseCaches(false);
int resultcode = conn.getResponseCode();
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
BufferedReader br = new BufferedReader(
new InputStreamReader(conn.getInputStream(),"euc-kr"));
for (;;) {
String line = br.readLine();
if (line == null) break;
html.append(line + '\n'); 
}
br.close();
}
conn.disconnect();
}
catch (Exception ex) {
Log.i("error",ex.getMessage());
return ex.getMessage();
//System.out.println(ex.getMessage());
}
return html.toString();
}
[출처]http://gbox3d.tistory.com/entry/javaeuckr
Posted by 컴투
프로그래밍/기타...2010. 12. 8. 16:47

Allman 식 이클립스 Java 코딩 스타일 프로파일

어떤 자바 코딩 스타일을 쓰시고 계신가요?

특별히 선호하는 스타일이 없으시다면 아마도 자바 코딩 규약을 따르시겠죠?

코딩 스타일이라고 하면 여러 가지가 고려할 것들이 있습니다. 들여쓰기를 어떻게 하는지, 블럭 지정은 어떻게 하는지, 언제 줄을 나눌 것인지, 띄어쓰기, 코멘트, 배열 초기화, 심지어 이름 정하는 규칙까지......

이런 여러 요소가 있지만 보통 코딩 스타일을 분류할 때에는 들여쓰기와 블럭 표현 방법을 주로 봅니다. 아마도 이 두 가지가 코딩 스타일의 외형에 가장 큰 영향을 주기 때문인 듯합니다. 몇몇 대표적인 블럭 표현 방법에는 따로 부르는 이름까지 붙어 있지요.

제가 프로그래밍을 배우기 시작할 때에는 베이식, 어셈블리, 포트란, 코볼 같은 언어들을 주로 사용했기 때문에 요즘과는 다른 코딩 스타일을 썼었습니다. 언어 구조가 좀 다르니까요. 제가 배운 베이식은 서브루틴 같은 것도 없었거든요. ^^

처음으로 배운 구조적 언어는 Pascal입니다. Apple II에서 돌아가는 UCSD Pascal이 있었는데 p-System이라는 가상 머쉰 위에서 p Code라는 중간 코드로 컴파일 되는 언어입니다. 지금 우리가 쓰는 자바 가상 머쉰과 비슷한 놈이었죠. 좀 다른 것은 JVM은 OS 위에서 돌아갔지만 p-System은 OS까지 포함하고 있습니다. 그다음에는 CP/M이라는 OS에서 Turbo Pascal로 프로그래밍을 했었고요.

좌우간 이런 이유로 Pascal처럼 블럭의 시작과 끝이 명시적인 Allman 스타일의 블럭 표현 방법을 선호하게 되었나 봅니다. K&R 스타일은 블럭의 시작 기호와 끝 기호를 신경 써서 주목하지 않으면 찾기가 힘들더라고요. 물론 요즘은 IDE를 쓰기 때문에 자동으로 찾아주기는 하지만 최근까지 VI로 개발했었기 때문에 이 스타일이 아니면 코드를 전혀 보지 못하는 지경입니다.

대표 Indent Style

말을 시작했으니 대표적인 코딩 스타일을 몇 가지 적어볼까요? 마침 위키 백과에 잘 정리가 되어 있군요.

K&R 방식

for (int i = 0; i < 10; i++) {
    s = s + i;
    if (s > 10) {
         ......
    } else {
         ......
}

자바 코딩 규약에서 사용하는 방식입니다. 우리나라에서는 이것이 가장 일반적인 듯합니다. C를 만든 커닝핸과 리치씨의 "The C Programming language"라는 책에 사용된 코딩 스타일이지요. 이 책 한 권씩 안 사본 사람이 없을 듯한데 요즘은 모르겠군요. 제가 처음으로 산 원서 같기도 하고...... 들여쓰기는 원래 8칸이지만 요즘은 4칸을 주로 씁니다.

이것의 변형으로 BSD KNF Style이 있다네요. 보통 kernel style이라고 부르는 놈입니다. 저는 이것과 K&R이 같은 것인 줄 알았는테 텝이 조금 다르군요. 하드 탭(탭문자)는 8칸으로 보이게 설정하고 소프트 탭(어이지는 공백 여러개로 탭을 표현)은 공백 4개로 설정합니다. 밑에 제 스크린샷 중 첫번째에서 Tab Policy를 Mixed로 하고 Use tabs only for leading indentations를 체크한 후에 블럭 들여쓰기 할 때에 tab을 두번 치면 비슷해질 듯 하네요.

이렇게 탭을 설정하고는 블럭을 들여쓸 때에는 하드탭으로 이어지는 줄을 들여쓸 때에는 소프트탭으로 처리한다고 합니다.

Allman 방식

for (int i = 0; i < 10; i++)
{
    s = s + i;
    if (s > 10)
    {
         ......
    }
    else
    {
         ......
    }
}

Sendmail과 많은 BSD 유틸리티들을 만든 Eric Allman의 코딩 스타일입니다. BSD Style이라고도 불렀었습니다. 원래는 들여쓰기를 공백 8칸으로 하는데 요즘은 4칸으로 합니다.

보시면 알겠지만 블럭의 시작과 끝이 명확합니다. 가독성이 높지요. 코드 한 줄씩 정확히 볼 수 있습니다. 단 한 화면에 보이는 코드 양이 많지 않아서 스크롤을 더 해야 하는 단점도 있습니다. 그래서 Cut & Paste 방식의 프로그래밍을 방해해서 저는 좋은데 다른 분들은 모르겠군요.

C에서는 가장 많이 사용하는 방식이라고 합니다.

Whitesmith 방식

for (int i = 0; i < 10; i++)
    {
    s = s + i;
    if (s > 10)
        {
         ......
        }
    else
        {
         ......
        }
    }


Whitesmith C라고 한참 잘 팔리던 C 컴파일러의 코딩 방식입니다. 저는 이 방식으로 코딩하는 사람을 한 번도 못 봤지만 Whitesmith C로 장난질을할 때에 잠깐 접해 보기는 했습니다. 어떻게 보이시나요? Allman 방식에 눈이 익어서 처음에는 적응하기 어렵지만 금방 적응이 되더군요.
이 방식 역시 원래 8칸이었지만 요즘은 4칸을 씁니다.
Allman 방식과 거의 비슷한 수준으로 많이 쓴다고 합니다.

GNU 방식

for (int i = 0; i < 10; i++)
  {
    s = s + i;
    if (s > 10)
      {
         ......
      }
    else
      {
         ......
      }
 }

GNU에서 사용하는 방식입니다. 아마도 리처드 스톨만의 방식이겠죠? Allman과 Whitesmith의 중간형으로 보입니다. 나름의 이유가 분명히 있겠지만 솔직히 전 이 방식을 별로 좋아하지 않습니다.  이렇게 작은 들여쓰기가 반복되면 가독성이 떨어지더군요. 눈이 어지럽습니다. 보통 2칸씩 두 번 들여씁니다.

위키 백과에는 pico 방식과 banner 방식도 설명하고 있는데 이것들은 그렇게 많이 쓰이지 않으므로 넘어가겠습니다.

이클립스 자바 코드 스타일 프로파일

좌우간 제가 이 글을 쓴 이유는 이런 방식 중에 제가 쓰는 allman 방식의 이클립스용 코딩 스타일 프로파일을 공개(?)하려는 것입니다.
혹시 allman 방식을 좋아하시는 분이 있다면 받아서 쓰세요. 제가 쓰던 것을 약간 손 봐서 올립니다.

allman.zip

이 파일을 내려 받아 압축을 푼 후에 이클립스의 자바 코드 스타일 프로파일로 등록 하십시오.

Window > Preferences > Java > Code Style > Formatter 에서 Import 하시면 됩니다.

설정 내용


간단히 설정 화면 갈무리한 것을 올려보겠습니다.

들여쓰기

들여쓰기는 공백 4칸입니다. 탭을 4칸으로 표시되도록 하는 방식은 다른 에디터에서 보면 다르게 보이기 때문에 탭은 8칸으로 보이게 했습니다.
저는 에디터를 고를 때에 들여쓰기를 탭 문자가 아닌 공백으로 처리할 수 있는지를 꼭 확인합니다.

대괄호

이 부분에서 Allman 방식의 대표 특징을 부여합니다.

빈 줄 삽입

널찍널찍한 코드가 가독성이 좋지요. ^^
가독성이 떨어지면 코드를 통제하기 힘들어지고 버그도 많이 생깁니다. cut & paste 해 놓고 "잘 돌아가던 코드인데 왜 안 돌아가지?" 하는 사람 많이 봤지요. 프로그래머는 코드 한 줄에 책임을 져야 하는 거라고 생각합니다. "네가 만들어 놓은 코드를 가져다 썼는데 작동 안 되니 네가 책임져"라고 말하는 프로그래머 보면 참 답답합니다. 자기가 제다이인 줄 알고 감으로 프로그래밍하죠.

줄 나누기

자바 코딩 규약과 비슷합니다. (아마도... ㅡ.ㅡ);


제어 코드

이 부분도 기본은 널찍널찍...


긴 줄 나누기

80칸에 맞춰서 긴 줄을 나누게 설정했습니다. 요즘은 화면이 넓으니 화면 가득한 크기로 에디터를 키우고 프로그래밍하는 사람들이 많습니다. 요즘 같은 시대에 누가 터미널을 쓴다고 80칸에 맞추느냐고 말하는 분들 많지요. 자바 코딩 규약에 쓰여 있는 것처럼 다양한 환경에서도 같은 모습을 유지하려면 80 칸에 맞추는 관례를 지키는 것이 좋기는 하지요.
저는 조금 다른 이유로 여전히 80칸에 맞춰서 코딩합니다. 가로로 길게 늘여 놓으면 눈에 잘 안 들어오기 때문입니다. 눈알을 이리저리 계속 굴려야 하거든요. 제가 노안이라서 그런가요? :-)
한번 해보세요. 진짜 코드에 대한 장악력이 높아집니다. 제 생각에 80칸 규칙을 에디터가 제한하도록 설정하는 것은 별로 좋은 것 같지는 않습니다. 어떤 줄은 이름이 너무 길다거나 해서 80칸을 넘는 것이 오히려 나을 수도 있으니까요. 그냥 기준선만 표시하고 프로그래머가 그런 습관을 지키도록 하는 것이 좋다고 생각되는데 일단 이 프로파일에서는 강제로 줄 나누기 하도록 했습니다.


주석 처리

이 부분은 그냥 제가 좋은 쪽으로 했는데 뭘 고쳤는지 모르겠네요.  ㅡ.ㅡ;


따~라 라~라 랄랄랄라 랄랄랄라~
따라라 라~라~ 라~
[출처] http://gyumee.egloos.com/1306012
Posted by 컴투
프로그래밍/Java2010. 11. 6. 16:38

이클립스 속도 향상 (eclipse.ini 수정)


최근 이클립스가 버벅대서 오랜만에 이클립스 속도 향상 정보를 정리해본다.


eclipse.ini 수정


  1) Before


-startup

plugins/org.eclipse.equinox.launcher_1.1.0.v20100507.jar

--launcher.library

plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.1.1.R36x_v20100810

-product

org.eclipse.epp.package.jee.product

--launcher.defaultAction

openFile

--launcher.XXMaxPermSize

256M

-showsplash

org.eclipse.platform

--launcher.XXMaxPermSize

256m

--launcher.defaultAction

openFile

-vmargs

-Dosgi.requiredJavaVersion=1.5

-Xms40m

-Xmx512m



  2) After


-vmargs

-Dosgi.requiredJavaVersion=1.6

-Xverify:none

-XX:+UseParallelGC

-XX:-UseConcMarkSweepGC

-XX:+AggressiveOpts

-XX:PermSize=128M

-XX:MaxPermSize=128M

-XX:MaxNewSize=128M

-XX:NewSize=128M

-Xms512m

-Xmx512m


  3) 설명

-Dosgi.requiredJavaVersion=1.6 => JDK 1.6 이상을 설치했을 경우에 1.6으로 설정하면 속도가 빨라진다.

-Xverify:none => 클래스의 유효성을 검사 생략. (시작 시간이 줄어 빨라진다.)
-XX:+UseParallelGC => 병렬 가비지 컬렉션 사용. (병렬 처리로 속도 향상)
-XX:+AggressiveOpts => 컴파일러의 소수점 최적화 기능을 작동시켜 빨라진다.
-XX:-UseConcMarkSweepGC => 병행 mark-sweep GC 수행하여 이클립스 GUI의 응답을 빠르게한다.

-XX:PermSize=128M        => Permanent Generation(영구 영역) 크기(Out Of Memory 에러시 크기 조절)

-XX:MaxPermSize=128M  => 최대 Permanent Generation 크기

-XX:NewSize=128M         => New Generation(새 영역) 크기

-XX:MaxNewSize=128M   => New Generation(새 영역) 의 최대 크기


-Xms512m : 이클립스가 사용하는 최소 Heap 메모리
-Xmx512m : 이클립스가 사용하는 최대 Heap 메모리
                     최소와 최대를 같은 값으로 설정하면 오르락 내리락 하지않아 빨라진다.

혹시, 오류로 이클립스가 죽는다면 설정값을 한줄씩 지우거나 숫자를 변경해서 테스트 후 사용하기바람.

[메모리 정의 예]
1 기가 이하 메모리인 컴퓨터인 경우 => -Xms256m -Xmx256m
2 기가 ~ 3 기가 메모리인 컴퓨터    => -Xms512m -Xmx512m
4기가 이상 메모리인 컴퓨터            => -Xms1024m -Xmx1024m

[ 참고 ]
JVM 은 3가지 메모리 영역을 관리합니다.
 1. Permanent(영구) 영역 : JVM 클래스와 메소드를 위한 공간. = PermSize 설정
 2. New/Young 영역 : 새로 생성된 개체들을 위한 공간. = NewSize 설정
 3. Old 영역 : 만들어진지 오래된 객체들의 공간.(New 영역에서 이동해 온다)

Posted by 컴투
프로그래밍/기타...2010. 10. 18. 11:15

일단, 왜 이클립스가 계속 멈춰버렸는지에 대한 해답을 찾았다 >>

http://blog.eclipsercp.or.kr/javanese/?p=34

 

그리고 문제를 해결하는 방법 >>

http://atin.tistory.com/223

 

자바 메모리 설정의 문제였다..

eclipse 폴더에 eclipse.ini 파일에

.......... 

openFile
-vmargs
-Dosgi.requiredJavaVersion=1.5
-Xms40m
-Xmx512m
"
-XX:MaxPermSize=128M" >> 추가

 

 

 

이렇게 하고 나니까 이클립스가 느려지거나 멈추지 않고 잘 된다 >_<!!

Posted by 컴투
일반적인 경우, 안드로이드 용 어플리케이션을 작성하게 되면 여러가지 Activity 들을 생성하게 됩니다. 이때, 가장 골치가 아픈 일 중 하나는 바로 Activity 와 Activity 간의 Flow 를 설계하고 이를 적절하게 구현하는 일입니다. (특히 안드로이드를 사용해보지도 않은 UX 팀과 함께 일하게 되는 경우라면 더욱 그러합니다...)

 기본적으로 안드로이드 플랫폼 상에서 Activity 는 또 다른 Activity 를 시작할 수 있고, 각각의 Activity 는 차곡 차곡 Task 라고 불리우는 Activity Stack 에 쌓이게 됩니다. 사용자는 일반적으로 Back 버튼을 이용해서 현재 화면상에 보이는 Activity 를 종료 시키고, 바로 직전에 사용된 Activity 로 돌아갈 수 있습니다. 안드로이드 펍의 회색님의 말을 빌리자면, 인터넷 브라우저를 통해 웹페이지를 검색하는 것과 유사한 방식입니다. 

 하지만 이러한 방법만으로는 효과적인 UX Flow 를 구축하는데 어려움이있습니다. 다행히, 구글에서는 Activity 를 호출할 때 사용되는 Intent 에 적절한 플래그 값을 설정해서 Activity Stack 을 제어할 수 있는 방법을 제공해 줍니다. 이 플래그들은  FLAG_ACTIVITY 라는 접두어를 갖고 있는데, 종류가 다양해 헷갈리는 수도 있는데, 개인적으로 제가 가장 요긴하게 사용하고 있는 FLAG_ACTIVITY 네 가지를 소개해 봅니다. 

 먼저 FLAG_ACTIVITY_SINGLE_TOP 입니다. 우선 간단하게 그림으로 표현해 보았습니다. A 와 B  두 가지 Activity 가 있는 데, A 라는 Activity 는 B 를 B 라는 Activity 는 다시 자기 자신인 B 를 호출 하는 경우라고 가정해 보겠습니다. 
< FLAG_ACTIVITY_SINGLE_TOP >

 호출하는 Activity B 가 이미 Task 의 가장 앞에 위치하는 경우, 또 하나의 B 를 생성하는 대신, 기존에 존재하는 B Activity 가 재활용됩니다. 이 때 B 가 재활용된다는 것을 개발자가 알아채고 새롭게 전달되는 Intent 를 사용할 수 있도록 B Activity 의 onPause() / onNewIntent() / onResume() 가 순차적으로 호출됩니다. 별 생각없이 동일한 Activity 를 여러번 생성하는 것은 메모리 사용량과 Activity 시작 속도 양쪽 모두에 악영향을 끼칠 수 있습니다. (특히 이미지가 덕지덕지 붙어 있는 Activity 라면). 이런 경우 FLAG_ACTIVITY_SINGLE_TOP 를 적절하게 활용하면 제법 큰 효과를 볼 수 있습니다.

 두 번째는, FLAG_ACTIVITY_NO_HISTORY 플래그입니다. 우선 간단하게 그림으로 표현해 보았습니다. A 와 B  두 가지 Activity 가 있는 데, A 라는 Activity 는 B 를 B 라는 Activity 는 A 를 호출한 후 에 (A->B->A) 사용자가 Back 키를 누르는 경우를 가정해 보겠습니다.
<FLAG_ACTIVITY_NO_HISTORY>

 말 그대로, FLAG_ACTIVITY_NO_HISTORY 로 설정된 Intent 로 시작된 Activity B 는 Task 에 그 흔적을 남기지 않게 됩니다. B 에서 또다른 A 를 시작한 후, Back 을 누르면 일반적인 경우 이전에 실행되었던 B 가 나타나지만, NO_HISTORY 를 사용하는 경우 맨 처음에 실행 되었던 A 가 화면에 표시됩니다. 몇 가지 주의할 점이 있습니다. 우선 NO_HISTORY 를 사용하게 되면 Task 에 해당 Intent 의 정보가 기록되지 않기 때문에, A->B 인 상황 (그림에서 두 번째 단계...) 에서 홈키등을 눌러 다른 Task 로 전환된 후, 다시 본 Task 로 돌아오게 되면, A Activity 가 화면에 표시됩니다. 또한, B Activity 의 onDestroy() 가 호출되는 시점이 조금 애매합니다.일반적인 예상과는 달리, B 에서 또다른 A Activity 를 호출하는 세 번째 단계에서는 onStop 까지만 호출되고, 이 후에 새롭게 호출된 A Activity 가 사라지는 순간 (네 번째 단계) 에서야 onDestroy() 가 호출 됩니다.

 FLAG_ACTIVITY_NO_HISTORY 는 여러가지로 쓸모가 있는데, 특히 특정한 이벤트에 대한 알람등을 위해 다이얼로그 형태로 화면에 표시되는 Activity 들에 적용하기에 편리합니다. (대게의 경우 팝업은 해당 시점에 한번만 보여주면 되니까.)

 다음으로 굉장히 유용한 플래그 두 가지를 동시에 설명해보고자 합니다. FLAG_ACTIVITY_REORDER_TO_FRONT 와 FLAG_ACTIVITY_CLEAR_TOP 플래그입니다. 우선 간략하게 그림으로 살펴 보겠습니다. A Activity 에서 B Activity 를 그리고 B 에서 A 를 호출하는 상황을 가정해보았습니다. (A->B->A)


 FLAG_ACTIVITY_REORDER_TO_FRONT 는 매우 특이하게도 Task 의 순서 자체를 뒤바꿔 줍니다. 이 플래그를 사용하면, 런치하고자 하는 Activity 가 이미 Task 상에 존재하는 경우 해당 Activity 를 새롭게 생성하는 대신, 아래쪽에 위치한 Activity 의 순서를 Task 의 가장 위로 끌어올려줍니다. 따라서 A->B->A 의 순서로 Activity 호출이 일어날때, 새로운 A 가 생성되는 대신 아래쪽에 위치한 A 가 위로 올라와 최종적으로 B->A 의 형태로 Task 가 구성되게 됩니다. 어떤 Activity 에서 특정 Activity 로 점프하는 형식의 Flow 를 구성해야하는 경우 요긴하게 사용될 수도 있지만, Task 의 순서를 뒤섞는 다는 점에서 사용에 주의를 기울일 필요가 있습니다.  (별 생각없이 남발하게 되면 Back 키가를 누를 때 엉뚱한 Activity 가 표시되어 사용자들이 굉장히 혼란스러워 하는 경우가 있습니다.) 

 마지막으로 소개해 드릴 플래그는 바로 FLAG_ACTIVITY_CLEAR_TOP 입니다. 제가 개인적으로 가장 사랑스럽게 생각하는 녀석입니다. 이 플래그가 사용되는 경우  
런치하고자 하는 Activity 가 이미 Task 상에 존재하는 경우, 해당 Activity 위에 존재하는 다른 Activity 를 모두 종료시켜 줍니다. 따라서 A->B->A 로 호출이 일어나는 경우, B Activity 가 종료 되고, A Activity 만 Task 에 남게 됩니다. (A->B->C->A 인 경우에도 마찬가지로 B와 C 가 종료되고 A 만 남게 됩니다.)

  이 Flag 는 특정 어플리케이션의 대쉬보드 (혹은 홈) Activity 를 호출할 때 굉장히 유용하게 사용될 수 있습니다. 즉 하나의 어플리케이션이 하나 혹은 두 가지의 주요한 Activity 와 그 외 특정 값을 선택하는등 단순한 일을 수행하기 위한 여러 개의 Sub-Activity 로 구성되어 있다면, 주요 Activity 를 호출하는데 이 Flag 를 사용함으로서 어플리케이션의 홈버튼등을 손쉽게 구현할 수 있습니다. 또 이 Flag 는 FLAG_ACTIVITY_REORDER_TO_FRONT 와는 달린 Task 의 순서를 뒤섞지 않음으로 사용자에게도 큰 혼란을 주지 않습니다. (사용을 적극 권장합니다.)

 한 가지 주의해야할 점은 A->B->A 형태로 Activity 를 호출 하고자 할 때, 단순히 FLAG_ACTIVITY_CLEAR_TOP 만을 사용하게 되면, 기존에 생성되었던 A Activity 가 종료된 후 (onDestroy() 가 호출됨) 새롭게 A 가 생성 (onCreate()) 됩니다. 만일 기존에 사용된 A Activity 가 계속 사용되기를 원한다면, SINGLE_TOP 플래그와 함께 사용해야 합니다.

 휴... 생각보다 내용이 길어졌네요. 대부분 SDK 문서를 읽어보면 잘 나와있는 내용이라 새로운 내용은 없습니다만... 문서 읽기를 게을리한 덕분에 한창을 고생했던 기억이 떠올라 (특히 CLEAR_TOP) 유용하게 사용한 Flag 를 정리하는 겸 작성해 보았습니다~

출처: http://surprisen.egloos.com/2511530
Posted by 컴투
출처 : http://miksnug.pe.kr/24


Android 에서 Multi Touch 를 구현한 Code 입니다.
허접하지만 튜닝하면 좀 더 나아지지 않을까 생각합니다.


+ MainActivity.java
  1. package kr.pe.miksnug;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. import android.app.Activity;  
  6. import android.content.Context;  
  7. import android.graphics.Canvas;  
  8. import android.graphics.Color;  
  9. import android.graphics.Paint;  
  10. import android.os.Bundle;  
  11. import android.os.Vibrator;  
  12. import android.view.MotionEvent;  
  13. import android.view.View;  
  14. import android.widget.FrameLayout;  
  15. import android.widget.TextView;  
  16.   
  17. /** 
  18.  * 안드로이드 멀티터치 입니다.<br/> 
  19.  * <br/> 
  20.  * 프로젝트 실행 Main Activity 클래스 <br/> 
  21.  * Android 2.0 이상 지원 <br/> 
  22.  * <br/> 
  23.  * 1. 멀티터치 감지 (구현상 무한대)<br/> 
  24.  * 2. 터치점에 원형 표시<br/> 
  25.  * 3. 누르는 힘에 따라 색깔 및 크기 변경<br/> 
  26.  * 4. 누르는 힘에 따라 진동 변경<br/> 
  27.  * <br/> 
  28.  *  
  29.  * @author yeongeon 
  30.  *  
  31.  */  
  32. public class MainActivity extends Activity {  
  33.   
  34.     /** 
  35.      * 메인 레이아웃 인스턴스 
  36.      */  
  37.     private FrameLayout m_mainLayout = null;  
  38.   
  39.     /** 
  40.      * 디버그 텍스트 출력용 뷰 
  41.      */  
  42.     TextView m_tvDebugText = null;  
  43.     TextView m_tvDebugText2 = null;  
  44.   
  45.       
  46.     /** 
  47.      * 입력된 이벤트 수 
  48.      */  
  49.     private int m_eventCnt = 0;  
  50.   
  51.     /** 
  52.      * 원 도형 View 클래스 
  53.      *  
  54.      * @author yeongeon 
  55.      */  
  56.     class Ball extends View {  
  57.   
  58.         /** 
  59.          * X 좌표 
  60.          */  
  61.         public float m_x;  
  62.   
  63.         /** 
  64.          * Y 좌표 
  65.          */  
  66.         public float m_y;  
  67.   
  68.         /** 
  69.          * 반지름 
  70.          */  
  71.         private int m_r;  
  72.   
  73.         /** 
  74.          * 페인트 인스턴스 
  75.          */  
  76.         private Paint m_paint = new Paint(Paint.LINEAR_TEXT_FLAG);  
  77.   
  78.         /** 
  79.          * 원 도형 생성자 
  80.          *  
  81.          * @param context 
  82.          * @param x 
  83.          * @param y 
  84.          * @param r 
  85.          * @param color 
  86.          */  
  87.         public Ball(Context context, float x, float y, int r, int color) {  
  88.             super(context);  
  89.             m_paint.setColor(color);  
  90.             this.m_x = x;  
  91.             this.m_y = y;  
  92.             this.m_r = r;  
  93.         }  
  94.   
  95.         /** 
  96.          * 도형 그리는 메소드 
  97.          *  
  98.          * @see android.view.View#onDraw(android.graphics.Canvas) 
  99.          */  
  100.         @Override  
  101.         protected void onDraw(Canvas canvas) {  
  102.             canvas.drawCircle(m_x, m_y, m_r, m_paint);  
  103.             super.onDraw(canvas);  
  104.         }  
  105.   
  106.     }  
  107.       
  108.   
  109.     /** 
  110.      * MyText View 클래스 
  111.      *  
  112.      * @author yeongeon 
  113.      */  
  114.     class FloatingText extends View {  
  115.   
  116.         /** 
  117.          * X 좌표 
  118.          */  
  119.         public float m_x;  
  120.   
  121.         /** 
  122.          * Y 좌표 
  123.          */  
  124.         public float m_y;  
  125.   
  126.         /** 
  127.          * 반지름 
  128.          */  
  129.         private String m_t;  
  130.   
  131.         /** 
  132.          * 페인트 인스턴스 
  133.          */  
  134.         private Paint m_paint = new Paint(Paint.LINEAR_TEXT_FLAG);  
  135.   
  136.         /** 
  137.          * 원 도형 생성자 
  138.          *  
  139.          * @param context 
  140.          * @param x 
  141.          * @param y 
  142.          * @param r 
  143.          * @param color 
  144.          */  
  145.         public FloatingText(Context context, float x, float y, String t, int color) {  
  146.             super(context);  
  147.             m_paint.setColor(color);  
  148.             this.m_x = x;  
  149.             this.m_y = y;  
  150.             this.m_t = t;  
  151.         }  
  152.   
  153.         /** 
  154.          * 도형 그리는 메소드 
  155.          *  
  156.          * @see android.view.View#onDraw(android.graphics.Canvas) 
  157.          */  
  158.         @Override  
  159.         protected void onDraw(Canvas canvas) {  
  160.             canvas.drawText(m_t, m_x, m_y, m_paint);  
  161.             super.onDraw(canvas);  
  162.         }  
  163.   
  164.     }  
  165.   
  166.     /** 
  167.      * 터치 이벤트 개별 노드 클래스 
  168.      *  
  169.      * @author yeongeon 
  170.      */  
  171.     class EventNode {  
  172.         /** 
  173.          * 포인터 아이디 
  174.          */  
  175.         private int m_pointerId = -1;  
  176.   
  177.         /** 
  178.          * 포인터 인덱스 
  179.          */  
  180.         private int m_pointerIndex = -1;  
  181.   
  182.         /** 
  183.          * x 좌표 값 
  184.          */  
  185.         private float m_x = -1;  
  186.   
  187.         /** 
  188.          * y 좌표 값 
  189.          */  
  190.         private float m_y = -1;  
  191.   
  192.         /** 
  193.          * 압력 값 
  194.          */  
  195.         private float m_pressure = -1;  
  196.   
  197.         /** 
  198.          * 도형 인스턴스 
  199.          */  
  200.         private Ball m_ball = null;  
  201.   
  202.         /** 
  203.          * Paint 색 
  204.          */  
  205.         private int m_color = Color.YELLOW;  
  206.           
  207.         /** 
  208.          * 진동 시간 간격 
  209.          */  
  210.         int m_vibrationInterval = 2;  
  211.           
  212.         /** 
  213.          * 반지름 
  214.          */  
  215.         int m_radius = 50;  
  216.           
  217.         /** 
  218.          * 떠다니는 문자 인스턴스 
  219.          */  
  220.         FloatingText m_floatingText = null;  
  221.           
  222.           
  223.         /** 
  224.          * 생성자 입니다. 
  225.          *  
  226.          * @param event 
  227.          * @param idx 
  228.          */  
  229.         public EventNode(MotionEvent event, int idx) {  
  230.             this.m_pointerId = event.getPointerId(idx);  
  231.             this.m_pointerIndex = event.findPointerIndex(this.m_pointerId);  
  232.             this.m_x = event.getX(this.m_pointerIndex);  
  233.             this.m_y = event.getY(this.m_pointerIndex);  
  234.             this.setPressure(event.getPressure(this.m_pointerIndex) );  
  235.             if (this.getPressure() >= 0.1 && this.getPressure() < 0.18) {  
  236.                 this.m_color = Color.GREEN;  
  237.                 this.m_vibrationInterval = 3;  
  238.                 this.m_radius = 60;  
  239.             } else if (this.getPressure() > 0.25) {  
  240.                 this.m_color = Color.RED;  
  241.                 this.m_vibrationInterval = 6;  
  242.                 this.m_radius = 100;  
  243.             } else if (this.getPressure() >= 0.18 && this.getPressure() < 0.25) {  
  244.                 this.m_color = Color.BLUE;  
  245.                 this.m_vibrationInterval = 4;  
  246.                 this.m_radius = 70;  
  247.             } else {  
  248.                 this.m_color = Color.YELLOW;  
  249.                 this.m_vibrationInterval = 2;  
  250.                 this.m_radius = 50;  
  251.             }  
  252.             this.m_ball = new Ball(getApplicationContext(), this.getX(), this  
  253.                     .getY(), this.m_radius, this.getColor());  
  254.               
  255.             this.m_floatingText = new FloatingText(getApplicationContext(), this.getX()-(this.m_radius/2), this  
  256.                     .getY()-this.m_radius, ""this.getPressure(), Color.WHITE );             
  257.               
  258.         }  
  259.           
  260.         public FloatingText getFloatingText(){  
  261.             return m_floatingText;  
  262.         }  
  263.           
  264.         public int getVibrationInterval() {  
  265.             return this.m_vibrationInterval;  
  266.         }  
  267.   
  268.         /** 
  269.          * 정의된 Paint 색 값을 반환하는 메소드입니다. 
  270.          *  
  271.          * @return 
  272.          */  
  273.         public int getColor() {  
  274.             return this.m_color;  
  275.         }  
  276.   
  277.         /** 
  278.          * Paint 색을 할당하는 메소드입니다. 
  279.          *  
  280.          * @param color 
  281.          */  
  282.         public void setColor(int color) {  
  283.             this.m_color = color;  
  284.         }  
  285.   
  286.         /** 
  287.          * 압력 값을 반환하는 메소드입니다. 
  288.          *  
  289.          * @return 
  290.          */  
  291.         public float getPressure() {  
  292.             return this.m_pressure;  
  293.         }  
  294.   
  295.         /** 
  296.          * 압력 값을 정의하는 메소드입니다. 
  297.          *  
  298.          * @param pressure 
  299.          */  
  300.         public void setPressure(float pressure) {  
  301.             this.m_pressure = pressure;  
  302.         }  
  303.   
  304.         /** 
  305.          * 포인터 아이디를 반환하는 메소드입니다. 
  306.          *  
  307.          * @return 
  308.          */  
  309.         public int getPointerId() {  
  310.             return this.m_pointerId;  
  311.         }  
  312.   
  313.         /** 
  314.          * 포인터 인덱스를 반환하는 메소드입니다. 
  315.          *  
  316.          * @return 
  317.          */  
  318.         public int getPointerIndex() {  
  319.             return this.m_pointerIndex;  
  320.         }  
  321.   
  322.         /** 
  323.          * x 좌표값을 반환하는 메소드입니다. 
  324.          *  
  325.          * @return 
  326.          */  
  327.         public float getX() {  
  328.             return this.m_x;  
  329.         }  
  330.   
  331.         /** 
  332.          * y 좌표값을 반환하는 메소드입니다. 
  333.          *  
  334.          * @return 
  335.          */  
  336.         public float getY() {  
  337.             return this.m_y;  
  338.         }  
  339.   
  340.         /** 
  341.          * 도형 인스턴스를 반환하는 메소드입니다. 
  342.          *  
  343.          * @return 
  344.          */  
  345.         public Ball getBall() {  
  346.             return this.m_ball;  
  347.         }  
  348.   
  349.         /** 
  350.          * 각 인스턴스 값을 초기화하는 메소드입니다. 
  351.          */  
  352.         public void setInit() {  
  353.             this.m_pointerId = -1;  
  354.             this.m_pointerIndex = -1;  
  355.             this.m_x = -1;  
  356.             this.m_y = -1;  
  357.             this.m_pressure = -1;  
  358.             this.m_color = Color.GREEN;  
  359.             this.m_ball = null;  
  360.         }  
  361.     }  
  362.   
  363.     /** 
  364.      * 모션 이벤트를 담아두는 ArrayList 인스턴스입니다. 
  365.      */  
  366.     private ArrayList<EventNode> m_aEventNodes = new ArrayList<EventNode>();  
  367.   
  368.     /** 
  369.      * Activity 생성시 접근 메소드 
  370.      *  
  371.      * @see android.app.Activity#onCreate(android.os.Bundle) 
  372.      */  
  373.     @Override  
  374.     public void onCreate(Bundle savedInstanceState) {  
  375.         super.onCreate(savedInstanceState);  
  376.         setContentView(R.layout.main);  
  377.   
  378.         // 레이아웃 인스턴드 할당  
  379.         m_mainLayout = (FrameLayout) this.findViewById(R.id.main);  
  380.   
  381.         // 디버그 텍스트 뷰 인스턴스 할당  
  382.         m_tvDebugText = (TextView) this.findViewById(R.id.debug_text);  
  383.         m_tvDebugText2 = (TextView) this.findViewById(R.id.debug_text2);  
  384.     }  
  385.   
  386.     /** 
  387.      * 터치했을때 반응하는 메소드입니다. 
  388.      *  
  389.      * @see android.app.Activity#onTouchEvent(android.view.MotionEvent) 
  390.      */  
  391.     @Override  
  392.     public boolean onTouchEvent(MotionEvent event) {  
  393.         m_eventCnt = event.getPointerCount();  
  394.   
  395.         m_tvDebugText.setVisibility(View.VISIBLE);  
  396.         m_tvDebugText.setText("Points : " + m_eventCnt  
  397.                 + " / EventNodes : " + m_aEventNodes.size());  
  398.   
  399.         switch (event.getAction()) {  
  400.         // 눌렀을 때  
  401.         case MotionEvent.ACTION_DOWN:  
  402.             drawBall(event);  
  403.             return true;  
  404.   
  405.             // 누르고 이동할 때  
  406.         case MotionEvent.ACTION_MOVE:  
  407.             moveBall(event);  
  408.             return true;  
  409.   
  410.             // 떼었을 때  
  411.         case MotionEvent.ACTION_UP:  
  412.             removeBall();  
  413.   
  414.             m_tvDebugText.setVisibility(View.GONE);  
  415.             return true;  
  416.         }  
  417.   
  418.         return false;  
  419.     }  
  420.   
  421.     /** 
  422.      * 도형 그리는 메소드 
  423.      *  
  424.      * @param event 
  425.      */  
  426.     private void drawBall(MotionEvent event) {  
  427.         removeBall();  
  428.         for (int i = 0; i < m_eventCnt; i++) {  
  429.             EventNode eventNode = new EventNode(event, i);  
  430.             m_aEventNodes.add(eventNode);  
  431.             m_mainLayout.addView(eventNode.getBall());  
  432.             m_mainLayout.addView(eventNode.getFloatingText());  
  433.             ((Vibrator)getSystemService(VIBRATOR_SERVICE)).vibrate(eventNode.getVibrationInterval());  
  434.         }  
  435.   
  436.     }  
  437.   
  438.     /** 
  439.      * 도형 이동 처리 메소드 
  440.      *  
  441.      * @param event 
  442.      */  
  443.     private void moveBall(MotionEvent event) {  
  444.         removeBall();  
  445.         drawBall(event);  
  446.     }  
  447.   
  448.     /** 
  449.      * 도형 제거 처리 메소드 
  450.      */  
  451.     private void removeBall() {  
  452.         int nSize = m_aEventNodes.size();  
  453.         for (int i = 0; i < nSize; i++) {  
  454.             m_mainLayout.removeView(m_aEventNodes.get(0).getBall());  
  455.             m_mainLayout.removeView(m_aEventNodes.get(0).getFloatingText());  
  456.             m_aEventNodes.remove(0);  
  457.         }  
  458.     }  
  459.   
  460. }  

+ main.xml
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:id="@+id/main" android:orientation="vertical"  
  4.     android:layout_width="fill_parent" android:layout_height="fill_parent">  
  5.     <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent">   
  6.         <TextView android:id="@+id/debug_text2"   
  7.             android:layout_width="wrap_content"  
  8.             android:layout_height="wrap_content"   
  9.             android:gravity="left" />  
  10.         <TextView android:id="@+id/debug_text"   
  11.             android:layout_width="wrap_content"  
  12.             android:layout_height="wrap_content"   
  13.             android:gravity="right"/>  
  14.     </LinearLayout>  
  15. </FrameLayout>  

+ strings.xml
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <string name="app_name">AndroidMultiTouch</string>  
  4. </resources>  

+ AndroidManifest.xml
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.       package="kr.pe.miksnug"  
  4.       android:versionCode="1"  
  5.       android:versionName="1.0">  
  6.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  7.         <activity android:name=".MainActivity"  
  8.                   android:label="@string/app_name"  
  9.                   android:theme="@android:style/Theme.NoTitleBar.Fullscreen">  
  10.             <intent-filter>  
  11.                 <action android:name="android.intent.action.MAIN" />  
  12.                 <category android:name="android.intent.category.LAUNCHER" />  
  13.             </intent-filter>  
  14.         </activity>  
  15.   
  16.     </application>  
  17. <uses-permission android:name="android.permission.VIBRATE"></uses-permission>  
  18. </manifest>   
저작자 표시

추가
--------------------------------------------------------------------
안드로이드 데브가이드 사이트에서 매니페스트에 
<uses-permission android:name="android.hardware.touchscreen.multitouch"/>
이 퍼미션도 주란다..
Posted by 컴투
프로그래밍/기타...2010. 7. 5. 14:14


구글링을 통해 다른 사용자가 만들어 놓은 Preferences파일(.epf)을 임포트 시켜 화면 설정을 적용시킬 수 있지만 그 epf파일에 화면설정 뿐 아니라 다른 설정들 까지 같이 포함되어 있어 왠지 깔끔하지 못 한 감이 있습니다.
그래서 제가 쓰고 있는 화면의 수동설정 항목들을 리스팅 합니다.

접어두기..

  1. General -> Appearance -> Colors and Fonts
    • Basic -> Text Font : 나눔고딕코딩, 10pt
  2. General -> Editors -> Text Editors
    • Current line highlight : Color - 34, 32, 32
    • Print margin : Color - 76, 76, 76
    • Find scope : Color - 25, 25, 25
    • Selection foreground color : System Default uncheck
    • Selection background color : System Default uncheck / Color - 65, 76, 59
    • Background color : System Default uncheck / Color - 25, 25, 25
    • Foreground color : System Default uncheck / Color - 128, 255, 0
  3. General -> Editors -> Text Editors -> Annotations
    • Occurrences : Color - 0, 196, 0 / Text as - Dashed Box
    • Write Occurrences : Color - 196, 0, 0 / Text as - Dashed Box
  4. General -> Editors -> Text Editors -> Quick Diff
    • Colors -> Deletions : Color - 255, 0, 0
  5. General -> Editors -> Spelling
    • Enable spell checking : uncheck
  6. Java -> Editor
    • Matching brackets highlight : Color - 0, 255, 0
    • Parameter hints background : Color - 0, 0, 0
    • Parameter hints foreground : Color - 230, 230, 230
  7. Java -> Editor -> Syntax Coloring
    • Java -> Abstract method invocations : Enable / Color - 241, 196, 56
    • Java -> Annotations : Color - 135, 19, 33
    • Java -> Brackets : Color - 255, 255, 255
    • Java -> Classes : Enable / Color - 156, 248, 40
    • Java -> Constants : Enable / Color - 156, 248, 40
    • Java -> Deprecated memebers : Color - 255, 255, 255
    • Java -> Enums : Enable / Color - 64, 128, 0
    • Java -> Fields : Color - 53, 122, 143
    • Java -> Inherited method invocations : Enable / Color - 241, 196, 56
    • Java -> Interfaces : Enable / Color - 156, 248, 40
    • Java -> Keyword 'return' : Color - 236, 108, 30
    • Java -> Keywords excluding 'return' : Color - 236, 108, 30
    • Java -> Local variable declarations : Enable / Color - 53, 122, 146
    • Java -> Local variable references : Enable / Color - 53, 122, 146
    • Java -> Method declarations : Enable / Color - 241, 196, 56
    • Java -> Methods : Color - 241, 196, 56
    • Java -> Numbers : Enable / Color - 255, 255, 0
    • Java -> Operators : Color - 255, 255, 255
    • Java -> Others : Color - 255, 255, 255
    • Java -> Parameter variables : Enable / Color - 64, 128, 0
    • Java -> Static Fields : Bold  / Color - 255, 255, 128 / Italic uncheck
    • Java -> Static method invocations : Bold  / Color - 255, 255, 255 / Italic uncheck
    • Java -> Strings : Color - 255, 64, 64
    • Java -> Type arguments : Enable / Color - 216, 176, 176
    • Java -> Type variables : Enable / Color - 216, 176, 176
    • Comments -> Multi-line comment : Color - 16, 184, 248
    • Comments -> Single-line comment : Color - 16, 184, 248
    • Comments -> Task tags : Color - 5, 142, 171
  8. Java -> Properties Files Editor
    • Arguments : Bold / Color - 128, 255, 0
    • Assignments : Color - 255, 255, 255
    • Keys : Color - 255, 200, 0
    • Values : Color - 255, 255, 255

출처 : http://bbare.tk/

Posted by 컴투
프로그래밍/기타...2010. 5. 6. 11:06

적용 대상
Microsoft Office Outlook® 2003
Microsoft Outlook® 2002

전자 메일 메시지는 모두 전자 메일 서버 (전자 메일 서버: 전자 메일 메시지를 저장하는 컴퓨터입니다.)를 통해 전자 메일 계정 (전자 메일 계정: Outlook에서 전자 메일 서비스에 연결하는 데 사용되는 서버 이름, 사용자 이름, 암호 및 전자 메일 주소입니다. 관리자 또는 ISP(인터넷 서비스 공급자)에서 제공하는 정보를 사용하여 Outlook에서 전자 메일 계정을 만듭니다.)으로 받습니다. 사용하는 전자 메일 계정 유형에 따라 전자 메일 메시지는 다음 방법 중 하나 이상을 사용하여 처리됩니다.

메일 위치

설명선 1 메시지가 서버에 남아 있습니다. Outlook이 서버에 연결되면 사용자는 메시지를 읽거나 삭제할 수 있습니다.

설명선 3 메시지 복사본이 다운로드되며 전자 메일 서버의 메시지와 동기화됩니다. Microsoft Exchange Server 계정은 로컬 오프라인 폴더 파일(.ost) (오프라인 폴더 파일: 오프라인 폴더를 포함하는 하드 디스크의 파일이며 확장명은 .ost입니다. Outlook을 설치하거나, 폴더를 처음으로 오프라인에서 사용 가능하도록 설정할 때 자동으로 오프라인 폴더 파일을 만들 수 있습니다.)을 만들어 이 기능을 제공합니다. 이 파일은 전자 메일 서버에 연결할 수 없거나 연결하지 않으려는 경우 오프라인으로 작업할 때 사용됩니다. 또한 Outlook 2003의 캐시된 Exchange 모드 기능에도 이 파일이 사용됩니다.

전자 메일 계정의 전자 메일 메시지의 저장 방식 및 전자 메일 서버와의 동기화 방식은 유형에 따라 다릅니다. 예를 들어 기본적으로 POP3 전자 메일 계정은 전자 메일 메시지를 Outlook으로 다운로드한 후 전자 메일 서버에서 메시지를 삭제합니다. 대신 전자 메일 메시지의 검색 및 저장 방식을 사용자가 지정할 수 있습니다. Exchange Server 전자 메일 계정과 같은 전자 메일 계정은 기본적으로 전자 메일 서버에 전자 메일 메시지를 모두 저장하는데, 전자 메일 메시지 복사본을 사용자 컴퓨터에 저장하도록 Exchange Server 전자 메일 계정을 구성할 수도 있습니다. 그러면 Exchange Server에 연결하지 않은 경우에도 전자 메일 메시지를 읽을 수 있습니다. 전자 메일 계정에 따라 전자 메일 메시지가 처리되는 방식에 대한 자세한 정보는 다음을 참고하십시오.

숨기기POP3 전자 메일 계정

POP3 (POP3: 인터넷 전자 메일 서버에서 전자 메일 메시지를 가져오는 데 사용되는 일반 프로토콜입니다.) 전자 메일 계정에서 전자 메일 메시지를 검색할 경우 메시지가 컴퓨터에 다운로드되면 전자 메일 서버에서 해당 메시지가 기본적으로 삭제됩니다. 대부분의 경우 이러한 기능은 매우 편리합니다.

그러나 여러 컴퓨터에서 전자 메일을 확인하려는 경우에는 전자 메일 서버에서 메시지를 삭제하지 않도록 Outlook을 구성해야 합니다. 이 시나리오는 집에서 사용하는 인터넷 서비스 공급자(ISP) (ISP(인터넷 서비스 공급자): 전자 메일, 대화방, 웹 등을 사용할 수 있도록 인터넷 액세스를 제공하는 회사입니다. ISP는 여러 위치에서 액세스를 제공하는 다국적 회사일 수도 있고, 특정 지역에서만 서비스를 제공하는 회사일 수도 있습니다.) 전자 메일 계정을 회사에서 확인하고 메시지는 집에 있는 컴퓨터의 영구 저장소에 다운로드하려는 사용자에게 가장 일반적으로 해당합니다.

메시지를 전자 메일 서버에 남겨둘 경우 여러 가지 옵션을 사용하여 메시지를 삭제할 수 있습니다. 이러한 옵션을 선택할 때는 여러 컴퓨터에서 메시지에 액세스할 수 있는 기간, 전자 메일 서버 관리자가 지정한 저장 용량 등 전자 메일 사용에 대한 여러 가지 요인을 고려해야 합니다. 저장 용량을 초과하면 새 메시지를 받을 수 없거나 추가 요금을 지불해야 할 수 있습니다. 일반적으로 컴퓨터 한 대는 전자 메일 메시지를 전자 메일 서버에 남기지 않도록 기본적으로 설정하는 것이 가장 좋습니다. 이 컴퓨터를 사용하여 전자 메일 메시지를 검색할 경우 메시지가 다운로드된 후 전자 메일 서버에서 메시지가 삭제됩니다. 이렇게 설정하지 않을 경우에는 Outlook에서 전자 메일 메시지를 전자 메일 서버에 저장하는 기간을 선택할 수 있습니다.

  1. 도구 메뉴에서 전자 메일 계정을 클릭합니다.
  2. 기존의 전자 메일 계정 보기 또는 변경을 클릭하고 다음을 클릭합니다.
  3. ISP 계정을 선택한 다음 변경을 클릭합니다.
  4. 기타 설정을 클릭합니다.
  5. 고급 탭을 클릭하고 배달에서 서버에 메시지 복사본 저장 확인란을 선택합니다.

    인터넷 전자 메일 설정 대화 상자

  6. 다음 옵션 중 하나를 선택합니다.
    • 다음 기간 후에 서버에서 제거 x   전자 메일 메시지가 컴퓨터에 다운로드되어도 지정한 기간 동안 전자 메일 서버에 남아 있습니다. 이 옵션은 회사에서 메시지를 읽고 집에 있는 컴퓨터의 영구 저장소에 다운로드하려는 사용자에게 가장 적합합니다. 필요에 맞는 가장 짧은 기간을 선택하는 것이 좋습니다. 메시지를 전자 메일 서버에 오래 저장할수록 사서함 크기 할당량을 초과할 가능성이 높아지기 때문입니다.
    • 지운 편지함에서 삭제하면 서버에서 제거   전자 메일 메시지가 컴퓨터에 다운로드되지만 Outlook에서 해당 전자 메일 메시지를 삭제하고 지운 편지함 폴더를 비울 때까지 전자 메일 서버에서 삭제되지 않습니다. 단순히 메시지를 삭제한다고 해서 전자 메일 서버에서 메시지가 제거되는 것은 아닙니다.

    두 확인란 중 하나를 선택하지 않으면 메시지가 서버에 무기한으로 저장됩니다. 이러한 경우 전자 메일 서버에서 메시지를 제거하도록 Outlook을 구성한 다른 컴퓨터에서 전자 메일 서버에 연결하지 않으면 결국 사서함 할당량이 초과됩니다.

  7. 확인을 클릭한 다음 마침을 클릭합니다.

여러 컴퓨터에서 POP3 전자 메일 계정을 사용하는 방법에 대한 자세한 내용은 이 문서의 참고 항목 섹션을 참고하십시오.

표시IMAP 전자 메일 계정

IMAP (IMAP(Internet Message Access Protocol): POP3 같은 인터넷 전자 메일 프로토콜과 달리 IMAP는 다른 컴퓨터에서 검색할 수 있도록 서버에 폴더를 만들어 메시지를 저장하고 구성합니다. 메시지 머리글만 읽을 수 있고 다운로드할 메시지를 선택할 수 있습니다.) 전자 메일 계정에 액세스할 경우 메시지가 로컬 위치에 복사됩니다. 그러나 삭제한 것으로 표시하고 "지운 편지함" 폴더 비우기 명령을 사용할 때까지 메시지가 전자 메일 서버에 남아 있습니다. IMAP 메시지 삭제에 대한 자세한 내용은 이 문서의 참고 항목 섹션을 참고하십시오.

표시HTTP 전자 메일 계정

MSN Hotmail과 같은 HTTP (HTTP(Hypertext Transfer Protocol): 인터넷에서 웹 페이지에 액세스할 때 사용되는 프로토콜입니다. Outlook에서는 HTTP를 전자 메일 프로토콜로 사용합니다.) 전자 메일 계정에 액세스할 경우 메시지를 삭제할 때까지 메시지가 전자 메일 서버에 저장됩니다.

표시Exchange Server 전자 메일 계정

Exchange Server 전자 메일 계정에 액세스할 경우 메시지를 삭제할 때까지 메시지가 전자 메일 서버에 저장됩니다.

by : http://office.microsoft.com/ko-kr/outlook/HA011507931042.aspx

Posted by 컴투
프로그래밍/기타...2010. 5. 6. 11:05

보안 메일 1탄. 이메일 인증서를 이용하여 아웃룩에서 보안 메일 주고받기

인터넷에서 자신의 신분을 확인하는 수단으로는 아이디/비밀번호로 접속하는 방식이 가장 보편적입니다. 그리고, 금융 등의 보안이 특히 요구되는 환경에서는 개인 인증서와 비밀번호를 통해 한층 더 보안을 강화합니다.

우리가 아웃룩이나 아웃룩 익스프레스를 사용하여 다른 사람들과 메일을 주고 받을 때에는 일반적으로 평문(Plain Text)으로 전송됩니다. 중간에 메일 서버 관리자나 보안 장비 등에서는 메일의 제목이나 내용을 엿볼 수 있습니다.

이러한 잠재적인 위험을 방지하려면 메일을 보낼 때에 보안 기능을 추가하여 보냅니다. 이러한 보안을 추가하는 방법은 모두 3가지가 있으며 이중 첫 번째로 개인 인증서를 사용하여 아웃룩에서 보안 메일을 주고 받는 방법에 대해 소개합니다.

이 방법은 보안 메일을 사용하고자 하는 모든 사용자들이 각자 인증서를 등록, 설치해야 합니다. 서버 단에서는 별도로 설정할 필요가 없습니다.

인증서는 서버용, 웹서버용, 그리고 개인용 등 다양한 인증서가 존재하지만, 여기에서는 개인용 이메일 인증서를 이용합니다.

이메일 인증서는 "공개 키", "개인 키", "디지털 서명" 등 세 가지로 구성됩니다. 메일을 작성할 때에는 "공개 키"와 "디지털 서명"을 추가합니다. 메일을 받는 쪽에서는 "디지털 서명"을 통해 보낸 사람을 확인하고, "개인 키"로 암호를 풀어 본문을 읽는 방식입니다.

인증서 작업을 진행하기에 앞서 아웃룩/아웃룩 익스프레스에서 전자 메일 계정을 설정해야 합니다. 설정한 이후에는 메일을 주고 받는 테스트를 해 둬야 편리합니다.

  1. 인증서 신청

    국내외에서는 개인용 인증서를 무료로 제공하는 곳이 다수 있습니다. 여기에서는 써트(http://www.thawte.co.kr)에서 제공하는 서비스를 중심으로 설명합니다

    1.1 인증서 신청: 인증서 신청은 아래 링크를 클릭합니다.

    https://www.thawte.com/cgi/enroll/personal/step1.exe

    신청서 화면에서 next 버튼을 클릭합니다.

    1.2 아래 화면에서 개인 정보를 입력합니다. 언어는 UTF-8을 선택하고 국가도 입력합니다. 그리고, next 버튼을 클릭합니다.

    1.3 사용할 메일 주소를 입력하고 next 버튼을 클릭합니다.

    1.4 사용할 언어와 문자셋을 아래와 같이 선택하고 next 버튼을 클릭합니다.

    1.5 사용할 비밀번호를 입력합니다. next 버튼을 클릭합니다.

    1.6 비밀번호 분실할 때에 사용할 질문 답변을 입력합니다. 적어도 5개 이상 입력합니다. 모두 입력하고 next 버튼을 클릭합니다.

    1.7 next 버튼을 누르면 지금까지 입력한 정보들을 일목요연하게 보여줍니다. 다시 한번 확인하고 next 버튼을 클릭합니다.

    1.8 인증서 발행을 위한 메일이 발송되었다는 안내 페이지가 나타납니다.

    1.9 아웃룩 익스프레스에서 메일을 확인하면 아래 그림과 같이 인증서 확인 코드가 포함된 메일을 볼 수 있습니다.

    1.10 메일 본문에 있는 첫 번째 링크를 클릭하여 웹 페이지를 띄우고 해당 코드 값 2가지를 정확히 입력하고, next 버튼을 클릭합니다.

    https://www.thawte.com/cgi/enroll/personal/step8.exe

    1.11 메일 계정이 정상적으로 생성되었다는 안내 화면이 나타납니다. 메일 주소를 확인하고 next 버튼을 클릭합니다.

    1.12 마지막으로 네트워크 암호 입력 창이 나타납니다. 앞서 입력했던 메일주소와 비밀번호를 입력하고 확인 버튼을 클릭합니다.

    지금까지 과정을 오류 없이 마쳤다면 일단 인증서의 요청은 성공적으로 마무리된 것입니다.

  2. 인증서 발급

    2.1 아래 링크로 접속합니다. 접속할 때에는 메일주소와 비밀번호를 다시 확인합니다.

    http://www.thawte.com/cgi/personal/cert/enroll.exe

    2.2 X.509 format Certificates 아래에 있는 request 버튼을 클릭합니다.

    2.3 Microsoft Internet Explorer, Outlook and Outlook Express 항목을 선택하고 request 버튼을 클릭합니다.

    2.3 No Employment Information Available을 선택하고 next 버튼을 클릭합니다.

    2.4 메일주소를 체크하고 next 버튼을 클릭합니다.

    2.5 복잡한 비밀번호를 사용하라는 간단한 안내 메시지가 나타납니다. Next 버튼을 클릭합니다.

    2.6 기본 설정값으로 수신합니다. Accept 버튼을 클릭합니다.

    2.7 Microsoft enhanced Cryptographic Provider v1.0 공개 키를 선택하고 Next 버튼을 클릭합니다.

    2.8 보안상 위험하다는 안내 화면이 나타납니다. 버튼을 클릭합니다.

    2.9 RSA 키를 생성하는 창이 나타납니다. 확인 버튼을 클릭합니다.

    2.10 마지막으로 Finish 버튼을 누르면 인증서 발급이 완료됩니다

  3. 인증서 설치

    3.1 아래 링크로 접속합니다. 이미 접속한 상태에는 메일주소와 비밀번호를 따로 입력하지 않아도 욉니다. http://www.thawte.com/cgi/personal/cert/contents.exe

    3.2 인증서를 요청한 기록이 있는지 확인합니다. 아래 그림처럼 view certificate status를 클릭합니다.

    3.3 발급 신청된 항목 중에 issued라고 되어 있는 부분의 MSIE를 클릭합니다.

    3.4 인증서를 설치한다는 안내 화면이 나타납니다. fetch 버튼을 클릭합니다.

    3.5 Install Your Cert 버튼을 클릭합니다.

    3.6 보안 경고 창이 나타납니다. 버튼을 클릭합니다.

    3.7 인증서 설치가 완료되었다는 대화상자가 나타납니다. 확인 버튼을 클릭합니다.

    3.8 IE의 인터넷 옵션에서 내용 탭을 클릭하고 인증서 버튼을 클릭합니다.

    3.9 아래와 같이 인증서 항목이 추가되어 있으면 성공입니다. 닫기 버튼을 클릭합니다.

  4. 아웃룩 익스프레스에서 인증서 설정

    4.1 아웃룩 익스프레스를 실행합니다.

    4.2 도구 -> 옵션 -> 보안 탭을 클릭합니다.

    4.3 보내는 모든 메시지의 내용 및 첨부파일 암호화보내는 모든 메시지에 디지털 서명에 체크합니다.

    4.4 고급 버튼을 클릭합니다. 아래 그림과 같이 비트 수를 맞추고 기타 옵션도 동일하게 설정합니다. 확인 버튼을 클릭합니다.

    4.5 이제 설정은 완료되었습니다. 메일을 작성할 때 아래와 같이 암호화디지털 서명 옵션이 체크되어 있는지 확인합니다. 체크가 안되여 있는 경우 체크합니다.

    4.6 메일을 새로 작성할 때 받는 사람이 디지털 ID가 없는 경우에는 보안 메일로 보낼 수 없습니다. 이러한 경우에는 아래와 같은 경고창이 나타나고 암호화하지 않음 버튼을 누르면 일반 메일로 발송하게 됩니다.

  5. 아웃룩 2007에서 인증서 설정

    5.1 MS 아웃룩을 실행합니다.

    5.2 도구 -> 보안 센터 -> 전자메일 보안 탭을 클릭합니다. 아래와 같이 설정합니다.

    5.2 설정 버튼을 클릭합니다. 아래와 같이 인증서가 맞는지 확인합니다. 정확하게 설정하고 확인 버튼을 클릭합니다.

    5.3 메시지를 작성할 때에 상단의 메뉴에서 서명 암호화에 체크가 되어 있는지 확인합니다. 이제 보안 메일을 발송할 수 있습니다. 오른쪽 아래에 있는 화살표 버튼을 클릭합니다.

    5.4 메시지 옵션 대화상자에서 보안 설정 버튼을 클릭합니다.

    5.5 아래와 같이 메시지 내용과 첨부 파일 암호화를 체크하고 확인 버튼을 누릅니다.


    만약 앞으로 모든 메일에 대해 보안을 적용하려면 아래 보안 설정에서 자동을 아래와 같이 바꿉니다.

    그리고 설정 변경 버튼을 누릅니다. 확인 버튼을 눌러 창을 닫습니다.

    5.5 메일을 새로 작성할 때 받는 사람이 디지털 ID가 없는 경우에는 보안 메일로 보낼 수 없습니다. 이러한 경우에는 아래와 같은 경고창이 나타나고 암호화하지 않음 버튼을 누르면 일반 메일로 발송하게 됩니다.

    사용자 삽입 이미지

    편지쓰기시 서명과 암호화 버튼 활성화




    6. 보안 메일 수신

    메라크에서 보안 메일을 수신하면 아래 이미지와 같이 메라크의 메일폴더에 메시지 파일이 저장됩니다.
    사용자 삽입 이미지

    이 파일을 문서편집기나 메모장으로 열어보면 다른 일반 메시지와 달리 메시지 본문이 base64로 인코딩되어 있지만 실제는 smime으로 암호화되어 첨부되어 있는 것을 볼 수 있습니다.

    사용자 삽입 이미지
     

    다른 메일들은 메일서버에 저장되어 있을때 일반 텍스트로 되어 있어 서버에 접속한 사람들은 메일 내용을 원문 그대로 보거나 다른 곳으로 복제할 수 있습니다. 이런 경우 메일 유출에 대한 위험성이 존재합니다만 보안메일의 경우 암호화되어 있기 때문에 서버 관리자가 파일을 복사하거나 유출하더라도 원본을 원본을 해독할 수 없어 보안상 안전한 메일이 되는 것입니다.

    수신자가 메일을 수신하면 아래와 같이 아웃룩에서 보안 메일임을 보여주고 확인 버튼을 누르면 복호화되어 메일 내용을 보여줍니다.

    사용자 삽입 이미지

    암호화된 SMIME 메일


    사용자 삽입 이미지

    복호화한 이후의 메일 내용



    지금까지 개인 인증서를 이용한 보안 메일 송수신에 대해 단계별로 설명하였습니다. 다음 편에서는 메라크 웹메일에서 개인 인증서를 이용하여 메일을 주고 받는 방법에 대해 소개할 예정이오니 많은 기대 바랍니다.


    by : http://www.softmail.co.kr

Posted by 컴투