반응형

DB 작업 중에 특정 Column의 값의 일부를 바꾸고 싶을 때가 있습니다.

저는 report라는 table에 있는 report_path 라는 Column 에 xxxx.pdf 라고 되어 있는 것들을 xxxx.html로 바꿔야할 일이 있었는데요


아래 처럼 replace()를 활용한 Update Query를 작성해 주면 됩니다.

UPDATE table SET column=replace(str,  find_string, replace_with)  ;


예시)  UPDATE report SET report_path=replace(report_path, 'pdf', 'html') WHERE signatured=1;


실행하면 아래와 같이 column의 내용 중 특정 문자만 바뀝니다.


       

 Query 실행 전 

  Query 실행 후

 

 

     



SQL Query 공부 좀 해야겠어요..

할 때마다 찾아보면서 하려니 일이 오래거리네요 ㅠ




반응형
반응형

오늘은 HTML 문서를 PDF로 변환해 주는 wkhtmltopdf 라는 Open source(LGPL) 프로그램을 소개하려 합니다.

http://wkhtmltopdf.org

http://wkhtmltopdf.org




저는 어떤 문서양식을 만들때 가능한 HTML을 사용해서 만듦니다. 왜냐하면 그것을 Web 서비스에 이식하기도 좋고 엑셀이든 워드든 어떤 문서 편집 프로그램 보다 원하는 형태의 문서를 쉽게 만들어 낼 수 있기 때문입니다.

물론 이렇게 말씀 드리면 마우스로 끄적거리는 것이 훨씬 쉽지 않냐고 말씀 하시는 분도 있겠지만 여러가지 CSS generator가 마련되어 있는 요즘은 상황에 따라 Ctrl+C, Ctrl+V 가 훨씬 빠르고 간편합니다.

물론 문서의 내용과 구조는 그대로 두고 각 요소의 배치나 색, 글꼴 같은 디자인만 바꾸고 싶을 때 HTML+CSS의 조합은 빛을 발합니다. 여러가지 이유로 요즘 개발 중인 프로젝트에 고객에게 프린트에서 줄 문서를 HTML로 만들었는데...한계에 부딪힙니다. 

제 깜냥으로는 세상에 존재하는 모든 웹 브라우저의 입맛을 마추지 못한 것이죠. 화면에 변환되어 나타나는 모습도 다르거니와 같은 브라우저라도 버전이 다르거나 사용자 설정이 다르니 인쇄되는 모양이 제각각이 되어 버립니다.

그러다 찾은 것이 이 wkhtmltopdf !!!
QT Webkit rendering engine 이라는 것을 사용해서 html 문서를 pdf로 변환해 줍니다.
이 프로그램 덕분에 어떤 환경에서도 항상 정형화된 사이즈와 모양의 문서를 출력할 수 있게 되었습니다.

사용 방식은 cmd (shell) 에서 아래와 같이 하면 됩니다.
 >wkhtmltopdf html경로+파일명(또는 URL) pdf경로+파일명

예) C:\>wkhtmltopdf test.html test.pdf 
     또는
    C:\>wkhtmltopdf google.com google.pdf



실행 방법이 간단해서 PHP와 Java에서 exec()함수와 ProcessBuilder로 어렵지 않게 사용할 수 있었습니다.
다른 언어에서도 마찬가지 방법으로 사용할 수 있겠지요.

이제 정말 필요한 것을 잘 찾는 사람이 능력자가 되는 세상이 오고 있는 듯 합니다.
읽어주셔서 감사합니다.

반응형
반응형


5천년만에 블로그에 글을 씁니다.^^ 반가워라.
자바(java)로 윈도우 어플리케이션을 만들고 있는데요.
자동완성 기능을 만들어 보려고 도전!!
JComboBox는 아래와 같이 생긴 녀석이죠.


아래와 같이 JComboBox에 Key Listener를 추가하니 이런..키보드를 아무리 눌러도 아무런 반응을 안 해주시네요..

combo1 = new JComboBox(model)
combo1.addKeyListener(new KeyAdapter() {
   @Override
   public void KeyTyped(KeyEvent ke) {
combo1.showPopup();
}



알고 보니.. JComboBox는 기본적으로 사용자 입력이 Item의 선택으로 이뤄지는 cmponent니깐
KeyEvent 가 먹지 않는 것이 이치에 맞는 것이더군요.


우리가 JComboBox의 editable 을 true로 설정하면 JComboBox라는 component에 editor라는 component가 덧 씌워지는 방식인가 봅니다.

그래서 찾아보니 아래 처럼 editor component에 KeyListener를 추가해줘야 하더군요^^
combo1 = new JComboBox(model)
combo1.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() {
   @Override
   public void KeyTyped(KeyEvent ke) {
   combo1.showPopup();
}


제가 원했던데로 키보드 입력이 있으면 popup메뉴가 열리는 이벤트가 발생하는 군요^^


(출처 : http://castever.wordpress.com/2008/12/09/keylistener-in-jcombobox/)

하..전문 프로그래머가 아닌 필요에 의한 개발을 하는 '엔지니어'로서 Google에게 감사합니다.


반응형
반응형

Eclipse에서 javadoc 생성을 하려는데
아래와 같은 에러가 났습니다.

javadoc unmappable character for encoding MS949

코드의 주석에 한글(UTF-8로 인코딩된)을 써서 그런 것 같아 구글링 해봤더니 역시나 그 문제 였네요.

해결 방법은 아래 창이 나타났을 때
VM options

-encoding UTF-8

을 적어주면 해결 됩니다.
그러면 한글이 포함된 JavaDoc을 생성할 수 있습니다.


 

반응형
반응형



자바로 만든 사칙연산 계산기 입니다.
인턴 출근하고 첫 번째 과제..
인터넷에서 가져온 녀석에 키보드 이벤트가 없어서 이벤트 추가해주고
키보드에 특수기호들 이름을 몰라서 걍 테스트로 System.out.print(블라블라);해서
콘솔에 나오는 숫자 그대로 넣어줬습니다..(부끄..어쨌든 잘 되네요..ㅎ;;)

기본적인 원리!!
입력한 숫자를 기억하고, 어떤 연산을 시켰는지 기억하면서 계산을 해나갑니다. 그리고 마지막 숫자가 들어 온 후 '='을 누르면 결과가 Text창에 뜨는 겁니다.

우선 GUI는 swing으로 덕지덕지 만들었습니다.
버튼들에 이벤트가 발생하면 무언가 일이 진행되게 합니다. 각각의 경우에 맞는 Listener와 Listener가 발견한 이벤트에 대해 할일을 만들어 주는 것이죠. 이벤트가 발생한 녀석이 어느 녀석이냐에따라 다른 일을 합니다. 이 땐 switch-case문을 사용했습니다.
에휴 설명이 허접해지네요ㅠㅠ
주석을 참고하세요^^ 설명을 위해서 주석을 엄청나게 써놨습니다... ㅎㅎ
아.. 프로그래밍 잘하고 싶다 ㅠ

그리고 인터넷에서 긁어온 소스의 닫기버튼에 대한 구현이 아래 처럼 되어 있어서 닫기 버튼을 눌러도 프로세스가 살아있더라구요..
엄청 띄웠더니 컴퓨터가 버벅 거려서 깜짝 놀랐습니다요..

addWindowListener(new WindowAdapter() {
public void windowClosed(WindowEvent e){
System.exit(0);
}
});

그래서 이러게 바꿔줬더니 잘 꺼지는 군요..

addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e){
System.exit(0);
}
});


코드는 아래와 같습니다. 아... 넘 길다 ㅠㅠ 첨부도 할게요...
딱 사칙연산만 하면 좀더 간단했을텐데.. 그래도 윈도우 계산기 켰을때 있는 녀석들은 다 있네요.^^;

 


package cal;
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.*;
public class Calculator extends JFrame implements ActionListener, KeyListener{
 final int MAX_INPUT_LENGTH = 20; //최대한 입력 가능한 길이를 제한하고
 
 //각 모드별로 index를 부여
 final int INPUT_MODE = 0;
 final int RESULT_MODE = 1;
 final int ERROR_MODE = 2;
 int displayMode;
 
 boolean clearOnNextDigit;  //화면에 표시될 숫자를 지울지 말지 결정하는 녀석
 
 double lastNumber;   //마지막에 기억될 수
 String lastOperator;  // 마지막에 누른 연산자를 기억.
 
 private JLabel output;    //숫자가 표시될 공간
 private JButton buttons[];   //각 버튼을 배열로 생성할 것임.
 private JPanel masterPanel, btnPanel, ctrPanel; //버튼과 레이블을 배치할 공간
 
 //GUI를 생성해보자.
 public Calculator(){
  
  setBackground(Color.gray);   //프레임의 배경은 회색
  
  masterPanel = new JPanel();
  
  output = new JLabel("0", JLabel.RIGHT); // 레이블의 초기 값은 0
  output.setBackground(Color.WHITE);
  output.setOpaque(true);
  
  buttons = new JButton[23];
  
  btnPanel = new JPanel();
  
  //숫자 버튼 만듦0에서9까지.
  for (int i=0 ; i<=9 ; i++){
   buttons[i] = new JButton(String.valueOf(i));   
  }
  
  //연산 버튼 만듦.
  buttons[10] = new JButton("±");
  buttons[11] = new JButton(".");
  buttons[12] = new JButton("=");
  buttons[13] = new JButton("/");
  buttons[14] = new JButton("*");
  buttons[15] = new JButton("-");
  buttons[16] = new JButton("+");
  buttons[17] = new JButton("√");
  buttons[18] = new JButton("1/x");
  buttons[19] = new JButton("%");
  
  //컨트롤 버튼 만듦.
  buttons[20] = new JButton("←");
  buttons[21] = new JButton("CE");
  buttons[22] = new JButton("C");
  
  //각 버튼의 색을 다르게
  for(int i=0 ; i<buttons.length ; i++){
   if(i<10){
    buttons[i].setForeground(Color.black); //숫자 버튼들
   }else if(i>=10 && i<21){
    buttons[i].setForeground(Color.blue); //연산자 버튼들
   }else{
    buttons[i].setForeground(Color.red); //컨트롤 버튼들.
   }
  }
  
  //패널에 숫자버튼 및 연산자 버튼 배치
  btnPanel.setLayout(new GridLayout(4,5,2,2));
  
  for(int i=7; i<=9 ; i++){
   btnPanel.add(buttons[i]);
  }
  
  btnPanel.add(buttons[13]); // /
  btnPanel.add(buttons[17]); // √
  
  for(int i=4; i<=6 ; i++){
   btnPanel.add(buttons[i]);
  }
  
  btnPanel.add(buttons[14]); // *
  btnPanel.add(buttons[18]); // 1/x
  
  for(int i=1; i<=3 ; i++){
   btnPanel.add(buttons[i]);
  }
  
  btnPanel.add(buttons[15]); // -
  btnPanel.add(buttons[19]); // %
  
  btnPanel.add(buttons[0]); // 0
  btnPanel.add(buttons[10]); // ±
  btnPanel.add(buttons[11]); // .
  btnPanel.add(buttons[16]); // +
  btnPanel.add(buttons[12]); // =
  
  //컨트롤 패널에 컨트롤 버튼을 배치
  ctrPanel = new JPanel();
  ctrPanel.setLayout(new GridLayout(1,2,2,2));
  
  
  ctrPanel.add(buttons[20]);
  ctrPanel.add(buttons[21]);
  ctrPanel.add(buttons[22]);
  
  
  // 각 컴포넌트를 프레임에 추가
  masterPanel.setLayout(new BorderLayout());
  masterPanel.add(ctrPanel, BorderLayout.NORTH);
  masterPanel.add(btnPanel, BorderLayout.SOUTH);
  
  
  getContentPane().add(output, BorderLayout.NORTH);
  getContentPane().add(masterPanel,BorderLayout.SOUTH);
  requestFocus();
  
  //버튼 ActionListener, Keylistener 활성! 이놈들을 추가해야 버튼에 뭔일이 발생하는지 봅니다.
  for(int i=0 ; i<buttons.length ; i++){
   buttons[i].addActionListener(this);
   buttons[i].addKeyListener(this);
  }
    
  clearAll(); //모든 값을 초기화!!
  
  addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent e){
     System.exit(0);
    }
   }
  );  
 }
 /*생성자 끝~~~~*/
 
 //마우스 입력에 대한 동작
 @Override
 public void actionPerformed(ActionEvent e){
  
  double result = 0;
  
  for(int i=0 ; i<buttons.length ; i++){
   if(e.getSource()==buttons[i]){
    if(i<10){
     addToDisplay(i);
     break;
    }else{
     switch(i){
      case 10: // ±
       processSingChange();
       break;
      case 11: // .
       addPoint();
       break;
      case 12: // =
       processEquals();
       break;
      case 13: // /
       processOperator("/");
       break;
      case 14: // *
       processOperator("*");
       break;
      case 15: // -
       processOperator("-");
       break;
      case 16: // +
       processOperator("+");
       break;
      case 17: // √
       if (displayMode != ERROR_MODE)
       {
          try
        {
         if (getDisplayString().indexOf("-") == 0)
             displayError("Invalid input for function!");
         result = Math.sqrt(getNumberInDisplay());
         displayResult(result);
        }
        catch(Exception ex)
        {
         displayError("Invalid input for function!");
         displayMode = ERROR_MODE;
        }
       }
       break;
      case 18: // 1/x
       if (displayMode != ERROR_MODE){
        try
        {
         if (getNumberInDisplay() == 0)
          displayError("영으로 나눌 수 없습니다.");
  
         result = 1 / getNumberInDisplay();
         displayResult(result);
        }
        
        catch(Exception ex) {
         displayError("영으로 나눌 수 없습니다.");
         displayMode = ERROR_MODE;
        }
       }
       break;
      case 19: // %
       if (displayMode != ERROR_MODE){
        try {
         result = getNumberInDisplay() / 100;
         displayResult(result);
        }
  
        catch(Exception ex) {
         displayError("Invalid input for function!");
         displayMode = ERROR_MODE;
        }
       }
       break;
      case 20: // ←
       backspace();
       break;
      case 21: //CE
       setDisplayString("0");
       clearOnNextDigit = true;
       displayMode = INPUT_MODE;
       break;
      case 22: //C
       clearAll();
       break;       
     }
    } 
   }
  }
 }
 
 
 //키보드 입력에 대한 동작
 public void keyPressed(KeyEvent e){
  int keycode = e.getKeyChar();
  //System.out.println(e.getKeyCode()+ "  "+ keycode ); 요걸로 특수기호 녀석들 코드를 알아냈습니다... ^^;;부끄
  switch(keycode){
   case KeyEvent.VK_0:
    addToDisplay(0);
    break;
   case KeyEvent.VK_1:
    addToDisplay(1);
    break;
   case KeyEvent.VK_2:
    addToDisplay(2);
    break;
   case KeyEvent.VK_3:
    addToDisplay(3);
    break;
   case KeyEvent.VK_4:
    addToDisplay(4);
    break;
   case KeyEvent.VK_5:
    addToDisplay(5);
    break;
   case KeyEvent.VK_6:
    addToDisplay(6);
    break;
   case KeyEvent.VK_7:
    addToDisplay(7);
    break;
   case KeyEvent.VK_8:
    addToDisplay(8);
    break;
   case KeyEvent.VK_9:
    addToDisplay(9);
    break;
   case 46: // .
    addPoint();    
    break;
   case 10: // =
    processEquals();
    break;
   case 47: // /
    processOperator("/");
    break;
   case 42: // *
    processOperator("*");
    break;
   case 43: // +
    processOperator("+");
    break;
   case 45: // -
    processOperator("-");
    break;
   case 8: //backspace
    backspace();
    break;
   case 27: //ESC
    clearAll();
    break;    
  }
 }
 private void clearAll() {
  setDisplayString("0");
  lastOperator = "0";
  lastNumber = 0;
  displayMode = INPUT_MODE;
  clearOnNextDigit = true;
 }
 
 private void backspace(){
  if (displayMode != ERROR_MODE){
   setDisplayString(getDisplayString().substring(0,
       getDisplayString().length() - 1));
   
   if (getDisplayString().length() < 1)
    setDisplayString("0");
  }
 }
 private void processOperator(String string) {
  if (displayMode != ERROR_MODE){
   double numberInDisplay = getNumberInDisplay();
   if (!lastOperator.equals("0")){
    try {
     double result = processLastOperator();
     displayResult(result);
     lastNumber = result;
    }catch(Exception e){}
   
   }else{
    lastNumber = numberInDisplay;
   }
   
   clearOnNextDigit = true;
   lastOperator = string;
  }
 }

 private double processLastOperator() throws Exception{
  double result = 0;
  double numberInDisplay = getNumberInDisplay();
  if (lastOperator.equals("/")){
   if (numberInDisplay == 0)
    throw (new Exception());
   result = lastNumber / numberInDisplay;
  }
   
  if (lastOperator.equals("*")){
   result = lastNumber * numberInDisplay;
  }
  if (lastOperator.equals("-")){
   result = lastNumber - numberInDisplay;
  }
  if (lastOperator.equals("+")){
   result = lastNumber + numberInDisplay;
  }
  
  return result;
 }
 private void processEquals() {
  double result = 0;
  if (displayMode != ERROR_MODE){
   try{
    result = processLastOperator();
    displayResult(result);
   }catch (Exception e){
    displayError("영으로 나눌 수 없습니다.");
   }
   lastOperator = "0";
  }
 }
 private void addPoint() {
  displayMode = INPUT_MODE;
  if (clearOnNextDigit)
   setDisplayString("");
  String inputString = getDisplayString();
 
  // 이미 점이 찍혀 있으면 안 찍음.
  if (inputString.indexOf(".") < 0)
   setDisplayString(new String(inputString + "."));
 }
 private void processSingChange() {
  if (displayMode == INPUT_MODE){
   String input = getDisplayString();
   if (input.length() > 0 && !input.equals("0")){
    if (input.indexOf("-") == 0)
     setDisplayString(input.substring(1));
    else
     setDisplayString("-" + input);
   }
  }else if (displayMode == RESULT_MODE){
   double numberInDisplay = getNumberInDisplay();
  
   if (numberInDisplay != 0)
    displayResult(-numberInDisplay);
  }
 }
 private void displayResult(double result) {
  setDisplayString(Double.toString(result));
  lastNumber = result;
  displayMode = RESULT_MODE;
  clearOnNextDigit = true;
 }
 private void displayError(String error) {
  setDisplayString(error);
  lastNumber = 0;
  displayMode = ERROR_MODE;
  clearOnNextDigit = true;
 }
 private double getNumberInDisplay() {
  String input = output.getText();
  return Double.parseDouble(input);
 }
 private void addToDisplay(int i) {
  if (clearOnNextDigit)
   setDisplayString("");
  
  String inputString = getDisplayString();
  
  if(inputString.indexOf("0") == 0){
   inputString = inputString.substring(1);
  }
  if(( !inputString.equals("0") || i>0 ) && inputString.length() < MAX_INPUT_LENGTH){
   setDisplayString(inputString + i);
  }
  
  displayMode = INPUT_MODE;
  clearOnNextDigit = false;
 }

 private void setDisplayString(String string) {
  output.setText(string);
 }

 private String getDisplayString() {
  return output.getText();
 }
 
 public static void main(String args[]){
  Calculator cal = new Calculator();
  cal.setTitle("Calculator");
  cal.setSize(300,300);
  cal.pack();
  cal.setVisible(true);
  cal.setResizable(false);  
 }
 @Override
 public void keyReleased(KeyEvent arg0) {}
 @Override
 public void keyTyped(KeyEvent arg0) {}
}

