2009-09-10

직각 삼각형의 각도 구하기

직각 삼각형 각도는 다음과 같이 구한다.


tan(각도 b)  = 높이(B) / 밑변(A)

각도 b = inverse tan(높이 / 밑변)

각도 a = 90 - 각도 b


자바에서는 다음과 같이 처리한다.

double angleInRadians = Math.atan(높이 / 밑변);

double degreeA = Math.toDegrees(angleInRadians);

double degreeB = 90 - degreeA;

2009-09-09

자바 HTTP POST 요청

자바(1.4 이상)로 HTTP POST 요청을 하는 방법이다.

먼저 URLConnection 객체를 생성한다.

URL url = new URL("http://example.dimdol.com/example.jsp");
URLConnection con = url.openConnection();

URLConnection 객체 setRequestProperty 메소드로 HTTP 헤더 정보를 설정한다.

con.setRequestProperty("Accept-Language",  "ko-kr,ko;q=0.8,en-us;q=0.5,en;q=0.3");

URLConnection 객체 setDoOutput 메소드로 POST 요청임을 설정한다.

con.setDoOutput(true);


요청 파라미터는 name=value 패턴으로 지정하고 두 개 이상은 &을 사용해서 연결한다.

String parameter = URLEncoder.encode("name", "UTF-8") + "=" URLEncoder.encode("dimdol", "UTF-8");

parameter += "&" + URLEncoder.encode("age", "UTF-8") + "=" URLEncoder.encode("35", "UTF-8");

HTTP 요청을 한다.

OutputStreamWriter wr = new OutputStreamWriter(con.getOutputStream());
wr.write(parameter);
wr.flush();  // 꼭 flush를 호출해야 한다.


응답 결과가 텍스트인 경우에는 다음과 같이 처리한다.

BufferedReader rd = null;

rd = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
String line = null;
while ((line = rd.readLine()) != null) {
  // 로직 처리
}

응답 결과가 XML인 경우에는 다음과 같이 처리한다.

DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document document = builder.parse(con.getInputStream());

// 이하 document를 이용해서 로직 처리

응답 헤더는 다음과 같이 확인할 수 있다.

String cookie = con.getHeaderField("Set-Cookie");


전체를 try/finally로 묶고 finally 절에서 OutputStreamWriter과 BufferedReader를 close한다.



2009-09-06

ALM 애플리케이션 목록

ALM(Application Lifecycle Management) 애플리케이션 목록이다.


YouTrack

IntelliJ IDEA로 유명한 JetBrains에서 만든 버그 이슈 트래커
아직은 베타 상태
키보드 단축키를 통한 빠른 사용을 장점으로 함

codeBeamer

기능적인 완성도는 모르겠지만 ALM 전체를 커버

tinyPM

Agile에 기반한 프로젝트 관리 도구

파이어폭스 3.5 느리다

파이어폭스 3.5 초기 부팅 과정이 느리다. 내 컴퓨터에서만 그런지는 모르겠지만 느리다.

느리다는 건 다른 웹 브라우저와 비교해도 파이어폭스 이전 버전하고 비교해도 그렇다.


프로그램 시작 자체도 느리지만, 즐겨 찾기 대신 Ctr + L 단축키로 URL을 직접 입력하는 내 사용 패턴이 더욱 답답하게 한다. 주소 입력 창에 URL을 입력할 때의 그 버벅임이란...

마이크로소프트 익스프레션

오늘 오후에 종각 영풍 문고에서 시간을 보내다가 두꺼움에 혹해서 크리에이티브 웹이라는 잡지를 구매했다.

서점을 지나가면서 표지를 본적이야 있겠지만 실제 내용을 보기는 처음이었다. 우리나라에 이렇게 많은 웹 에이전시 회사가 있다는 사실을 알았다.


그러다가 뒷면 광고에 나온 마이크로소프트 REMOIX09 행사 내용에 포함되어 있는 마이크로소프트 익스프레션이라는 솔루션에 눈길이 갔다.


그 중에 SketchFlow가 있었는데 일종의 와이어프레임 솔루션인 것 같다.

2009-09-02

홈페이지 메인 화면

http://www.gracesmith.co.uk





이런 디자인이 사람에게 주는 의미가 다양하겠지만 나는 좋다^^


http://vaadin.com


텍스트가 얼마나 중요한 요소인지를 보여준다.

2009-09-01

와이어프레임

구글 리더로 구독하는 Smashing Magazine에서 와이어프레임(Wireframes)과 관련한 35 Excellent Wireframing Resources을 보았다.


