[Comparison] CHAR와 VARCHAR (VARCHAR2)

CHAR와 VARCHAR (VARCHAR2)


문자의 경우 CHAR와 VARCHAR의 차이는 저장 영역과 문자열의 비교 방법이다.

VARCHAR 유형은 가변 길이이므로 필요한 영역은 실제 데이터 크기뿐이다. 그렇기 때문에 길이가 다양한 컬럼과, 정의된 길이와 실제 데이터 길이에 차이가 있는 컬럼에 적합하다. 저장 측면에서도 CHAR 유형보다 작은 영역에 저장할 수 있으므로 장점이 있다.


비교 방법에서도 차이가 있다.

CHAR 에서는 문자열을 비교할 때 공백을 채워서 비교하는 방법을 사용한다. CHAR(8) 이고 'AA'가 저장되어 있다면, 'AA' 뒤에 공백 6자리를 붙여 8자리로 비교하는 것이다. 따라서  'AA' = 'AA  ' 은 실제로 'AA      ' = 'AA      ' 가 되어 같다는 결과가 나온다.


반면에 VARCHAR 에서는 공백도 하나의 문자로 취급하므로 끝에 공백이 들어가면 다른 문자로 판단한다.

같은 예로 들면 'AA' != 'AA '  로 공백이 있어 서로 다른 문자로 판단한다.


따라서 이름, 주소 등의 길이가 변할 수 있는 값은 VARCHAR를 사용하고, 사번, 주민등록번호와 같이 길이가 일정한 데이터는 CHAR를 사용하는게 좋다. 

[Comparison] 추상메서드와 인터페이스


추상메서드와 인터페이스


1. 공통점

1) 둘 다 모두 추상 메소드라는 것을 가진다. 구현 클래스에서는 반드시 만들어야만하는 강제성을 가진다. 또한 추상 메소드는 컴파일러를 속인다. 

추상 클래스는 변수를 인터페이스나 부모 클래스 타입으로 보았을 때 아무런 호출에 문제를 일으키지 않는다. 

따라서 컴파일러는 실제로 메소드가 어떻게 동작할지는 모르고, 아무 문제 없이 실행해준다. 즉 컴파일러를 속여서 내가 원하는 동작을 마음대로 조종하게 한다는 것이다.


2) 둘 다 객체 생성은 불가능하고, 타입으로만 사용된다.

추상 클래스와 인터페이스 둘 다 객체의 생성이 목적인 클래스가 아니라. 변수나, 파라미터, 리턴 타입, 자료구조를 유연하게 쓰기 위한 도구이다.


2. 차이점

1) 인터페이스는 스펙이나 원하는 기능을 정의하고자 쓰지만, 추상 클래스는 ‘상속+강제성’이 목적이다.

인터페이스각 객체 간의 통신을 위해서 사용되는 반면에 추상 클래스는 본연의 상속 기능에 강제성을 추가하는 것이 목표로, 만들어진 시작점이 다르다는 것이다.


2) 인터페이스는 상수, 추상 메소드만 존재하지만, 추상 클래스는 상속이 원래 목적이므로 실제 변수나 메소드를 그대로 가지고 있다.

인터페이스는 상호 간의 규칙이기 때문에 private으로 변수를 선언할 수도 없고 선언된 변수는 자동으로 상수로 처리된다. 반면에 추상 클래스는 상속의 수단이기 때문에 상속의 본연의 기능을 그대로 가지고 있다. 따라서 공통적인 메소드나 변수를 부모 클래스로 모아서 사용할 수 있다.


3) 인터페이스는 부채만 남겨주지만, 추상 클래스는 재산도 남겨 준다. 인터페이스는 추상 메소드만 존재하기 때문에 부채만 잔뜩 던져주게 되지만 추상 클래스는 상속의 원래 기능을 그대로 사용할 수 있다는 얘기이다.


4) 인터페이스는 다중 상속도 가능하지만, 추상 클래스는 단일 상속만 된다. 추상 클래스는 상속이 본 목적이므로 기존 상속처럼 단일 상속만 가능하다.


[Comparison] 후손 선택자와 자식 선택자


후손 선택자와 자식 선택자 


<!DOCTYPE html>

<html>

<head>

    <title>CSS3 Selector Basic</title>

    <style>


    </style>

</head>

<body>

    <div>

        <h1>CSS3 Selector Basic</h1>

        <h2>Lorem ipsum</h2>

        <ul>

            <li>universal selector</li>

            <li>type selector</li>

            <li>id & class selector</li>

        </ul>

    </div>

</body>

</html>

이때 div 태그를 기준으로 바로 한 단계 아래에 위치한 태그를 자식(h1, h2, ul)이라고 부르고,

