레이블이 JavaScript인 게시물을 표시합니다. 모든 게시물 표시
레이블이 JavaScript인 게시물을 표시합니다. 모든 게시물 표시

javascript async, await 로 axios 순차 수행하기

// promise 는 비동기 처리가 완료된후 결과를 주겠다는 약속이다.
// promise 를 리턴하고 ms 만큼 지연하는 함수
delay(ms) {
  // promise 는 pending(진행중), fulfilled(수행완료/성공), rejected(수행실패) 상태가 있다.
  // 비동기처리를 되고 있음을 가정하기 위해 setTimeout 사용
  // 1초 후
  // success 함수를 호출하며 fulfilled 상태가 되고
  // fail 함수를 호출하면 rejected 상태가 된다.
  return new Promise(function(success, fail) {
    setTimeout(() => {
      success();
    }, ms);
  });
}

// async 를 붙이면 비동기 함수로 정의되며 promise 를 리턴받을 수 있다.
async function gogo(items) {
  for (const v of items) {
    // await 는 async 함수내에서만 사용할 수 있다.
    // await 은 promise 리턴하는 함수에서만 사용할 수 있다.
    // await 이 붙인 함수가 종료될때까지 기다린다.
    // async 함수내에서 await 로 axios 요청
    await axios
      .post("/api/query", v, {
        headers: {
          "Content-Type": "application/json",
        },
      })
      .then(() => {
        console.log("요청 성공");
      })
      .catch((err) => {
        console.log("요청 실패");
      });
    // 전송 후 1초 대기
    await this.delay(1000);
  }
}


vue axios 모든 요청에 헤더,파라메터 추가하기

# 프로젝트내 모든 axios 요청 또는 응답에 공통으로 추가할 데이터(파라메터가,헤더)가 있는 경우
# 각 axios 구문 마다 일일히 추가하는 대신 axios intercepter 를 활용할 수 있다.
# 공통 파라메터 값이 vuetify store 에 저장된 경우
# vue 인스턴스 내부에서 axios.interceptors 를 명시해놓아야 한다.

# 얘시
# src/store.js 가 있고
# src/rouster/index.js 에 다음과 같이 추가한다.

import { store } from '@/store';

// axios 모든 요청 보내기전에 수행
// Add a request interceptor
axios.interceptors.request.use(function (config) {
  // Do something before request is sent
  if (config.params == null) {
    config.params = {};
  }
  config.params['ysoftman1'] = store.state.mydata.value;
  config.headers['fruit1'] = "lemon";
  config.headers['fruit2'] = "apple";
  console.log("----- config:", config);
  return config;
}, function (error) {
  // Do something with request error
  return Promise.reject(error);
});

// axios 모든 응답 리턴전에 수행
// Add a response interceptor
axios.interceptors.response.use(function (response) {
  // Any status code that lie within the range of 2xx cause this function to trigger
  // Do something with response data
  return response;
}, function (error) {
  // Any status codes that falls outside the range of 2xx cause this function to trigger
  // Do something with response error
  return Promise.reject(error);
});


js fetch() with credntial 옵션 사용시 CORS 에러 방지 서버 설정

# javascript(js) fetch 함수 요청시 CORS(Cross-Origin Resource Sharing) 에러 방지하기
# js fetch() 로 ysoftman1 에서 ysoftman2 로 요청하는 상황으로 다음과 같다.
# 크롬 개발자 도구 console 에서 실행
fetch("http://ysoftman2/lemon", {
  "headers": {
    "accept": "application/json, text/plain, */*",
    "accept-language": "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7",
    "authorization": "Bearer aaabbbccc123456789",
    "sec-fetch-dest": "empty",
    "sec-fetch-mode": "cors",
    "sec-fetch-site": "same-site"
  },
  "referrer": "https://ysoftman1/apple",
  "referrerPolicy": "no-referrer-when-downgrade",
  "body": null,
  "method": "GET",
  "mode": "cors",
  "credentials": "include"
}).then(response => response.json());

# 이때 요청 흐름은 js fetch() --> browser --> server 이 된다.
# browser 는 OPTIONS 메소드로 서버에게 접근 가능한지 물어본다.(preflight 과정)
# 이때 서버는 응답 헤더에 다음 값들을 설정할 수 있고
Access-Control-Allow-Origin: 접근 가능한 호스트
Access-Control-Allow-Methods: 접근 가능한 메소드
Access-Control-Allow-Headers: 접근 가능한 헤더

