Pages

2016년 2월 28일 일요일

[JAVASCRIPT] KB927917 오류

HTML Parsing Error: Unable to modify the parent container element before the child element is closed

이 문제는 자식 컨테이너 HTML 요소에 자식 컨테이너의 부모 컨테이너 요소를 수정하려고 시도하는 스크립트 코드가 포함되어 있기 때문에 발생합니다. 이 스크립트 코드는 innerHTML 메서드 또는 appendChild 메서드를 사용하여 부모 컨테이너 요소를 수정하려고 시도합니다.

이 문제를 해결하려면 닫힌 컨테이너만 수정하거나 스크립트의 바로 아래 수준 컨테이너 요소만 수정하는 스크립트 블록을 작성하십시오. 이렇게 하려면 자리 표시자를 사용하여 대상 컨테이너를 닫거나 수정할 컨테이너로 스크립트 블록을 이동하면 됩니다.


2016년 2월 2일 화요일

비동기 처리 구현을 위한 Ratpack

Ratpack은 HTTP 응용 프로그램 구축을위한 JAVA 라이브러리의 집합입니다.
Ratpack은 앱을 실용적이고 높은 성능을 작성하기 위해 제공합니다.
처리 베이스는 non-blocking형 이벤트 구동 네트워크 엔진인 Netty를 사용하여 비동기처리를 구현하고 있습니다.
Ratpack은 JSON과 같이 특정 언어에 비 종속적인 프로토콜을 최 우선적으로 서포트하고 있으며, 
옵션으로 넷플릭스의 서킷 브레이커 라이브러리인 Hystrix나 레포팅을 위한 Dropwizard Matrics를 지원하고 있습니다.
설정정보관리는 YAML과 JSON 그리고 Java프로퍼티가 사용 가능합니다.
Ratpack은 오픈소스 프로젝트로서 개발이 진행되고 있으며, 아파치 라이센스를 사용하고 있습니다.

Ratpack의 개발 목표
매뉴얼에 기재된 Ratpack이 표방하는 개발 목표는 다음과 같습니다.
    1. 빠르고, 확장가능하며, 고효율이어야 한다.
    2. 응용프로그램을 성능저하 없이 복잡하게 발전시킬 수 있어야 한다.
    3. non-blocking 프로그래밍의 장점을 활용하면서도 비용을 절감시킬 수 있어야 한다.
    4. 다른 툴과 라이브러리들과 통합함에 있어서 유연하고 개방적이어야 한다.
    5. 응용 프로그램을 쉽고 완벽하게 테스트 할 수 있어야 한다.

반면 다음의 사항들에 대해서는 지양하고 있음을 밝히고 있습니다.
    1. 완벽하게 통합된 "풀스텍" 솔루션
    2. 필요한 모든 기능을 제공하는 "만능 칼"
    3. "비즈니스 로직"을 위한 프레임웍 혹은 아키텍처

심플한 비동기 처리의 구현
Ratpack의 가장 큰 특징은 뭐니뭐니해도 심플한 비동기 처리의 구현입니다. JVM위에서 비동기 처리라는 과제에 도전하고 있다는 점 에서 자주 Akka와 비교되곤 하는데, 코딩스타일에 있어서 자바8을 기반으로 도입하고 있는것이 메뉴얼에서 잘 드러납니다. 

Ratpack의 메뉴얼에 실려있는 RESTful HTTP API 헨들러 체인의 구현부 입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package springpack;
import ratpack.server.RatpackServer;
public class Main {
  public static void main(String[] args) throws Exception {
    RatpackServer.start(spec -> spec
      .handlers(chain -> chain (1)
          .prefix("api", pchain -> pchain (2)
            .all(ctx -> ctx (3)
              .byMethod(method -> method (4)
                .get(() -> ctx.render("Received GET request"))
                .post(() -> ctx.render("Received POST request"))
                .put(() -> ctx.render("Received PUT request"))
                .delete(() -> ctx.render("Received DELETE request"))
              )
            )
          )
      )
    );
  }
}
cs


처리모델

Ratpack의 처리 모델은 node.js와 닮아 있습니다. 다음 그림은 4코어 시스템에서 동작하는 Ratpack의 처리 모델의 개요를 나타내고 있습니다.


Ratpack은 기동과 함께 지정한 코어 수 만큼의 이벤트 루프가 바인딩 됩니다. Ratpack은 Netty를 이용해 "이벤트 루프 그룹"을 생성하고 사용 가능한 CPU코어에 각각의 Single Thread로 동작하는 이벤트 루프를 바인딩 합니다. 각각의 이벤트 루프는 응용 프로그램에서 도착하는 non-blocking 네트워크 요청을 처리합니다. 즉, 하나의 비동기처리 요구에 대하여 하나의 CPU에 바인딩 되도록 하는 처리 방식을 통해 고성능 비동기 처리를 실현하려 하고 있는데, 최근 실시한 벤치마크에서는 단순 Hello World의 경우 32코어 머신에서 초당 1억 리퀘스트를 단일 JVM인스턴스로 처리 할 수 있는 것으로 알려져 있습니다.