div 태그 아래에 위치한 모든 태그를 후손(h1, h2, ul, li)이라고 한다.

-->  후손이 자식보다 포괄적이다.


1. 후손 선택자

후손 선택자는 특정한 태그 아래에 있는 후손을 선택할 때 사용하는 선택자이다.

(1) 선택자 형태

선택자A 선택자B

ex.) #header h1, h2  { color: red; }

      #header h1, #header h2  { color: red; }


(2) 설명

선택자A의 후손에 위치하는 선택자B를 선택한다.

--> 후손 선택자를 사용해 h1 태그를 선택하지만 특정한 대상의 후손을 선택할 수 있다.


2. 자식 선택자

자식 선택자는 특정한 태그 아래에 있는 자식을 선택할 때 사용하는 선택자이다.

(1) 선택자 형태

선택자A > 선택자B 

ex.) #header > h1  { color: red; }


(2) 설명

선택자A의 자식에 위치하는 선택자B를 선택한다.


[Comporison] 언어환경별 문자열 추출


언어환경별 문자열 추출


1. Java

substring(시작 인덱스 , 종료 인덱스)


"hamburger".substring(4, 8);

--> "urge" 

"smiles".substring(1, 5);

--> "mile"


2. JavaScript

(1) substring

substring(시작인덱스, 종료인덱스);


var string='19860711';

var year=string.substring(0,4); 

--> 1986

var month=string.substring(5,7);

--> 07

var day=string.substring(8,10);

--> 11


(2) substr

substr(시작인덱스, 자르고 싶은 길이)


var string='19860711';

var year=string.substr(0,4);

--> 1986

var month=string.substr(5,2);

--> 07

var day=string.substr(8,2);

--> 11


3.Oracle

substr(대상[문자열], 시작인덱스, 자르고 싶은 길이)


SELECT SUBSTR('나는 대한민국 사람입니다.',1,7) COUNTRY FROM DUAL;


COUNTRY

-----------

나는 대한민국


4. MySQL

MySQL에서 substr 함수는 문자열의 일부를 추출하는 함수로 substring 함수의 동의어입니다.

substring(대상[문자열], 시작인덱스, 자르고 싶은 길이)

substr(대상[문자열], 시작인덱스, 자르고 싶은 길이)


SELECT SUBSTRING('habonytest', 5);

--> nytest

SELECT SUBSTRING('habonytest', 3, 2);

--> bo

SELECT SUBSTRING('habonytest', FROM 2);

--> abonytest


음수는 끝자리에서 수를 카운터합니다.

SELECT SUBSTRING('habonytest', -3);

--> est

SELECT SUBSTRING('habonytest', -5, 2);

--> yt

SELECT SUBSTRING('habonytest', FROM -5 FOR 4);

--> ytes


cf.) substring_index 함수

이 함수는 substr 함수와 기능은 비슷하지만 구분자가 있습니다. str 문자열에 delim 구분자를 기준으로 count 수 만큼 반환받습니다. 음수이면 뒤에서 카운터합니다.

SELECT SUBSTRING_INDEX(str, delim, count);

. 를 기준으로 2개를 반환받습니다.

SELECT SUBSTRING_INDEX('www.php.net', '.', 2);

--> www.php

SELECT SUBSTRING_INDEX('www.php.net', '.', -2);

--> php.net

SELECT SUBSTRING_INDEX('myid@domain.com', '@', -1);

--> domain.com

SELECT SUBSTRING_INDEX('myid@domain.com', '@', 1);

 --> myid



[Comporison] Dispatcher방식과 Redirect 방식


Dispatcher방식과 Redirect 방식

서블릿에서 특정 URL이나 페이지로 이동하게 하는 두 가지 방식이 있는데, 두 방식의 차이점에 대해 알아보자.


1. Dispatcher방식 -->forward()

forward()[전달하기]는 클라이언트가 요청하면서 전송한 데이터를 그대로 유지한다.


(1) 예제

RequestDispatcher dispatcher = request.getRequestDispatcher("dispatcher.jsp");

      request.setAttribute("request","requestValue");

     dispatcher.forward(request, response);


dispatcher.jsp

request 속성 값 : <%=request.getAttribute("request") %>

포워딩이 되더라도 주소가 변경되지 않는다. (같은 request영역을 공유하게 됨)


1) 송신 

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;