반응형
반응형





지금 인턴하고 있는 회사 첫 출근에 과장님께 과제로 받은 것이
자신있는 언어로 사칙연산이 가능한 계산기를 만들고 키보드와 연동하라는 것이었습니다. 
그나마 익숙한 자바로 사칙연산하는 계산기를 만들며 생각난 것이
파이썬으로 하면 정말 간단한 솔루션이 나올것 같은 예감이 들었습니다.
역시나 구글링을 하니 제 예감이 적중했더군요.
50줄도 안되는 계산기입니다...

파이썬에는 eval()이라는 내장 함수가 있습니다.
이 eval() 함수는 인자로 받은 텍스트 데이터를 파이썬 인터프리터가 번역할 수 있는 파이썬 코드로 변환합니다.
GUI는 tkinter 모듈을 이용하면 간단히 만들 수 있군요.

예를 들어 result =eval("1+2*3/4") 이라고 하면 인자에 들어간  텍스트를 파이썬 코드로 변환하여
result에는 1+2*3/4 의 연산 결과인 2.25가 들어가게 되는 것이죠.

정말 획기적이지 않나요??
텍스트 창 안의 내용을 그대로 계산하는 초간단 계산기 였습니다.!!
키보드와 바로 연동되는 것은 아니지만
텍스트 창 안에 수식을 입력하면 바로 계산되어 나왔습니다.

역시 파이썬이 강력한 이유는 유용한 내장함수와 다양한 모듈들 이겠지요!!

코드 출처 : http://lexlove.egloos.com/10763317
#calculator.py
#-*-coding=utf-8-*-
#GUI를 만들어주는 tkinter 모듈을 임포트!
from tkinter import *

#이벤트 처리함수
def enter(btn):
    if btn == 'C':
        ent.delete(0, END)
    elif btn == '=':
        #eval()함수는 텍스트로된 데이터를 바로 파이썬 코드로 변환합니다.대박..
        #그래서 ent라는 곳에 입력된 수식을 바로 계산해 냅니다.
        ans = eval(ent.get())
        ent.delete(0, END)
        ent.insert(0, ans)
    else:
        #C와 =을 제외한 버튼은 그대로 ent에 추가.
        ent.insert(END, btn)

def quit():
    root.destroy()
    root.quit()
#창만들기
root=Tk()
root.title('계산기')

#숫자 입력란 만들기
ent=Entry(root)
ent.insert(0, ' ')
ent.pack(pady=5)

#숫자 버튼 만들기
buttons = ['7410', '852=', '963+', 'C/*-']
for col in buttons:
    frm=Frame(root)
    frm.pack(side=LEFT)
    for row in col :
        btn=Button(frm, text=row, command=(lambda char=row: enter(char)))
        btn.pack(fill=X, padx=5, pady=5)

#프로그램 실행
root.mainloop()
반응형
반응형

Tomcat symbol

<

Apache httpd symbol



  예전에 포스팅했던 글에서 제가 웹서버의 성능을 향상 시키기 위해 아파치(Apache, httpd)톰캣(Tomcat)을 연동한다고 했었습니다. 그런데 열심히 항해를 하다가 그것이 불필요한 일이라는 것을 알아버렸네요.

출처를 먼저 밝히겠습니다.
Tomcat expert라는 커뮤니티입니다.

http://www.tomcatexpert.com/blog/2010/03/24/myth-or-truth-one-should-always-use-apache-httpd-front-apache-tomcat-improve-perform

내용을 제 나름대로 해석하고 요약해봤습니다.
정말 제 나름이니 정확한 내용을 보실분은 출처를 꼭 한번 따라가 보시길^^;;


Myth or truth : 사람들은 항상 성능을 향상시키기 위해 아파치 Tomcat 앞에 아파치 httpd 를 사용해야합니까?

간단히 말하면 그 것은 Myth이다. 좀 더 이야기하면 Tomcat 3 이전에는 상황에 따라 어느 정도 진실이었다. 하지만 요즘 사용하는 Tomcat (5.5.x 이후)은 순전히 성능상의 이유만으로 httpd (아파치) 를 사용할 필요가 없다. Tomcat은 현재 low-level I/O를 위해서 httpd와 같은 기본 라이브러리를 사용하여 httpd와 비슷한 기능을 수행할 수 있는 native/APR(Apache Portable Runtime) connector를 지원한다. Tomcat으로 정적인 컨텐츠를 제공할 경우 httpd에 비해 약간 부하가 더 있지만 그 차이는 눈에 띄지 않을 정도다.

종종 벤치마크에서 예상외로 httpd보다 Tomcat이 좋을 성능을 발휘했다. 이는 Tomcat은 기본적으로 메모리에 작은 정적 파일을 캐시하고 httpd는 기본적으로 메모리에 파일을 캐시하지 않기 때문이다.

최상을 성능을 달성하기 위한 설정은 다양하다. 이는 여러가지 요인에 크게 의존한다.

