https://jeong-pro.tistory.com/86

'프로그래밍 > JAVA' 카테고리의 다른 글

NullPointerException  (0) 2019.01.22
abstract와 Interface  (0) 2019.01.04
public static void main(String[] args)  (0) 2018.11.22
java exe 파일 만들기  (0) 2018.09.01
자바 OutputStream 줄바꿈  (0) 2018.08.31

http://gakari.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-Nodejs%EC%84%9C%EB%B2%84%EB%A1%9C-POST%EB%B0%A9%EC%8B%9D%EC%9C%BC%EB%A1%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%EB%B3%B4%EB%82%B4%EA%B8%B0

Http 통신 vs Socket 통신


단말기와 웹서버와 통신 방식은 다음과 같이 크게 두 가지로 구분할 수 있습니다. 


    ① HTTP 통신

    ② Socket 통신


HTTP와 Socket의 가장 큰 차이점은 접속(Connection)을 유지하는지의 여부입니다. 물론 파일 전송만을 전문으로 처리하는 FTP도 있지만 이것은 HTTP를 확장한 개념이므로 HTTP에 포함시키겠습니다.



1. HTTP 통신


HTTP 통신은 웹브라우저에 정보를 표시하는 것과 같이 클라이언트의 요청이 있을 때 서버가 해당 페이지에 대한 자료를 전송하고 곧바로 연결을 끊는 방식입니다. 현재 여러분이 제 블로그를 보고 있지만 맨 처음 이 페이지가 보여지는 순간만 서버와 연결되고 현재는 서버와 접속이 끊어진 상태입니다. 이 상태에서 F5 키를 눌러 새로고침을 하거나 다른 페이지로 이동하면 그때 다시 서버에 연결이 될 것입니다.


이렇게 하는 이유는 단 한가지. 서버의 부하를 줄여서 다른 접속을 원활하게 처리하기 위해서입니다. 여러분이 F5 키를 계속 누르거나 아예 F5 키에 연필을 꽂아서 클라이언트가 서버를 계속해서 물고 늘어지면 서버는 이 클라이언트의 연결을 유지하느라 다른 컴퓨터의 응답이 늦어질 것입니다. 이런 방식으로 여러 대의 PC가 서버를 붙잡고 늘어져서 서버가 다른 일을 하지 못하도록 하는 것을 DDOS 공격이라고 하죠...



2. Socket 통신


Socket 통신은 클라이언트가 서버와 접속이 되면 서버나 클라이언트에서 강제로 접속을 해제할 때까지는 계속해서 접속이 유지됩니다. 따라서 서버의 능력이 무한대가 아닌 이상 동시에 접속할 수 있는 클라이언트의 수가 제한이 될 수 밖에 없겠죠. 



Socket 통신은 실시간으로 정보 교환이 필요하는 채팅이나 온라인 게임, 실시간 동영상 강좌 등에 사용됩니다. 따라서 이와 같은 경우가 아니라면 서버와의 통신은 HTTP를 사용하는 것이 시스템의 자원을 보다 효과적으로 사용할 수 있습니다.



3. 시스템의 구성


단말기가 서버에 접속하기 위해서는 서버에 단말기의 응답을 처리하는 별도의 프로그램이 있어야 합니다. 저는 이것을 서버 모듈이라고 부르겠습니다. 서버 모듈은 C, PHP, Java, ASP 등 다양한 언어로 작성될 수 있을 것지만, 제가 사용하는 서버가 아파치 웹서버를 사용하므로 PHP로 구성하기로 합니다. 서버와 통신하기 위한 시스템의 구성은 다음 그림과 같습니다.




출처: http://k9e4h.tistory.com/150 [Kim's :D]

'서버 > 기술' 카테고리의 다른 글

CURL 이란?  (0) 2018.12.22
restful api  (0) 2018.12.03