public class Round14_06_Servlet extends HttpServlet {

public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

request.setCharacterEncoding("euc-kr");

//한글 변환 Encode 설정

String area = request.getParameter("area");

//지역 정보만 먼저 가져온다.

ServletContext context = this.getServletContext();

//서블릿 환경 객체의 값을 획득한다. 이 객체가 있어야 RequestDispatcher 객체를 생성할 수 있다.


RequestDispatcher dispatcher = null;

response.setContentType("text/html;charset=euc-kr");

PrintWriter out = response.getWriter();

out.println("<html><body>");

out.println("서울 지역 관련 정보<br/>");

dispatcher = context.getRequestDispatcher("/Servlet06_Seoul");

dispatcher.include(request, response);

//서울 지역 관련 정보를 include 한다.

out.println("<br/><br/>");

out.println("대구 지역 관련 정보<br/>");

dispatcher = context.getRequestDispatcher("/Servlet06_Taegu");

dispatcher.include(request, response);

//대구 지역 관련 정보를 include 한다.

out.println("</body></html>");

out.close();


if(area == null) { //라디오 버튼 체크를 하지 않았다면

response.sendError(512, "라디오 버튼 체크 오류!!!");

return;

}

else if(area.equals("서울")) { //서울 지역을 체크 했다면

dispatcher = context.getRequestDispatcher("/Servlet06_Seoul");

//서울 지역에 대한 서블릿으로 위치를 이동할 수 있도록 객체 생성

}

else if(area.equals("대구")) { //대구 지역을 체크 했다면

dispatcher = context.getRequestDispatcher("/Servlet06_Taegu");

//대구 지역에 대한 서블릿으로 위치를 이동할 수 있도록 객체 생성

}

dispatcher.forward(request, response);

//설정된 Dispatcher로 요청과 응답 권한을 넘기는 작업

}

}


(2) 수신

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;


public class Round14_06_Seoul_Servlet extends HttpServlet {

public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

request.setCharacterEncoding("euc-kr");

//넘어온 데이터에 대한 POST 방식 한글 처리

String name = request.getParameter("name");

String id = request.getParameter("id");

String pw = request.getParameter("pw");

String area = request.getParameter("area");

//forward에 의해 이동이 이루어 지면 request 영역은 

//보존되기 때문에 그대로 데이터를 추출해 낼 수 있다.

response.setContentType("text/html;charset=euc-kr");

PrintWriter out = response.getWriter();

out.println("<html><body>");

out.println("그러므로 당신의 이름이 " + name);

out.println("이라는 말이고,<br/>");

out.println("당신이 사용하려는 아뒤가 " + id);

out.println("라는 말인가?");

out.println("</body></html>");

//out.close();

}

}


2. Redirect 방식 --> sendRedirect()

Redirect()[이동하기]는 새로운 페이지로 완전히 이동해서 기존 데이터를 하나도 사용할 수 없다.


request.setAttribute("request", "requestValue");

response.sendRedirect("redirect.jsp");


 redirect.jsp

 request 속성 값 : <%=request.getAttribute("request") %> // null

포워딩될 때 브라우저의 주소 표시줄의 URL이 변경된다. 포워딩된 jsp페이지에서는 서블릿에서 request영역에 공유한 속성값에 접근 할 수 없다.


(1) 예제

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;


public class Round14_05_Servlet extends HttpServlet {

public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

//한글 데이터가 없기 때문에 Encode 설정 하지 않음.

String method = request.getMethod();

//요청 메서드를 얻어내는 작업

if(method.equalsIgnoreCase("GET")) {

//요청 방식이 GET이라면

response.sendRedirect("http://localhost:8080/Round14/Round14_05_Get_Servlet.htm");

//Round14_05_Get_Servlet.htm으로 이동한다.

return;

}

else if(method.equalsIgnoreCase("POST")){

//요청 방식이 POST라면

response.sendRedirect("Round14_05_Post_Servlet.htm");

//Round14_05_Post_Servlet.htm으로 이동한다.

return;

}

}

}



[Comparison] include 지시어와 include 액션원소


include 지시어와 include 액션원소


1. include 지시어 <%@ include file="~"%>

include 지시어는 다른 파일의 내용을 현재 위치에 삽입한 후 JSP 파일을 자바 파일로 변환하고 컴파일 하는 방식이다. 즉, include 지시어는 포함시키려는 파일의 코드 자체가 현재 페이지에 포함되어서 하나의 서블릿으로 컴파일된다. include 지시어를 사용하면, JSP 파일을 자바 파일로 변환하기 전에 include 디렉티브에서 지정한 파일의 내용을 해당 위치에 삽입하고, 그 결과로 생긴 자바 파일을 컴파일하게 된다.


2. include 액션 원소 <jsp:include ~ />

include 액션 원소는 다른 JSP로 흐름을 이동시켜 그 결과물을 현재 위치에 포함시키는 방식이다.