그외에 복 수의 Tomcat 인스턴스에 로드밸런싱을 위해 Apache를 사용한다. (로드밸런싱을 위한 유일한 옵션은 아니지만)

요약하면 Tomcat과 httpd를 합께 사용하면 좋은 이유들이 있지만 정적 페이지의 성능을 위한 이유는 그 중 하나가 아니다.


  원문에는 벤치마크에 대한 내용과 이런저런 connector 들에 대한 이야기가 나와 있습니다. 저는 그렇게까지 전문적인 내용은 필요가 없으므로 제가 이해할 만한 내용만 적어봤습니다.

  때로는 그저 그냥 당연하다고 생각한 것이 사실은 전혀 당연한게 아닐 수도 있군요.

반응형
반응형

저는 Apache 웹서버를 이용해서 웹서비스를 하고 있습니다.
아아 서비스가 아니라 실습정도요?^^

얼마전 저에게 한 가지 과제가 생겼습니다.
한 컴퓨터에서 두 개의 도메인 이름으로 각기 다른 페이지를 서비스 할 수 있게하라!!

예를 들면 kkosseul.domain.net ksk.domain.net 이 서로 다른 페이지로 연결되도록 하라는 것이었습니다.

IIS에서는 걍 도메인만 추가하면 알아서 되는 걸로 알고 있는데 Apache에서는 어떻게 해야할까요??

구글링도 해보고 네이버 아저씨한테 물어봐도 다양한 답이 있지만 핵심을 찝어 주신 분들이 없더라구요.
혼자 삽질에 삽질 삽질을 거듭한 끝에 꼭 필요한 몇가지만으로 가능하다는 걸 알았습니다.

의외로 간단했습니다.
우선 이 작업을 위해서 DNS 서버에 제 IP주소에 대해서 CNAME으로 별명을 하나더 지어 줬습니다.
그러니깐 제 호스트 명이 ksk06 이라면, CNAME이 kkoseul이 되는 것이죠.

nslookup을 통해 확인해보면 같은 IP주소인 것을 확인 할 수 있습니다.



Apache는 text 파일을 이용해서 여러가지 설정을합니다.
이 파일 들은 Apache를 설치한 디렉토리 아래 conf 라는 디렉토리 내에 있죠.
그 중 httpd.conf 라는 파일을 엽니다.

이 파일에 서 제일 앞에 #을 포함한 줄은 모두 주석입니다. 즉 Apache가 읽어서 처리하는 부분이 아니라는 것이죠.
Ctrl+F 를 이용해서 Virtual hosts를 찾아보시면 아마 다음과 같은 부분을 찾으실 수 있을겁니다.
아마 두번째 줄이 주석으로 처리되어 있을건데 #을 지워서 주석을 풀어줍니다.

# Virtual hosts
Include conf/extra/httpd-vhosts.conf

주석을 풀면 Apache가 시작되면서 설정들을 읽을 때 conf/extra/httpd-vhosts.conf 파일을 함께 읽게 됩니다.
그럼 그 다음 순서는 무엇일까요?
당연히 Apache가 읽어들일 httpd-vhosts.conf 파일을 우리가 원하는 동작을 하도록 수정해줍니다.

Apache 설치 디렉토리에서 conf/extra/httpd-vhosts.conf 파일을 열어봅시다.
파일을 열어보면 Virtual Hosts에 대한 설명들이 주석으로 적혀 있습니다.
중요한 부분은 다음 부분들입니다.
NameVirtualHost 000.000.000.000:00

<VirtualHost kkoseul.domain.net>
    DocumentRoot "C:\Dev\Apache2.2\htdocs\kkoseul"
</VirtualHost>

<VirtualHost ksk.domain.net>
    DocumentRoot "C:\Dev\Apache2.2\htdocs\ksk"
</VirtualHost>

NameVirtualHost에 가상 호스트의 이름을 적어줍니다.
포트번호는 안적으셔도 되지만 80번 포트로 들어온 요청에만 답하기 위해 저는 적어줬습니다.

<VirtualHost host.domain.net> 태그에 호스트 명을 적어줍니다. 호스트 이름을 적는 것이 가장 중요합니다.!!
이 호스트 이름과 같은 이름으로 접속을 요청한 가상 호스트로 연결시켜 주니깐요!!

그리고 <VirtualHost>와</VirtualHost> 사이에 서비스할 문서의 DocumentRoot "루트경로"를 지정해 줍니다.

<VirtualHost>내부에 호스트 이름, 로그파일 위치, 관리자 이메일 등등 여러가지 정보를 넣을 수 있습니다.
하지만 가상호스트가 동작하는 것만을 보여 드리기 위해서 다 지웠습니다.

이런 동작이 가능한 것은 우리가 웹 브라우저의 주소창에 입력한 주소 정보가 서버에 도달하면 서버는 그 주소를 해석해서 해당 주소와 같은 가상 호스트에 연결 시켜주기 때문입니다.

그리고 위의 httpd-vhosts.conf 파일의 내용을 그대로 httpd.conf 파일에 적어줘도 무관합니다.
하지만 설정파일의 가독성을 위해서는 파일을 따로 두고 include 시키는 방법이 더 나을 것 같네요.

위처럼 설정하면 브라우저를 통해 하나의 Apache 서버에서 둘 이상의 서비스가 뜨는 것을 확일 할 수 있습니다.
제가 서로 다른 디렉토리에 간단한 html 파일을 넣어두었는데 제대로 나타나는군요
(주소 뒤의 도메인 부분은 동일합니다. domain.net 이런 식으로여)



원래 웹서버를 운영하시던 분이라면 상관없겠지만
혹시나 그닥 요청량이 높지 않은 두 개 이상의 웹을 서비스 하기 위해서 컴퓨터를 두대 사버리는 실수를 범하지 않으시길 ^^
이상 Apache 초보의 가상호스트 설정이었습니다!!
반응형
반응형

(편의상 폴더와 디렉토리를 섞어 쓰겠습니다;;)

간편한 무료 FTP 서버인 FileZilla FTP server를 사용하고 있습니다.
4개의 계정에 각 다른 4개의 홈디렉토리를 설정해서 사용하고 있었습니다.

그런데 어쩌다보니 네 계정에 모두 공유하고 싶은 디렉토리가 생겼습니다.
어떻게 하면 좋을까요?? 홈디렉토리가 최상위 디렉토리라 홈 디렉토리 보다 상위에 있거나 홈디렉토리 밖에 있는 디렉토리로 접근할 수가 없군요ㅠㅠ

물론 평소에 FTP 서버를 운영하시던 분이라면 문제거리도 아니겠지만 그 외의 분들에게는 엄청난 고민거리죠^^
저도 사실 어떻게 해야할지 고민했으니깐요.
속편하게 생각해서 바로가기를 만들어주면 어떨까? 생각해봤지만 FTP에서는 바로가기 조차도 하나의 파일일 뿐이죠^^

어떻게 할까요???
해결 방법은 alias입니다.
컴퓨터 공부를 하다 보면 여러 영역에서  alias라는 말을 듣게 됩니다.
말그대로 어떤 대상이나 위치에 대해서 별명을 붙여주는 기능입니다.

대부분의 FTP 서버 프로그램에는 alias를 설정할 수 있습니다.
이 alias를 통해서 만들어진 링크가 디렉토리를 마치 홈디렉토리 안에 있는 것 처럼 해줍니다.


FileZilla Server Interface를 실행해서 한 번 설정해 볼까요?
메뉴의 [Edit] - [Users]로 가봅시다.



Users 창에서 왼쪽에 Shared folders를 클릭합니다. 그리면 공유된 디렉토리와 user의 권한이 나타납니다.
지금은 bi4라는 계정에 대해 '보건의료정보'라는 디렉토리 하나만 홈디렉토리(H로 표시된 부분)로 지정되어 있군요.


[Add]를 눌러서 공유할 디렉토리를 추가합니다.
 홈디렉토리보다 상위에 존재하는 'TED'라는 디렉토리를 추가했습니다.


이 상태 에서는 FTP client 프로그램을 통해 접속해도 TED 디렉토리는 나타나지 않습니다.
TED 디렉토리에 대해 Alias를 추가해 줍니다. 해당 디렉토리에 마우스 오른쪽 버튼을 클릭하고 Edit aliases를 클릭합니다.
(또는 Aliases 부분을 더블클릭합니다.)



저는 alias를 홈 디렉토리 아래에 TED라는 이름으로 하기 위해 /TED 라고 해주었습니다.



이제 alias가 추가 되었습니다. 한번 확인해 볼까요?



분명히 FTP server 가 구동 중인 server의 local 탐색기에서 '보건의료정보'라는 폴더에는 'TED'라는 폴더가 존재 하지 않습니다.



하지만 FTP client를 통해 FTP server에 접속해 보니 'TED'라는 폴더가 보이는 군요.


이렇게 alias를 이용해서 다양한 위치에 있는 파일을 하나의 계정을 통해 공유할 수 있습니다.
FileZilla server 뿐만 아니라 다른 FTP 서버에도 설정 메뉴나 방법이 조금 다를 뿐 같은 원리를 이용해서 서비스할 수 있습니다.
이상입니다^^

반응형
반응형




PyScripter를 사용해서 공부를 시작하려고 하는데 이녀석이 초반부터 사람 갈 길을 막습니다.

작성할 때 한글을 포함한 문서를 저장하고 다시 불러오면 한글이 다 깨져 버리네요.

 



헉 이게 무슨 음모인가요?
포스팅 할려고 "한글"이라 하니 "?쒯?" 이라 뱉어 주시는 PyScripter님. 유머감각도 넘치셔라;;;
ㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎ




수업 시간에 배운 방법은 File encoding comment를 적어주는 방법이었습니다. 아래 처럼 하면 되죠.

[Edit] - [Insert Template] 을 선택해서 File encoding comment를 추가하는 것입니다.  직접 타이핑 해도 되구요.




이렇게 하면 문서를 닫고 다시 불러와도 한글이 깨지지 않습니다. 하지만 이 방법은 솔직히 좀 불편하더군요. 추가해줘야하니깐요.
(물론 아예 처음부터 추가되게 하는 방법이 있겠지만요.)

그래서 열심히 PyScripter의 메뉴를 뒤져 봤습니다!! 
안 되면 되게하라!!

역시나 친절히도 파일 포멧을 설정할 수 있는 부분이 바로 근처에 있더군요.
영어권에서 사용하는 녀석이라 파일 포멧이 ANSI로 되어 있었습니다. 
그래서 이걸 과감히 UTF-8로 바꿔 줬습니다.


다시 문서를 저장하고 불러오니 한글이 전혀 깨지지 않는군요.^^
이제 해결 했으니 다시 열공모드로 고고싱!!

아아.. 그런데..
뒤늦게 문제점 하나를 발견했습니다.ㅠㅠ
파일마다 새로 file format을 정해줘야하네요....








반응형
반응형


Python을 설치하면 기본적으로 파이썬 셸과 IDLE이 설치됩니다.
하지만 윈도우에서 텍스트 에디터 또는 이클립스 등 다른 개발환경에 익숙해져 버린 저는 조금 어색하기만 합니다.

그래서 수소문하다보니 PyScripter라는 무료 IDE(통합개발환경:Integrated development environment)이 있더군요^^ 아싸!

어떤 언어를 배우기 위해서 환경을 꾸리는 일은 너무도 당연한 일이라고 생각해서 지나칠 수 있지만
대부분의 책머리에 이런 환경을 꾸리는 방법을 설명하듯이 저도 시작합니다!!

PyScripter 설치하기!!

먼저 PyScripter를 다운 받기 위해서 http://code.google.com/p/pyscripter/ 에 접속합니다. 
구글에서 PyScripter를 검색하셔도 링크가 나옵니다.



상단 메뉴의 Downloads를 클릭하기면 PyScripter 설치 파일을 다운로드 할 수 있습니다.



압축 파일 하나와 설치 파일 두개가 보일 겁니다. 자신의 컴퓨터 환경에 맞는 버전을 다운 받으시면 됩니다.
(저는 64bit 윈도우를 사용하기 때문에 64용 설치 파일을 다운 받았습니다.)



이제 다운로드 받은 파일을 실행합니다!
인터넷 익스플로러의 SmartScreen 필터 기능을 사용하신다면 설치 파일을 실행시 경고 메시지가 뜰 수 있습니다.
이 때  [작업] 버튼을 눌러 프로그램을 강제로 실행시켜 주시면 설치가 진행됩니다.