# browser 는 이 허용된 값들 내에서 서버에 실제 요청을 하게 된다.

# 서버가 와일드카드(Access-Control-Allow-Origin: *)를 사용하더라도 
# 클라가 credential (ajax, xmlhttp 로 다른도메인에 쿠키를 설정할때 사용하는 옵션)를 사용하면 CORS 정책으로 블럭된다.
# 다음과 같이 exact 한 호스명과 vary (브라우저가 캐시 사용시 어떤 헤더를 보고 구분해야 하는지 알려준다) 헤더에 origin 을 설정해야 한다.
Access-Control-Allow-Origin: https://developer.mozilla.org
Vary: Origin

# 서버쪽 설정 방법들
# 방법1 - k8s ingress 사용시, enable-cors true 설정(디폴트 false)
# enable-cors 를 사용하면 cors 관련 응답헤더들(Access-control-xxx)이 자동으로 추가된다.
# 그리고 Access-Control-Allow-Origin 가 * 로 고정된다.
# configuration-snippet 의 Access-Control-xxx 헤더가 응답에 중복되어
# cors 가 동작하지 않으니 같이 사용하지 않는다.
metadata
  annotations:
    ingress.kubernetes.io/rewrite-target: /
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/cors-allow-origin: "*"
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/cors-allow-headers: "x-test-header"
    
# 방법2 - k8s ingress 사용시, configuration-snippet 로 설정
metadata
  annotations:
    ingress.kubernetes.io/rewrite-target: /
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/cors-allow-origin: "*"
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
    # configuration-snippet 현재 location 의 설정에 추가된다.
    nginx.ingress.kubernetes.io/configuration-snippet: |
      if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' "$http_origin";
        add_header 'Access-Control-Allow-Credentials' "true";
        add_header 'Access-Control-Allow-Methods' "GET, PUT, POST, DELETE, PATCH, OPTIONS";
        add_header 'Access-Control-Allow-Headers' "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,X-Client-Identifier";
        add_header 'Access-Control-Max-Age' "1728000";
        add_header 'Content-Type' "text/plain charset=UTF-8";
        add_header 'Content-Length' "0";
        add_header 'Vary' "Origin";
        return 204;
      }
      add_header 'Access-Control-Allow-Origin' "$http_origin";
      add_header 'Access-Control-Allow-Credentials' "true";
      add_header 'Access-Control-Allow-Methods' "GET, PUT, POST, DELETE, PATCH, OPTIONS";
      add_header 'Access-Control-Allow-Headers' "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,X-Client-Identifier";
      add_header 'Vary' "Origin";

# 방법3 - k8s ingress 사용시, 특정 도메인에만 cors 허용할때 변수를 설정해 구분
metadata
  annotations
    nginx.ingress.kubernetes.io/configuration-snippet: |
      if ($http_origin ~* "^https?:\/\/(.*\.)?((ysoftman\-lemon\.com)|(ysoftman\-apple\.com))$") {
        set $cors = "cors";
      }
      if ($request_method = 'OPTIONS') {
        set $cors = "cors_options";
      }
      if ($cors = "cors_options") {
        add_header 'Access-Control-Allow-Origin' "$http_origin";
        add_header 'Access-Control-Allow-Credentials' "true";
        add_header 'Access-Control-Allow-Methods' "GET, PUT, POST, DELETE, PATCH, OPTIONS";
        add_header 'Access-Control-Allow-Headers' "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,X-Client-Identifier";
        return 200;
      }
      if ($cors = "cors") {
        add_header 'Access-Control-Allow-Origin' "$http_origin";
        add_header 'Access-Control-Allow-Credentials' "true";
        add_header 'Access-Control-Allow-Methods' "GET, PUT, POST, DELETE, PATCH, OPTIONS";
        add_header 'Access-Control-Allow-Headers' "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,X-Client-Identifier";
        return 204;
      }

# 방법4 - 서버에 직접 설정하는 경우
# 아래는 go chi 핸들러 사용하는 예시
func CORSHandler(next http.Handler) http.Handler {
  fn := func(w http.ResponseWriter, r *http.Request) {
    // CORS(Cross-Origin Resource Sharing) 에러 방지 헤더 추가
    if r.Method == http.MethodOptions {
      // w.Header().Set("Access-Control-Allow-Origin", "*")
      // js fetch() credentials 옵션 사용시 와일드카드(*) 대신 요청 origin 으로 설정해야 한다.
      w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin"))
      w.Header().Set("Access-Control-Allow-Credentials", "true")
      w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
      w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
      // options (preflight) 일때는 CORS 에러 방지 헤더 추가하여 바로 응답을 줘 클라가 다시 요청을 시도할 수 있도록 한다.
      return
    }
    w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin"))
    w.Header().Set("Access-Control-Allow-Credentials", "true")
    w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
    w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
    next.ServeHTTP(w, r)
  }
  return http.HandlerFunc(fn)
}