일반적으로 include 액션 원소는 레이아웃의 한 구성 요소를 모듈화 하기 위해 사용된다. include 액션 원소는 포함시키려는 페이지의 실행 결과만 가져오기 때문에 실제 서블릿으로 변환될때 에는 따로 작성된다.


따라서, 변수를 공유할 때에는 include 지시어를 사용해야 한다. include 액션 원소는 파일이 따로 작성되기 때문에 변수를 공유할 수 없다.

그러나 include 지시어와는 달리 동적인 변화가 많은 페이지는 include 액션 원소를 사용하는 것이 바람직하다.



비교항목 

include 지시어

include 액션 원소 

 처리시간

 요청 시간에 처리

 JSP 파일을 자바 소스로 변환할 때 처리 

기능 

 별도의 파일로 요청 처리 흐름을 이동

 현재 파일에 삽입시킴 

데이터 전달 방법 

 request 기본 객체나 <jsp:param>을 이용한 파라미터 전달 

 페이지 내의 변수를 선언한 후, 변수에 값 저장 

용도 

 화면의 레이아웃의 일부분을 모듈화 할 때 주로 사용된다. 

 다수의 JSP 페이지에서 공통으로 사용되는 변  수를 지정하는 코드나 저작권과 같은 문장을 포  함한다. 




[Comporison] LEFT JOIN 과 RIGHT JOIN


LEFT JOIN 과 RIGHT JOIN


left, right등의 outer join은 기준이 되는 테이블이 무엇이냐에 따른 것입니다.

결과가 왼쪽 테이블 전체 데이터 대상이라면 left를 ,오른쪽 테이블의 전체 데이터가 대상이라면 right를 사용합니다.


1. 조인 대상 테이블


(1) EMP 테이블

SELECT * FROM  EMP;


(2) DEPT 테이블

SELECT * FROM DEPT;


2.  LEFT JOIN 과 RIGHT JOIN 차이


(1) [ A left join B on (a.id = b.id) ]


LEFT OUTER JOIN은 오른쪽 테이블(아래 예제에서 emp테이블)에 조인시킬 컬럼의 값이 없는 경우 사용한다.

SELECT * FROM dept d LEFT OUTER JOIN emp e ON d.deptno = e.deptno; 

A(왼쪽) 테이블과 B(오른쪽) 테이블을 조인을 걸건데, B테이블에 A테이블과 맵핑되는 값이 있건 없건 A의 값은 반드시 모두 나오게 됩니다.

(outer는 적어도 그만 안 적어도 그만이지만, 명시적으로 적어주는 것이 좋습니다 .^^)


위의 결과를 보면, A 에 있는 모든 값이 나오고,B와 맵핑 되지 않는 값은 NULL 이 됨을 볼 수 있습니다.

 

(2) [ A right join B on (a.id = b.id) ]


RIGHT OUTERL JOIN은 왼쪽 테이블(아래 예제에서 emp테이블)에 조인시킬 컬럼의 값이 없는 경우 사용한다.

SELECT * FROM dept d RIGHT OUTER JOIN emp e ON d.deptno = e.deptno; 

B(오른쪽) 테이블을 기준으로 A(왼쪽) 테이블을 조인 거는 경우입니다.

이럴 경우도 left 와 마찬가지로 생각해본다면, B테이블의 전체값이 결과로 나올 것이고, A 테이블의 값은 있으면 나오고 없으면 안나온다.


[Comporison] PreparedStatement 와 Statement


PreparedStatement 와 Statement


PreparedStatement 와 Statement의 가장 큰 차이점은 캐시(cache) 사용여부이다.

1) 쿼리 문장 분석

2) 컴파일

3) 실행


Statement를 사용하면 매번 쿼리를 수행할 때마다 1) ~ 3) 단계를 거치게 되고, PreparedStatement는 처음 한 번만 세 단계를 거친 후 캐시에 담아 재사용을 한다는 것이다. 만약 동일한 쿼리를 반복적으로 수행한다면 PreparedStatment가 DB에 훨씬 적은 부하를 주며, 성능도 좋다.



1. Statement 

String sqlstr = "SELECT name, memo FROM TABLE WHERE num = " + num 

Statement stmt = conn.credateStatement(); 

ResultSet rst = stmt.executeQuerey(sqlstr); 

sqlstr를 실행시 결과값을 생성

Statement  executeQuery() 나 executeUpdate() 를 실행하는 시점에 파라미터로 SQL문을 전달하는데, 이 때 전달되는 SQL 문은 완성된 형태로 한눈에 무슨 SQL 문인지 파악하기 쉽다. 하지만, 이 녀석은 SQL문을 수행하는 과정에서 매번 컴파일을 하기 때문에 성능상 이슈가 있다. 


2. PreparedStatement 

