2018년 7월 29일 일요일

[기초]실행 파라미터?

오픈채팅방에서 누군가 구슬피 울며 과제를 도와달라고 했는데, 마침 정리하고싶던 실행 파라미터에 대한 주제라 성심성의껏 도와주었는데..


(쓰나미처럼 몰려오는 허무함..)

그래서 혼자 다시 정리하고 마무리 지어보자고 간단하게 글을 써봅니다.

우선 익숙한 예제부터 보면서 시작해 볼까 합니다.

어려분들 중에서는 이런걸 경험해 보신분들이 있으실 겁니다.

...
(게임의) 실행파일의 바로가기를 만들어서,
속성의 대상에 -skipintro 를 치고 실행 해 주세요!
..

요즘은 스팀으로 손쉽게 쓰기 때문에, 모르는분도 있겠네요..
제가 어릴때는 저렇게 어떤 명령어를 추가해서 게임을 좀더 편하거나 쉽게 하는 꼼수가 있었는데요. 이것이 실행 파라미터로 보면 매우 간단한 예제가 되지 않을까 싶군요!

실행 파라미터는, 해당 프로그램이 실행, 그러니 메인이 작동할때, 파라미터에 추가적인 인자값을 전달하는 것 입니다.

사용자 정의 함수/ 혹은 메소드를 만들때, 인자값을 통해서, 해당 함수/메소드에 값을 주고받는것을 해보신적 있으실 거에요.
(매우 간단한 메소드입니다! 인자값으로 int를 받아오죠!)

문득 이런생각을 해보신적이 있으신가요?

"메인함수는그런게 없나" 혹은.."(자바에서) String[] args 이놈은 도대체 뭘까?"

바로 이놈들이 실행 패러미터입니다!

C에서는..

(이런걸 본적 있으신가요?)

이렇게 기본적으로 정의되어 있습니다!
하지만 공부하면서 저렇게 치진 않죠.. 없어도 되게 짜여져 있나봐요!

자바에서는...
(이놈은 자바 해보신분이라면 익숙히 보셨을 거에요)

요렇게 되어있습니다!
이것들이 실행 파라메터값들을 받아먹는 곳 입니다.

그럼 이제 어떻게 실행 파라메터에 값을 집어넣을까요?

C로 IDE를 통하지 않고 직접 짜 보겠습니다!



(코드!)

요렇게 작성해서 컴파일/링킹을 끝내고, hello_world.exe 를 만들었습니다.


(exe파일이 있는곳으로 cmd창을 열어서, 해당 exe를 실행 합니다.)

명령 프롬포트 창에서, hello_world.exe 가 존재하는 디랙토리로 이동을 합니다!
저의 경우는 D:\juicy\Documents 폴더 하위에 존재합니다!
cd D:\juicy\Document 를 치면 간단하게 이동 할 수 있습니다.
이제 hello_world.exe 를 입력하시면 작성했던 코드가 작동하게 되죠!
우리는 여기까지의 번거로운 과정을 IDE들로(비쥬얼스튜디오/이클립드 등..)쉽게 하는것 입니다!

그럼 이제 실행 파라메터를 추가 해 봅시다!

 (실행 파라메터로 hello world 라는 문자열을 썻습니다)

단순하게 hello_world.exe 뒤에 원하는 인자값들을 써주면 됩니다!
hello_world.exe hello world! 를 입력해 실행해 보면, 위와 같은 결과를 얻어보실 수 있습니다.

C의 경우 argv[0]은 항상 실행 프로그램의 이름이 뜹니다. 자바의 경우에는 없워요!

여기까지 따라 쳐 보셨다면, 이제 감이 조금씩 올거에요! 그렇쥬?

언어마다 다르지만 c와 자바를 보자면,

c에서는 argc 와 argv 두개를 받으며,
argc == argument count (int)즉 실행시 받아들인 인자의 갯수
argv ==argumnet value (char[] 의 *)즉 실행시 받아들인 인자들의 값 입니다

자바에서는 args 하나를 받으며,
args == arguments 즉, 인자들 입니다.
c와는 다르게, *argv[] 하나만 있으면 argc는 필요없기 때문에, 하나로 통일되었습니다.

자, 이제 끝입니다. 네? 뭐 어쩌라고요? 그건 저도몰라요. 프로그램을 실행하면서 값을 가져오는것 뿐이에요, 써먹는건 여러분의 몫이죠!

