0. 업무 중 불편사항

 

업무중 여러 설정 정보를 취합 하여 전달하는 API가 존재 한다.

해당 정보들은 RDB에 저장되어 있으며 일반적으로는 1개의 row가 존재하는 마스터 테이블이다.

 

해당 데이터들은 변경이 필요하지만 자주 변경은 되지않으므로 CRUD를 위하여 WEB과 API가 필요하다.
Ex) A 설정정보를 위해 A테이블에 대한 API CRUD와 WEB 개발 (데이터 1건)

B 설정정보를 위한 B 테이블에 대한 API CRUD와 WEB 개발 (데이터 1건)

C 설정정보를 위한 C 테이블에 대한 API CRUD와 WEB 개발 (데이터 1건)

... 등등등

단 해당 데이터들은 반드시 1건은 아니며 최대 5건 내외 정도 될 듯 하다 (3건 이상은 못 본듯 하지만 설계상 가능)

 

해당 건들을 조건에 따라 조합하여 1개의 종합 설정정보를 만들어 API로 전달한다.

 

위 데이터들을 위해 CRUD API와 WEB 개발 하는 것은 불필요해 보이며, 변동이 적고, 조건에 따른 조합이 필요했다.

 

이를 위해 WorkFlow를 도입하여 테스트 해보고자 했다

 


1. Node-Red 란 무엇인가.

Node-RED(노드 레드)는 하드웨어 장치들, API, 온라인 서비스를 사물인터넷의 일부로 와이어링(배선화)시키기 위해 본래 IBM이 개발한 시각 프로그래밍을 위한 플로 기반 개발 도구이다.

Node-RED는 브라우저 기반 플로 편집기를 제공하므로 자바스크립트 함수를 개발하는데 사용할 수 있다. 애플리케이션의 요소들은 재사용을 위해 저장하거나 공유할 수 있다. 런타임은 Node.js 위에서 개발되어 있다. Node-RED에서 만든 플로는 JSON을 사용하여 저장된다. 버전 0.14 이후 MQTT 노드들은 적절하게 구성된 TLS 연결을 만들 수 있다.

2016년에 IBM은 Node-RED를 오픈 소스 "JS Foundation" 프로젝트로 기여했다.

출처 위키백과

 


2. Node-Red 설치

2-1. 도커 설치

  • 추후 docker compose로 구성하여 volume 또한 잡아주어야 관리가 용이하다.
docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered nodered/node-red

 

2-2. 로컬 설치

  • 주의 Node.js 설치가 필요하다.
npm install -g --unsafe-perm node-red

 

실행

node-red

 

 

접속

브라우저에서 http://localhost:1880

 


3. Node-Red에서 RestAPI 테스트

왼쪽의 팔레트에서 http in, function, http response를 드래그하여 플로우 화면에 이동 시킨 후 각 컴포넌트들을 연결한다.

 

 

 

http in을 더블클릭하여 수정

 

function을 클릭하여 수정

 

http response 수정 후 오른쪽 상단의 배포하기 클릭

 

 

http://localhost:1880/apiTest로 테스트


4. 추가 컴포넌트 설치

시간에 따른 분기처리하는 컴포넌트가 기본으로 제공 되지 않는다.

 

오른쪽의 = 메뉴 > 팔렛트 관리 > 설치 가능한 노드 > node-red-contrib-time-switch 검색 > 설치

 

 

기능 노드 > time switch가 생긴 것을 확인 할 수 있다.


5. 샘플 설정 API 구성해보기

5-1. 전체 구성

 

5-2. 구성 설명

  1. request로 codeValeu를 받는다.
  2. codeValue별 projectId를 다르게 세팅한다.(스위치 노드 사용하여 분기)
  3. target을 설정하는데 나중에 변경 할 수 있도록 A노드를 만들어두고 연결을 끊어둔다.(미사용 처리)
  4. 현재 시간에 따라 ment를 세팅한다. (타임 스위치 노드 사용하여 분기)

5-3. 테스트


6. 내보내기/가져오기

 

현재플로우/ 전체 플로우를 export, import가 가능하다. 해당 데이터는 json으로 만들어지며 파일/클립보드 형식으로 사용할 수있다.

 

테스트 샘플 json 공유