String sqlstr = "SELECT name, memo FROM TABLE WHERE num = ? " 

PreparedStatement stmt = conn.prepareStatement(sqlstr); 

pstmt.setInt(1, num);

ResultSet rst = pstmt.executeQuerey(); 

sqlstr 은 생성시에 실행

PreparedStatement 은 이름에서부터 알 수 있듯이 준비된 Statement 이다. 이 준비는 컴파일(Parsing) 을 이야기하며, 컴파일이 미리 되어있는 녀석이기에 Statement 에 비해 성능상 이점이 있다. 요 녀석은 보통 조건절과 함께 사용되며 재사용이 되는데, ? 부분에만 변화를 주어 지속적으로 SQL을 수행하기 때문에 한눈에 무슨 SQL 문인지 파악하기는 어렵다.


2.와 같이 이용할 경우 해당 인자만 받아서 처리하는 구조로 갈 수 있는것입니다.내부적으로 상세하게 뜯어 보지는 않았지만, 2.는 생성시 메모리에 올라가게 되므로 동일한 쿼리의 경우 인자만 달라지게 되므로, 매번 컴파일 되지 않아도 된다는 결론이 날듯 합니다. 


3. API

(1) Preparedstatement

public interface PreparedStatement extends Statement 

프리컴파일 된 SQL 문을 나타내는 오브젝트입니다. PreparedStatement 는 Statement를 상속받고 있습니다. 

SQL 문은 프리컴파일 되어 PreparedStatement 오브젝트에 저장됩니다. 거기서, 이 오브젝트는 이 문장을 여러 차례 효율적으로 실행하는 목적으로 사용할 수 있습니다. 


(2) Statement

public interface Statement 

정적 SQL 문을 실행해, 작성된 결과를 돌려주기 위해서(때문에) 사용되는 오브젝트입니다. 

디폴트에서는 Statement 오브젝트 마다 1 개의 ResultSet 오브젝트만이 동시에 오픈할 수 있습니다. 따라서, 1 개의 ResultSet 오브젝트의 read가, 다른 read에 의해 끼어들어지면(자), 각각은 다른 Statement 오브젝트에 의해 생성된 것이 됩니다. Statement 인터페이스의 모든 execution 메소드는 문장의 현재의 ResultSet 오브젝트로 오픈되고 있는 것이 존재하면, 그것을 암묵에 클로우즈 합니다. 

그리고 FOR 문등을 통하여 동일한 SELECT 를 여러번 실행해야 하는 경우에는, 그 사용성에 볼때 2번이 훨씬 효과적이라고 볼 수 있습니다. 


(3) 예제

1) Statement 

String sqlstr = null; 

Statement stmt = null; 

ResultSet rst = null; 


FOR(int i=0; i< 100 ; i++){ 

sqlstr = "SELECT name, memo FROM TABLE WHERE num = " + i 

stmt = conn.credateStatement(); 

rst = stmt.executeQuerey(sqlstr); 


2) PreparedStatement

String sqlstr = null; 

PreparedStatement pstmt = null; 

ResultSet rst = null; 


sqlstr = "SELECT name, memo FROM TABLE WHERE num = ? " 

pstmt = conn.prepareStatement(sqlstr); 


FOR(int i=0; i< 100 ; i++){ 

pstmt.setInt(1, i); 

rst = pstmt.executeQuerey(); 

}


4. PreparedStatement를 사용해야 하는 경우

(1) 사용자 입력값으로 쿼리를 생성하는 경우 

사용자에의해 입력되는 값을 가지고 SQL 작업을 할 경우 statement를 사용한다면 다음과 같이 될 것이다.

String content = request.getParameter("content");

stmt= conn.createStatement();

stmt.executeUpdate("INSERT INTO TEST_TABLE (CONTENT) VALUES('"+content+"');


사용자가 제대로 입력 하였다면 상관 없지만 content값에 "AA'AA"를 입력하였다면?

stmt.executeUpdate("INSERT INTO TEST_TABLE (CONTENT) VALUES('"+content+"'); 에서 에러가 발생할 것이다.

즉 SQL문은 다음과 같이 되는 것이다. INSERT INTO TEST_TABLE (CONTENT) VALUES('AA'AA');


이를 다음과 같이 수정한다면 위와같은 에러나 장애를 원천적으로 봉쇄할 수 있다

pstmt = conn.preapreStatement("SELECT * FROM TEST_TABLE WHERE CONTENT = :content");

pstmt.setString(1, content);

pstmt.executeUpdate();

이는 content값이 "'"가 들어왔다 하더라도 알아서 파싱 해주기 때문이다.

고로 사용자 입력 값으로 쿼리를 바인딩 할 경우에는 필히 pstmt를 사용하도록 하자! :)


(2) 쿼리 반복수행 작업일 경우

일반적으로 반복 수행 작업을 할 경우 아래와 같이 코딩 하게 된다.

1) Statement 사용

for (int i = 0; i < 100000; i++) {

stmt.executeUpdate("INSERT INTO TEST_TABLE VALUES('"+content+"');

}


2) PreparedStatement 사용

pstmt = conn.preapreStatement("INSERT INTO TEST_TABLE VALUES(?)"); <--- ⓐ

for (int i = 0; i < 10000; i++) {

pstmt.setString(1, content+i);

pstmt.executeUpdate();

}

종종 실수로 ⓐ번 문장이 for문으로 들어가는것을 보게된다! 주의!


cf.) DB의 종류에 따라 상황이 달라진다.