그래도 이렇게 끝내기엔 찝찝합니다..
그러므로 위의 질문자가 올렸던 문제를 보고 써먹을곳을 찾아보죠.



(질문자가 냈건 문제 전문입니다)

조건을 정리해 보니 :
    1. 자바로 구동합니다.
    2. 실행 파라메터로 값을 받으며,
    3. 받은 값은 5와 10 까지의 int만을 받아야 합니다.
    4. 받은 값 j 는 1부터 j까지 짝수들을 더한 값을 출력합니다.


2번을 보면 위의 작동방법을 배웠습니다. easy!
3번을 보니..받은 값은 int여야만 하며, 심지어 범위도 제한되어있습니다!
흠..조금 까다로워 보이네요!
4번? 껌이죠. 이건 넘어가죠.


자 자바로 실행 파라미터를 받고, 그 받은 값이 int인가/5-10사이값인가 를 확인하는것 부터 짜 봅시다!




(자바코드 입니다!)

위와 같이 코드를 작성합시다! 이 코드는 자바로 실행 파라미터를 받는 코드입니다!


(Eclipse IDE에서 실행 파라미터 설정해서 디버깅 방법!)

이클립스의 경우에는, Run -> Run Configurations -> Arguments -> Program arguments 에 작성해 주시면 됩니다!

저는 안녕깐깐징어야! 아하하하핳 -5 1 2 3 4 5 6 7 8 9 10 11
총 15개의 인자를 넘겨봅니다



(15개의 인자값들을 잘 받아오는군요!) 

다음, 어떻게 해야 조건에 부합하는지 .ARABOZA

숫자인가?
특정범위 이내인가?

 

int num = Integer.parseInt(args[i]); 

를 해서 파싱이 되면 숫자, 뻗으면 숫자가 아니겠군요..

try catch로 묶어 봅니다.


 (working well!)

좋네요! 이제간단하게 if문으로 특정 숫자를 제한하면 되네요!
이제 인자값을 하나만 받고, 받은 값이 숫자인가, 5-10 사이인가 를 정리해 보면


(ez ez!)

자알 작동되는군요!

문제의 나머지는 이번 포스트의 핵심내용도 아니고, 누군가 이 문제를 검색하면 배낄수 있게 하는건 원치않으니, 실행 파라미터에 관한 부분인 여기까지 설명을 하고 끝냅니다.
 
애초에 남은 부분이 여기까지 읽으면서 안막힌 사람이라면 못풀게 아니니깐..

installing opencv.js probloms/how to install

opencv.js 는 c베이스로 만들어진 opencv를 js환경으로  동작하게만든 패키지입니다.
구동환경은 현제 3.1이며, https://github.com/ucisysarch/opencvjs
에서 다운로드 및 설치방법이 설명되어 있습니다.

하지만 현제 설치에 필요한 것들을 찾다보면 버전이 불일치하여, 설치에 번번히 실패하게 되는데, opencvjs 깃허브에서조차 뚜렷하게 설명된 글이 없으며, 마지막 업데이트도 반년이 넘어가고있습니다.

아래의 글은 현제 버전
파이썬 2.7
emsdk 1.38.8
opencv.js 3.1
버전에서 작동을 기준으로 하였으며, 이후 업데이트는 자신의 버전과 맞게끔 수동 설정이 필요로 합니다.

  • 들어가기에 앞서..
우선 지옥같은 설치에 들어가기앞서, 매우 생소한 emsdk에 대해서 간단하게 살펴봅니다.
저는emsdk가 무엇인지 모른상태로 설치를했고, 결과적으로 수많은 시행착오를 가지게 되었기 때문에, 설치에 들어가기 앞서 배경을 대강이라도 이해가 필요함을 느꼇습니다.

제얼처음 언급했다싶이, opencv는 c/c++ 을 기준으로 만들어져 있습니다. 그런 이유로 js환경에서 구동을 위해서는 c코드를 js코드로 컨버팅이 필요로 합니다.
emsdk가 이 컨버팅을 돕는 프로그램입니다.

우리는 emsdk를 설치한 후에 opencvjs 패키지를 js용으로 컴파일 해야합니다.
이제 설치를 시작합니다.

  • 설치는..
-windows-
https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html
에서 최신버전을 받아, 압축을 푼뒤
해당 디랙토리로 cmd로 가
1. emsdk update
2. emsdk install latest
3. emsdk activate latest
4. emcmdprompt.bat
를 하면 성공