statement 와 preparedStatement 가 왜 두개가 있는지부터 생각해보아야 할꺼에요?
먼저 statement 는 동적으로 변하지 않는 쿼리를 날리고자 하는 경우에 사용되고요
preparedStatement 는 동적으로 쿼리를 변경해서 날릴 때 사용하지요.
그렇기 때문에 in parameter 만 다른 많은 쿼리를 날리고자 할 때는
preparedStatement 를 사용하는 것이 매우 효과적입니다. 왜냐하면 statement 로 날릴 경우에는 매번 dbms 에서 컴파일을 하고 실행하는데 반해 preparedStatement 는 한번 컴파일해놓고 in parameter 만 변경해서 실행하거든요 하지만 모든 쿼리를 preparedStatement 로 사용할 경우에는 문제가 생길 수 있습니다. dbms 자원이 낭비되거든요 모든 쿼리를 메모리에 가지고 있을려니 힘들죠 그리고 필요하지도 않는 쿼리가 메모리에 있으니 메모리가 꽉차면 매번 제거하는 작업도 해야하구..
jdbc programming in oracle 라는 책이던가.. 거기서는 65번 이상 반복적으로 쿼리를 실행할 경우에는 preparedStatement 를 사용하라고 합니다. oracle 이외에는 어떤게 적정수치라고 할 수 없지만 ...
암튼 결론을 내리자면 반복적인 실행이 필요없는 쿼리이고 자주 사용되지 않는 쿼리라면 꼭 statement 를 사용하세요. 어떤 회사에는 preparedStatement 가 좋다고 모든 쿼리를 이걸로 작성하는데 이는 분명 잘못된겁니다. 


출처 : http://uclee1124.tistory.com/m/28

'DB' 카테고리의 다른 글

DataSet DataTable DataGridView  (0) 2019.03.25
DB 정규화  (0) 2019.01.09
프로시저란?  (0) 2018.12.26
left, right, inner, outer, natural join  (0) 2018.11.20
DB 성능 순서  (0) 2018.09.20

Interface, Abstract

Interface

- 일종의 추상 클래스

- 오직 추상메서드와 상수만을 멤버로 갖는다.

- Implements 키워드를 사용

- 상속의 관계가 없는 클래스간 서로 공통되는 로직을 구현하여 쓸 수 있도록한다.

- Extends는 하나의 클래스만 상속 가능하나 Interface는 다중 상속이 가능하다.

Abstract

- 추상메서드를 하나 이상 가진 클래스

- 자신의 생성자로 객체 생성 불가능

- 하위 클래스를 참조하여 상위 클래스의 객체를 생성

- 하위 클래스를 제어하기 위해 사용


Abstract vs Interface

추상 클래스(Abstract)

클래스를 설계도에 비유한다면 추상클래스는 미완성 설계도에 비유할 수 있다. 미완성 설계도란, 단어

의 뜻 그대로 완성되지 못한 채로 남겨진 설계도를 말한다. 클래스가 미완성이라는 것은 멤버의 개수에

관계된 것이 아니라, 단지 미완성 메서드(추상메서드)들 포함하고 있다는 의미이다. 미완성 설계도로

완성된 제품을 만들 수 없듯이 추상클래스로 인스턴스는 생성활 수 없다. 추상클래스는 상속을 통해서

자손클래스에 의해서만 완성될 수 있다.

**자바의 정석 참고**

인터페이스 (Interface)

인터페이스는 일종의 추상클래스이다. 인터페이스는 추상클래스처럼 추상메서드를 갖지만 추상클래스 보다 추상화 정도가 높아서 추상클래스와는 달리 몸통을 갖춘 일반 메서드 또는 멤버변수를 구성원으 로 가질 수 없다. 오직 추상메서드와 상수만을 멤버로 가질 수 있으며, 그 외의 어떠한 요소도 허용하지 않는다. 추상클래스를 부분적으로만 완성된 '미완성 설계도'라고 한다면, 인터페이스는 구현된 것은 아 무것도 없고 밑그림만 그려져 있는 '기본 설계도'라고 할 수 있다. 인터페이스는 인터페이스로부터만 상속받을 수 있으며, 클래스와는 달리 다중상속, 즉 여러개의 인터페이스로부터 상속을 받는 것이 가능 하다.

**자바의 정석 참고**


공통점 

- new 연산자로 인스턴스 생성 불가능.

- 프로토타입만 있는 메서드를 갖는다.

- 사용하기 위해서는 하위클래스에서 확장/구현 해야 한다.

차이점

- 사용하는 키워드가 다르다.

- Abstract는 일반 메서드를 사용할 수 있지만, Interface는 메서드 선언만 가능하다.



출처: http://ktko.tistory.com/

'프로그래밍 > JAVA' 카테고리의 다른 글

NullPointerException  (0) 2019.01.22
싱글턴 패턴 사용하는 이유  (0) 2019.01.06
public static void main(String[] args)  (0) 2018.11.22
java exe 파일 만들기  (0) 2018.09.01
자바 OutputStream 줄바꿈  (0) 2018.08.31