지금부터는 너무나 쉽습니다. 곰플레이어 설치하듯이 네이트온 설치하듯이 넘어가주시면 됩니다.



우선 설치할 폴더 경로를 확인하고 다음으로 넘어갑니다.



시작 메뉴에 등록할 이름을 지정하고 다음으로 넘어갑니다.



설치할 PyScripter에 대한 정보를 확인하고 다음으로 넘어갑니다.
제가 받은 PyScripter는 최소한 Python2.4 버전 이상은 설치 돼있어야 한다고 적혀있네요.



다음 바탕화면과 빠른실행메뉴에 추가적으로 아이콘을 생성할지 선택하고,
탐색기의 context menu에 "Edit with PyScripter"라는 항목을 넣을지 선택합니다.(마우스 우클릭 시 나오는 메뉴에요.)



실제 설치가 되기전 마지막으로 선택 사항들을 확인하고 Install 버튼을 클릭!!!!



설치는 순식간에 끝납니다.(캡쳐하기조차 힘들었네요;;;)



설치가 끝나고 또 PyScripter에 대한 정보가 출력됩니다 .블라블라~~ @ㅁ@;;



설치가 끝났습니다 PyScripter를 바로 실행 하시려면 Launch PyScripter를 체크하고 Finish를 눌러줍니다.



짜잔~~ 오오 그래도 뭐가 편집기도 있고 탐색기도 있고 파이썬 인터프리터도 함께 뜨는 모양새 있는 파이썬 개발 환경이 설치 됬습니다. 이제 공부 열심히 할 일만 남았네요 에공. 화이팅!!

 

 

 

 

 

 

 

반응형
반응형

제가 자바에서 실수형 그러니간 double 형으로 변수를 정하고 0.5라는 결과는 기대하며 아래와 같이 작성했습니다.

double num = 1/2;

이런 식으로 해서 num을 콘솔에 출력해보니 에잉?? 게 뭡니까??? 0.0이 출력되네요 ㅠㅠ




제가 실수 한게 무엇일까요??
갑자기 옛날에 자바를 처음 배울때 읽었던 한 문장이 생각 났습니다.
자바는 형검사를 엄격히 한다? 물론 관련 없는 생각이었을 수도 있지만 이 문장이 생각나더군요

아무튼 제가 double 형(실수)으로 num이라는 변수를 선언하기는 했지만 그 속에 있는 오퍼레이터 /(나누기)는 1이라는 정수와 2라는 정수를 연산한 것입니다.
즉 정수와 정수를 연산했기 때문에 결과도 정수가 나와야 했던 것입니다. 그래서 결과 값에서 0에 가까운 정수를 결과로 취하게 됩니다.
즉 3/2를 하면 1.0, 5/2를 하면 2.0이 된다는 말이죠.

자바에서 이 문제를 해결하는 방법은 간단합니다. 오퍼레이터 /를 기준으로 양옆의 데이터 중 하나라도 실수형 데이터라는 것을 알려주면 됩니다.
아래 처럼 말이죠.





제가 요즘 파이썬을 공부하느라 데이터 타입에 무심해진건가 하는 생각을 하게 됐습니다.

하지만 제가 지금 고민 하는 것은 분명히 학교에서 배우기를 '정수 나누기 정수는 실수이다' 라고 배웠습니다.
즉 파이썬은 이 내용 그대로를 출력으로 제공하지만 대부분의 언어는 아니라는 사실이죠.

학교의 어떤 교수님께 물었더니 단호히 말씀하십니다.
 "전 파이썬을 싫어해요. 그건 스크립트 언어일 뿐이고, 정수와 정수를 계산한 결과가 실수로 나오는 그건 잘못된 것이에요."

현업에 계신 어떤 전문가분께 물었더니 이렇게 말씀하십니다.
"옛날에는 정수 나누기 정수가 정수라고 해서 크게 문제 될 것이 없었지요. 하지만 '빅데이터'시대에서 데이터 마이닝을 위해서는 파이썬의 방식이 더 좋다고 생각합니다."

예전에 읽었던 컴퓨터에 관한 책에서 본 한마디가 생각납니다.
"인간과 더 가까이!"
컴퓨터의 최종 목적이 인간과 더 가까워지는 것이라고 하더군요. 그렇다면 컴퓨터가 인간과 더 유사하게 동작하기 위해서 이런 사소한 문제부터 해결되어야 하는 것 아닐까요?

중학생에게 물어봐도 1/2은 0.5라고 대답하지 0.0이라고 답하지는 않을테니까요.

반응형
반응형


파이썬(Python)에 대한 몇몇 글을 쓴 적이 있는데 정작 파이썬을 설치하는 방법은 소개한 적이 없네요.
이제 막 파이썬을 시작하시는 분들을 위해서 파이썬 설치에 대해서 간략히 소개하겠습니다^^
저는 Python 3.2.2 버전으로 공부를 하고 있으므로 이 버전의 설치에 대해서 쓰도록 하겠습니다.

우선 파이썬이라는 언어는 공개되어 있고 무료입니다.
즉 필요하다면 다운받아서 사용하면 된다는 것이죠.


먼저 http://www.python.org에 접속합니다.
구글이나 네이버등 검색 사이트에서 'python' 또는 '파이썬'으로 검색하셔도 최상위에 검색 결과가 나올겁니다.



페이지 왼쪽에 몇가지 메뉴가 보입니다. 이중에 DOWNLOAD를 클릭하세요!



Download Python 페이지에서 스크롤을 조금만 내리시면 Python 3.2.2 에대한 여러가지 배포판 링크가 보입니다.
여러분의 컴퓨터 환경에 맞는 bit와 OS를 선택해서 다운 받습니다. 
저는 Windows 64bit 환경에서 사용할 것이므로 Python 3.2.2 Windows X86_64 MSI Installer를 다운 받았습니다.



다운로드가 완료되면 설치 파일을 실행 합니다.



윈도우에서의 설치는 우리가 흔히 알집이나 곰플레이어를 설치할 때처럼 편하게 진행됩니다.
먼저 윈도우 사용자 중 누가 파이썬을 사용할지에 대한 선택부터 시작됩니다. 저는 제 컴퓨터를 혼자 쓰므로 Install for all users를 선택했습니다. 혹시 여러 사용자가 같이 사용하는 컴퓨터에서 혼자 사용하시려면 Install just for me를 선택하시면 됩니다.



그 다음 Python을 설치할 폴더를 정해줍니다. Python 3.2.2의 기본 경로는 C:\Python32\로 지정되어 있군요.



마지막으로 선택사항에 대해 물어보는데요 다음으로 넘어가시면 되겠습니다. 각 항목을 선택하면 아래 상자에 항목에 대한 설명이 나옵니다. 참고하세요.



설치가 진행됩니다.
진행 중 아래와 같이 사용자 계정 컨트롤 메시지가 나온다면 반드시 '예'를 클릭 하셔서 설치가 진행되도록 해주세요. '아니오'를 클릭하시면 당연히 설치가 안됩니다.



설치가 완료되었습니다. 이제 파이썬을 사용할 수 있습니다.

 

시작 메뉴에서 Python 3.2라는 폴더가 등록 되었군요.



이대로 파이썬을 사용할 수도 있지만 좀 더 편리하고 원활한 사용을 위해서 환경 변수 Path에 Python이 설치된 경로를 추가해 줍니다.
[제어판] - [시스템 및 보안] - [시스템] 에서 왼쪽 메뉴의 [고급 시스템 설정] 을 선택합니다.



시스템 속성 창이 뜹니다. 그러면 고급 탭을 선택하고 아래의 환경 변수를 선택합니다.


환경 변수 창에서 시스템 변수 Path를 찾아서 선택한 후 편집을 클릭합니다.


변수 값에 다른 값들이 있다면 지우지 마시고 그 변수의 마지막에 ;(세미콜론)을 적으시고 그 다음에 Python의 설치된 경로명을 적어줍니다.


이렇게 환경 변수 Path를 지정해 주시면 사용자가 어떤 위치에서 python을 실행 시키더라도 Python 설치 경로에 있는 Python.exe가 실행 됩니다.



이렇게 파이썬을 공부하기 위한 첫번째 준비! Python 설치하기가 끝났습니다^^
다같이 Python 세계에 빠져 봅시다!
반응형
반응형

오늘 저희 팀에서 운영하는 이메일 서버를 이용하는 계정 중 하나에 문제가 생겼습니다.
아웃룩에서 pop3 를 통해 접속하는데 문제가 생긴 것입니다.

다음과 같은 에러 메시지가 출력 되었습니다.



받는 메일서버(pop3)에 로그온: 전자 메일 서버에 로그인할 수 없습니다. [계정 설정]에서 이 계정의 사용자 이름 및 암호를 확인하십시오. 서버가 응답했습니다. -ERR [SYS/PERM] Unable to process From lines (envelopes), change recognition modes or check for corrupted mail drop.

처음엔 에러 메시지가 무슨 말인지 이해가 안되서 아래와 같은 형태로 mailx 를 사용해서 메일 읽기를 시도했습니다.

% mailx -u [계정이름]

이렇게 하니 mailx 에서도 에러 메시지가 출력 되었습니다.

mailx: Your mailfile was found to be corrupted (Content-length mismatch).Message #0 may be tryncated,with another message concatenated to it.


mailx: Your mailfile was found to be corrupted (Content-length mismatch).Message #0 may be tryncated,with another message concatenated to it.

그래서 열심히 구글링을 했습니다. 그러던 중 오라클 사이트에 있는 트러블슈팅 가이드를 찾았습니다.
http://docs.oracle.com/cd/E19455-01/806-1075/msgs-1612/index.html
(SUN이 오라클에 옛~ 날에  넘어가서 오라클에 이런 자료들이 있는 거겠죠 ㅎ)

mailfile의 콜론(:)이 붙지 않은 From 라인에 문제가 있었던 것이군요. 그래서 직접 mailfile을 읽었습니다.


빨간 상자 부분이 이상하군요. From 라인이었을 것 같은 흔적이 있네요.
그래서 파일을 다른이름으로 복사하여 백업한 후 처음부분의 메일을 텍스트 에디터(vi)를 이용해서 삭제했습니다.
그러니깐 mailfile에서 처음 완전한 From 라인 앞까지 삭제한 것입니다.
삭제 후 mailx를 사용해서 메일을 확인하니 정상적으로 작동하는군요.


(** 참고로 mailfile의 첫번째 From 라인 앞에 빈 줄이나 공백이 있으면 또 다른 에러가 발생합니다. 저는 처음에 빈줄 하나가 들어가 있어서 오류가 났었습니다 빈 줄을 제거하고 나서 제대로 동작했습니다.)

아쉽게도 제일 앞의 From 라인이 망가지는 이유는 아직 명확히는 알아내지 못했습니다. 일부 검색 결과로는 스팸 메일 중에 종종 이렇게 깨져서 오는 경우가 있다고도 하는데 혹시 원인을 아시는 분은 댓글 부탁 드립니다.^^



반응형
반응형

  아래 글을 쓰기 위해 사용한 환경은 다음과 같습니다.
  - MS Windows 7 ultimate 64bit
  - Apache 2.2.21
  - Apache Tomcat 6.0.35
  - mod_jk 1.2.31


  제가 예전에 공부했던 JSP(Java Server Page) 페이지를 좀 만들어보려고 톰캣(tomcat)을 설치했습니다.

  그런데 톰캣만 사용하기에는 일반적인 웹서버가 아니라서 80번 포트로 접속되는게 아니라 8080이나 사용자가 정의한 포트로 접속하는 거라서 약간의 불편함이 있지요. 아래 그림 처럼 말이죠.. 귀여운 고양이를 만나기 위해 8080포트를 꼭 명시해 줘야 합니다 ㅠ


  또 톰캣은 http 서버를 내장하지만 정적 페이지를 로딩하는데에 웹 서버보다 수행 속도가 느리기 때문에 아파치(apache) 같은 정적인 페이지를 로드하는데 사용하는 웹 서버와 연동해서 사용합니다.

  그래서 저도 아파치를 설치하고 톰캣과 연동해서 사용하기로 했습니다. 이렇게 하면 정적인 페이지는 아파치가 jsp 나 서블릿은 톰캣이 처리하게 되죠.

  본격적으로 아파치와 톰캣이 정상적으로 설치되었다는 가정하에 연동 방법에 대해 설명드리겠습니다.

  우선 http://mirror.apache-kr.org//tomcat/tomcat-connectors/jk/binaries/windows/ 에서 톰캣 커넥터를 다운로드 받습니다. 저는 윈도우의 아파치 웹서버 환경이라서 위 링크로 따라갔지만 다른 환경(IIS같은 다른 웹서버 또는 다른 운영체제)이라면 당연히 다른 경로와 파일을 선택해서 다운 받으셔야합니다. 

 