처음 알았는데 화면 스케치를 와이어프레임이라고 하는 것 같다. 혹은 프로토타입이라고 하거나...


파워포인트나 모델링 도구와는 달리 스케치 느낌을 살린 화면 스케치를 프로그램으로 구현할 수 있을까 생각한 적이 있는데 이를 구현한 제품(iPlotz)도 볼 수 있었다.

종이로 그린 후에 디지털 카메라나 스케너로 스캔하는 것과 이런 애플리케이션을 사용하는 것 중에서 어느 것이 더 생산적일까?



요구사항 관리 애플리케이션이 텍스트 편집기와 와이어프레임 편집기를 함께 제공하면 좋을 듯 하다. 여기디가 유스케이스 모델링 정도까지 추가해서...


와이어프레임 도구

Balsamiq Mockups

인상적임

Mockup Screens


관련 글

MockupScreens Review

2009-08-30

display: block과 inline

아래 태그는

<div>div1</div>
<div>dIv2</div>
<div>div3</div>

웹 브라우저에 아래와 같이 표시된다.
반면에 아래 태그는

<span>span1</span>
<span>span2</span>
<span>span3</span>

웹 브라우저에 아래와 같이 표시된다.

이 둘 사이에 나타나는 가장 큰 차이는 줄 바꿈 여부이다. div 태그는 줄바꿈되고, span 태그는 줄바꿈되지 않는다.

div 태그가 줄바꿈되는 이유는 CSS display 속성 기본 값이 block이기 때문이고, span 태그가 줄바꿈되지 않는 이유는 CSS display 속성 기본 값이 inline이기 때문이다.


아래처럼 반대로 설정하면

div {
  display: inline;
}

span {
  display: block;
}

웹 브라우저에 아래와 같이 표시된다.

block과 inline의 차이점은 줄바꿈만은 아니다.
  • block으로 설정하면 줄바꿈 되고, inline으로 설정하면 줄바꿈이 되지 않는다.
  • block으로 설정하면 상/하 margin과 padding 속성을 사용할 수 있지만, inline으로 설정하면 상/하 margin과 padding 속성을 사용할 수 없다.
  • block으로 설정하면 width, height 속성을 사용할 수 있지만, inline으로 설정하면 width, height 속성을 사용할 수 없다.

2009-08-28

드래그 앤 드랍

드래그 앤 드랍을 자바 스크립트로 구현하는 예제이다.

<div>드래그 앤 드랍</div>

위의 div 태그를 드래그 앤 드랍하려면 우선 onmousedown 속성을 설정한다.

<div onmousedown="drag(this, event);">드래그 앤 드랍</div>

사용자가 div 태그를 마우스로 누른 순간에 onmousedown 속성으로 선언한 자바 스크립트 함수(drag - 아래에서 설명)가 수행된다.

drag 함수는 다음과 같다.

/*
drag 함수의 첫번째 파라미터(element)는 드래그할 대상이고, 두번째 파라미터(event)는 이벤트이다.
*/


function drag(element, ev) {
}


다음은 drag 함수 구현부이다. 우선 마우스 커서를 드래그를 의미하는 것으로 변경한다.

document.body.style.cursor = "move";

/*
마우스 커서는 드래그할 대상(<div>드래그 앤 드랍</div>)이 아닌 body에 설정해야 한다. 마우스를 드래그를 하면 마우스 포인터가 대상 밖으로 벗어나는 것이 일반적이기 때문이다.
*/


그리고 document에 대해서 onmousemove 이벤트 리스너를 설정한다.

/*
onmousemove로 설정한 함수는 마우스가 움직일 때마다 반복적으로 계속 호출된다.  마우스 커서와 동일한 이유로 드래그할 대상(<div>드래그 앤 드랍</div>)이 아닌 document에 대해서 onmousemove 이벤트 리스너를 등록한다.
*/

document.onmousemove = function(ev) {
    // IE 6.0은 해당 함수 파라미터로 이벤트 객체를 전달하지 않는다.
    // 대신 window.event 변수로 전달한다.
    ev = ev || window.event;

    // prototype이 제공하는 API로 현재 마우스 커서의 위치 값을 추출한다.
    var top = Event.pointerY(ev);
    var left = Event.pointerX(ev);

    // 드래그할 대상을 움직이게 하려면 onmousemove 이벤트 리스너가 호출될 때마다
    // CSS 속성으로 위치 값을 변경한다.
    // position 속성을 absolute로 설정하고 left와 top 속성으로 위치를 지정한다.
    element.style.position = "absolute";
   element.style.left = left + "px";
   element.style.top = top + "px";
    // left, top 속성을 설정할 때 px(단위)를 명기해야 한다.

    // prototype이 제공하는 API로 이벤트를 종료하고 false를 반환한다. 그렇지 않으면
    // 주변에 있는 텍스트를 선택하는 것과 같은 현상이 일어난다.
    Event.stop(ev);
    return false;
  };