프로시저는 PL/SQL을 통해 만들어지고 특정 작업을 수행하는 서브 프로그램이다. 자주 사용되는 SQL문을 DB 객체로 생성해서 저장한 후 사용시에 프로시저명을 호출해서 사용한다. PL/SQL에서 FUNCTION 은 리턴값을 반환하는데 반해 프로시저는 지정된 작업을 수행 후에 결과값을 반환할 수도 있고 반화나지 않을 수 있다. FUNCTION과 프로시저의 차이점은 FUNCTION은 SQL문 내부에서 사용할 수 있지만, 프로시저는 EXEC 또는 EXECUTE의 실행문을 통해서 사용된다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CREATE OR REPLACE PROCEDURE "프로시저명" (
  PARAMETER IN|OUT DATATYPE
 
)  IS
 
  
  --변수선언부
  
  
  BEGIN
 
  --처리내용
 
  EXCEPTION 
  --예외처리부분
          
  END;
 
cs

CREATE OR REPLACE PROCEDURE : 프로시저를 생성 또는 이미 있으면 기존 프로시저를 대체

프로시저명 : 생성할 프로시저이름

파라메터 : 프로시저에게 전달할 파라미터 이름과 데이터 타입을 명시한다.

IN  : 변수값을 입력받을때 사용

OUT : 프로시저 처리 후 리턴할 변수명

INOUT : 파라미터로 변수값을 받고 프로시저 처리후 리턴할 변수명

 

변수 선언 부 : 사용할 변수를 명시한다.

 

 

 

출처:실전 DB 모델링과 SQL for ORACLE



출처: http://kkiuk.tistory.com/16 [평범한 개발자의 이야기]

'DB' 카테고리의 다른 글

DataSet DataTable DataGridView  (0) 2019.03.25
DB 정규화  (0) 2019.01.09
statement와 preparedStatement의 차이  (0) 2019.01.05
left, right, inner, outer, natural join  (0) 2018.11.20
DB 성능 순서  (0) 2018.09.20

함수 호출시 메모리를 통으로 복사해서 사용하면 너무 느리니깐요. 메모리 위치만 주고 받으면 빠르죠.


포인터란 자료가 저장되는 기억장치의 기억주소를 가리키는 지시자로써 포인터는 다른 기억장소의 자료를 참조하는데 사용되는 데이터입니다.

 

1. 포인터를 써야 하는 이유

 

어떠한 변수이든지 어떠한 버퍼를 할당 받아서 사용하는데모든 변수의 저장과 참조는 변수가 저장될 혹은 저장된 주소를 알아야 가능하다그래서 컴퓨터는 변수를 참조할 때 그 변수가 저장되어 있는 주소를 먼저 찾아내고 그 주소가 가리키는 내용을 참조하게 된다이렇게 변수의 주소를 저장하거나 사용하기 위한 변수가 포인터이다.

포인터를 사용하면 간결하고 효율적인 표현과 처리가 가능하고 더 빠른 기계어 코드를 생성할 수 있으며복잡한 자료 구조(배열구조체 등)와 함수의 쉬운 접근이 가능하다또한 포인터를 사용하지 않았을 때 코드로 표현할 수 없는 경우가 생길 수 있다.

 

2. 포인터를 사용하면 어떤 장점이 있을까?

 

메모리 주소를 참조해서 다양한 자료형 변수들의 접근과 조작 용이


예제_

#include <stdio.h>

int main() 

int a=5; 

int *b; 

b = &a; 

printf("a = %d, &a = %d, b = %d, *b = %d\n", a, &a, b, *b); 

*b += 5; 

printf("a = %d, &a = %p, b = %p, *b = %d\n", a, &a, b, *b); 

              return 0; 

}


-----------------------------------------------------------------------

a = 5, &a = 1245052, b = 1245052, *b = 5 

a = 10, &a = 0012FF7C, b = 0012FF7C, *b = 10


위 예제에서 보면 정수형 변수 a 5로 초기화되고 정수형 포인터 변수 b a의 시작주소가 대입됩니다

따라서 주소 b가 가리키는 내용인 *b 3이 될 것입니다이렇듯이 변수들의 접근에 용이합니다.

 

메모리 주소를 참조하여 배열과 같은 연속된 데이터에 접근과 조작 용이

동적 할당된 메모리 영역(힙 영역)에 접근과 조작 용이

한 함수에서 다른 함수로 배열이나 문자열을 편리하게 보낼 수 있음