다운로드가 완료되면 파일 앞축을 풀고 mod_jk.so 파일아파치 설치 폴더 아래의 modules 폴더에 복사합니다.

아파치설치폴더\modules\



  그 다음은 아파치 설치 폴더 아래의 conf 폴더에 있는 설정 파일인 httpd.conf 파일을 조금 수정해줍니다. 찾아보시면 LoadModule로 시작하는 줄들이 죽~ 있는 것을 보실 수 있는데  거기에 다음 한 줄을 추가해 줍니다.

LoadModule jk_module modules/mod_jk.so

모듈을 로드하고 그 모듈의 so 파일이 있는 위치를 정해 준것이라 생각하시면 되겟네요.

다음은 마지막 즈음에 다음을 추가해 줍니다.

Include conf/mod_jk.conf

  jk_module에 대한 설정을 적은 파일을 httpd.conf에 포함시켜주는 것이죠. jk_module에 대한 설정 파일을 따로 만들기 싫으시면 그 파일의 내용을 위 한 줄 대신 써주시면 됩니다.

  저는 설정 파일을 따로 만들기로 했으니 위에 적은 경로인 아파치 설치 폴더 아래의 conf 폴더에 mod_jk.conf라는 파일을 만들겠습니다. 방금 말씀 드렸듯이 이 방법이 싫다면 아래 내용을 httpd.conf 파일에 직접 추가하시면 됩니다.

