Node.jsで設定ファイルを読み込む(https://qiita.com/_daisuke/items/0d3a76a1290f08f4fea5)

 この記事は最終更新日から1年以上が経過しています。

Node.jsでアプリを作った時に、パラメータを設定ファイルに書き出して開発環境やステージング、プロダクション環境などで切り替えたことがあります。この時に使用できるのが、node-configモジュール。

設定ファイルとして対応しているフォーマット

  • Javascript Object Notation - .json
  • Javascript5 Object Notation - .json5
  • Yet another markup language - .yaml
  • Javascript - .js
  • CoffeeScript - .coffee
  • CoffeeScript Object Notation - .cson
  • Properties file format - .properties

ファイルの読み込み順

通常は実行しているアプリの./configディレクトリ下の設定ファイルを読み込みます。また、$NODE_ENV環境変数の値を見て読み込むファイルを切り替える様にすることもできます。

./configディレクトリ以下のファイルは次の順番で読み込まれる様です。

default.EXT
default-{instance}.EXT
{hostname}.EXT
{hostname}-{instance}.EXT
{deployment}.EXT
{deployment}-{instance}.EXT
{hostname}-{deployment}.EXT
{hostname}-{deployment}-{instance}.EXT
local.EXT
local-{instance}.EXT
local-{deployment}.EXT
local-{deployment}-{instance}.EXT  
  • .EXT 対応しているフォーマットの拡張子
  • {instance} Multi-Instnance Deploymentsのためのオプションのインスタンス名文字列
  • {hostname} サーバーのホスト名。HOSTorHOSTNAME環境変数の値
  • {deproyment} デプロイメント名。$NODE_ENV環境変数の値

defalut.EXTは他のファイルでパラメータを上書きしてマージすることができます。

サンプル

準備

$ mkdir sample-config
$ cd sample-config/
$ mkdir config
$ npm install config
config@1.8.1 node_modules/config
$ npm install js-yaml
js-yaml@3.2.3 node_modules/js-yaml
├── esprima@1.0.4
└── argparse@0.1.15 (underscore@1.4.4, underscore.string@2.3.3)
$ ls
config      node_modules
$ cd config

設定ファイル作成

configディレクトリ以下に設定ファイルを作成します。

default.yaml

config:
    fname: "defalut.yaml"
    defaultParam: "default.yaml parameter"

hostname.yaml

config:
    fname: "hostname.yaml"
    hostnameParam: "hostname.yaml parameter"

myDevelopment.yaml

config:
    fname: "myDevelopment.yaml"
    myDevelopmentParam: "myDevelopment.yaml parameter"

hostname-myDevelopment.yaml

config:
    fname: "hostname-development.yaml"
    hostDevParam: "hostname-development.yaml parameter"

local.yaml

config:
    fname: "local.yaml"
    localParam: "local.yaml parameter"

設定ファイルを読み込む実行スクリプトを作成

app.js

ConfigFile = require('config');

console.log(ConfigFile.config);

// 全ての設定ファイルで共通項目
console.log("config.fname              : " + ConfigFile.config.fname);
// default.yaml only
console.log("config.defaultParam       : " + ConfigFile.config.defaultParam);
// hostname.yaml only
console.log("config.hostnameParam      : " + ConfigFile.config.hostnameParam);
// myDevelopment.yaml only
console.log("config.myDevelopmentParam : " + ConfigFile.config.myDevelopmentParam);
// hostname-myDevelopment.yaml only
console.log("config.hostDevParam       : " + ConfigFile.config.hostDevParam);
// local.yaml only
console.log("config.localParam         : " + ConfigFile.config.localParam);

実行する

$HOST(or $HOSTNAME)、$NODE_ENV未設定

環境変数を設定しないで事項すると、次の通り。

$ node app.js
{ fname: 'local.yaml',
  defaultParam: 'default.yaml parameter',
  localParam: 'local.yaml parameter' }
config.fname              : local.yaml
config.defaultParam       : default.yaml parameter
config.hostnameParam      : undefined
config.myDevelopmentParam : undefined
config.hostDevParam       : undefined
config.localParam         : local.yaml parameter

default.yaml、local.yamlでマージされている。
両ファイルの共通項目はファイルの読み込み順に則って、local.yamlの値で上書きされる。

$HOST環境変数を設定

$ export HOST=hostname
$ node app.js
{ fname: 'local.yaml',
  defaultParam: 'default.yaml parameter',
  hostnameParam: 'hostname.yaml parameter',
  localParam: 'local.yaml parameter' }
config.fname              : local.yaml
config.defaultParam       : default.yaml parameter
config.hostnameParam      : hostname.yaml parameter
config.myDevelopmentParam : undefined
config.hostDevParam       : undefined
config.localParam         : local.yaml parameter

hostname.yamlが読み込み対象となる。

$NODE_ENV環境変数を設定

$ export HOST=hostname
$ export NODE_ENV=myDevelopment

$ node app.js
{ fname: 'local.yaml',
  defaultParam: 'default.yaml parameter',
  myDevelopmentParam: 'myDevelopment.yaml parameter',
  hostnameParam: 'hostname.yaml parameter',
  hostDevParam: 'hostname-development.yaml parameter',
  localParam: 'local.yaml parameter' }
config.fname              : local.yaml
config.defaultParam       : default.yaml parameter
config.hostnameParam      : hostname.yaml parameter
config.myDevelopmentParam : myDevelopment.yaml parameter
config.hostDevParam       : hostname-development.yaml parameter
config.localParam         : local.yaml parameter

HOSTNODE_ENVに設定してファイルの情報が読み込まれている。

runtime.json

実行後にconfigディレクトリにruntime.jsonファイルができている場合があります。
これは、node-configが自動で設定を反映してくれるファイルです。

詳細は、GitHubにあるnode-cofigのWikiを見ると色々書いてあります。(英語ですが・・・)


リバースプロキシ (reverse proxy)

pointこの用語のポイント

pointプロキシだよ

pointWebサーバのパシリだよ

pointWebサーバの身代わりをするよ

スポンサーリンク

 簡単に書くよ

リバースプロキシ (reverse proxy)とは

恥ずかしがり屋なWebサーバさん用代理交渉人のこと。
もう少し真面目に書くと

Webサーバさんの身代わりになってホームページのファイルを返してくれるサーバさんのこと
です。

image piyo

 詳しく書くよ

プロキシは「Webブラウザさんの身代わりになってホームページアクセスしてくれるサーバさん」です。
詳細は用語「プロキシ」の解説をご覧ください。

リバースプロキシ

文字通り、このプロキシさんの逆バージョンが「リバースプロキシ」です。
普通のプロキシさんはWebブラウザの身代わりになってくれますが、リバースプロキシさんはWebサーバの身代わりになってくれます。

リバースプロキシ2

……と、いきなり言われても分かりませんよね。

大丈夫です。
順番に見ていきましょう。

あなたがホームページを見ようとすると、まず、ホームページを見るときに使うソフト(Webブラウザ)からホームページのファイルが置いてあるコンピュータ(Webサーバ)に対して「このページをおくれ」とお願いが出されます。

リバースプロキシ3

そのお願いに対して、WebサーバさんからWebブラウザさんに「ほれ、そのページだよ」とお返事がきます。

リバースプロキシ4

お返事を受け取ったWebブラウザさんは、受け取ったページを画面上に表示します。

リバースプロキシ5

これが普通にホームページを見るときの流れです。

ホームページが表示されるまでの流れは

1.Webブラウザ→「このページおくれ」→Webサーバ
2.Webブラウザ←「ほれ、そのページだよ」←Webサーバ


となります。

リバースプロキシ6

次に、普通のプロキシさんが混ざる場合の流れを見てみましょう。

普通のプロキシさんは「Webブラウザさんの身代わり」です。
Webブラウザさんは、まず、プロキシサーバさん(=普通のプロキシ)に対して「あのページを貰ってきておくれ」というお願いを出します。

リバースプロキシ7

次に、プロキシサーバさんがWebブラウザさんの代わりに「このページをおくれ」なお願いをWebサーバさんにします。

リバースプロキシ8

お願いを受け取ったWebサーバさんは、プロキシサーバさんに対して「ほれ、そのページだよ」とお返事を出します。

リバースプロキシ9

Webサーバさんからお返事を受け取ったプロキシサーバさんは、Webブラウザさんに「ほれ、そのページだよ」とお返事を出します。

リバースプロキシ10

プロキシサーバさんからお返事を受け取ったWebブラウザさんは、受け取ったページを画面上に表示します。

リバースプロキシ11

これが普通のプロキシさんが混ざった場合の流れです。

ホームページが表示されるまでの流れは

1.Webブラウザ→「俺の代わりにこのページ貰ってきておくれ」→プロキシサーバ
2.プロキシサーバ→「このページおくれ」→Webサーバ
3.プロキシサーバ←「ほれ、そのページだよ」←Webサーバ
4.Webブラウザ←「ほれ、貰ってきたページだよ」←プロキシサーバ


になります。

リバースプロキシ12

「ページをおくれ」とお願いする側を「クライアント」と呼びます。
「ほれ、そのページだよ」とお返事をする側を「サーバ」と呼びます。
「Webブラウザ+プロキシサーバ」で1つのクライアントなイメージです。
よく分からなければ、Webブラウザのパシリが普通のプロキシだと考えてください。

リバースプロキシ13

さぁ、いよいよ本題です。
ホームページを表示する流れにリバースプロキシさんが混ざる場合を見てみましょう。

流れにリバースプロキシさんが混ざった場合、Webブラウザさんはリバースプロキシサーバさん(=リバースプロキシ)に対して「あのページが見たい」というお願いを出します。

リバースプロキシ14

お願いを受け取ったリバースプロキシサーバさんは、本来のWebサーバさんに「このページをくれってきたよ」と伝えます。

リバースプロキシ15

それに対して、本来のWebサーバさんは「じゃあ、このページ返してあげて」とリバースプロキシサーバさんに対して、お返事をします。

リバースプロキシ16

本来のWebサーバさんからお返事を受け取ったリバースプロキシサーバさんは、Webブラウザさんに「ほれ、そのページだよ」とお返事します。

リバースプロキシ17

リバースプロキシサーバさんからお返事を受け取ったWebブラウザさんは、受け取ったページを画面上に表示します。

リバースプロキシ18

これがリバースプロキシさんが混ざった場合の流れです。

ホームページが表示されるまでの流れは

1.Webブラウザ→「このページおくれ」→リバースプロキシサーバ
2.リバースプロキシサーバ→「このページをくれってきたよ」→Webサーバ
3.リバースプロキシサーバ←「じゃあ、このページ返してあげて」←Webサーバ
4.Webブラウザ←「ほれ、そのページだよ」←リバースプロキシサーバ


になります。

リバースプロキシ19

普通のプロキシさんの場合は「Webブラウザ+プロキシサーバ」で1つのクライアントでしたが、リバースプロキシさんの場合は「リバースプロキシサーバ+Webサーバ」で1つのサーバになるイメージです。
よく分からなければ、Webサーバのパシリがリバースプロキシだと考えてください。

リバースプロキシ20

リバースプロキシを使うメリットは

(1).身元を隠せる
(2).負荷分散ができる


でしょうかね。

(1)のメリットは普通のプロキシと同じです。
矢面に立つのはリバースプロキシサーバさんです。
裏に控えるWebサーバの正体はバレません。

(2)はちょっとややこしいのですが、1つのリバースプロキシに複数のWebサーバを割り当てることができるのです。
普段は

Webブラウザ←→リバースプロキシサーバ←→Webサーバ

の流れですが、Webサーバを複数用意して

Webブラウザ←→リバースプロキシサーバ←→Webサーバ1、Webサーバ2、Webサーバ3

のようにすることもできます。

リバースプロキシ21

そうすれば、Webブラウザさんとやり取りする部分は何も変えないで、Webサーバさん1台あたりの大変さを減らすことができますよね?

リバースプロキシ22

そのようにして負荷分散に使えたりもします。

image piyo2

 一言でまとめるよ

まぁ「リバースプロキシ」って単語が出てきたら「Webサーバさんの身代わりなんだな~」と、お考えください。

一番上に戻るよ


Webhookって何?を子どもでもわかるように描いてみた
(https://kintone-blog.cybozu.co.jp/developer/000283.html)

시작하기전 임팩트있게 요약하면

어떤 데이타를 url(http post/get)을 이용해서 다른 서버로 리퀘스트 보내는 것.

はじめに

こんにちは。最近娘に絵本を読むのがめんどくさいダン吉です。今日は、巷で話題のWebhookとは何かをわかりやすく伝えるために、画力に圧倒的に自信のない私が恥を覚悟で、子どもによく描いてあげるような絵で表してみます。

Webhookとは

Webhookとは何?という方のために、cybozu developer network内のこちらのTipsの冒頭の記述を引用します。

Webhookとは(略)、Webアプリケーションでイベントが実行された際、外部サービスにHTTP で通知する仕組みです。
(参照)「コーディングなしで超簡単!kintoneのWebhookでGmailに通知する」-cybozu developer network

サービス同士の連携に使うものだとシステムに関わる方はピンと来ると思いますが、そうでない方にはちょっとまだかたいでしょうか。
IMG_20170215_0014.jpg

私も最初に聞いたときは、上のハンガーのフックのようなものを想像し、それでどうやって外部サービスに通知?と違和感を感じました。

そこで、「イベント」=何かのきっかけ、「HTTPで通知」=HTTPでデータを送る というイメージで脳内変換をしてみました。すると頭に浮かんできたのは、フックではなくてむしろ以下のこれでした。

lgi01a201402210300.jpg

投石機です。中世で使われたという兵器、カタパルトです。某オンラインゲームシリーズ界隈では有名ですね。しかし、今回は子どもでもわかりやすいイメージで伝えたいと思いますので、本当に下手なので恥ずかしい限りですが、このように表してみました。

じゃじゃん。

▼ Webhookのイメージ(子どもにもわかるカタパルトVer.)
IMG_20170215_0012.jpg

画力の関係で投石機がシーソーになってしまいましたがこのようなイメージです。あえて手描きのみです。

以下に補足の解説をします。

1. 送り手のサービスでデータの追加などの「きっかけ(event)」が起こる
2. 「きっかけ(event)」により、指定した「宛先※」へのHTTP通信が発生 ※ここでいう「宛先」とはURLのことです
→webhook URL로 request를 보내면(물론 http 프로토콜), 웹훅에서 request를 받아 일을 처리함
3. 指定した「宛先」へデータを送ることができる

もっとわかりやすくするために、イメージをパラパラマンガにしてみました。

▼ Webhookのイメージ(パラパラVer.)
1487106701.gif

いかがでしょうか。細かいところでつっこみどころはあるかもしれませんが、自分の娘(6歳)に「これ何かわかる?」と聞いたところ、「別のところに荷物をシーソーで送ってる!」と答えてもらえましたのでよしとしましょう。

Webhookで何ができるのか

そんなWebhook機能が、2017年2月版でkintoneに標準でつきました。
(ご利用にはスタンダードコースのご契約が必要です。)

具体的には、使える「きっかけ」としてアプリのレコード追加、編集、ステータスの更新のタイミングで、他のサービスにkintoneのデータを送ることができます。

たとえば、こんなことができます。

● kintoneのToDoアプリにレコードの追加があったら、Eメールやチャットで通知を受け取る
● kintoneで投稿管理アプリのレコードのステータスが「承認」になったら、レコードの内容をSNSに投稿する

ただし、ひとつ気をつけなければいけないことは、受け手のサービスに対応したデータの変換の必要です。

しつこく下手な絵、いきます。

▼ 送ったはいいものの、宛先で受け入れられない場合がある
IMG_20170215_0014 のコピー.jpg

ただ送っただけでは、データ形式が対応していないと受け入れてもらうことができません。そのため変換処理のプログラミングが必要になることがあります。Webhookで簡単にサービス連携ができると期待をした人は少し敷居が高く感じられるかもしれません。


-인텐트와 엔티티는 연관성이 없는 서로 다른 개념

:인텐트는 사용자의 "의도"를 파악하는 지표료, 같은 의도를 나타내는 여러개의 문장을 하나의 인텐트에 저장함으로써 어떤 유저로부터 어떤 반응이 나오면 인텐트에 저장된 문장들과 일치하는지를 파악하여 인식한다.

:엔티티는 비슷한 단어들의 집합

:사용자가 어떤 인풋을 나타낼시 왓슨은 인텐트를 통해 인식하거나, 엔티티를 통해 인식하거나, 둘 다를 통해 인식한다.


-dialog의 기능

1.If bot Recogizes :  가장 기본적인 기능으로, #인텐트, @엔티티, $변수 의 값이 들어갈 수 있고, 이에 간단에 함수들이 합쳐진 논리도 들어올 수 있다.

2.slot : 내부에 found, unfound의 기능이 있다.

3.multi response : 조건에 따라 다른 response를 주고 싶을때 사용한다.

4.setup context : $변수에 값을 줄 수 있다.

5.and finally : dialog이후에 어떤 행동을 할지 정해주는 기능으로, wait for user input/ skip user input / jump to other dialog 의 기능이 있다.


-dialog에서 response는 하지 않고 변수 설정만 하고 싶을 시에는 if bot Recognizes 를 true로 설정 후 .and finally를 jump to other dialog 하면 된다.


-dialog내에 들어가는 각 #인텐트, @엔티티 는 내가 지정해 놓은 인텐트와 엔티티가 저장되는 것이 아니고, 유저로부터 받은 일회적인 input 만들어온다.


-dialog내에서 사용할 수 있는 함수들을 다음 사이트에서 참고하라.

(https://console.bluemix.net/docs/services/conversation/dialog-methods.html#expression-language-methods)


-try it을 시행하면 우상단에 manage context가 있는데 각페이즈별로 내가 설정한 $변수 들에 어떤 값들이 들어오는지 볼 수 있다.


-【기본이해】

왓슨은 유저인풋에 대응하여 엔티티와 인텐트를 매칭하는 작업을 함. 스스로 스마트하게 매칭하는 작업이 AI의 내부 논리가 하는 일이며, 서비스에 대해 비싼 가격을 요구하는 이유이기도 함

예를 들어 


@food:ham,hamburger,cheese,sushi,bulgogi,coffee

@drink:coffee,coke,sprite,wine

#hungry:I want to eat hamburger

의 인덴트와 엔티티가 존재할 때


유저 인풋이 【cheese】이면, @food가 매칭되므로

・ @food에 cheese라는 값을 담고

・ entities객체에 매칭된 @food:cheese의 정보를 담음

[{"entity":"food","location":[x,x],"value":"cheese","confidence":1,"expected":true}]


유저 인풋이 【hamburger】이면, @food와 #hungry가 매칭되므로

・ @food에 cheese라는 값을 담고

・ entities객체에 매칭된 @food:cheese의 정보를 담음

[{"entity":"food","location":[x,x],"value":"cheese","confidence":1,"expected":true}]

・ #hungry:I want to eat hamburger라는 값을 담고

・ intent객체에 매칭된 #hungry:I want to eat hamburger의 정보를 담음

[{"intent":"hungry","confidence":0.8247748613357544}]


유저 인풋이 【coffee】이면, @food,@drink가 매칭되므로

・ @food에 coffee라는 값을 담고, @drink에 coffee라는 값을 담음

・ entities객체에 매칭된 @food:coffee, @drink:coffee의 정보를 담음

[{"entity":"food","location":[x,x],"value":"coffee","confidence":1,"expected":true},{"entity":"drink","location":[x,x],"value":"coffee","confidence":1,"expected":true}]


유저 인풋이 【sushi,bulgogi】이면, @food,@food(@food가 두번 매칭됨)가 매칭되므로

・ @food에 sushi라는 값을 담고, @food에 bulgogi라는 값을 담음

・ entities객체에 매칭된 @food:sushi, @food:bulgogi의 정보를 담음

[{"entity":"food","location":[x,x],"value":"sushi","confidence":1,"expected":true},{"entity":"food","location":[x,x],"value":"bulgogi","confidence":1,"expected":true}]


entities에 접근하는 방법

・<? entities ?> <- 왓슨이 유저인풋에 대응하여 매칭시킨 엔티티들을 배열로 담음

[{"entity":"シネマズギフトカード関連","location":[0,6],"value":"ギフトカード","confidence":1,"expected":true},{"entity":"テスト","location":[0,6],"value":"ギフトカード","confidence":1,"expected":true}]

・<? entities['テスト'] ?>하면, 일치된 entities중에서 엔티티명이 テスト인 것만 필터링됨(intent는 이런식의 문법 사용 안됨.)

예를 들어 <? entities ?> 인식된 모든 엔티티의 결과가

[{"entity":"シネマズギフトカード関連","location":[0,6],"value":"ギフトカード","confidence":1,"expected":true},{"entity":"テスト","location":[0,6],"value":"ギフトカード","confidence":1,"expected":true}]

일때,

<? entities['テスト'] ?> 하면, 

[{"entity":"テスト","location":[0,6],"value":"ギフトカード","confidence":1,"expected":true}]이 검색돼

하나만 일치시에 객체인것처럼 보이지만 배열로 리턴됨에 주의


【intent에 접근하는 방법

・<? intent ?> <- 왓슨이 유저인풋에 대응하여 매칭시킨 인텐츠들중 confidence(일치도)가 높은 상위 10개를 내림차순 배열로 리턴됨

[{"intent":"シネマズギフトカード販売","confidence":0.5247748613357544},{"intent":"シネマズギフトカード残高確認","confidence":0.35115565061569215},{"intent":"シネマズギフトカード利用方","confidence":0.32244925498962407},{"intent":"シネマズギフトカード有効期限","confidence":0.3199282050132752},{"intent":"挨拶","confidence":0.2722834348678589},{"intent":"TCXとは","confidence":0.2501681208610535},{"intent":"IMAXとは","confidence":0.24999908208847046},{"intent":"劇場オープン時間","confidence":0.2475628912448883},{"intent":"プレミアボックスとは","confidence":0.24686517417430878},{"intent":"スクリーン12と13の場所","confidence":0.2400550663471222}]

・객체내부값에는 json에 접근하는 방법과 동일하게 접근하면됨.

<? intent[0]['intent'] ?> => "シネマズギフトカード販売"

<? intent[1]['confidence'] ?> => 0.35115565061569215


@entities와 #intent에 관해

*watson doc에 의하면 intent의 생략표시구문은 존재하지 않는다.

@entities는 순수하게 값만 들어가는 배열이므로, @entities.confidence라던지, @entities.location같은 문법을 사용할 수없다.

사용할 수 있는 것은 배열에 관한 함수들 뿐 @entities.size() @entities[0] 등

#intent는 boolean이다.




-개행은 \n로 하고, 프론트에 따라 다른데 프론트가 웹이면 </br>로 줘야함


-digression:여러 조건트리에서 일치하는게 없으면 루트로 보냄(지금까진 true로 처리했던것)

go away

come into

return


제약: 루트 노드로밖에 이동읆 못함

차일드 노드로 true를 설정하면 digression 사용 불가


-폴더 나누기 기능

노드와 다른점은 폴더의 경우 레스폰스가 없음

폴더의 if bot recongnize기능 0

레스폰스 x


디그리션을 다이알로그 하나하나 설정하지 않고

폴더 에서 디그리션 설정하면 그 아래 것들도 외괄 설정이 가능


ui로써 보기가 좀 좋아지고, digression 관리가 쉬우저ㅣ는 정도일가




-도중에 그만두는 기능

일단 return을 오프로(그만뒀는데 다시 돌아오면 안되니까)


-루트 마지막에 공통 노드를 

리셋토, 안내종료 같은 최후의 노드를 넣어두고 return은 off 로함





-assign코맨드로 변수에 값 저장

-uiexplorer : 오브젝트의 프로퍼티같은걸 변경할 수 잇음

-ocr - screnn scraping

-오케스트라 : 웹(오케스트라)에 로봇의 특정 번호를 등록함

-get Asset : 웹에 등록한 변수를 가져올수 있음. AA랑 비슷하네

-vb에서 조작가능한 모든것이 다들어감. 근데 type을 맞춰줘야함

-기본 오프젝트들의 객체는 이미선언되어 있는듯.

-datatable : output에서 datatable의 변수를 설정하면 read range 등 결과가 datatable로 들어오는 결과를 변수에 담음

-output datatable : input에 datatable 타입의 변수를 넣으면 datatable 결과를 string으로 변환시켜줌, 결과를 시각적으로 나타내어 주지는 않음

-변수의 type에 주의할 것

-변수를 각 페이즈에 따라 로컬, 글로벌로 설정 가능

-플로우차트와 시퀀스 : 설계로써, 플로우차트안에 플로우차트와 시퀀스를 담을 수 있고, 역으로 시퀀스 안에 플로우차트를 담을 수도 있음

-invoke code

-DateTime.Now.AddMonths(-1).ToString("MM") : 전달의 달

/ DateTime.Now.AddMonths(-1).ToString("yyyyMMdd")  : 전달의 년월일

/ DateTime.DaysInMonth(DateTime.Now.Year,DateTime.Now.AddMonths(-1).Month).ToString : 전달의 마지막날


-String.IsNullOrEmpty ->isempty

-IS/ IsNot

-()x -> offset


-셀안에 값저장후 엔터누르지않으면 오브젝트가 셀에 귀속되어 버림


-selector 설정 -> *로 범용성을 높여 비슷한 이름의 윈도우가 열려도 반응할 수 있도록하기







1.設定方法

openfiles コマンド が機能するには事前に以下の設定、及び設定後のリブートが必要です。

C:\>openfiles /local on

成功: システム グローバル フラグ 'maintain objects list' は有効になりました。
システムを再起動すると、変更が有効になります。

(注意)ネットワーク経由で他のユーザが開いているローカルのファイル(ローカルサーバの共有を使用して他のユーザが開いているファイル)一覧は "openfiles /local on"の設定をしなくても一覧表示可能。
openfiles /query /v で出力されます。

2.一覧表示

現在開かれているファイルの一覧を表示するには以下のコマンドを実行します。

C:\>openfiles /query /v

以下例では test.txtを開いているプロセスを表示しています。ローカルファイルと共有ファイル(ネットワーク経由で他のサーバ開く)で結果が異なります。

(1)ローカルファイルの場合

C:\>openfiles /query /v | findstr test.txt
408 Administrator 1340 Hidemaru.exe C:\temp\test.txt

(注) 秀丸の「ファイルの排他制御」「読み書き禁止」でファイルを排他的に開いた場合。


(2)共有ファイルの場合(openfilesを実行しているサーバに対して、ネットワーク経由で他のユーザが開いているファイル)

C:\>openfiles /query | findstr test.txt
210 administrator Windows C:\temp\test.txt

(注) openfiles コマンドはリモートコンピュータ上の情報を見ることも可能です。

openfiles /query /s <ipアドレス> /u <ユーザ名> /p <パスワード>



(3)切断方法(強制クローズ)
●ローカルファイルの場合
ローカルで開いているファイルは切断(強制クローズ)できません。ファイルを開いているアプリケーションを終了させましょう。
(不明なプロセスがファイルを開いて削除できない場合などの強制ファイルクローズは不可となります。)

●共有ファイルの場合
openfilesを実行しているサーバに対して、ネットワーク経由で他のユーザが開いているファイルは切断(強制クローズ)が可能です。
以下の例ではネットワーク経由で開かれている test.txtを強制切断しています。

C:\>openfiles /query | findstr test.txt
210 administrator Windows C:\temp\test.txt

(上記ファイルはネットワーク経由でadministratorが共有を使用して test.txtを開いている)

C:\>openfiles /Disconnect /ID 210
成功: 開いているファイル "C:\temp\test.txt" への接続は切断されました。

C:\>openfiles /query | findstr test.txt
(結果無し)

(注)
ファイルを排他無しで開いている場合は開いているファイル一覧には表示されません。
例として、秀丸の「ファイルの排他制御」が「しない」の場合、結果の一覧に表示されません。「ファイルの排他制御」が「上書きだけ禁止」あるいは「読み書き禁止」の場合は表示されます。

3.設定を戻す

・/local on の設定を行うと性能が悪化します。よって設定が不要なら設定を戻すことを推奨します。

C:\>openfiles /local off

成功: システム グローバル フラグ 'maintain objects list' は無効になりました。
システムを再起動すると、変更が有効になります。


var, let, const 차이점은?

  • var는 function-scoped이고, letconst는 block-scoped입니다.

  • function-scoped와 block-scoped가 무슨말이냐?

var(function-scoped)

jsfiddle 참고주소

// var는 function-scope이기 때문에 for문이 끝난다음에 i를 호출하면 값이 출력이 잘 된다.
// 이건 var가 hoisting이 되었기 때문이다.
for(var j=0; j<10; j++) {
  console.log('j', j)
}
console.log('after loop j is ', j) // after loop j is 10


// 아래의 경우에는 에러가 발생한다.
function counter () {
  for(var i=0; i<10; i++) {
    console.log('i', i)
  }
}
counter()
console.log('after loop i is', i) // ReferenceError: i is not defined

그럼 항상 function을 만들어서 호출해야 할까? 그건 아니다.

javascript에서는 immediately-invoked function expression (or IIFE, pronounced "iffy")라는것이 있다.

IIFE로 function-scope인거 처럼 만들 수가 있다.

// IIFE를 사용하면
// i is not defined가 뜬다.
(function() {
  // var 변수는 여기까지 hoisting이 된다.
  for(var i=0; i<10; i++) {
    console.log('i', i)
  }
})()
console.log('after loop i is', i) // ReferenceError: i is not defined

근데 javascript는 여기서 좀 웃긴 부분이 있다.

위에서 잠깐 말했지만 IIFE는 function-scope처럼 보이게 만들어주지만 결과가 같지는 않다.

// 이 코드를 실행하면 에러없이 after loop i is 10이 호출된다.
(function() {
  for(i=0; i<10; i++) {
    console.log('i', i)
  }
})()
console.log('after loop i is', i) // after loop i is 10

위에 코드가 아무 에러 없이 실행되는 이유는 i가 hoisting이 되어서 global variable이 되었기 때문이다.

그래서 아래와 같이 된 것이다.

var i
(function() {
  for(i=0; i<10; i++) {
    console.log('i', i)
  }
})()
console.log('after loop i is', i) // after loop i is 10

IIFE는 쓰는데 이렇게 hoisting이 된다면 무슨 소용이 있겠는가?!

그래서 이런 hoisting을 막기 위해 use strict를 사용한다.

// 아까랑 다르게 실행하면 i is not defined라는 에러가 발생한다.
(function() {
  'use strict'
  for(i=0; i<10; i++) {
    console.log('i', i)
  }
})()
console.log('after loop i is', i) // ReferenceError: i is not defined

어떤가? 뭔가 변수 선언때문에 너무 많은 일을 한다고 생각하지 않는가?

그럼 letconst에 대해서 알아보자.

let, const(block-scoped)

  • es2015에서는 letconst가 추가 되었다.

javascipt에는 그동안 var만 존재했기 때문에 아래와 같은 문제가 있었다.

// 이미 만들어진 변수이름으로 재선언했는데 아무런 문제가 발생하지 않는다.
var a = 'test'
var a = 'test2'

// hoisting으로 인해 ReferenceError에러가 안난다.
c = 'test'
var c

위와 같은 문제점으로 인해 javascript를 욕 하는 사람이 참 많았다.

하지만 letconst를 사용하면 var를 사용할때보다 상당히 이점이 많다.

두개의 공통점은 var와 다르게 변수 재선언 불가능이다.

let과 const의 차이점은 변수의 immutable여부이다.

let은 변수에 재할당이 가능하지만,

const는 변수 재선언, 재할당 모두 불가능하다.

// let
let a = 'test'
let a = 'test2' // Uncaught SyntaxError: Identifier 'a' has already been declared
a = 'test3'     // 가능

// const
const b = 'test'
const b = 'test2' // Uncaught SyntaxError: Identifier 'a' has already been declared
b = 'test3'    // Uncaught TypeError:Assignment to constant variable.

letconst가 hoisting이 발생하지 않는건 아니다.

var가 function-scoped로 hoisting이 되었다면

letconst는 block-scoped단위로 hoisting이 일어나는데

c = 'test' // ReferenceError: c is not defined
let c

위에 코드에서 ReferenceError가 발생한 이유는 tdz(temporal dead zone)때문이다.

let은 값을 할당하기전에 변수가 선언 되어있어야 하는데 그렇지 않기 때문에 에러가 난다.

이건 const도 마찬가지인데 좀 더 엄격하다.

// let은 선언하고 나중에 값을 할당이 가능하지만
let dd
dd = 'test'

// const 선언과 동시에 값을 할당 해야한다.
const aa // Missing initializer in const declaration

이렇게 javascript에 tdz가 필요한 이유는 동적언어이다 보니깐 runtime type check 가 필요해서이다.

Reference


XML Tree


XML documents form a tree structure that starts at "the root" and branches to "the leaves".


XML Tree Structure

DOM node tree

An Example XML Document

The image above represents books in this XML:

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
  <book category="cooking">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
  <book category="children">
    <title lang="en">Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <price>29.99</price>
  </book>
  <book category="web">
    <title lang="en">Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <price>39.95</price>
  </book>
</bookstore>


XML Tree Structure

XML documents are formed as element trees.

An XML tree starts at a root element and branches from the root to child elements.

All elements can have sub elements (child elements):

<root>
  <child>
    <subchild>.....</subchild>
  </child>
</root>

The terms parent, child, and sibling are used to describe the relationships between elements.

Parent have children. Children have parents. Siblings are children on the same level (brothers and sisters).

All elements can have text content (Harry Potter) and attributes (category="cooking").


Self-Describing Syntax

XML uses a much self-describing syntax.

A prolog defines the XML version and the character encoding:

<?xml version="1.0" encoding="UTF-8"?>

The next line is the root element of the document:

<bookstore>

The next line starts a <book> element:

<book category="cooking">

The <book> elements have 4 child elements: <title>, <author>, <year>, <price>.

<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>

The next line ends the book element:

</book>

You can assume, from this example, that the XML document contains information about books in a bookstore.

'C Lang > Web Lang Program Diary' 카테고리의 다른 글

WebSocket이란?  (0) 2018.07.23
ngrok로 터널열기  (0) 2018.05.22
무료 도메인 만들기  (2) 2018.03.15
웹 서버와 웹 애플리케이션 서버  (0) 2018.02.04
Web client/server side 프로그래밍 일기  (0) 2017.12.19

+ Recent posts