복잡한 자료구조를 효율적으로 처리

배열로 생성할 수 없는 데이터를 생성

메모리 공간을 효율적 사용

- call by reference에 의한 전역 변수의 사용을 억제

 

3. 포인터의 단점

 

포인터 변수는 주소를 직접적으로 컨트롤하기 때문에 예외 처리가 확실하지 않을 경우 예상치 못한 문제가 많이 발생. ( 널 포인트 같은 경우에 바로 접근할 경우 예외 발생)

선언만 하고 초기화를 하지않을 경우 쓰레기 주소를 가리키고 있기 때문에 사용에 주의해야 함.

포인터 변수는 주소를 직접 참조하기 때문에 의도하지않게 원본의 값이 수정 될 수 있다.

오류를 범하기 쉽고 기교적인 프로그램이 되기 쉽다.

프로그램의 이해와 버그 찾기가 어렵다.

메모리 절대 번지 접근 시 시스템 오류를 초래한다.

 

 하지만 단점 보다는 장점이 더 많아서 포인터를 사용한다고 한다.

 

 

4. 포인터와 배열의 차이

 배열과 포인터는 완전 같지는 않다고 한다그럼 차이점은 무엇일까?

 

포인터는 변수이지만 배열은 상수이다.

         int *p와 int arr[n]이 있다고 할 때, p는 고유의 메모리를 차지하고 있고 언제든지 다른 대상을 가르킬 수 있지만 arr는 선언 할 때 그 위치가 이

미 고정되므로 다른 대상을 가리킬 수 없다. arr로는 오로지 배열의 선두 번지를 읽을 수 있을 뿐이다.


가리키는 배열의 크키는 동적으로 결정할 수 있지만 arr이 가리키는 배열의 크기는 선언할 때 정적으로 결정된다.
 
고정된 길이의 배열이 필요하면 int arr[n]; 선언문으로 배열을 생성하는 것이 편리하고 가변길이의 배열이 필요하면 int *형의 포인터 변수를 선언한    malloc으로 할당해서 사용해야 한다포인터로 할당한 배열은 실행 중에라도 realloc으로 크기를 재할당하여 변경할 수 있다.
 
- 배열은 그 자체가 크기 때문에 함수의 인수로 전달할 수 없지만 포인터는 대상체가 무엇이든간에 4바이트와 크기밖에 차지하지 않으므로 함수로 전달할 수 있다
 
그래서 배열을 함수로 전달할 때는 반드시 포인터를 사용해야 한다

- 동작의 속도 차이가 있다
 
배열은 매번 배열선두에서부터 출발하지만 포인터는 대상체로 직접 이동해서 바로 읽으므로 액세스 속도가 빠르다. *p p가 가리키는 곳을 바로 읽지만ar[n] *(ar+n)으로 일단 번지를 더한 후 읽어야 하므로 조금 느리다포인터가 배열보다 두배 정도 빠르다.


출처 : http://blog.hyomin.xyz/10

'프로그래밍' 카테고리의 다른 글

C# , C++, JAVA 비교  (0) 2018.09.22

https://www.w3schools.com/sql/trysql.asp?filename=trysql_select_all

'DB > Oracle' 카테고리의 다른 글

DB 쿼리  (0) 2018.12.25
Statement 대신 preparedStatement 사용하는 이유  (0) 2018.12.25
프로젝트 DB 설계  (0) 2018.09.05
SQL실습을 위한 Oracle XE 11g 설치 및 준비  (0) 2018.07.27
sqldeveloper 테스트 실패  (0) 2018.07.27


관계형 데이터베이스에서 SQL을 이용해 관계를 맺는 것을 '조인'이라고 합니다. 테이블 간의 연결 고리로 관계를 맺고 데이터를 추출하는 방법입니다. 테이블의 기본키와 외래키가 연결고리가 됩니다.


조인의 종류에 대해 알아보겠습니다. 조인은 크게 내부 조인과 외부 조인으로 구분이 됩니다. 


내부 조인에는 동등 조인, 세미 조인, 안티 조인, 셀프 조인이 있습니다. 

하나 하나 알아보겠습니다. 


동등 조인 

WHERE절에서 등호 연산자를 사용해 2개 이상의 테이블이나 뷰를 연결하는 조인입니다. 


세미 조인

서브 쿼리를 사용해 서브 쿼리에 존재하는 데이터만 메인 쿼리에서 추출하는 조인입니다. 