일반적으로 위와같은 코딩을 할 경우 2)경우가 1)보다 더 낳은 성능을 보인다고 알려져 있다. 즉 자바의 PreparedStatement의 사용은 오라클 DB에서 bind변수를 사용하도록 함으로 해서 DB서버에 미리 준비된 SQL을 사용하게 되고 파싱과정을 생략하기 때문에 결국 DB리소스를 효율적으로 사용하도록 하는 방법이 된다.

하지만 이것이 DB서버에 따라 다르다. MySql같은 경우는 1)과2)의 성능차이가 거의 나지 않는다.


--> 적당한 PreparedStatement의 사용

위와같은 이유로 PreparedStatement가 좋다! 모든 쿼리를 PreparedStatement로 하자! 만약 이와 같이 된다면 또다른 문제가 생긴다. 각 DB마다 SQL캐싱할 수 있는 한계가 있기 때문에 정작 성능상 캐싱되어야 할 쿼리가 그렇지 않은 쿼리 때문에 캐싱이 안 될 수 있기때문에 꼭 필요한 문장만 PreparedStatement를 쓰는것을 권고한다.


5. Statement를 받드시 사용해야 하는 경우

(1) Dynamic SQL을 사용할 경우

Dynamic SQL을 사용한다면 매번 조건절이 틀려지게 됨으로 statement가 낳다. 즉 캐싱의 장점을 잃어버립니다. 또한 Dynamic SQL일 경우 코딩도 Statement가 훨신 편하다.




[Comparison] 웹 서버와 웹 어플리케이션 서버


웹 서버와 웹 컨테이너 서버


웹서버와 JSP컨테이너는 별개라고 할수도 아니라고 할수도 있다. 대부분 JSP로 만들어진 사이트는 웹서버와 JSP컨테이너를 탑재하고 있는 WAS를 연동해 사용하기 때문이다.


쉽게 말하면 웹서버가 하는 일은 html,img등 일반 웹문서를 사용자에게 보여주는 역할만을 하지만, JSP컨테이너를 탑재하고 있는 WAS(Web Application Server)는 JSP를 컴파일하여 실행한 결과를 html으로 만들어 보여준다.웹서버만 구축되어 있는 서버는 웹페이지,이미지,영상등을 전달해 줄수는 있지만, JSP페이지를 컴파일해 동적인 페이지를 생성하지는 못한다. 이를 위해서는 JSP컨테이너가 탑재되어 있는 WAS가 필요한 것이다. 웹 서버는 웹문서를, WAS는 JSP 페이지를, 이런식으로 양분하여 역할분담을 함으로 서버에 부담되는 양을 줄이고자 함이다. 


웹 서버 : 정적인 처리 담당 html, 이미지등     ex)아파치

웹 어플리케이션 서버  (WAS) : jsp, 서블릿 담당(동적처리)   ex)톰켓

톰켓은 was의 기능 뿐만아니라 일반적인 html 이미지 처리도 가능, 굳이 둘을 분리해서 쓰는 이유는 속도면에서 분리하는게 조금더 빠르고 프록시를 이용하여 보안을 강화할 수 있음


1. 웹 서버

인터넷 웹브라우저의 요청이 들어오면 그에 해당하는 웹페이지를 찾아서 보내주는 일을 하는 컴퓨터를 지칭한다.

정확히 표현하면 인터넷 사용자의 URL요청을 받아서 그에 해당하는 웹페이지(HTML문서나 이미지)를 찾아서 다시 웹브라우저로 보내주는 것이다.


2. 웹어플리케이션 서버(WAS)

웹어플리케이션 서버는 웹서버에 웹어플리케이션을 합친 것이다.

