2016년 5월 25일 수요일

Oracle database의 JDBC 사용에 필요한 url 정보에 대해





※ Oracle Database 11g Express Edition 중심으로



자바에서 Oracle DB를 사용할 때 JDBC 라이브러리를 사용하게 되는데 이때 JDBC를 사용하기 위해 몇가지 필요한 정보가 있다. 즉 JDBC를 통해 Oracle DB에 connection하기 위해 몇 가지 필요한 정보가 있다. 대표적으로
Oracle 사용자 계정에 대한 id, password...
그 중에서 Oracle database에 대한 url 정보가 있다.
대체로 다음과 같은 형태이다.

jdbc:oracle:thin:@localhost:1521:xe

이것이 무엇을 의미하는지에 대해서 살펴본다.
이에 대한 프로토타입은 다음과 같다.

jdbc:oracle:driver_type:[username/password]@[//]host_name[:port][/XE]

위의 프로토타입으로부터 아래 정보를 해석해 보면 다음과 같다.

jdbc:oracle:thin:@localhost:1521:xe

-. jdbc:oracle:thin은 사용하는 JDBC드라이버가 thin 타입을 의미한다. 자바용 오라클 JDBC드라이버는 크게 두가지가 있는데 하나는 Java JDBC THIN 드라이버고, 다른 하나는 OCI기반의 드라이버라고 한다.

-. username/password은 option이다. [ ]안에 있는 정보는 반드시 명기할 필요는 없다는 뜻이다.

-. :port 번호도 option이다. 다만 Oracle의 listener port인 1521을 사용하지 않을 경우는 이 값을 명기해 줘야 된다. 예를 들어서 jdbc:oracle:thin:hr/hr@//localhost:1522

-. localhost는 Oracle DB가 설치되어 있는 서버의 IP인데 위 경우는 로컬에 설치되어 있다는 뜻이다.

-. 1521 은 오라클 listener의 포트번호이다.

-. /XE는 Oracle database client의 고유한 service name이다. 디폴트로 XE를 사용하므로 이 정보도 option이다. 이에 대한 설정 정보는 Oracle이 설치된 폴더 아래의 app\oracle\product\11.2.0\server\network\ADMIN\listener.ora 파일에 다음과 같이 표시되어 있다.

DEFAULT_SERVICE_LISTENER = (XE)

2016년 5월 23일 월요일

JSP 쿠키(cookie) 설정에 한글을 사용할 경우 발생하는 에러 : Control character in cookie value or attribute





java.lang.IllegalArgumentException: Control character in cookie value or attribute.

위 에러는 JSP의 쿠키(cookie) 설정에 한글을 사용할 경우 발생하는 에러이다.
다음과 같은 JSP 코드가 있다고 가정하자.

<%@ page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>쿠키 설정</title>
</head>
<body>
<%
Cookie c = new Cookie("MemberID", "12345");
c.setMaxAge(60*60);
c.setComment("회원 ID");
response.addCookie(c);
%>
<p/>
<a href="GetCookie.jsp">쿠키 확인하기</a>
</body>
</html>

위 코드를 실행하면 

JSP java.lang.IllegalArgumentException: Control character in cookie value or attribute.라는 에러가 발생한다.
에러가 발생하는 위치는 한글을 사용한 
c.setComment("회원 ID")에서 에러가 발생한다.

해결할려면 한글을 utf-8로 인코딩한 값을 set하거나 Base64로 인코딩한 값을 set하면 된다. 
물론 쿠키를 받는 곳에서 동일한 인코딩 값으로 받아야 할 것이다.

2016년 5월 15일 일요일

추상 메소드(abstract method)의 목적, 용도, 쓰임새(추상 메소드를 만드는 이유)





인터페이스나 혹은 추상클래스에 있는 추상메소드의 목적
추상메소드에 대해 제대로 이해하기가 쉽지는 않는듯 하다.
추상메소드와 관련된 일반적인 '지식'에 해당되는 내용들은 얼마든지 있다.
그러나 이것이 어디에 쓰기위해 존재하는지에 대해서 명확한 정립이 되어있지 않으면 남들이 만들어 놓은 추상메소드를 코딩은 하지만 정작 내가 클래스를 만들면서 추상 메소드가 가진 목적을 발휘하는 그런 클래스를 디자인하고 만들어 쓰는데까지는 가지 못하는 것을 보게된다.
오늘은 추상 메소드(abstract method)가 존재하는 목적이 뭔지에 대해 뿌리를 캐보고자 한다.

가령 예를 들어서 우리가 어떤 디바이스를 켜는(power on) 행위(method)를 한번 생각해 보자.
power on에는 다양한 종류가 있을 것이다.
PC를 켜거나(Power On), 스마트폰을 켜거나, TV를 켜거나, ... 이럴 때 켤때마다 첫번째 초기 화면으로 그 제품을 만든 회사의 로고 이미지가 뜨도록 강제하고 싶을 경우가 있을 것이다.
PC를 켤때 삼성에서 만들었으면 삼성 로고가 뜨고 LG에서 만들었으면 LG 로그가 뜨고... 스마트폰도 마찬가지로...
이와같이 Power On 할때 초기 화면에 제조사 로고를 뜨도록 강제하고 싶을 경우 이때 이 목적을 위해서 존재하는 것이 추상 메소드(abstract method)이다.

이것을 클래스로 만들어 PowerOn이라는 클래스로 만들어보자. 
이때 PowerOn을 상속받는 하위 클래스들에서는 power on할 때(켤 때) 반드시 제조사의 로고 이미지를 뜨도록 강제하고자 하면 그에 해당하는 기능을 추상 메소드로 만들어 두면 하위 클래스에서는 반드시 로고 이미지가 뜨는 기능(method)을 만들어야만 되도록 되어 있다. 그렇지 않으면 컴파일 단계에서 에러를 발생시킨다. 따라서 그것을 상속 받는 하위 클래스에서는 무조건 로고 이미지 뜨는 기능을 구현해야만되고 이것은 하위 클래스들은 이 면에서 동일한 공통성을 띄게 강제하게 되는 결과가 된다.
말하자면 사용자들에게 동일한 인터페이스를 제공해 주게 되는 결과를 창출하게 된다.
이런 목적으로 존재하는 것인 추상 메소드이다.
예제 코드를 만들어 보자.

abstract class PowerOn
{
//하위 클래스들은 무조건 로고를 띄우는 기능을 만들도록 하고 싶다.
//그럴 경우 로고를 띄우는 메소드를 추상메소드로 만들면 된다.
abstract void showLogo(); 

public String getName() {
...
return name;
}
}


class SamsungPhone extends PowerOn
{
public void showLogo() {
//여기서 삼성 로그 띄우게
}
}

class LGPC extends PowerOn
{
public void showLogo() {
//여기서 LG 로그 띄우게
}
}

그래서 결론적으로 interface나 abstract class에 있는 abstract method의 목적은 어떤 특정 기능을(메소드를) 하위 클래스에서 반드시 만들도록 강제하고자 할때 사용하는 것이다.


그런 점에서 interface라는 것의 존재 목적이 보이는 것이다.
interface는 interface가 가지고 있는 모든 메소드는 전부 abstract 메소드이다.
추상 메소드(abstract 메소드)의 목적은 하위 클래스에 특정 기능을 반드시 만들도록 강제하고자 하는 것이 그 목적이다.
그로 인해 창출되는 결과(효과)는 하위 클래스들은 모두가 특정 기능(메소드)이 다 공통적으로 존재하게 된다는 점이다. 따라서 사용자는 어떤 하위 클래스를 사용하더라도 동일한 사용자 인터페이스를 경험하게 되는 것이다.

따라서 abstract 클래스와 유사하게 interface는 그 이름 그대로 이 interface를 상속받는(구현하는 implements하는) 하위 클래스들은 모두가 공통된 기능들을 갖추게 된다. 즉 interface에 있는 메소드들을 모든 하위 클래스들은 모두다 그 기능을(그 메소드를) 만들어야 하므로 사용자는 특정 interface를 상속받은(implements한) 모든 하위 클래스들에서는 동일한 사용자 인터페이스를 경험하게될 것이다.

이것이 interface가 노리는 목적이다.