-linux-
git으로 설치가 편합니다.

# Get the emsdk repo
git clone https://github.com/juj/emsdk.git

# Enter that directory
cd emsdk
 
하면 간단하게 복사가 되며,

1. emsdk update
2. emsdk install latest
3. emsdk activate latest
4. source emask_env.sh
를 하면 성공

별거없네요.
위의 홈페이지에도 동일하게 설명서가 있으며, 설치테스트도 쉽게 가능합니다.

설치가 끝난뒤, 이제 opencv.js를 설치합니다.
https://github.com/ucisysarch/opencvjs



  • 이제 본격적인 지옥이 시작됩니다.

윈도우 리눅스 공통적으로 위 사이트의 installation을 따라 설치하면 되나,

두 운영체제가 공통적으로 겪는 문제는 아래와 같습니다.


1.

( 설명서에서 제시하는 emsdk버전)

성명서에서는 명확하게 emsdk버전을 명시합니다. 하지만 제가 시도했을땐, 두 운영체제 모두 설치가 실패합니다.
결과적으로 latest버전을 써도 무방합니다. 걱정하지말고 넘어갑니다.


2.


(diff 파일을 패치하는 방법을 설명합니다)

우선은 diff가 무엇인지 알아봐야 합니다.
unix계열에 있는 diff는 두 파일을 비교하여, 무엇이 추가되어있고, 무엇이 빠져있는지 정리가 되어있는 파일입니다. 유닉스 계열에서 설계되어있으므로 윈도우에는 공식적으로는 지원하지 않습니다.

patch 스크립트는, 위의 주어진 diff파일을 읽어들여, 현제 내 파일의 정보를 diff가 제공하는 정보에 맞게 수정하는 스크립트 입니다. 이 역시 유닉스용 입니다.

-linux-
환경에서는 간단합니다.
emsdk 설치 디렉토리로 이동후, 3번의 명령어를 치는데, patch_emscript_master.diff(이제 diff파일이라 부릅니다)의 full directory를 입력해 줍니다.
diff파일은 git으로 받은 opencvjs 폴더하에 존재합니다.

-windows-
환경에서는 diff파일을 읽어주는 서드파티 프로그램을 설치해야 합니다.
저의 경우는 수동으로 파일을 수정했습니다. diff파일을 메모장으로 열면, 어떤 파일의 어떤 라인을 수정하는지 정보가 존재합니다.




  • 그럼 마음놓고 3번을 시행하지만.. 
역시 작동하지 않습니다.
이부분에서 막혀서 많은 유저들이 설치중 멘붕한것 같습니다 -_-
 (수많은 설치실패 문제로 고통받고있는 유저들..)

답은 간단하게도 diff파일이 잘못된 경로를 지정하고 있기 때문이며, diff파일을 수동으로 수정하면 됩니다.

에디터로 diff파일을 열어보면 ;
(diff파일 에디터로 열어본 상태...)

이러한 내용이 잔뜩 있습니다.


  • 당황해 하지말고 살펴봅니다.
1번라인  : 경로상의 파일을 수정한다는 뜻 입니다. bind.h 파일 내부에
3번라인 : 999번 라인 다음의
4번 5번 라인 : 의 문자 다음에 존재하는
7번 라인 : 코드는 붉은색 하이라이트와 네거티브 - 표시가 되어있습니다.
이 뜻은 기존의 bind.h 파일에 적혀있는 코드입니다.
해당코드를
8번라인: 으로 바꿉니다.
그 뒤,
12번라인 : 1035번라인에서
13 14번라인 : 문자 다음에
16번라인 ~ : 해당코드를 추가합니다.

모두 풀어썻을때 이러한 뜻입니다.

  • 이제 다시 코드를 면밀히 살펴봅니다.
혹은, 에러로그를 살펴봅니다.

에러로그는 diff파일의 1번과 2번 라인에 문제가 있다고 합니다.
과연, 실제로도 1번과 2번라인의 상대주소를 따라가보면, 경로가 조금 틀린것을 확인 할 수 있습니다.

(현제 제 버전의 기준에서는) master 폴더 대신 1.38.8 이라는 폴더가 그 자리를 대신하고 있습니다.

diff파일 또한 위 처럼 틀린 경로를 알맞게 수정해 줍니다.

 (수정된 코드의 일부분, 아래쪽에 또 수정이 필요한 코드가 있으니 꼼꼼히 살펴보세요)