마우스 커서 위치 값 추출에 Prototype 라이브러리를 사용했다. 자세한 사항은 다음을 참조한다.


그리고 document에 대해서 onmouseup 이벤트 리스너를 설정한다.

/*
onmouseup으로 설정한 함수는 마우스 누른 것을 해제할 때(드랍) 호출된다. 마우스 커서와 동일한 이유로 드래그할 대상(<div>드래그 앤 드랍</div>)이 아닌 document에 대해서 onmousemove 이벤트 리스너를 등록한다.
*/

document.onmouseup = function(ev) {
    ev = ev || window.event;
    // 마우스 커서를 초기화한다.
    document.body.style.cursor = "auto";
   
   // 여기에서 필요한 작업을 한다. 이는 드래그 앤 드랍 성격에 따라서 달라진다.
   // 예를 들어, AJAX를 이용해서 현재 위치 값을 서버에 저장할 수도 있다.

    // 드래그앤 드랍과 관련한 이벤트 리스너를 초기화한다.
    document.onmousemove = null;
    document.onmouseup = null;
    Event.stop(ev);
    return false;
  };


최종적인 drag 함수는 다음과 같다.

function drag(element, ev) {
  document.body.style.cursor = "move";

  document.onmousemove = function(ev) {
    ev = ev || window.event;
    var top = Event.pointerY(ev);
    var left = Event.pointerX(ev);
    element.style.position = "absolute";
    element.style.left = left + "px";
    element.style.top = top + "px";
    Event.stop(ev);
    return false;
  };

  document.onmouseup = function(ev) {
    ev = ev || window.event;
    document.body.style.cursor = "auto";

    // 필요한 작업 수행

    document.onmousemove = null;
    document.onmouseup = null;
    Event.stop(ev);
    return false;
  };
  Event.stop(ev);
  return false;
}


2009-08-27

간단한 사용자 가입 폼 - Mint/Basecamp

Mint Account Center 화면이다.



사용자는 최소한의 정보만을 입력하면 된다.

  • 아이디 대신 이메일 주소를 사용한다.
  • 패스워드 뿐만 아니라 이메일 주소도 올바르게 입력했는지 확인한다.
  • 시간대를 입력받는다.


Basecamp Signup 화면이다.



이름, 이메일, 아이디(Username)을 모두 입력받는다.

2009-08-25

탭 메뉴 작성

CSS와 ul/li 태그로 탭 메뉴를 작성하는 방법이다.


기본 설정

XHTML 1.0을 준수하여 ul, li 태그로 아래처럼 작성한다.

<ul>
  <li><span>소프트웨어</span></li>
  <li><span>하드웨어</span></li>
  <li><span>네트워크</span></li>
</ul>

웹 브라우저에 아래처럼 표시된다.


탭 메뉴 1

CSS를 이용해서 ul, li 태그의 margin과 padding 값을 조정한다. 그리고 ul 태그의 list-style 속성 값을 none으로 한다.

ul {
  list-style: none;
  margin: 2em 1em;
  padding: 0;
}

li {
  margin: 0;
  padding: 1em 0.5em;
}

웹 브라우저에 아래처럼 표시된다.

li 태그의 display 속성 값을 inline으로 한다.

li {
  display: inline;
  margin: 0;
  padding: 1em 0.5em;
}


웹 브라우저에 아래처럼 표시된다.

li 태그에 border 속성을 준다.

li {
  border-bottom: 1px solid rgb(192, 192, 192);
  display: inline;
  margin: 0;
  padding: 1em 0.5em;
}


MS IE 6.0의 버그로 인해서 ul 태그 아래에 다른 태그가 없으면 선이 나타나지 않는다. 따라서 HTML을 아래처럼 수정한다.

<ul>
  <li><span>소프트웨어</span></li>
  <li><span>하드웨어</span></li>
  <li><span>네트워크</span></li>
</ul>

<div/>

 
모질라 파이어 폭스와 오페라에서는 아래 처럼 li 태그 사이에 간격이 생긴다.


이를 방지하기 위해서 아래처럼 li 태그 사이의 여백을 제거한다.
 