# 주의사항
# 만약 k8s ingress 과 서버내 양쪽에서 모두 access-controll-allow 헤더들을 설정하면 중복 설정되고 CORS 정책에 위배돼 에러가 발생한다.
The 'Access-Control-Allow-Origin' header contains multiple values 'https://....', 
but only one is allowed. 
Have the server send the header with a valid value, or, 
if an opaque response serves your needs, 
set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

# 그래서 한쪽에서만 설정해줘야 한다.
# 참고로 curl 로 cors 확인(access-control-xxx 헤더)을 위해선 다음 옵션을 사용해야 한다.
curl -X GET "https://ysoftman.lemon.com/aaa/bbb?ccc=lemon" \
-H "accept: application/json" \
--header 'Origin: http://ysoftman.lemon.com' \
--header 'Access-Control-Request-Headers: Origin, Accept, Content-Type' \
--header 'Access-Control-Request-Method: GET'

vue local devserver proxy

# 예시
# 현재 로컬 서버 http://localhost:8080
# 요청 서버 http://my.ysoftman.com:443

# 로컬에서 vue 개발시, 도메인이 다른 호스트 요청시 발생하는
# cors(Cross-origin resource sharing) 에러 해결을 위해
# vue.config.js (webpack) proxy 를 설정한다.
 