위와 같이 모든 잘못된 경로들을 바로잡아주면, 비로쏘 patch가 올바르게 작동합니다.

이제 다시한번 emsdk install latest 를 입력 해 주면, opencvjs 를 컴파일 할 준비가 된 것 입니다!

opencvjs 로 이동후, python make.py를 입력합니다.


이제 설치가 정상적으로 끝이 납니다.


라고 생각했는데 또 다른 에러 터져서 집어던짐


2018년 7월 11일 수요일

in powershell, cannot find drive error/ 파웨쉘 드라이브 를 찾을 수 없습니다.

윈도우 환경에서 VS Code를 통한 터미널 진입시 아래와 같은 문제가 생긴적이 있습니다.

(특정 명령어를 입력하면 드라이브를 찾을수 없다고뜹니다.)


비단 이미지의 npm 명령어 뿐만아니라, 가장 기본적인 기능인 cd나 help따위도 일제히 먹히지 않는 증상이 생겨버렸는데요, 검색을 해도 도무지 저랑 연관있는 해결법을 찾지 못하던 도중 너무나도 쉬운 해답을 얻었습니다.

에러 로그를 읽으면
이름이 '.D' 인 드라이브가 없다는데, 이 말은 진짜 말 그대로 .D 라는 드라이브를 못찾아서 내뿜은 애러인데요,

그럼 도대체 어디서 .D 라는것을 가지고 왔느냐 부터 거슬러 가 봅니다.

그 어떤 스크립트를 실행해도 위와 같은 에러를 내뿜는데,
그럼 스크립트가 어디에서 어떻게 실행되는지 생각을 해봅니다.
스크립트는 스크립트가 실제로 있는 디렉토리가 있는데, 스크립트를 하나 칠려고 디렉토리까지 다 치고 하는게 번거롭기 때문에 alias를 만들어 놨습니다.
그래서 실제로 cd 를 쳐도, 윈도우 그 어딘가에 있는 cd라는 스크립트를 자동으로 불러와서 작동되는건데요, 그럼 이 실제 위치를 어떻게 shell이 참조하느냐 하면,
변수를 참조합니다.
여기까지 생각하고 환경변수의 상태를 조사해 보았습니다.

(이 에러를 겪는분들에 따라 다르겠지만 저의 경우, 문제는 파이썬이었습니다)

A ha! 환경변수 중에 파이썬에 관한 path가 엉뚱하게 .D 로 지정되어있습니다.

파이썬을 설치할떄 자동으로 path를 설정하게 했는데, 이런식으로 설정이 된 것이 원인인거 같습니다!

이 오류난 놈을 수정하면,

 (Good to be back! terminal!)

잘 작동되는군요!

저는 .D가 문제라고 썻으나, 구글 검색시 .C .E .F 등 다양하더군요.
앞서 설명됬다싶이, path 자체가 잘못 설정된 것 이니, 본인의 환경변수를 찬찬히 살펴 보시어, 틀린부분을 찾아 수정하 봅시다!

2018년 7월 9일 월요일

Communicate with Node Socket.IO to another Node server

현제 진행중인 프로젝트에서는 두개의 작동되는 별도의 서버가 있으며, 각자 기능이 분담되어있습니다.( 퍼포먼스 이슈를 피하기위해+여러 케이스를 연습해보기 위해)

기존에 완성된 웹사이트 프로젝트와 연계 프로젝트이나, 현제 구동중인 서버의 Spec과,
연계 프로젝트에서 요하는 CPU구동 수준을 비교/ Node의 특성(Single Thread)을 고려했을때, 모든 기능을 하나의 노드 프로젝트에 구겨넣는것은(물론 작동은 하겠지만) 만족스럽지 못할것으로 판단이 되었습니다.

클라이언트가 Serv2와 통신을 하기위해서, 굳이 Serv2에도 Serv1과 같은 Http프로토콜을 개설해 줄 수도 있으나, 이전의 프로젝트들을 구상하며 항상 발목을 잡았던 보안적인 측면을 강화하는 연습을 위해, Serv2는 외부와의 통신이 일제 없는 Serv1과 동일한 내부 내트워크망/ 알려진 포트만을 사용하는 로컬 서버로 지정합니다.

기획중인 DataDB의 내용은 보안이 특별히 중요하기 때문에 이런 서버 나누기는 여러 의미로 해볼 가치가 있어보입니다.