<ul>
  <li><span>소프트웨어</span></li
  ><li><span>하드웨어</span></li
  ><li><span>네트워크</span></li>
</ul>


선택한 탭 메뉴는 클래스 속성으로 표현한다.

<ul>
  <li><span>소프트웨어</span></li
  ><li class="selected"><span>하드웨어</span></li
  ><li><span>네트워크</span></li>
</ul>

아래와 같은 CSS 스타일을 추가한다.

li.selected {
  border: 1px solid rgb(192, 192, 192);
  border-bottom: none;
}

최종 결과는 아래와 같다.



탭 메뉴 2

배경 이미지를 이용해서 탭 메뉴를 수정한다.

앞의 예제에서 li 태그의 border 속성을 삭제하고 background 속성을 추가한다.

li {
  background: url("/resource/image/tab_off.gif") no-repeat;
  display: inline;
  margin: 0;
  padding: 1em 0.5em;
}

li.selected {
  background: url("/resource/image/tab_on.gif") no-repeat;
}


이미지를 이용했기 때문에 width 속성으로 넓이를 지정한다. 그리고 inline 요소는 넓이를 지정할 수 없기 때문에 display 속성을 삭제하고 float 속성의 값을 left로 지정한다. 그리고 좌우 padding 속성 값을 0으로 하고 텍스트를 가운데로 정렬한다.
 
li {
  background: url("/resource/image/tab_off.gif") no-repeat;
  float: left;
  margin: 0;
  padding: 1em 0;
  text-align: center;
  width: 78px;
}


2009-08-24

CSS 기본 설정

CSS 작성할 때 가장 먼저하는 것들이다.


웹 브라우저마다 다른 기본 값 초기화


block 유형 태그 기본 값이 웹 브라우저마다 다른 경우가 있다. 따라서 다음과 같이 border, margin, padding 등의 속성을 모두 0으로 설정한다.

html, body, form, ul, li, div, p, h1, h2, h3 {
  border: 0;
  margin: 0;
  padding: 0;
}

/*
html과 form에 대해서도 초기화를 해준다.
모든 태그를 초기화하지는 않고 실제로 사용할 태그들에 대해서만 초기화한다.
*/

예전에는 다음 방법을 사용한 적도 있는데 단점이 많았다.

* {
  border: 0;
  margin: 0;
  padding: 0;
}


이미지에 대한 외곽선 제거를 위한 설정

a img {
  border: 0;
}


테이블 작성

CSS와 HTML에 관심을 갖게된 계기가 table 목록이었다. 2003년 가을에 참여했던 프로젝트에서 웹 디자이너가 작성한 table 목록은 다음과 같았다.

  • table 태그 안에 table 태그를 넣고 첫번째 테이블 배경색으로 선을 표시한다.
  • 선과 글자 사이의 간격은 &nbsp;로 하는 것이었는데, 결과적으로 &nbsp;를 제대로 신경쓰지 않는 게으름이나 HTML 코드 상에서 태그와 글자 사이의 여백이나 줄 바꿈 등의 이유로 들죽날죽이었다.

그러다가 CSS padding 속성으로 이를 손쉽게 제어할 수 있다는 걸 알게 되면서 CSS와 HTML에 대한 관심을 가지게 되었다.



그 이후로 이런 저런 시행착오를 거쳐 지금 주로 사용하는 table 태그로 목록을 작성하는 간결한 방법은 다음과 같다. 우선 table 태그를 다음과 같이 작성한다.

<table>
  <thead>                       <!-- 목록 이름과 목록 내용을 thead와 tbody 태그로 명시적으로 구분 -->
    <tr>
      <th>Column 1</th>   <!-- 목록 이름에는 td 대신에 th 태그를 사용 -->
      <th>Column 2</th>
      <th>Column 3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Content 11</td>
      <td>Content 12</td>
      <td>Content 13</td>
    </tr>
    <tr>
     <td>Content 21</td>
     <td>Content 22</td>
     <td>Content 23</td>
   </tr>
  </tbody>
</table>


지금까지 작업 내용을 웹 브라우저로 보면 다음과 같다.
th와 td 태그에 선을 설정한다.

th, td {
  border: 1px solid silver;
}

이러면 선은 표시되지만 셀과 셀 사이에 여백이 보인다.
이 셀과 셀 사이 여백은 다음과 같이 제거한다.

table {
  border-collapse: collapse;
}

그리고 답답함을 없애기 위해서 셀에 여백을 준다.