세미 조인은 최종 반환되는 메인 쿼리 데이터에 중복되는 건이 없습니다.




안티 조인

서브 쿼리의 B 테이블에는 없는 메인 쿼리의 A 테이블의 데이터만 추출하는 조인입니다.



셀프 조인

동일한 한 테이블을 사용해 조인하는 방법입니다. 



외부 조인

조인 조건에 만족하는 데이터 뿐만 아니라, 어느 한 쪽 테이블에 조인 조건에 명시된 컬럼에 값이 없거나 (NULL이라도) 해당 로우가 아예 없더라도 데이터를 모두 추출하는 것입니다.  데이터가 없는 테이블의 컬럼에 (+) 표시를 붙이는 방식이고 조인 조건이 여러 개일 때 모든 조건에 (+) 표시를 붙여야 합니다.




카타시안 조인

FROM절에는 2개 이상의 테이블이 명시되어 있지만 WHERE절에는 조인 조건이 없는 조인입니다.  결과는 두 테이블의 건수의 곱만큼 나오게 됩니다.



ANSI 조인

ANSI SQL 문법을 사용한 조인으로 조인 조건이 WHERE절이 아닌 FROM절에 위치하는 것입니다.


ANSI 내부 조인



ANSI 외부조인 

다음 코드를 보면 데이터가 더 많은 쪽이 왼쪽에 쓰여진 테이블(employees)이기 때문에 LEFT [OUTER] JOIN이라고 합니다.



CROSS 조인은 기존 카타시안 조인을 ANSI 조인에서 쓴 것입니다.



FULL OUTER 조인은 외부 조인의 하나로 ANSI 조인에서만 제공하는 것입니다. 두 테이블 모두 기준이 되어 부족한 것들까지 다 나오도록 하는 방식입니다. 



서브 쿼리

SQL 문장 안에서 보조로 사용되는 또 다른 SELECT문을 의미합니다. 서브 쿼리는 여러 개를 사용할 수 있습니다. 서브 쿼리를 구분해보면 다음과 같이 나눌 수 있습니다.


- 연관성이 없는 서브쿼리

  : 메인 쿼리와 조인 조건이 걸리지 않는 서브쿼리로 단지 순차적으로 처리 되는 경우

- 연관성이 있는 서브쿼리

  : 메인 테이블과 조인 조건이 걸린 서브쿼리


- 일반 서브쿼리(SELECT절)

- 인라인 뷰(FROM절)

- 중첩쿼리(WHERE절)

[출처] DB - 조인과 서브 쿼리|작성자 DeveloperBee



SQL을 작성하다 보면 테이블에 저장된 데이터를 원하는 목적에 맞게 집계해서 데이터를 추출해야 할 때가 많은데 이때 사용하는 것이 그룹 쿼리입니다.


그룹 쿼리란, 특정 항목별로 그룹을 지어 정보를 추출할 때 사용하는 SQL 구문으로 집계 함수와 GROUP BY절의 결합이라고 할 수 있습니다.


먼저 기본 집계 함수에 대해 알아보겠습니다.

우선 집계 함수란, 대상 데이터를 특정 그룹으로 묶은 다음 이 그룹에 대해 총합, 평균, 최댓값, 최솟값 등을 구하는 함수를 말합니다.


COUNT(expr)

쿼리 결과 건수, 즉 전체 로우 수를 반환하는 함수입니다. expr에 * 또는 컬럼명이 올 수 있고 NULL이 아닌 것만을 체크하게 됩니다.


DISTINCT

중복을 제거할 때 사용하여 유일한 값만을 조회하게 됩니다. 중복된 값을 제거하지만 NULL인 것도 하나로 체크하게 됩니다.


SUM(expr)

expr의 전체 합계를 반환합니다. expr은 숫자형만 올 수 있습니다.


AVG(expr)

expr의 평균 값을 반환합니다.


MIN(expr) / MAX(expr)

최솟값과 최댓값을 반환합니다.


VARIANCE(expr) / STDDEV(expr)

분산과 표준편차를 반환합니다. 분산이란 개별 값과 평균 값의 차이인 편차를 구해 이를 제곱하여 평균한 값을 의미합니다. 표준 편차는 이 분산 값의 제곱근을 의미합니다.


다음으로 GROUP BY절과 HAVING절에 대해 알아보겠습니다.


GROUP BY절이란, 