module.exports = {
  // 로컬 개발시(이 파일 수정시 npm run serve 로 다시 시작해야함)
  devServer: {
    https: true,
    // /api 로 시작하는 경로 요청을 target 으로 요청
    proxy: {
      '^/api': {
        target: 'https://my.ysoftman.com:443',
        changeOrigin: true,
      },
    disableHostCheck: true,
  },
};

# 위와 같이 프록시 설정하면, cors 이슈도 없고, 쿠키등의 헤더도 잘 전달된다.

# 주의사항
# xmlhttprequest, axios 등으로 요청 호스트명을 빼서 로컬 호스트로 요청해야 한다.
# 그래야 위 (로컬서버에 대한) 프록시 처리가 된다.


#####


# 만약 호스트명이 필요한 실제 서비스 환경과 로컬 develop 개발 환경 구분이 필요한 경우
# host 변수을 두고 다음과 같이 process.env.NODE_ENV 에 따라 '' 로 설정해 처리하자.

let host = "http://my.ysoftman.com:443"
if (process.env.NODE_ENV != null && process.env.NODE_ENV == 'development')
{
  return '';
}


JSON number type range

# json number 타입의 값이 커지면 사용하는 프로그램에 따라 값이 달라 질 수 있다.
# 다음과 같은 json_sample.json 이 있을때,
{
    "strval": "ysoftman",
    "intval1": -123456789123456789,
    "intval2": 123456789123456789,
    "intval3": 123456789123456789123456789123456789,
    "floatval1": -1.123456789123456789,
    "floatval2": 1.123456789123456789123456789,
    "floatval3": 1.123456789123456789123456789123456789
}
# JSON number 스펙을 보면 범위에 제한은 없지만
# JSON 을 사용하는 대부분의 프로그램이 IEEE754 64bit 의 범위 제한이 있다.
IEEE754 64bit 표준에 따라

# 2^64(9223372036854775808 ~ 9223372036854775807) 까지 표시할 수 있다.
# 이 범위를 넘어가면 int 타입은 0, float 타입은 범위 내까지만 표현된다.
{
    StrVal: "ysoftman",
    IntVal1: -123456789123456789,
    IntVal2: 123456789123456789,
    IntVal3: 0,
    FloatVal1: -1.1234567891234568,
    FloatVal2: 1.1234567891234568,
    FloatVal3: 1.1234567891234568
}

# jq 도 float 타입은 64bit 범위 까지만 지원한다.
# man jq : jq currently only has IEEE754 double-precision (64-bit) floating point number support 
# 하지만 정수형은 지수 형태로 최대한 표현된다.
# jq  . ./json_sample.json
{
  "strval": "ysoftman",
  "intval1": -123456789123456780,
  "intval2": 123456789123456780,
  "intval3": 1.2345678912345678e+35,
  "floatval1": -1.1234567891234568,
  "floatval2": 1.1234567891234568,
  "floatval3": 1.1234567891234568
}

# javascript JSON.parse() 도 jq 와 같은 결과
floatval1: -1.1234567891234568
floatval2: 1.1234567891234568
floatval3: 1.1234567891234568
intval1: -123456789123456780
intval2: 123456789123456780
intval3: 1.2345678912345678e+35
strval: "ysoftman"

vue object data 에 새 필드 추가시 변경 감지

# vue 는 data() 명시된 데이터들은 변경 감지(추적)해 자동으로 업데이트 한다.
# 아래와 같이 오브젝트 데이터의 경우 신규 필드를 추가시 일반 할당 연산을 사용하면
# 감지가 안돼 &set 을 사용해야 한다.
data() {
  ysoftmanObj : {
     a : '',
     b : 0,
  },
},

...

methods: {
  updateysoftmanObj() {
     // 신규 c 필드 추가시 set 을 사용해야 업데이트 된다.
     //this.ysoftmanObj.c = 'ysoftman',
     this.$set(ysoftmanObj, 'c', 'ysoftman');
  }
},

# 참고 https://vuejs.org/v2/guide/reactivity.html#For-Objects

URL 공백 인코딩

URL 인코딩시 함수나 프로그래밍 언어에 따라 공백을 %20 또는 + 로 변경할 수 있는데,
사실 URI 스펙 상으로 + 는 reserved word 이고 공백은 %20 이다.
https://tools.ietf.org/html/rfc3986#section-2.2

javascript encodeURI()/encodeURIComponent() URL 인코딩에서도
공백은 %20 으로 처리한다.
테스트 코드
https://github.com/ysoftman/test_code/blob/develop/js/encoding.html

libapreq2(apr_util.h) apreq_escape() 로 URL 인코딩을 하면 공백을 + 로 처리하기 때문에 별도로 + 를 %20 으로 변경하는 작업이 필요하다.
테스트 코드
https://github.com/ysoftman/test_code/blob/develop/apr_test/apr_test.cpp

간단한 http server 프로그램

# 테스트를 위해 http 요청을 처리할 수 있는 간단한 http server 프로그램들
# node.js 기반 http-server
# 설치
npm install http-server -g

# 현재 디렉토리의 파일을 서빙하는 http server 실행
# http://127.0.0.1:8080 로 접속
http-server ./

# python 기반 simple-http
# 현재 디렉토리의 파일을 서빙하는 http server 실행
# http://127.0.0.1:9999 로 접속
python -m SimpleHTTPServer 9999

# python3 에선 http.server 를 사용한다.
python3 -m http.server 9999

package.json 버전 의존성

node.js 의 패키지 설정 파일 package.json 에서 버전을 명시할때의 규칙

기본적으로 연산자가 없으면 version 버전이 정확히 일치하는 것을 사용
1.2.x  는 1.2.0 1.2.1 ... 1.2.9999
"" (empty string) 또는  * 는  >=0.0.0
>version 버전 초과
>=version 버전 이상(버전 포함)
<version 버전 미만
<=version 버전 이하(버전 포함)
version1 - version2 는 >=version1 <=version2 와 같다.
version1 || version2 버전1 또는 버전2
^version 명시된 버전부터 0이 아닌 숫자로 명시된 단위에서의 최대 버전까지의 범위
(예시)
^1.2.3 는 >=1.2.3 <2.0.0
^0.2.3 는 >=0.2.3 <0.3.0
^0.0.3 는 >=0.0.3 <0.0.4
~vesrion 명시된 버전부터 마이너 버전이 명시되면 패치버전 최대까지, 그렇지 않으면 마이너버전 최대까지 범위
(예시)
~1.2.3 는 >=1.2.3 <1.3.0
~1.2 는 >=1.2.0 <1.3.0
~1 는 >=1.0.0 <2.0.0
~0.2.3 는 >=0.2.3 <0.3.0

[참고]
1.2.3.99 버전에서 각 단위
1 : major version
2 : minor version
3 : patch version
99 : build version
https://docs.npmjs.com/misc/semver

golang json marshal escape

// Marshal 은 기본적으로 특수문자들이 유니코드 escape 으로 인코딩된다.
// json/encoding.go Marshal() 주석 중 발췌
// String values encode as JSON strings coerced to valid UTF-8,
// replacing invalid bytes with the Unicode replacement rune.
// The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e"
// to keep some browsers from misinterpreting JSON output as HTML.
// Ampersand "&" is also escaped to "\u0026" for the same reason.
// This escaping can be disabled using an Encoder with DisableHTMLEscaping.
// <, >, &  ====> \u003c, \u003e, \u0026
// Marshal 대신 encoder 를 사용하여 escape 없이 인코딩할 수 있다.
bytesbuffer1 := new(bytes.Buffer)
encoder := json.NewEncoder(bytesbuffer1)
// html escape 없이 인코딩
encoder.SetEscapeHTML(false)
encoder.SetIndent("", "  ")
encoder.Encode("<script>ysoftman</script>")
fmt.Println("jsonString = ", bytesbuffer1.String())

// 참고 javascript 에서 특수 문자 변경시
str = str.replace(/\\u003c/g, '<');
str = str.replace(/\\u003e/g, '>');
str = str.replace(/\\u0026/g, '&');

JavaScript No Access-Control-Allow-Origin 에러 해결하기

# 보안상의 이유로 ajax(XMLHttpRequest) 로 요청하는 도메인과 요청받는 도메인이
# 다를 경우(크로스 도메인) 브라우저 개발 콘솔창에서 다음 에러메시지를 확인 할 수 있다.
"No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. "
# Firefox 로 보면
# CORS(cross origin resource sharing), same origin(동일 출처) 원칙에 따르면 현재 웹페이지의 리소스(스크립트, 이미지, 동영상등)의 출처가 현재 도메인과 다르면 안되지만 이를 가능하게 하는 메커니즘이다.

"교차 원본 요청 차단: 동일 출처 정책으로 인해 http://10.10.10.10/ysoftman 에 있는 원격 자원을 읽을 수 없습니다. 자원을 같은 도메인으로 이동시키거나 CORS를 활성화하여 해결할 수 있습니다."

# 예를 들어 로컬 디스크에서 개발중인 ajax내용이 있는 .html파일 크롬으로 실행시키면 발생할 수 있다.

# 내 PC 도메인은 file:///C:어쩌구저쩌구... 인데 실제 ajax 로 요청하는 호스트 도메인은 http://10.10.10.10 등으로 서로 다르기 때문이다.
# 서버단에서 해결방법
# 서버쪽에서 응답 헤더에 Access-Control-Allow-Origin 값을 모두 허용하도록 설정
# 서버 언어에 맞게 응답 헤더에 설정하도록 한다.
header("Access-Control-Allow-Origin", "*");
header("Access-Control-Allow-Origin: *");

# 클라(브러우저)에서 해결방법
# 크롬의 경우 현재 열려진 모든 크롬을 닫고 아래 옵션을 주어 실행
chrome --disable-web-security

# 아래 크롬 주소창로 크롬 실행시 어떤 옵션으로 실행되었는지 파악할 수 있다.
chrome://version

# IE의 경우
# 요청 후 나타나는 "차단된 콘텐츠 허용" -> 예 선택
# 외부 URL 요청이라면 웹브라우저가 preflight 요청을 수행한다.
# preflight 는 method=options 로 설정하고 해당 URL 로 미리 요청을 날려 요청이 허용(allow) 되는지 파악하는 과정이다.
# preflight 요청시에 다음과 같이 헤더 설정을 한다.
# POST 메소드를 사용할것이고 X-PINGOTHER 헤더가 포함될것이라고 알린다.
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER

# preflight (method=options) 요청후 서버 응답으로 서버에서 사용가능한 리소스, 메소드, 헤더등의 정보를 알려준다.
# http://foo.example 도메인에서만 허용된다.
# POST, GET, OPTIONS 메소드 허용된다.
# 86400 초 동안 preflight 응답을 캐싱
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400

# preflight 응답이 다음과 같다면 모든 도메인에서 접근(요청)이 가능하다.
Access-Control-Allow-Origin: *

# 참고

MongoDB Stored JavaScript 사용

////////////////////////////////////////////////////////////////////////////////
// ysoftman
// MongoDB Test - Stored JavaScript 사용
////////////////////////////////////////////////////////////////////////////////
# 클라이언트 접속하기
bin\mongo 10.10.10.100:10000

# testdb 사용하기(DB 를 미리 생성하지 않는다.)
use testdb

# collection 의 document 전체 삭제
function test1 () {
db.col1.drop();
return true;
}
db.eval(test1);


// insert 하기 데이터 크기가 4GB 를 넘어가서 64bit mongodb 사용
// 100만개(mongovue) 경과시간: 2분 35초 DB크기: 0.5GB
// 1000만개(mongovue) 경과시간: 47분15초 DB크기: 5.95GB (인덱스 메모리에 저장되어 사용)
function test2() {
for (var i=1; i<=1000000; i++)
{
str = {
Name:"HongGilDong",
Mobile:"010-123-4567",
"E-Mail":"ysoftman@naver.com",
Clan:"Best_of_Best",
Inventory:{
Sword:"HighLevel",
Robe:"MediumLevel",
Potions:{
HP_Potion:"SmallSize",
MP_Potion:"BigSize"
},
PortalScroll:"1"
},
Status:{
HP:i,
MP:i
},
Skill:{
FireBall:"1",
Blizzard:"2"
}
}

db.col1.save(str);
}
return 1;
}
db.eval(test2);

# memory dependent 하기 때문에 page fault 가 발생하지 않을 정도의 메모리가 있을 경우를 가정
# 100만개시 index 사용 없이 1초내 검색 완료
# 1000만개시 index 사용 없이 약 2분 소요, index 사용시 1초내
# Status.HP 가 123 인것
db.col1.find({"Status.HP":123}).count()

# Status.HP 가 1 보다 큰것
# 100만개시 index 사용 없이 1초내 검색 완료
# 1000만개시 index 사용 없이 약 2분 소요, index 사용시 1초내
db.col1.find({"Status.HP":{$gt:1}}).count()

# Status.HP 가 1 보다 작은것
# 100만개시 index 사용 없이 1초내 검색 완료
# 1000만개시 index 사용 없이 약 2분 소요, index 사용시 1초내
db.col1.find({"Status.HP":{$lt:1000000}}).count()

# Status.HP 가 1 보다 큰거나 같은것
db.col1.find({"Status.HP":{$gte:1}}).count()

# Status.HP 가 1 보다 작거나 같은것
db.col1.find({"Status.HP":{$gte:1}}).count()

JavaScript getElementByID --> getElementsByName

JavaScript 에서 getElementByID 이 작동되지 않는다면 getElementsByName 사용하도록 하자.

<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<script language="javascript">
function button_action(value)
{
alert(value);
//var param = document.getElementById("aaa").value;
//getElementByID 않는다면 getElementsByName 을 사용
//var param = document.getElementsByName("bbb")[0].value;
alert(param);

}
</script>
<input id="aaa" name="bbb" type="text" value="Yoon Byoung Hoon">
<input id="abc" type="submit" value="Execute" onclick="button_action('ysoftman')">

</html>

Acrobat Javascript 를 이용한 일괄 처리 시퀀스 작업

Acrobat (Acrobat Reader 아님)의 자바스크립트 기능을 이용하여 다수의 pdf 에 대해 일괄작업을 할 수 있다.
Acrobat 실행(문서는열지않음)후 고급 -> 문서처리 -> 일괄 처리 ->새 시퀀스(이름 입력) -> 명령어 선택 -> Javascript 실행 추가 -> 편집에 코드 추가
코드 추가후 실행 대상(입력)에 폴더경로를 지정하고, 출력위치선택(출력)을 선택후 시퀀스 실행하면된다.
참고 :http://www.adobe.com/devnet/acrobat/javascript.html

[예제]
// 특정 폴더(Sub폴더포함)안에 있는 다량의 pdf 의 파일들에서 특정 단어를 파악해 보기
// 출력위치를 변경사항 저장하지 않음으로 선택한다.
// 시퀀스 실행 후 결과 파일은 JavaScript Debugger(Ctrl+J) 를 통해 콘솔 창으로 확인 할 수 있다.
var targetWord = '그리고';
var curWord;
var totalWords;
var i=0, j=0;
console.show();
//console.clear(); // 이전 pdf 시퀀스 결과를 남기기 위해 주석 처리
for (i=0; i<this.numPages; i++)
{
totalWords = this.getPageNumWords(i);
for (j=0; j<totalWords; j++)
{
curWord = this.getPageNthWord(i,j);
if (curWord == targetWord)
{
// 탭(tab)을 넣어 엑셀에 갖다 붙이기 쉽도록 한다.
console.println(this.documentFileName + "\t" + i + "\t" + curWord);
}
}
}