참고 URL

2016년 1월 18일 월요일

똑똑한 프로그래머를 멍청이로 만드는 방법

http://okky.kr/article/309518

평소 알고 있는 내용이지만 글로 정리된 부분이 있어서 흥미롭게 읽었다.

한 번 쯤 생각하고 넘어가야 할 부분인 것 같다. 즐겁게 일을 하고 있다고 생각했는데,

최근에는 즐겁게 일 하는것 보다는 누구의 눈치를 보면서 일을 해야 한다는 아쉬움이

있다.

"개발자의 무한 희생이 아니라 '개발' 자체가 개발자에게 기쁨과 즐거움이 될 수 있어야 한다." 

이 부분이 마음에 와 닿는 것 같다. 개발이 즐거울때 며칠이고 열심히 일에 몰두해서 그

결과를 내는데 효율적이지만, 그렇지 않은 억지 업무 및 개발이 진행 될때는 그 개발이

효율적이지 못하다는 것은 참 아쉽기만 하다.

얼마나 남을지 모르지만 적어도 1년은 참고 가봐야 하지 않을까 쉽다.


2015년 8월 18일 화요일

[ ORACLE ] INDEX SCAN (MIN/MAX) 성능 개선 방안


 [ 출처 – 오라클클럽 위키]
위의 그림은 인덱스 B-Tree를 그림으로 표현한 내용인데, INDEX FULL SCAN은 LEAF 블록을 처음부터 끝까지 모두 읽는 ‘수평적 탐색’을 의미합니다. 이 중 ’INDEX FULL SCAN (MIN/MAX)’  operation은 MIN() 또는 MAX() 함수로 데이터 추출 시 INDEX LEAF BLOCK의 양 끝(MIN/MAX)의 데이터를 읽어 빠르게 데이터를 추출하는 방법입니다. 이렇게 데이터를 추출할 경우 전체 데이터를 모두 읽지 않고 MIN/MAX 데이터를 빠르게 가져올 수 있어 성능을 극대화 시킬 수 있습니다.
‘INDEX FULL SCAN (MIN/MAX)’ operation이 어떻게 데이터를 액세스하는지 예제를 통해 살펴보도록 하겠습니다.

1. 테스트 데이터 생성
(MIN/MAX) operation을 살펴보기 위해 테스트 데이터를 만들도록 하겠습니다. 테스트 데이터는 ‘PARENT_T : CHILD_T = 1 : M’ 관계의 테이블을 만들고 CHILD_T 테이블에는 약 100만건의 데이터를 만들도록 하겠습니다.
테스트 환경은 오라클 11g이며, PARENT_T 테이블에는 7건의 코드성 데이터를, CHILD_T 테이블에는 숫자 자리수를 하나의 그룹으로 하고 여기에 날짜값이 순차적으로 증가하도록 CHILD_DATE 값을 넣었습니다. 또한, PARENT_T, CHILD_T 테이블에 각각 인덱스를 생성하였으며, CHILD_T의 경우 ‘CHILD_DATE’, ‘CNT + CHILD_DATE’ 2개 인덱스를 생성하였습니다. 아래는 각각의 테이블 데이터 출력 결과입니다.