JkWorkersFile "F:/Apache2.2/conf/workers.properties"
JkLogFile "F:/Tomcat 6.0/logs/mod_jk.log"
JkLogLevel error
JkAutoAlias "F:/Tomcat 6.0/webapps"
JkMount /* ajp13
JkUnmount /*.php ajp13
<Directory "F:/Tomcat 6.0/webapps">
 Options Indexes FollowSymLinks
 allow from all
</Directory>

  그리고 다음은 상자 첫줄에 있는 workers.properties 파일을 작성해 줍니다.
  첫 줄에 톰캣이 설치된 경로, 둘째 줄에 자바가 설치된 경로입니다. 나머지 부분은 내공이 부족하여 설을 못드리겠습니다. ㅠㅠ
  이렇게 하면 된다는 것 까지밖에.. 어쩌면 불필요한 줄이 있을지도 모르겠군요. 고수님의 댓글 부탁드립니다.!!

workers.tomcat_home="F:/Tomcat 6.0"
workers.java_home="F:/Java/jdk1.6.0_30"
ps=/
 
worker.list=ajp12, ajp13
worker.ajp12.port=8007
worker.ajp12.host=localhost
worker.ajp12.type=ajp12
worker.ajp12.lbfactor=1
 
worker.ajp13.port=8009
worker.ajp13.host=localhost
worker.ajp13.type=ajp13
worker.ajp13.lbfactor=1
 
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=ajp12, ajp13
worker.inprocess.type=jni
worker.inprocess.class_path=$(workers.tomcat_home)$(ps)lib$(ps)tomcat.jar
worker.inprocess.cmd_line=start
worker.inprocess.stdout=$(workers.tomcat_home)$(ps)logs$(ps)inprocess.stdout
worker.inprocess.stderr=$(workers.tomcat_home)$(ps)logs$(ps)inprocess.stder

  이렇게 모든 과정을 거치는 동안 느낀 것은 거의 모든 작업은 텍스트파일에 의해 이루어 진다는 것입니다. 사람이 이해하기 좋으면서 가장 단순한고 왜곡이나 압축 없이도 그 용량이 적은 것은 텍스트가 아닐까 생각되네요.

  아파치와 톰캣을 다시 시작한 후 결과는 다음과 같습니다.
  이제 80번 포트로 접속해도 귀여운 고양이 한마리가 웃고 있네요 ^^연동이 잘 되었군요!!


반응형
반응형

 

저번에 Windows live writer로 티스토리 블로그에 글을 포스팅하는 방법을 알아봤었는데 솔직히 저는 평소에 문서 편집할 때 MS Word를 써서 그런지 좀 불편하더군요. 가장 큰 불편함은 [Ctrl] 키를 사용한 다중 선택이 안 된다는 것이었습니다.

어릴 때부터 문서 작성할 때는 내용을 모두 친 후에 편집하는 게 몸에 배어 있어서 소제목 같은 걸 편집할 때 매우 불편하더라구요. 같은 서식을 적용 시키고 싶은데 다중 선택이 안되니 여간 귀찮은 일이 아니죠.

그래서 이번에 MS Word 로 포스팅 해보기로 했습니다. 도전!!

 우선 예전 live writer 때처럼 관리 페이지의 [글 설정] - [BlogAPI] 에서 API사용을 선택해야 합니다.

 

 

 그 다음은 정말 익숙한 MS Word를 켜고 [새로 만들기]-[블로그 게시물]을 선택합니다.

 

 새 게시물을 작성하기 전에 블로그 계정을 등록할 건지 물어보는군요. [지금 등록]을 눌러줍니다!!


 블로그 계정의 공급자를 선택하는 메뉴가 있는데요. 티스토리(tistory)는 여기 없네요^^ [기타]를 선택하고 다음으로 넘어갑니다.

 그리고 추가할 계정의 정보를 입력해 줍니다. 자신의 티스토리 블로그 주소 뒤에 " /api "를 써 주심 됩니다.^^
 사용자 이름(아이디)와 암호도 넣어주시구요.

 확인을 눌러주면 블로그를 선택하는 창이 뜨네요. 저는 팀블로그 하나랑 제 개인 블로그 하나를 하고 있어서 제 개인 블로그인 꼬슬꼬슬 Convergence!!를 선택 했습니다.^^ 




 이제 블로그 계정에 대한 설정을 끝이 났군요 문서를 작성하러 고고싱!!!!!! 



 블로그 게시물을 쓸 때 메뉴의 구성을 이렇군요. 스크린샷 기능은 정말 유용할 거에요^^

  다 작성하고 글을 올려 보니 불편한 점이 하나 발견되었네요.. 이미지의 크기가 제 생각처럼 잘 조절되지 않았습니다.;;; 편집할 때 cm 단위로 되있어서요 ㅠ pixel이어야되는디.......ㅠㅠ. 그리고 태그는 어떻게 넣어야하는 걸까요 ㅠㅠ 이건 아닌데 ㅠㅠ 아무튼 워드에서도 무리 없어 게시는 할 수 있군요! 
  이번 시도의 결론은.. 별 무리가 없는한 더 좋은 편집기를 찾을 때까지 그냥 티스토리 편집기를 쓰기로 했습니다

.

반응형
반응형

 

지금 이 글은 티스토리의 에디터가 아닌 Windows Live Writer로 작성한 글입니다.

 

티스토리 블로그 정말 편한 블로그 입니다. 하지만 블로그에 글을 쓸 때 사용하게 되는 에디터의 기능이 제한 적이라 불편함이 있습니다.

 

티스토리에서 제공하는 에디터를 쓰기 위해서는 일단 웹에 접속해야만 글을 쓸 수 있습니다. 그리고 임시 저장 기능이 있기는 하지만 또 다른 글을 써야 할 때에는 임시 저장 본이 날아가는 것도 있구요. 결정적으로 사진의 배치 같은 게 너무 제한적입니다.

 

그러던 중 웹에 접속하지 않은 상태에서 글을 쓰고 내 컴퓨터에 저장하고 블로그에도 포스팅 하는 방법을 찾았습니다. 생각보다 방법은 멀지 않은 곳에 있더군요.

바로 Windows Live Writer 같은 에디터를 블로그와 연동하는 것입니다. 다른 프로그램도 가능한데 오늘은 일단 Windows Live Writer를 사용하는 방법을 알아보겠습니다.

 

우선 http://explore.live.com/windows-live-writer 에서 Windows Live Writer을 설치합니다.!!

 

다음 꼭 해야 할 한가지!!!

블로그의 관리자 페이지에서 [글 설정]->[BlogAPI] 의 API사용을 사용으로 선택 해줍니다!

 

 

라이브 라이터를 설치 후에 처음 실행 시키면 아래와 같은 대화창이 나타납니다. 여기서부터 안내되는 데로 따라 하시면 됩니다^^

 

사용하는 블로그 서비스는 ‘기타 서비스’ 선택해주세요!

 

계정을 추가합니다 자신의 티스토리 주소아이디, 암호를 입력!

 

설정한 제 계정의 정보를 읽어오는군요.

 

설정이 완료되면 블로그 닉네임을 적고 마칩니다.

 

이제 이렇게 글을 씁니다!! 카테고리 선택도 가능하고 날짜 선택도 가능합니다.

 

그리고 마지막에 게시를 눌러주시면!!!!!

 

짜잔~~~!!! 잘 게시가 되었군요^^

 

써서 게시했던걸 수정해서 다시 올리니 수정된 것이 게시 되는 군요^^

아아.. 그런데 제가 쓰고 나니 태그를 입력하는 부분도 좀 다르고, 이미 티스토리 에디터에 익숙해서 인지 좀 불편하고 기능도 생각보다 허접하네요.

또 발행이 자동으로 안 돼서 좀 그렇네요.. 다음에 MS word로 다시 시도해 봐야겠습니다.

일단 웹에 접속하지 않고 게시물을 작성하는 시도를 했다는 것에 만족합니다. ㅎㅎ

 

반응형
반응형
 
프롬프트(prompt)?
명령 프롬프트(command prompt)?

  갑자기 생각나서 포스팅 하는데요 위의 두 가지 말이 같은 것을 지칭하는 말이라 지금부터 '프롬프트(prompt)'라고 통일하겠습니다.

  80년대 후반에 태어 났거나 90년대 이후에 태어난 친구들, 그러니깐 딱 저와 같은 세대, 지금 대학생이거나 사회 초년생들에게는 매우 생소한 말입니다. 물론 그 중에 저 처럼 이 말을 들어보고 이게 뭔지 직접 본 친구도 있지만요.

  지금이야 GUI(Graphical User Interface)라는 인터페이스 방식이 널리 퍼져 있어서 우리는 편하게 마우스로 그림을 클릭하는 것만으로 프로그램을 실행 시킵니다. 하지만 제가 어릴적에 컴퓨터를 처음 배울 때는 이 프롬프트(prompt) 라는 녀석에게 키보드를 통해 말을 걸 듯이 컴퓨터에게 일을 시켰죠. 아마 제 기억이 맞다면 문자를 이용해 컴퓨터에게 일을 시키는 인터페이스를 CUI(Character User Interface)라고 했던것 같습니다.

  사실 지금도 복잡한 명령을 컴퓨터에게 시킬 때에는 프롬프트를 사용하는게 속 편할 때가 많습니다. 예를 들면 네트워크에 연결하기 위해서 몇 단계를 거쳐서 화면의 그림을 클릭하며 네트워크 설정을 하는 것 보다 단 한 줄의 텍스트로 네트워크 설정을 하는 것이 편할 수 있다는 것이죠. 물론 이것은 네트워크 설정에 대한 명령과 그 사용 방법을 아는 경우에 한하지만요.

  그러니깐 GUI환경에서 유리한 작업이 있고 CUI 환경에서 유리한 작업이 있을 수 있으므로 각자의 편의에 따라 사용할 수 있다는 겁니다. 개인적으로는 프롬프트에서 명령을 입력하면 컴퓨터와 대화한다는 느낌(?)이 나서 좋은 것 같습니다. 하지만 요즘 사람들이 하는 대부분의 작업에는 매우 불편하죠 ^^

  아래는 프롬프트에 명령을 입력해서 컴퓨터에게 현재 디렉토리의 내용을 보여달라고 한 결과와 현재 ip설정을 보여달라고 한 결과 입니다.



그럼 본격적으로 "프롬프트(prompt)"에 대해서 알아보겠습니다.


■ prompt (command prompt)

  prompt는 사용자의 입력, 즉 명령을 받아들일 준비가 되어 있음을 표시하는 하나 이상의 문자(characters) 서열입니다. 이 것의 목적은 prompt라는 문자 그대로 사용자의 활동을 받아들이기 위함입니다. 일반적으로 #, $, %, > 중 하나가 프롬프트의 마지막 문자로 자주 쓰이며 그 외에 현재 작업 디렉토리(폴더) 같은 정보를 포함하기도 합니다.

  대부분의 Unix 시스템과 그 파생 시스템에서 prompt는 일반사용자의 경우 %나 $로 끝나지만 슈퍼유저(root)인 경우 #으로 끝납니다. 즉 프롬프트를 통해 현재 사용자가 어떤 권한을 가지고 있는지도 짐작할 수 있습니다.

  일반적으로 prompt는 사용자의 편의나 취향에 따라 변경할 수 있습니다. 다시 말하면 무언가를 구분할 색깔, 특별한 문자, 시간, 사용자이름, 작업 디렉토리, 쉘 번호 등의 다양한 정보를 포함시킬 수 있다는 것입니다. 더 나아가서 prompt의 정의를 통해 특별한 token을 이용해서 외부 명령어가 명령 인터프리터에 의해 실행되도록 할 수도 있습니다.

  WINDOWS 이전에 많이 사용하던 운영체제인 DOS(Disk Operating System)의 COMMAND.COM과 WindowsNT의 cmd.exe에서 prompt를 변경하는 방법은 %PROMPT% 라는 환경 변수를 직접 변경하는 것입니다. 보통 요즘 시스템의 prompt 기본 스타일은 C:\> 입니다. 이것은 C드라이브의 가장 상위 디렉토리에 있다는 의미 입니다. 이와 같은 prompt를 표기하기 위해서는 'prompt $P$G'를 입력해서 환경 변수를 변경하면  됩니다. 오래된 DOS는  A: 나 B: 플로피 드라이브를 사용하지 않는다면 C> 모양의 prompt를 제공하는데 이 때는 'prompt $N$G'가 자동으로 기본 값으로 스타일을 정의합니다.


  대부분의 Unix 시스템에서는 쉘(쉽게 말하자면 사람이 입력한 명령을 컴퓨터에게 해석해주는 것)에 따라 다른 변수도 프롬프트에 영향을 미칠 수 있지만 $PS1 변수를 사용해서 prompt를 변경할 수 있습니다.
  bash 쉘의 경우 프롬프트의 형태가
   [time]user@host:work_dir$
 인데 이것은 다음 명령을 실행하면 얻을 수 있는 형태입니다.
   export PS1='[\t]\u@\H:\W$'



다 쓰고 나니 생각보다 많은 정보를 드리지는 못 했네요.^^
prompt에 대한 포스팅은 여기서 마칩니다^^ 아차!! 위 내용은 wikipedia에서 참고 했습니다.(그대로 배낀건가???)
반응형
반응형



티스토리 블로그를 하면서 느낀게 나름 분류한다는 생각으로 카테고리를 만들어 놓았지만 항상 접혀 있기 때문에 불편함이 많았습니다. 그리고 블로그에 오는 손님들도 제 블로그에 어떤 글들이 올라 오는지 한 눈에 파악이 안 됐겠죠.

아래는 기존의 꽉 닫힌 제 블로그의 카테고리 입니다.



그래서 카테고리를 펼치는 방법을 알아봤습니다.

사소한 블로그 팁~~카테고리 펼치기 입니다.!!!

[관리자] -> 꾸미기의 [HTML/CSS 편집] 으로 이동하셔서

skin.htmlBODY 태그(<body>와</body>사이) 에 아래 스크립트를 추가해주시면 카테고리가 펼쳐진 화면을 보실 수 있습니다.^^
expandTree() 라는 함수가 있었네요 ㅋㅋ

<!--카테고리 펼침-->
<script language="JavaScript">
     try{
         expandTree();
     }catch(e){
     }
</script>


적용 후 시원하게 펼쳐진 카테고리 입니다.
펼치고 나니 분류가 너무 많네요.. 이것도 다시 수정해야할 듯. ㅋ


아무튼 카테고리 펼쳐놓기 성공!
반응형
반응형

다음 프로그램이 이 컴퓨터를 변결할 수 있도록 허용 하시겠습니까?

오잉? 이건 에러인가요?? 컴퓨터가 이상해진건가??
뭔가 실행시키기만 하면 컴퓨터가 '사용자 계정 컨트롤'이라는 창 하나를 띄우더니 아무것도 되질 않습니다.

윈도우 7 이나 윈도우 서버 2008 R2 등을 설치해 보면 뭔가 실행될 때마다 사용자 계정 컨트롤이라는 제목의 창이 뜨면서 화면이 검게 변하는 것을 볼 수 있습니다.
처음엔 당황스러울 겁니다.  
그리고 실행해야 하는 프로그램인데도 이 메시지 때문에 실행 안 하시는 분도 꾀 있을겁니다.
하지만 이것은 사용자의 컴퓨터를 보호하기 위한 것 중 하나입니다.
비스타부터 있었던걸로 기억나네요
UAC (User Account Control) 이라고
예전에 XP에서는 윈도가 모든 것을 열었다고 한다면 비스타 부터는 모든 것을 닫아놓고 필요한 것만 열어 쓰도록 했다고 하면 이해하기 쉬우실거에요.

정확한 표현은 아니지만 관리자 권한이 필요한 경우 (이 프로그램이 뭔가 시스템을 수정할 수 있는 경우)에 뜬다 정도?


창에서 오른쪽 아래 '알림이 표시될 때 변경'을 클릭하시면 사용자 계정 컨트롤 설정을 변경할 수 있습니다.
네가지 모드가 있군요. 저는 개인적으로 세번째 모드를 추천합니다.

가장 강력한 모드입니다. 뭔가 할 때마다 메시지를 띄우는 녀석입니다.

두번째는 기본적으로 설정되있는 녀석입니다. 사용자가 직접 프로그램을 실행 시킬 때 나타납니다. 그리고 웹브라우져 등에서 플로그램을 실행 시킬때로 나타납니다. 그리고 배경이 검게 변하면서 사용자 계정 컨트롤 창 외에는 불활성이 됩니다.


세번째는 제가 주로 설정해 놓는 모드 인데 두번째와 비슷하지만 화면이 검게 변하지 않고 사용자 계정 컨트롤 창 이외의 창도 활성화 할 수 있습니다.


마지막은 알림을 표시하지 않는 모드 입니다. 이 모드는 비추천입니다. 이 모드로 설정하면 신뢰할 수 없는 어떤 프로그램이 컴퓨터를 헤집어 버려도 알림을 표시하지 않게 되겠죠.

 

 

 

반응형
반응형

이번에 어플을 만들면서 아주 쉽게 할 수 있었는데도 불구하고 찾아보지도 않고 끙끙댔던 인코딩 문제가 있었습니다.
쉽다고 생각했기 때문에 더 길을 찾지 못 했는지도 모르겠어요^^;
안 그래도 초보인데 워낙 프로그래밍을 안하다보니 ㅠㅠ

네이버 검색 API에 들어가는 키워드는 UTF-8 인코딩이라고해서
예전에 DB에 값을 넣고 받아오거나 할때의 기억을 살려서 UTF-8로 인코딩을 해봤지만 소용이 없더군요.

절망에 빠졌는데.. 이런.. 그랬습니다.
이전까지 제 경험과 다른 점이 있군요.

바로 API에 요청을 URL로 보낸다는 것입니다.
그리고 자바의 환경과 안드로이드의 환경 차이도 있겠지요?? (물음표인 이유는 저도 궁금해서..ㅎㅎ)
그래서 인코딩시 URLEncoder를 사용해야합니다.

제가 범했던 실수는 바로 이것입니다.
이러니 에러가 날 수 밖에 없었군요. URL에 표시되는 것과는 다르니까요.
처음에 정말 당당하게 이런 코드를 작성했습니다. 그러나 낭패 ^^;;

    String keyword = "편의점"; //이부부은 검색어를 UTF-8로 넣어줄거임.
    System.out.println("변환전:"+keyword);
    String query = null;
    try {
        query = new String(keyword.getBytes("8859_1"), "UTF-8");
    } catch (UnsupportedEncodingException e1) {
        e1.printStackTrace();
    }
      System.out.println("변환후 :"+query);
  
     try{
            URL url = new URL("http://openapi.naver.com/search?"
           +"key="+key
           +"&query="+query
           +"&target=local&start=1&display=4");

LogCat에 이렇게 엉뚱하게 변환 된 것이 기록 되었네요^^; 이건 뭔지;;


애뮬에도 아무것도 파싱되지 않았습니다;; 요청 URL이 에러니 뭔가 나올 거리가 없죠. 에러 태그에 대한 처리를 하지 않은 이상.


같이 어플 만드는 동생이 URLEncoder를 사용하니 바로 해결 되더군요. 짜잔~^^ 원래 알고 계셨던 분들은 피식 웃으실지도 모르지만 저에겐 대단한 발견이었습니다. 
  String keyword = "편의점"; //이부부은 검색어를 UTF-8로 넣어줄거임.  
  System.out.println("변환전:"+keyword);    
  String query = null;
  try {
   query = URLEncoder.encode(keyword,"UTF-8");
  } catch (UnsupportedEncodingException e1) {
   e1.printStackTrace();
  }  
  System.out.println("변환후 :"+query);    
        try{
            URL url = new URL("http://openapi.naver.com/search?"
           +"key="+key
           +"&query="+query
           +"&target=local&start=1&display=4");

LogCat에 깔끔하게 UTF-8로 변환된 것을 확인 했습니다.


애뮬에도 편의점에 대한 검색요청의 결과가 파싱되었습니다^^

반응형
반응형


만들고 있는 안드로이드 어플이 네이버 검색 API를 통해 검색 결과로 나온 곳의 좌표를 받아오는데 카텍좌표계라는 것으로 값을 받아오더군요. 그런데 저는 WGS84 좌표계가 필요한 상황이었습니다 ㅠㅠ

이를 어떻게 해야할지..
처음에 열심히 검색을 했습니다. 수학 공식으라도 찾으면 그걸 프로그래밍하면되니깐요.
그러다 변환 공식이 아닌 API를 찾았습니다. 가까운 다음 지도 API좌표계 변환 API가 있더군요^^

좀 더 조사한 결과 네이버는 KTM 좌표계라는 걸 알아냈습니다.
결론 적으로 저는 다음 좌표계 변환 API를 써서 WGS84 좌표계로 변환하면 된다는 말씀!!

다음 API의 요청 주소 예는는 아래와 같습니다.

http://apis.daum.net/maps/transcoord?apikey=key&x=경도&y=위도&fromCoord=KTM&toCoord=WGS84&output=xml

파라미터로 x = 경도, y = 위도, fromCoord = 입력좌표계, toCoord = 출력좌표계, output = 출력형식 이 있네요.

모든 파라미터의 값은 string 형이고,

입,출력 좌표계의 값은 TM, KTM, UTM, CONGNAMUL, WGS84, BESSEL, WTM, WKTM, WUTM, WCONGNAMUL 이 있습니다.
위에 열거된 좌표끼리의 변환이 가능합니다.

출력 형태는 xml json 이 있고 기본은 xml입니다. 기본이 xml이니 받아와서 파싱만 하면 끝이겠군요^^

우선 KTM인 좌표 x=311277, y=552098을 KTM에서 WGS84로 변환하여 xml로 받아오도록 URL을 익스플로러에 보내보면


이렇게 xml로 값을 받아 오는군요 .

그럼 간단히 필요에 따라 아래와 비슷하게 메소드 하나만 만들면 될 것 같네요.^^
제가 만든 코드가 너무 허접하여 고수님들께서 댓글 좀 남겨주시면 감사하겠습니다.
다른 코드들을 보니깐 좌표를 x와 y로 표현한게 많던데 그렇게 하면 경도와 위도가 헷갈려서 힘들더라구요 ㅎㅎ
그래서 저는 longitude와 latitude라고 변수명을 줬습니다.

HashMap과  XmlPullParser를 사용하기 위해 사전에 import시켜줍니다.
import java.util.HashMap;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

그리고 메소드를 만들어 봐요~ ㅋㅋㅋㅋㅋ

 private HashMap<String, String> transCoord(String longitude, String latitude) { 

       private HashMap<String, String> map = new HashMap<String,String>();  //경위도를 넣을 해시에용

       final String key = "key"; //이부분의 발급받은 Key를 넣습니당.
         
       try {
        //다음 API를 사용하여 ㅁㅁㅁ 형식의 좌표를 ㅇㅇㅇ형태로 바꾼다 XML로 받아 와서 파싱한다.
        URL text = new URL("http://apis.daum.net/maps/transcoord?"
              +"apikey=" + key        //apikey
              +"&x=" + longitude                 //원래 좌표계 경도
              +"&y=" + latitude                 //원래 좌표계 위도
              +"&fromCoord=KTM"  //원래 좌표계
              +"&toCoord=WGS84"   //변환한 후 좌표계
              +"&output=xml");        //출력형식
      
     //파서를 생성하고 파싱을 시작해요. 
     XmlPullParserFactory parserCreator = XmlPullParserFactory.newInstance();
     XmlPullParser parser = parserCreator.newPullParser();
     parser.setInput(text.openStream(), null);
     int parserEvent = parser.getEventType();
    while (parserEvent != XmlPullParser.END_DOCUMENT) {
           switch(parserEvent) {
             case XmlPullParser.START_TAG:
                String tag = parser.getName();
                if (tag.compareTo("result") == 0) { //파서가 result 태그를 만나면 x의 y의 속성 값을 각각 longitude,latitude에 넣음.
                      map.put("longitude", parser.getAttributeValue(null, "x"));             
                      map.put("latitude", parser.getAttributeValue(null, "y"));
              }
              break;
            }
        parserEvent = parser.next();
     }
    } catch (Exception e) {
     Log.e("Net", "Error in network call", e);
       }
       return map;
   }

제가 만든 메소드를 사용해서 HashMap 으로 결과를 받아오면 매우 편리할거에요^^ 아마도 ㅎㅎ
더 편리한 방법 제보를 기다립니당~^^
반응형
반응형


요즘 만들고 있는 어플에 네이버 검색 API를 쓸 일이 있어 포스팅합니다.

네이버 오픈 API는 네이버 개발자 센터
http://dev.naver.com/openapI 로 가시면 상세한 설명을 보실 수 있습니다.

네이버 검색 API 중 지역 검색을 사용하는데요.
요청 URL(request url)요청변수(request parameter) target 값에 따라 검색 분야가 달라지네요.
지역 검색은 target값이 local입니다.
display는 받아올 결과의 수 입니다.

샘플 URL은 다음과 같습니다.
http://openapi.naver.com/search?key=test&query=%EA%B0%88%EB%B9%84%EC%A7%91&target=local&start=1&display=10

key에 자신이 받은 key값을 넣고 query에 검색할 키워드를 넣으시면됩니다.
검색어의 문자셋은 UTF-8을 써야한다고 하네요.
저는 일단 파싱만 하고 테스트만 할 목적이므로 샘플 URL에 key값만 넣어서 실행 했습니다.
샘플 URL의 검색어는 '갈비집'이네요.

출력결과로 다양한 값들이 있는데 저는 제게 필요한 것들만 받아옵니다.
우선 결과를 먼저 보여 드리면 이렇습니다.^^;; 허접하죠


결과로 주어지는 항목들은 네이버 개발자 센터에 테이블로 잘 정리가 되있습니다 ㅎㅎ
PullParser를 사용할건데요 뭐 속도가 느릴거라는 말도 있던데 어차피 전 테스트이므로 4개만 받아올거라서 크게 못 느낄 것 같아요.(그렇겠죠??????아닌가??)

package ksk06.naverapi;
import java.net.URL;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class NaverTest extends Activity {
     
 /** Called when the activity is first created. */
 @Override   
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        TextView status = (TextView)findViewById(R.id.status);
        TextView status1 = (TextView)findViewById(R.id.status1); //파싱된 결과를 보자
        TextView status2 = (TextView)findViewById(R.id.status2);
          
        boolean inItem = false, inTitle = false, inAddress = false, inMapx = false, inMapy = false;
       
  String title = null, address = null, mapx = null, mapy = null;
  String query = "%EA%B0%88%EB%B9%84%EC%A7%91"; //이부부은 검색어를 UTF-8로 넣어줄거임.
  System.out.println(query);
  
        try{
            URL url = new URL("http://openapi.naver.com/search?"
           +"key=여기에 발급받은 키값을 넣으세요"
           +"&query="+query //여기는 쿼리를 넣으세요(검색어)
           +"&target=local&start=1&display=4");
            
      
         XmlPullParserFactory parserCreator = XmlPullParserFactory.newInstance();
         XmlPullParser parser = parserCreator.newPullParser();
           
         parser.setInput(url.openStream(), null);
                  
         status.setText("파싱 중이에요..");
         
         int parserEvent = parser.getEventType();
         
         while (parserEvent != XmlPullParser.END_DOCUMENT){
          switch(parserEvent){                     
           case XmlPullParser.START_TAG:  //parser가 시작 태그를 만나면 실행
            if(parser.getName().equals("item")){
             inItem = true;
            }
            if(parser.getName().equals("title")){ //title 만나면 내용을 받을수 있게 하자 
             inTitle = true;              
            }
            if(parser.getName().equals("address")){ //address 만나면 내용을 받을수 있게 하자
            inAddress = true;              
            }
            if(parser.getName().equals("mapx")){ //mapx 만나면 내용을 받을수 있게 하자  
             inMapx = true;              
            }
            if(parser.getName().equals("mapy")){ //mapy 만나면 내용을 받을수 있게 하자  
             inMapy = true;              
            }            
            if(parser.getName().equals("message")){ //message 태그를 만나면 에러 출력
             status1.setText(status1.getText()+"에러");
              //여기에 에러코드에 따라 다른 메세지를 출력하도록 할 수 있다.
            }            
            break;
            
           case XmlPullParser.TEXT://parser가 내용에 접근했을때
            if(inTitle){ //isTitle이 true일 때 태그의 내용을 저장.
             title = parser.getText();             
                inTitle = false;
            }
            if(inAddress){ //isAddress이 true일 때 태그의 내용을 저장.
             address = parser.getText();             
                inAddress = false;
            }
            if(inMapx){ //isMapx이 true일 때 태그의 내용을 저장.
             mapx = parser.getText();             
                inMapx = false;
            }
            if(inMapy){ //isMapy이 true일 때 태그의 내용을 저장.
             mapy = parser.getText();             
                inMapy = false;
            }
            break;            
           case XmlPullParser.END_TAG:
            if(parser.getName().equals("item")){
             status1.setText(status1.getText()+"상호 : "+ title +"\n주소 : "+ address +"\n좌표 : " + mapx + ", " + mapy+"\n\n");
             inItem = false;
            }
            break;                   
          }          
           parserEvent = parser.next();
         }
         status2.setText("파싱 끝!");
        } catch(Exception e){
         status1.setText("에러가..났습니다...");
        }       
    }
}