그러면 어떻게 Serv1과 Serv2가 통신을 하도록 할것인가 인데,
가장 단순하게 떠오른 방식은 역시 http통신 이었습니다.

하지만 socket 통신이 http통신보다 훨씬 유리할것 이라는 추측은 오래가지 않아 나오게 되었습니다.

(추후 바뀔수 도 있으나) 그럼 이제 Node간 socket통신을 가능캐 하는것이 목표가 되었는데, 다행히도 Socket통신을 매우 쉽게 모듈화 한 Socket.Io 패키지가 이미 있으며, 상당히 쓰이고 있었습니다. Npm의 Socket.io

사용할 패키지와 기초적인 구상은 끝났으니, 구동 테스트에 돌입하였습니다.



SocketIo에서 재공하는 기초예제입니다.
간단하게 http서버를1번라인에서 선언하며, 10번라인에서 8080포트로 열었습니다.
socket.io패키지의 이름을 io라 부르며, 방금 선언한 http서버를 인자값으로 넣어 host가 무엇인지 3번라인에서 명시합니다.
4-8번라인까지는 io가 연결된뒤, 기능들의 라우터입니다.
테스트용으로 저는 disconnect때에 로그를 찍게 했습니다.

이제 클라이언트 코드를 쳐보려고 하니...api를 훑어봐도 client용으로 그럴듯한 코드가 보이지 않았습니다..

잠깐 구글링 끝에, socket.io 개발팀은 socket.io-client 라는 이름으로 클라이언트 전용 패키지를 따로 만들어 놨던것 입니다..
Github의 socket.io-client

클라이언트 패키지도 찾았으니 마저 코드를 완성해 봅니다.



역시 기초예제입니다.
4번라인에 곧바로 socketio 서버와 통신을 선언과 동시에 시작합니다.뒤의 인자값에 서버 주소가 들어갑니다.

6번부터 마지막 라인까지는,연결 성공시, 이벤트 수락시, 연결 해제시 이벤트 헨들러들이네요.

둘다 저장하고, 서버,클라이언트 순으로 실행을 한뒤, 클라이언트는 곧바로 종료했습니다.


(좌측 : 서버 로그 , 우측 : 클라이언트 로그)

아- 완벽하고 짧게 작동하네요. socket.io 개발팀에게 찬사를..
이제 저는 Node1에서 실제 클라이언트(Client)에게 받은 정보를 토대로
Node2에게 해당 정보를 전송할 것이기에, 두 Node간의 이벤트 처리를 테스트 해 봐야 합니다.

간단하게 문자열, 숫자, JSON을 정상적으로 받는지 확인을 하면 될거 같네요.
Node1이 저에게는 socketio-client가 될것 이기 떄문에, io-client에서 io-server로  이벤트를 작동시킬것 입니다.

이런경우에는 emit이라는 함수를 사용하는것 같습니다.


io-client의 마지막 라인에 새롭게 추가했습니다.
emit함수의 첫번째 인자값은 서버로 전송하는 이벤트의 '이름' 입니다.
그 이후는 사용자가 원하는만큼 인자값을 설정이 가능합니다.
저는 (string,number,JSON) 이렇게 세개를 보내 볼것 입니다.

이제 io-server 코드를 봅시다.



3번 라인의 io.on 안에 새롭게 이벤트 헨들러를 작성하면 됩니다.
6번라인이 새롭게 추가되었습니다.
'pushData' 라는 이름의 이벤트가 들어오면, 6번라인이 해당 이벤트를 처리합니다.
받는 파라메터값은 (dataStr,dataInt,dataJSON) 이군요.
올바르게 데이터타입을 받았는가와, 올바르게 데이터를 받았는지 콘솔창에 뿌려줍니다.

이제 실행을 해 봤습니다.


(좌측: 서버 로그, 우측: 클라 로그)

Splender!완벽하게 읽어들입니다!



걱정관 달리, 정말 어처구니없을 정도로 손쉽게 만들어져 있는 Socket.IO덕분에 넘어야 할 산 하나의 허들이 상당히 낮아졌습니다. 최대한 효율적으로 쓰기위해서, Socket.IO를 사용하는것이 맞는지 한번만 더 확인한뒤 문제가 없다면, 기꺼이 행복하게 Socket.IO를 쓸 준비가 된것 같습니다...