2. (MIN/MAX) operation
위에서 만든 샘플 데이터를 통해 (MIN/MAX) operation을 살펴보도록 하겠습니다. 우선 일반 그룹함수인 SUM() 함수를 이용하여 MIN/MAX() 함수와 어떤 차이가 있는지 보겠습니다.
보시는 것처럼 100만건이 존재하는 CHILD_T 테이블에 SUM() 함수를 사용할 경우 당연히 100만건을 모두 액세스하고 SUM을 구해야 합니다. 하지만 MAX() 함수의 경우 인덱스에서 딱 1건만 액세스하고 바로 데이터를 가져오고 있으며, 수행시간 및 I/O도 약 1,000배 감소된 걸 볼 수 있습니다.
하지만 (MIN/MAX) operation은 MIN, MAX 값을 동시에 가져올 수는 없습니다. 만약 MIN, MAX 함수를 동시에 사용할 경우 어떻게 되는지 살펴보겠습니다.
위의 결과처럼 MIN, MAX 함수를 동시에 사용할 경우  (MIN/MAX) operation은 실행계획에 나타나지 않으며, TABLE FULL SCAN으로 전체 데이터를 액세스하여 가져오는 것을 볼 수 있습니다. 그럼 MIN, MAX 값을 동시에 가져오면서 (MIN/MAX) operation을 사용하려면 어떻게 해야 할까요?
방법은 바로 MIN과 MAX를 가져오는 SQL을 각각 구현한 후 이를 UNION ALL로 묶어 데이터를 추출할 수 있습니다.  즉, MIN/MAX는 동시에 추출할 수 없다는 것을 이 테스트를 통해 확인할 수 있습니다.
(MIN/MAX) operation의 장점은 테이블에 조건이 없어도 INDEX FULL SCAN을 통해 데이터를 빠르게 가져온다는 장점이 있는데, 만약 조건이 들어갈 경우 operation에 어떤 변화가 있는지 살펴보겠습니다. 아래 예제는 CHILD_T 테이블에 CNT 조건을 추가하여 MAX(CHILD_DATE) 값을 가져오는 SQL입니다.
CHILD_T 테이블에 CNT=5 조건을 추가하여 MAX(CHILD_DATE) 값을 구할 경우에도 마찬가지로 빠르게 한건을 가져오고 있는데, 조건이 안 들어간 경우와 비교하여 실행계획에 변화가 생겼습니다. 변화가 생긴 operation은 바로 ‘INDEX FULL SCAN (MIN/MAX)’에서 ‘INDEX RANGE SCAN (MIN/MAX)’으로 바뀐 점입니다. 즉, MIN/MAX operation의 경우 조건이 없을 경우 INDEX FULL SCAN을 통해 양 끝의 데이터를 가져올 수 있으며, 조건이 있을 경우 해당 조건을 INDEX RANGE SCAN으로 액세스 한 뒤 해당 인덱스의 양 끝 데이터를 또한 MIN/MAX로 가져올 수 있다는 것을 의미합니다.

3. (MIN/MAX) operation 튜닝
그럼 CNT 값을 조건으로 넣기 않고 CNT 값에 따른 MAX_CHILD_DATE 값을 가져오려고 하면 어떻게 될까요? 아래의 예제에서 살펴보겠습니다.
보시는 것처럼, TABLE FULL SCAN을 통해 100만건을 모두 액세스한 후 데이터를 추출하는 것을 볼 수 있습니다. 즉 CHILD_T_N02(CNT, CHILD_DATE) 인덱스를 활용하여 MIN/MAX operation을 사용하지 못하는 것을 확인할 수 있습니다.
그럼 CNT 값에 값을 직접 상수로 입력할 경우 MIN/MAX operation을 사용할 수 있는지 살펴보겠습니다.
보시는 것처럼 CNT 값을 상수로 넣을 경우 TABLE FULL SCAN이 아닌 INDEX RANGE SCAN으로 operation이 변경되었지만 여전히 MIN/MAX operation으로 데이터를 가져오지 않기 때문에 100만건을 액세스하는 것은 변함이 없습니다. 여기서 두 번째 특징을 찾을 수 있는데 MIN/MAX operation은 반드시 특정값에 속한 경우에만 MIN/MAX 값을 가져올 수 있다는 것입니다. CHILD_T 테이블에서 조건없이MAX(CHILD_DATE) 값을 추출할 경우 ‘CHILD_T_N01(CHILD_DATE)’ 인덱스를 통해 ‘INDEX FULL SCAN (MIN/MAX)’  operation을 사용할 수 있으며, CNT 값이 들어갈 경우 ‘CHILD_T_N02(CNT, CHILD_DATE)’ 인덱스를 통해 특정 선두값(CNT)에 대해서만 ‘INDEX RANGE SCAN (MIN/MAX)’을 사용할 수 있습니다. 하지만 선두값이 여러개일 경우 MIN/MAX operation을 사용할 수 없으며 전체 데이터를 모두 읽어야 하는 한계가 있습니다.
이와 같이 선두 컬럼을 여러개 추출해야 할 경우 MIN/MAX operation을 이용하여 빠르게 데이터를 추출할 수 있는 방법은 없는것일까요? 방법이 있습니다. 그것은 바로 위에서 나열한 특정을 활용하는 것인데, ‘INDEX RANGE SCAN (MIN/MAX)’을 사용하려면 특정 선두값을 반드시 한건만 입력해야 한다는 것을 알았으므로 이 특징을 활용하도록 SQL을 변경해주면 됩니다. 아래의 예제에서 살펴보겠습니다.
CHILD_T 테이블에 선두컬럼을 넣으려면, ’PARENT_T : CHILD_T = 1 : M’ 관계를 활용하면 되며 이를 1:1 관계로 만들 경우, 즉 CHILD_T 테이블을 스칼라 서브쿼리로 변경할 경우 성능 선두컬럼(CNT)을 항상 받을 수 있기 때문에 MIN/MAX operation을 이용할 수 있으며, 이와 같이 극대화된 성능 개선이 가능합니다.

4. MIN/MAX operation 정리
이처럼 MIN/MAX operation 특징을 정확히 이해하고 활용할 경우 성능개선이 가능하며 이 기능을 정리한 내용은 아래와 같습니다.