[
    {
        "id": "389108cf5e372918",
        "type": "tab",
        "label": "API 테스트",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "5c24f9ea6863049d",
        "type": "http in",
        "z": "389108cf5e372918",
        "name": "propertiesSetting",
        "url": "/apiTest",
        "method": "get",
        "upload": false,
        "swaggerDoc": "",
        "x": 200,
        "y": 260,
        "wires": [
            [
                "691f00ddb0f0f4d1"
            ]
        ]
    },
    {
        "id": "691f00ddb0f0f4d1",
        "type": "switch",
        "z": "389108cf5e372918",
        "name": "code 별 분기처리",
        "property": "payload.codeValue",
        "propertyType": "msg",
        "rules": [
            {
                "t": "btwn",
                "v": "10001",
                "vt": "num",
                "v2": "10005",
                "v2t": "num"
            },
            {
                "t": "btwn",
                "v": "10006",
                "vt": "num",
                "v2": "10010",
                "v2t": "num"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 430,
        "y": 260,
        "wires": [
            [
                "dd2e6d4c3f91d1a1"
            ],
            [
                "8d56be140949ad6c"
            ]
        ]
    },
    {
        "id": "dd2e6d4c3f91d1a1",
        "type": "function",
        "z": "389108cf5e372918",
        "name": "projectNum01",
        "func": "msg.payload.projectId='projectNum01'\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 660,
        "y": 220,
        "wires": [
            [
                "23994dbc840a7ce6"
            ]
        ]
    },
    {
        "id": "411363cd9bd10a0c",
        "type": "comment",
        "z": "389108cf5e372918",
        "name": "A 설정 세팅(projectId)",
        "info": "",
        "x": 680,
        "y": 160,
        "wires": []
    },
    {
        "id": "8d56be140949ad6c",
        "type": "function",
        "z": "389108cf5e372918",
        "name": "projectNum02",
        "func": "msg.payload.projectId='projectNum02'\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 660,
        "y": 300,
        "wires": [
            [
                "bbf5e59569ef9c5e"
            ]
        ]
    },
    {
        "id": "23994dbc840a7ce6",
        "type": "function",
        "z": "389108cf5e372918",
        "name": "target(local)",
        "func": "msg.payload.targetUrl='localhost'\nmsg.payload.targetPort='8080'\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 970,
        "y": 220,
        "wires": [
            [
                "735dd47aa923edda"
            ]
        ]
    },
    {
        "id": "8db7557e970a9a9d",
        "type": "comment",
        "z": "389108cf5e372918",
        "name": "B 설정 세팅(target)",
        "info": "",
        "x": 950,
        "y": 160,
        "wires": []
    },
    {
        "id": "21a72f6b7be84d83",
        "type": "function",
        "z": "389108cf5e372918",
        "name": "target(serverA)",
        "func": "msg.payload.targetUrl='http:serverA.com'\nmsg.payload.targetPort='8081'\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1180,
        "y": 280,
        "wires": [
            [
                "735dd47aa923edda"
            ]
        ]
    },
    {
        "id": "bbf5e59569ef9c5e",
        "type": "function",
        "z": "389108cf5e372918",
        "name": "target(ServerB)",
        "func": "msg.payload.targetUrl = 'http:serverB.com'\nmsg.payload.targetPort='8082'\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 980,
        "y": 340,
        "wires": [
            [
                "735dd47aa923edda"
            ]
        ]
    },
    {
        "id": "b584ee422c183395",
        "type": "comment",
        "z": "389108cf5e372918",
        "name": "C 설정 세팅 분기 (ment)",
        "info": "",
        "x": 240,
        "y": 440,
        "wires": []
    },
    {
        "id": "735dd47aa923edda",
        "type": "time-switch",
        "z": "389108cf5e372918",
        "name": "근무시간 여부",
        "lat": "37.564214",
        "lon": "127.001699",
        "startTime": "09:00",
        "endTime": "18:00",
        "startOffset": "0",
        "endOffset": 0,
        "x": 140,
        "y": 500,
        "wires": [
            [
                "2117890feccac6aa"
            ],
            [
                "4e28e016aecb2cd3"
            ]
        ],
        "outputLabels": [
            "근무시간",
            "근무 외 시간"
        ]
    },
    {
        "id": "2117890feccac6aa",
        "type": "function",
        "z": "389108cf5e372918",
        "name": "근무시간",
        "func": "msg.payload.ment=\"근무시간 입니다.\"\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 440,
        "y": 480,
        "wires": [
            [
                "6b3c1c70b041e627"
            ]
        ]
    },
    {
        "id": "4e28e016aecb2cd3",
        "type": "function",
        "z": "389108cf5e372918",
        "name": "근무외 시간",
        "func": "msg.payload.ment=\"근무외 시간입니다.\"\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 450,
        "y": 540,
        "wires": [
            [
                "6b3c1c70b041e627"
            ]
        ]
    },
    {
        "id": "6b3c1c70b041e627",
        "type": "http response",
        "z": "389108cf5e372918",
        "name": "",
        "statusCode": "200",
        "headers": {},
        "x": 720,
        "y": 500,
        "wires": []
    },
    {
        "id": "cf30e87595d4e294",
        "type": "comment",
        "z": "389108cf5e372918",
        "name": "C 설정 세팅(ment)",
        "info": "",
        "x": 450,
        "y": 440,
        "wires": []
    }
]

+ Recent posts