우리가 웹페이지를 볼때 화면이 동적일 때가 있을 것이다. 동적이란 말은 이를테면 특정 URL을 요청했을 때 뉴스페이지 같은 곳에서는 각각의 기사에 대하여 다른 기사제목과 내용들이 표시 되는일들을 말하는데 정적인 웹 서버로는 이것을 처리가 불가능하다. 웹 서버가 웹어플리케이션 프로그램을 호출해야 가능한 일이다. JSP같은 기술이 웹어플리케이션의 역할을 담당한다.


3. 웹 컨테이너

웹어플리케이션을 실행해주는 도구이다. 웹어플리케이션이 JSP나 서블릿인데 이것을 실행 가능하게끔 해주는 것을 말한다. JSP를 해본 개발자라면 알 것이다. 톰캣이 웹컨테이너의 역할을 한다. 웹 어플리케이션을 실행할 수 있는 컨테이너. JSP, 서블릿을 해석할 수 있는 웹 서버


cp.) 웹 컨테이너란?

JSP와 서블릿을 사용한 웹 서버는 크게 URL 주소의 해석을 맡아 주는 HTTP 서버와 서블릿 클래스 또는 JSP 파일의 실행 요청을 처리해주는 웹 컨테이너(Web Container)로 구성된다. HTTP 서버는 단순히 어떤 주소(URL) 요청이 들어왔을 경우 그 주소에 미리 매핑되어 있는 콘텐츠(HTML 파일이나 이미지 등)를 사용자의 브라우저에 응답 형태로 전송하는 역할을 한다. 이 때 만일 요청된 URL이 서블릿 클래스 또는 JSP파일(ex. http://www.sevlet.com/servlet 또는 http://www.wervlet.com/home.jsp)일 경우 HTTP 서버는 이를 웹 컨테이너에서 처리하도록 클라이언트의 요청을 넘겨준다. 웹 컨테이너에서는 요청된 URL에 맞는(미리 설정된) 서블릿 클래스 또는 JSP 파일을 실행하여 그 결과를 HTTP 서버에 넘겨주게 되고 이는 응답 메시지의 형태로 사용자의 브라우저에 전성된다. 

즉 웹 컨테이너란 웹 서버의 내부에서 서블릿 클래스 또는 JSP 파일을 실행하기 위한 실행 환경을 제공하는 역할을 하며 특히 서블릿 클래스에 대한 웹 컨테이너를 서블릿 컨테이너, JSP 파일에 대한 웹 컨테이너를 JSP 컨테이너라고 한다. 다만 실제적으로 이 둘을 혼용하여 웹 컨테이너(서블릿 컨테이너)로 통칭하는 경우가 많다. 대표적인 웹 컨테이너로 자카르타 톰캣, 웹로직, Resin 등이 있다.


[Comparison] 윈도우 32비트와 64비트


윈도우 32비트와 64비트


윈도우 비스타나, 세븐(7)의 경우 32비트(86x)와 64비트(64x)를 지원합니다. 그런데 왜 이렇게 둘로 나뉘어 있을까?

32비트와 64비트를 의미하는것은 한번에 데이터를 처리하는량을 말합니다. 

32비트운영체제는 32비트만큼 데이터를 전송하고 64비트는 한번에 64비트를 전송한다는것입니다. 32비트는 수학으로따지자면 2의 32제곱, 64비트는 2의 64제곱만큼의 데이터가 전송됩니다. 그래서 데이터 처리능력, 속도, 동작등이 32비트보다 64비트가 훨씬빠를수밖에없는 것 입니다.

32비트와 64비트를 나누는 이유는 램사용량입니다. 자기가가지고있는 램이 4GB이상이면 64비트를 써야할것이고 4GB이하이시면 32비트를 써야할것입니다.(구지 4GB아니더라도 64비트는 구동가능합니다)


1. 속도가빠른 64비트를 쓰지 왜 구지 32비트를 쓰는것인가?

이문제의 답은 호환성에 따라 달라집니다. 현재 나와있는 대부분의 프로그램들은 32비트 위주로 개발되어있기때문에 64비트 운영체제에서는 32비트프로그램이 실행이 안되죠, 32비트가 64비트보다 처리속도과 동작속도가 느리지만 안정적으로 사용할수있기때문에 32비트를 쓰는것입니다.


2. 64비트를 쓰는 이유는 무엇인가?

여러가지 이유가 있을수있지만 대부분 이유는 메모리 용량때문입니다. 32비트 운영체제에서는 램을 3.9GB정도까지 인식을 하기 때문에 4GB이상의 램을끼워도 4GB전체를 읽지못하기때문에 별필요가 없는것입니다. 하지만! 64비트운영체제에서는 약100GB정도까지 인식이가능합니다 그렇기 때문에 4GB이상이신분들이 64비트를 쓰는이유입니다!


3. 64비트 운영체제를 사용하기위한 기본사양

Windows 7의 기준으로 하자면 64비트를 지원하는 3.0Ghz듀얼코어이상 프로세서 CPU, 3GB이상의 램, 10GB정도의 하드디스크 여유공간, DVD읽기와 쓰기를 지원하는 드라이브, Windows Aero사용가능한 그래픽카드와 64비트전용 드라이버가 필요합니다.


4. 64비트를 쓰면 32비트프로그램을 못쓰는가?

Windows 7 64비트의경우 WOW64라는 프로그래밍기술이 적용되었기때문에 32비트에서 사용하던 프로그램을 64비트에서도 실행가능합니다. Windows 7 64비트를 설치하시면 Program Files폴더가 두개있습니다.

하나는 'Program Files' 또다른 하나는 'Program Files(86x)' 86x가 붙여져 있지 않은것은 64비트 프로그램 설치공간이고 86x라고 되어있는 것은 32비트프로그램 설치공간입니다. 

만약 64비트만 지원하는 프로그램이면 Program Files에 설치가되고 32비트만 구동되는프로그램이라면 Program FIles(86x)에 저장됩니다. 32비트와 64비트 모두지원한다면 두개의폴더중 아무곳에 설치가 됩니다.


5. 조언글

왕복4차선과 8차선은 동시에 소화할 수 있는 교통량의 차이가 있습니다. 이론상으로는 두배의 차이가 나지만, 실제적으로는 그렇게 많은 차이는 아니고 약 50%정도 더 많이 소화할 수 있지요. 32비트와 64비트도 마찬가지라고 보시면 됩니다. 4차선도로에 맞는 신호체계를 8차선 도로에 그대로 적용하면 문제가 발생하지요. 따라서 8차선 도로에는 신호체계도 바꿔야합니다. 

보행자 신호도 더 길어져야하고, 차량 신호도 더 길어져야 합니다.

마찬가지로 32비트에서 64비트로 넘어가면서 하드웨어의 구조가 바뀌었으므로 소프트웨어도 바뀌어야합니다. 일례로 하드웨어가 잘 작동하도록 하는 드라이버도 32비트와 64비트는 달라야합니다. 그래서 32비트 드라이버를 64비트 환경에 설치할 수 없습니다.

뿐만 아니라 소프트웨어도 변경이 되어야합니다. 문제는 32비트에서 64비트로 넘어갈때의 시간이 오래 걸리고 있다는 것이지요. 32비트 환경이 10년이 넘은 상황에서 IT 환경도 엄청나게 바뀌었습니다. 그리고 거의 대부분이 32비트에 맞춰진 지금 "64비트가 좋으니 64비트로 다 바꾸자!"라고 해도 그 시간과 비용이 많이 필요하기 때문에 손바닥 뒤집듯히 휙하고 바꾸지 못하는 것이지요.

그래서 운영체제인 윈도우도 32비트와 64비트가 따로 나오고 있으며, 하드웨어도 두가지를 동시에 지원하도록 설계되고 있습니다. 물론 64비트 운영체제를 설치한다고 해서 32비트 소프트웨어를 사용할 수 없는 것은 아닙니다. 하위호환을 보장해서 현재의 환경에서 사용해도 문제가 없도록 하고 있지요. 

그럼 구태여 32비트에서 64비트로 넘어갈 필요가 없는거냐고 물으실 분들이 많습니다. 여기에 대한 제 답변은 "네. 넘어갈 필요 없습니다"입니다.

현재의 32비트와 64비트의 컴퓨팅 속도 차이는 거의 없습니다. 단 일례적으로 64비트 전용 소프트웨어에서는 더 속도가 빠르지요.

예를 들어서 이번에 새로 나온 어도비 CS5의 제품들중 일부는 64비트 전용으로 개발된 것이 있습니다. 이들 프로그램은 64비트 환경에서 제대로 그 성능을 발휘합니다.

64비트 환경은 더 많은 물리적 메모리를 지원하며, 더 많은 동시처리능력을 갖춥니다. 사진이나 동영상 편집등 많은 물리메모리를 필요로 하는 작업에서 64비트 환경은 더 나은 컴퓨팅을 보장합니다.따라서 강력한 컴퓨팅 환경을 필요로 하는 전문가들에게는 64비트 환경이 더 좋은 것입니다. 반면 그렇게까지 강력한 컴퓨팅을 필요로 하지 않는 분들에게는 32비트 환경으로도 충분한 것 입니다. 단순히 32비트에서는 3GB이상의 메모리를 지원 안하니까 64비트를 쓴다는 것은 어찌보면 낭비입니다. 중요한 것은 "자신이 무엇을 할 것이냐"입니다.