특정 그룹을 묶어 데이터를 집계하는 것을 말합니다. WHERE와 ORDER BY절 사이에 위치하며 그룹으로 묶을 컬럼명이나 표현식을 명시하게 됩니다. 집계함수가 아닌 컬럼과 집계함수를 같이 조회하는 경우 반드시 일반 컬럼은 GROUP BY절에 명시가 되어야 합니다.


HAVING절은 GROUP BY절 다음에 위치해서 GROUP BY한 결과를 대상으로 다시 필터를 거는 역할을 합니다.


GROUP BY절에서 그룹별 소계를 추가로 보여주는 역할을 하는 ROLLUP과 CUBE절이 있습니다. 이 절들에는 집계 함수를 제외한 컬럼 등의 표현식이 올 수 있습니다.


ROLLUP(expr1, expr2,...)은 명시한 표현식 수와 순서(오른쪽 -> 왼쪽)에 따라 레벨별로 집계한 결과를 반환합니다.


CUBE(expr1, expr2,...)는 명시한 표현식 개수에 따라 가능한 모든 조합별로 집계한 결과를 반환합니다.


추가적으로 분할(partial) ROLLUP과 분할 CUBE도 있습니다.


마지막으로 집합 연산자에 대해 알아보겠습니다.


집합 연산자란,

데이터 집합(쿼리 조건에 맞아 조회된 일련의 데이터)을 대상으로 연산을 수행하는 연산자로 여러 SELECT문을 연결해 또 다른 하나의 쿼리를 만드는 역할을 합니다.


UNION

합집합과 같은 의미로 각 집합 원소 (SELECT 결과)를 모두 포함한 결과를 반환합니다. 여기서 중복되는 값은 한번만 조회됩니다.


UNION ALL

UNION과 비슷하지만 중복되는 값을 각각 하나로 조회한 결과를 반환합니다.


INTERSECT

교집합과 같은 의미로 데이터 집합에서 공통된 항목만 추출한 결과를 반환합니다.


MINUS

차집합과 같은 의미로 한 데이터 집합을 기준으로 다른 데이터 집합과 공통된 항목을 제외한 결과만 추출하여 반환합니다.




집합 연산자를 사용할 때 제한 사항은 다음과 같습니다.

  - 집합 연산자로 연결되는 각 SELECT문의 SELECT 리스트의 개수와 데이터 타입 일치

  - 집합 연산자로 SELECT문을 연결할 때 ORDER BY절은 맨 마지막 문장에서만 사용 가능

  - BLOB, CLOB, BFILE 타입의 컬럼에 대해서는 집합 연산자를 사용할 수 없음

  - UNION, INTERSECT, MINUS 연산자는 LONG형 컬럼에는 사용할 수 없음


그 외 GROUPING SETS절이 있는데 이는 GROUP BY절에서 사용되고 UNION ALL 개념이 셨여 있다고 할 수 있습니다. 간단히 설명하면 GROUPING SETS(expr1, expr2, expr3)이면 세 표현식 별로 각각 집계가 이루어진다는 것입니다.


이유는 Statement 객체에서 사용한 createStatement()라는 메소드 때문입니다. 이것을 사용할 경우 사용자의 입력 값을 미리 만들어 놓은 sql문에 적용한 후 컴파일을 하기 때문에 사용자의 입력 값에 따라 쿼리문의 형태가 바뀔 수 있어 보안에 취약합니다. 사용자가 입력 값과 함께 'OR 1=1'과 같은 코드를 함께 전달할 경우 모든 사용자의 정보 등이 노출될 수 있기 때문입니다.


따라서 해결책으로 Statement 객체의 preparedStatement(query) 메소드를 사용하였습니다. 이것은 미리 개발자가 작성한 쿼리문을 컴파일 하고 ?로 처리한 부분에 사용자의 입력 값을 넣기 때문에 쿼리문의 형태가 바뀌지 않아 보안성을 높일 수 있습니다.


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가 훨신 편하다.






출처: http://devbox.tistory.com/entry/Comporison?category=577782 [장인개발자를 꿈꾸는 :: 기록하는 공간]

'DB > Oracle' 카테고리의 다른 글

데이터베이스 sql 쿼리 연습하는 곳  (0) 2018.12.25
DB 쿼리  (0) 2018.12.25
프로젝트 DB 설계  (0) 2018.09.05
SQL실습을 위한 Oracle XE 11g 설치 및 준비  (0) 2018.07.27
sqldeveloper 테스트 실패  (0) 2018.07.27

+ Recent posts