레이아웃은 간단히 파싱되는걸 확인만 할거라서 텍스트뷰로 만들었습니다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView
 android:id="@+id/status" 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    />
    <TextView
 android:id="@+id/status1" 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    />
    <TextView
 android:id="@+id/status2" 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    />
</LinearLayout>

절대로 빠뜨리시면 안될 한가지가 있습니다.
AndroidManifest.xml 파일에 인터넷에 접근하기 위한 권한을 설정해 주셔야합니다^^
<uses-permission android:name="android.permission.INTERNET"/>

저는 이렇게 간단히 검색어에 대한 건색 결과 중 상호와, 주소, map의 좌표를 받아 온 것을 String에 넣어서 출려해 봤습니다. 실제로 편리하게 쓰시려면 List 같은 걸 사용하시면 더 좋을 거 같아요.

네이버의 다른 오픈 검색 API 도 똑같은 URL을 사용하기 때문에 target값만 바꿔 주시고 받아올 결과들에 대한 코드만 수정해 주시면 다른 검색도 쉽게 사용하실 수 있을겁니다. 
반응형
반응형


종종 어딘가 공모전이 있거나 글을 써야할 일이 있을 때 이런 문구를 많이 보게 됩니다.

 '200자 원고지 00매 내외'

이걸 보고 나면 어떤 생각이 드시나요?

"원고지 00매가 A4 몇장이지?"
"이거.. 원고지를 사야되나?"
"한글에 원고지 모양이 있던거 같던데 그걸 써야하나?"
"글을 쓰고 글자를 세어봐야하나?"

저는 이때까지 이런 생각들을 했었네요^^;

가장 편한 방법이 원고지 모양의 문서를 만드는 거라 생각했는데 이건 가독성도 떨어지고 원고지 사용법에 대한 오류도 좀 있더군요.

그런데 알고보니 한글과컴퓨터에서 만든 한글에 문서의 정보를 보여주는 기능이 있더군요.
물론 원고지로 몇매 정도 되는지의 정보도 나옵니다.

본론!

한글에서 메뉴의 [파일]-[문서 정보] 또는 단축키로 Ctrl + Q + I 를 눌러주시면 문서에 대한 상세한 정보를 볼 수 있습니다.
다섯개의 탭이 있군요.

[일반] 탭에는 문서 파일의 정보를 보여주는것 같네요.


[문서요약] 탭은 제목이나 주제등의 요약정보(이 문서는 제가 초딩때 어떤 선배님께서 작성하셨나봅니다. 날짜가 1999...;;)


[문서통계] 탭은 문서에 매우 상세한 수치로된 정보가 나옵니다. 여기에 우리가 원하는 원고지 매수에 대한 정보도 나오네요^^
이 37쪽의 문서는 원고지로 240.1장이 되는군요


[글꼴] 탭엔 문서에 사용한 글꼴 정보, [그림 정보] 탭에는 문서에 포함된 그림이 나오네요^^


오호호~ 이제부터 원고지 00매 내외라는 문구에 당황할 필요가 없어졌습니다^^
글쓰기를 좋아하시는 분들 화이팅!!
반응형
반응형

제가 푸리에 급수에 대해 포스팅을 하려다보니 수식을 넣어야 겠는데 방법을 몰라 검색해보니 여러가지 방법이 소개되어 있더군요. 그 중 지금 소개 드리려는 방법이 가장 간단한 방법인 것 같습니다.

우선 TeX라는 문법을 알아야 쓸 수 있다고 하는데 제가 써보니 공학계산기 정도 쓰는 수준이라면 간단한 수식은 별 어려움 없이 입력할 수 있을 것 같네요^^
이 글을 쓰고 있는 지금 저는 TeX문법이 자세히 어떤 것인지 잘 모른답니다
기회가 되면 상세히 알아보고 포스팅하겠습니다^^

그럼 본론으로 넘어가서 블로그에 수식 입력하는 방법을 소개하겠습니다.
html이나 javascript에 대한 간단한 지식만 있다면 매우 쉽습니다^^.
사실 뭐 그런 지식이 없어도 따라만 하시면 수식을 입력할 수 있습니다.
제가 티스토리를 사용하니 티스토리를 예로 설명해 드리겠습니다.

블로그에 로그인해서 관리자에서 [스킨]-[HTML/CSS 편집] 으로 이동합니다.
여기서 skin.html <head>와 </head> 사이에  아래 코드를 넣어줍니다.

<script type="text/javascript"  src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=default"> </script>

<script type="text/x-mathjax-config"> MathJax.Hub.Config({ tex2jax: {inlineMath: [['$','$'], ['$$','$$']]} }); </script>

사실 첫 번째 줄만 넣어줘도 수식 입력이 가능합니다.

아래 줄은 우리가 입력할 때 수식임을 알리는 문자를 사용자 정의 하는 코드 입니다. $ 부분이 글자와 글자 사이에 수식을 입력할때 쓰이고 $$는 한 줄을 차지하는 수식을 입력할 때 쓰입니다.
다시 말하면, 저 부분을 다른 문자로 바꿔주면 그 문자가 수식임을 알리는 문자가 되겠지요 HTML의 tag처럼요^^

만약에 $f(x)=x^2$이라고 입력하면 그 줄에 $f(x)=x^2$ 로 출력됩니다.
그리고 $$f(x)=x^2$$ 이라고 입력하면 한줄을 차지하는 $$f(x)=x^2$$ 이 출력 되겠지요^^