th, td {
  border: 1px solid silver;
  padding: 4px 5px;
}

문자열이 긴 경우에는 셀 안에서 줄 바꿈이 일어나기 때문에 line-height 보다는 padding 속성으로 상하 여백을 설정한다.


그리고 목록 이름에 대해서 배경색을 준다.

thead {
  background: navy;
  color: white;             /* 배경색을 설정하면 글자 색도 함께 지정하는 것이 일반적이다. */
}


다음은 최종적인 모습이다.
table01.html

다운로드 편의를 위해서 HTML에 CSS를 포함시켰다.

2009-07-17

자바 2D 두선이 교차하는 지점

http://blog.persistent.info/2004/03/java-lineline-intersections.html


http://mathworld.wolfram.com/Line-LineIntersection.html

2009-07-15

웹 브라우저 버전 체크

클라이언트나 서버 프로그래밍에서 사용자 웹 브라우저 정보를 알아야 하는 경우가 있다. 이를 위한 방법이다.


자바 스크립트에서는 아래 함수를 사용한다.

function getBrowser() {
  var agent = navigator.userAgent;
  var result = "unknown";
  if (agent == null) {
  } else if (agent.indexOf("MSIE 6.0") > -1) {
    result = "ie6";
  } else if (agent.indexOf("MSIE 7.0") > -1) {
    result = "ie7";
  } else if (agent.indexOf("MSIE 8.0") > -1) {
    result = "ie8";
  } else if (agent.indexOf("Firefox") > -1) {
    result = "firefox";
  } else if (agent.indexOf("Opera") > -1) {
    result = "opera";
  } else if (agent.indexOf("Chrome") > -1) {
    result = "chrome";
  } else if (agent.indexOf("Safari") > -1) {
    result = "safari";
  }
  return result;
}


자바에서는 아래 메소드를 사용한다.

package com.dimdol.util;

import javax.servlet.http.HttpServletRequest;

public final class WebUtils {

  private WebUtils() {
  }

  public static String getBrowser(HttpServletRequest request) {
    String agent = request.getHeader("User-Agent");
    String result = "unknown";
    if (agent == null) {
    } else if (agent.indexOf("MSIE 6.0") > -1) {
      result = "ie6";
    } else if (agent.indexOf("MSIE 7.0") > -1) {
      result = "ie7";
    } else if (agent.indexOf("MSIE 8.0") > -1) {
      result = "ie8";
    } else if (agent.indexOf("Firefox") > -1) {
      result = "firefox";
    } else if (agent.indexOf("Opera") > -1) {
      result = "opera";
    } else if (agent.indexOf("Chrome") > -1) {
      result = "chrome";
    } else if (agent.indexOf("Safari") > -1) {
      result = "safari";
    }
    return result;
  }

}

Ruby on Rails에서는 아래 함수를 사용한다.

module ApplicationHelper

  def get_browser
    agent = request.env['HTTP_USER_AGENT']
    result = "unknown"
    if agent.nil?
    elsif agent.include?("MSIE 6.0")
      result = "ie6"
    elsif agent.include?("MSIE 7.0")
      result = "ie7"
    elsif agent.include?("MSIE 8.0")
      result = "ie8"
    elsif agent.include?("Firefox")
      result = "firefox"
    elsif agent.include?("Opera")
      result = "opera"
    elsif agent.include?("Chrome")
      result = "chrome"
    elsif agent.include?("Safari")
      result = "safari"
    end
    return result
  end

end


2009-07-02

MS SQL Server 2005 Express

SQL Server 2005 Express


SQL Server 2005 Management Studio Express


SQL Server JDBC Driver



[MSSQL] Microsoft SQL Server 2005 Express Edition 설치 및 사용후기

자바 스크립트 라이브러리

나중에 나온 jQueryPrototype보다는 조금은 우수한 API라는 평가가 있지만

익숙함으로 인해서 아직은 Prototype...

로그

Apache log4jApache Commons Logging을 사용하는 것이 고전적인 방법이기는 하지만

사용하는 라이브러리를 줄이기 위해서 Java Logging API를 사용하는 것을 권장한다.


* 톰켓을 사용하는 경우에는 톰켓 기본 설정 사용
* 동적으로 로깅 관련 설정을 변경할 수 있는가?

웹 디자인

PNG 사용을 검토한다. (IE 6.0에서는 사용할 수 없음)

Getting Creative With Transparency in Web Design

자바 플랫폼

Java SE 5.0 Update 19

Tomcat 6.0.20

Derby 10.5.1.1