그런데 저는 이 글에 $를 어떻게 입력할 수 있었을까요?? HTML 태그 처럼 보이지 않아야 정상일텐데요^^
저는 <FONT>$</FONT> 이렇게 태그로 감싸버렸습니다.^^ 저도 이것 때문에 한참을 고민했네요 ㅋㅋㅋ
hyunkyukim.tistory.com/31 을 참고했습니다^^

아무튼 블로그에 수식 입력 성공입니다^^!!!!!
다른 블로그에서도 HTML 수정하는 부분에서 수정해 주신다면 똑같이 적용할 수 있겠지요. ㅎㅎ

반응형
반응형

파이썬에서 리스트는 값들의 나열로 여러 종류의 값을 담을 수 있고 문자열 처럼 0부터 시작하는 인덱스를 가지고 있어서 슬라이싱도 가능합니다.



[ ] 를 이용해서 리스트를 만듭니다.





append() 메서드를 사용해 기존 리스트에 값을 추가할 수 있습니다. 이 때 값은 리스트의 맨 뒤에 추가됩니다.
insert() 메서드를 사용하면 append()와 다르게 리스트의 원하는 위치에 값을 추가할 수 있습니다. 이 때 인자 값은 리스트의 인덱스입니다.
extend() 메서드로는 튜플이나 리스트 같은 여러 값을 한번에 삽입할 수 있습니다. 이 때도 append() 처럼 맨 뒤에 추가됩니다.




리스트에서는 + 연산자를 지원하는데 이 것을 사용할 때에는 튜플이나 리스트 처럼 반복되는 값을 넣어야 합니다. 만약에 문자열을 넣을 경우에는 문자열의 문자 하나하나가 슬라이싱되서 리스트에 들어가게됩니다.




index() 메서드를 사용해서 특정 값의 인덱스를 찾을 수 있습니다. 이 때 index()는 처음 찾은 값만을 반환 합니다. 만약 리스트의 인덱스 0에 '슬기'가 있고 5에도 '슬기'가 있으면 0만을 반환합니다. 그래서 index()의 두 번째 인자에 시작점을 세 번째 인자에 종료점을 지정해 줄 수있으며 범위 안에 특정 값이 없을 경우 리스트 내에 그 값이 없다는 에러를 출력합니다.




pop() 메서드로 리스트에서 값을 뽑아낼 수 있습니다. 인자가 없을 경우 뒤에서부터 차례로 값을 뽑고, 인자가 있을 경우 해당 위치의 값이 뽑힙니다. 뽑힌다고 표현한 이유는 pop된 값은 리스트에서 없어지기 때문입니다.




count() 메서드는 해당 값이 리스트 안에 몇개 있는지를 반환합니다.




remove() 메서드는 말 그대로 해당 값을 삭제합니다. 동일한 값이 있을 경우에는 앞 쪽의 값을 삭제합니다.




sort() 메서드와 reverse() 메서드로 리스트를 정렬할 수 있습니다. sort()는 순방향, reverse()는 역방향 입니다.
이 두 메서드는 정말 편리한 메서드라느 생각이 드네요 ㅎㅎ




그리고 sort()의 key값을 정해서 자신이 원하는 방식으로 리스트를 정렬할 수 있습니다.
아래는 단어의 마지막 문자를 비교해서 정렬하는 것을 보여주는 코드입니다.
단어의 마지막 문자를 반환하는 함수 sorttest()를 정의하고 sort()메서드의 key로 지정합니다.



단어의 마지막 문자를 기준으로 오름 차순으로 정렬된 것을 볼수 있습니다.

reverse를 True로 하면 역방향도 가능합니다.

 

반응형
반응형

자바 응용프로그램(application)을 실행하기 위해서는 main() 함수가 있어야 합니다.
다시 말하면 프로그램이 실행되면 가장 먼저 찾는 것이 main() 함수라는 것이고, main()함수가 프로그램의 시작점인 것입니다.
main() 함수의 생긴 모양과 각각의 의미를 한 번 알아볼까요?

class A
{
public static void main(String[] arg)
{

...

}
}

위에서 A는 클래스의 이름 입니다.

main() 함수의 모양을 보면

처음에 접근권한이 public 으로 시작합니다. 이 것은 어떤 인터프리터(interpreter)도 접근 가능하게 하기 위함입니다.

다음으로 static 키워드가 나오는데 이것은 main()이 제일 먼저 실행되어야하기 때문에 static 키워드를 붙여 프로그램 시작시 먼저 메모리에 올라가도록 해서 이 함수를 사용하기 위함이라고 합니다.
static 키워드를 빼도 문법에 어긋나지 않기 때문에 컴파일 에러는 나지 않지만 프로그램이 실행되지 않습니다. 즉 static 키워드가 없으면 프로그램의 시작점인 main()함수를 찾을 수 없는 것입니다.

void는 반환형(return type)이 되겠습니다. C++에서는 main()함수의 반환형이 int로 되어 있어 숫자 0을 반환함으로써 프로그램의 자원을 반납하고 종료시키는데 자바에서는 void로 반환하는 것이 없습니다. 이것은 아마도 자바는 메모리 관리를 프로그래머가 직접하지 않기 때문이 아닌가 생각됩니다. 정확히 아시는분은 댓글 부탁드립니다^^

그리고 인자(argument)가 String 클래스의 배열로 되어있는데 이 것은 그 값이 어떤 형태이든 모든 값을 문자열로 받아들이고 또 여러 개의 인자를 받아들이겠다는 의미라고합니다.
프로그램 실행 시에 인자를 여러 개 입력할 때 띄어쓰기로 구분하고, 띄어쓰기가 포함된 문자열은 " "을 이용해 입력합니다.

만약 java A 1 2.5 text 라고 실행한다면

문자열 '1', '2.5', 'text'가 A클래스의 main()함수의 인자로 들어가는 것이죠.

제가 아는 바는 여기까지입니다 ㅋㅋ
저의 설명에 잘 못된 점이나 추가할 것이 있으면 댓글 부탁드립니다^^
반응형
반응형

파이썬에서는 영어는 물론 한글도 문제없이 화면에 출력됩니다. 하지만 이런 출력이 내 컴퓨터뿐 아니라 다른 사람의 컴퓨터 특히 다른 언어권과 운영체제에서도 동일하다고는 확언할 수 없습니다.

세계 각국의 다양한 문자 표현하기 위한 표현 방식을 인코딩(Encoding)이라고 합니다.

각각의 언어권마다 서로 다른 인코딩을 사용한다면 프로그램을 다른 나라 사람도 사용하게 하려면 엄청 애를 먹을 겁니다. 그래서 세계의 모든 문자를 한 방식으로 표현할 수 있는 유니코드(Unicode)를 사용합니다.



파이썬 3.x 에서는 일반 문자열이 기본적으로 유니코드입니다. 즉 프로그램에서 글씨가 깨질 걱정을 할 필요가 없는 것입니다. 유니코드를 제외한 나머지 인코딩된 문자는 bytes로 표현됩니다.
그리고 문자를 특정 코드로 인코딩하고 싶을 때는 encode()를 사용하고




어떤 문자의 유니코드 값을 알고 싶을 떄는 ord()를 사용하고




어떤 유니코드 값에 해당하는 문자를 알고 싶을 때는 chr()을 사용합니다.





현재 시스템의 인코딩이 뭔지 알고 싶을 때는 아래와 같이 확일 할 수 있습니다.

반응형
반응형

파이썬(python)에서는 몇 가지 문자열 연산자를 지원합니다.
 
' + ' 는 문자열을 병합합니다.
' + ' 는 문자열 상수끼리에서는 생략할 수 있습니다.
 
' * '는 문자열을 반복 시킵니니다.

확인해 보면 아래와 같습니다.

 



그리고 파이썬에서는 문자열은 a[x] 형태로 인덱싱 됩니다. 제일 첫 문자는 0부터 시작합니다.
하지만 문자열 인덱싱을 이용한 문자열 변경은 허용되지 않습니다.





인덱싱을 사용해서 특정 위치의 한 문자 뿐만 아니라 문자열을 꺼낼 수도 있는데 이를 슬라이싱(slicing)이라고 합니다. 문자열 변수 뒤에 [시작위치:끝위치]를 분여서 원하는 문자열을 꺼냅니다.

시작 위치는 0을 문자열 첫 문자의 바깥쪽(왼쪽)으로 시작해서 한칸씩 이동합니다. 'kkoseul'을 예로 들면
0 k 1 k 2 o 3 s 4 e 5 u 6 l 7
이 됩니다.

만약에 시작 위치가 음수 인 경우는 문자열의 끝에서 부터 세어갑니다.
(-7) k (-6) k (-5) o (-4) s (-3) e (-2) u (-1) l

그리고 a[:2]나 a[-4:] 처럼 위치를 생략한 경우 각각 문자열의 처음이나 끝으로 처리합니다.



title에 'kkoseul'을 넣고 슬라이싱을 해보면 다음과 같은 결과가 나옵니다.





그리고 :를 이용해 인덱스를 증가시킬 수를 정할 수 있습니다. a[::2] 처럼 입렵하면 문자열의 처음부터 2칸 씩넘어서 문자를 출력합니다. 그리고 이 증가 인자가 생략되면 1씩 증가시킵니다.





그리고 문자열이나 수치들 사이의 변환은 각 타입 클래스의 생선자를 사용합니다.
아래를 보면 각가의 타입의 변한것을 확인할 수 있습니다.
출력을 확인해 보니 정수 1024로 입력한 a는 1024.0으로, 문자열 "500"으로 입력한 b는 정수 500으로, 실수 1.414로 입력한 c는 문자열 '1.414'로 출력되네요^^



이렇게 정리를 하다보니 파이썬은 문자열을 처리하는 일이나 각 자료의 타입을 변환하기에 제가 아는 다른 언어에 비해 편리하다는 생각을 하게 되네요. 앞으로 계속될 파이썬 공부가 기대됩니다^^




반응형
반응형

 


파이썬에서 변수들은 해당 객체의 주소를 가지고 있습니다.
예를 들어 a=1이라고 하면 a가 1이라는 값을 가지는 것이 아니라 1이라는 객체가 생성되고 이 객체의 주소가 변수에 저장되는 것입니다.

객체의 고유한 id 값을 반환하는 id() 함수를 사용해서 확인해 보겠습니다.

리스트로 만든 a는 리스트가 있는 주소를 기억 하고 b 역시 이 주소를 복사하기 때문에 리스트 안의 내용을 수정하면 b를 호출해도 수정된 내용이 표시됩니다. 새로운 객체를 생성한 것이 아니라 객체 내의 a[0] 내용만 바꿨으므로 객체의 id역시 처음과 똑같이 유지 되는군요.

한마디로 말하자면 a와 b는 같은 객체를 공유하고있는 것입니다.



하지만 integer형으로 a와 b를 만들었을 때는 조금 다른 결과가 나오네요. a에 다른 값을 넣으니 a의 id가 바뀐 것을 확인할 수 있습니다. 아마도 이런 타입에서는 변수의 값이 바뀌면 새로운 id로 객체가 생성되나 봅니다. 정확한 속 사정을 아시는 분은 코멘트 좀 부탁드려요~~!




혹시나 해서 자바에서도 제 나름 비슷하게 따라 해봤는데 유사한 결과가 나오네요.






리스트의 경우에 a와 b가 같은 객체를 공유하지 않게하려면 아래와 같이 [:]을 써서 복사하면 됩니다.
복사 후에 id를 확인해 보면 서로 다른 id를 가진 것을 확인할 수 있습니다. a[0]만 수정했을 때 당연히 a와 b를 호출하면 서로 다른 값이 나옵니다.





리스트 이외의 경우는 copy 모듈을 사용합니다. copy 모듈의 copy()함수는 주소가 복사되는 얕은 복사(shallow copy)를 하며, deepcopy()함수는 객체를 공유하지 않는 깊은 복사(deep copy)를 합니다.



다시 한번 자세히 비교해 보면 다음과 같습니다.
마지막 줄에 리스트 각각의 id는 다르지만 그 리스트의 1번 인덱스의 id를 비교해 보면 a[1]와 cp[1]은 같은 id를 가지고 있는 것을 확인 할 수 있습니다. 분명히 copy()가 얕은 복사라고 했는데 a와 cp의 id가 서로 다르게 나와서 처음에 많이 헷갈렸습니다.


프로그래밍할 때 얕은 복사와 깊은 복사에 유의해서 사용해야겠네요^^

 


반응형

+ Recent posts