Total: Today: Yesterday:
노하우/Server | 2019. 4. 19. 22:47 | Posted by 자수씨

스카우터 설치

2019.04.19 기준 2.6.1 버전으로 설치

서버 (collector) 설치

서버만 돌릴 거면 agent 는 제거

$ wget https://github.com/scouter-project/scouter/releases/download/v2.6.1/scouter-all-2.6.1.tar.gz
$ tar xzf scouter-all-2.6.1.tar.gz

$ cd scouter
$ rm -rf agent.*

scouter/server/conf/scouter.conf 설정 (6180 은 api 서버에서 쓸 예정이므로 다른 포트로 변경해준다.)

# Agent Control and Service Port(Default : TCP 6100)
net_tcp_listen_port=6100

# UDP Receive Port(Default : 6100)
net_udp_listen_port=6100

# Http Port for scouter-pulse(Default : 6180)
net_http_port=6101

# DB directory(Default : ./database)
db_dir=/<스토리지경로>/scouter/database

# Log directory(Default : ./logs)
log_dir=/<스토리지경로>/scouter/logs

실행법은 startup.sh 로 한다. (java 가 설치안된 경우에는 별도로 설치)

[ec2-user@~~ server]$ ./startup.sh 
nohup: redirecting stderr to stdout
  ____                  _            
 / ___|  ___ ___  _   _| |_ ___ _ __ 
 \___ \ / __/   \| | | | __/ _ \ '__|
  ___) | (_| (+) | |_| | ||  __/ |   
 |____/ \___\___/ \__,_|\__\___|_|                                      
 Open Source S/W Performance Monitoring  
 Scouter version 2.6.1

[ec2-user@~~ server]$ netstat -na | grep LISTEN    
tcp        0      0 :::6100                     :::*                        LISTEN      
tcp        0      0 :::6101                     :::*                        LISTEN      

client 에서 정상적으로 접근되면 서버는 설치 완료

에이전트 (agent.host) 설치

리눅스 서버에 agent.host 를 설치할 예정이므로 min 버전을 다운 받아 설치한다.
(server 는 필요 없으므로 제거)

$ wget https://github.com/scouter-project/scouter/releases/download/v2.6.1/scouter-min-2.6.1.tar.gz
$ tar xzf scouter-min-2.6.1.tar.gz

$ cd scouter
$ rm -rf server

scouter/agent.host/conf/scouter.conf 설정

obj_name=<agent이름>
net_collector_ip=<collector IP>
net_collector_udp_port=6100
net_collector_tcp_port=6100
#cpu_warning_pct=80
#cpu_fatal_pct=85
#cpu_check_period_ms=60000
#cpu_fatal_history=3
#cpu_alert_interval_ms=300000
#disk_warning_pct=88
#disk_fatal_pct=92

scouter/agent.host 에서 ./host.sh 로 실행시킨다.

[ec2-user@ip~~ agent.host]$ ./host.sh 
nohup: redirecting stderr to stdout
  ____                  _            
 / ___|  ___ ___  _   _| |_ ___ _ __ 
 \___ \ / __/   \| | | | __/ _ \ '__|
  ___) | (_| (+) | |_| | ||  __/ |   
 |____/ \___\___/ \__,_|\__\___|_|                                      
 Open Source S/W Performance Monitoring  
 Scouter version 2.6.1

Configure -Dscouter.config=./conf/scouter.conf
Scouter Host Agent Version 2.6.1 2019-03-17 08:45 GMT
System JRE version : 1.8.0_201

클라이언트에 정상적으로 host 정보가 집계되면 성공

에이전트 (agent.java) 설치

데이터를 집계할 WAS 는 Tomcat 이기 때문에 catalina.sh 에 다음과 같이 추가한다.

$CATALINA_HOME/bin/catalina.sh

# scouter settings
JAVA_OPTS="$JAVA_OPTS -javaagent:/home/ec2-user/scouter/agent.java/scouter.agent.jar"

Tomcat 을 재시작 하면 collector 쪽에 데이터를 전송한다.

참고자료

http://gunsdevlog.blogspot.com/2017/07/scouter-apm-1.html

'노하우 > Server' 카테고리의 다른 글

[nginx] websocket forwarding  (0) 2020.05.31
[MongoDB] CentOS 7에 설치하기  (0) 2019.08.10

노하우/Linux | 2019. 4. 13. 12:28 | Posted by 자수씨

EC2 인스턴스나 리눅스 기본 패키지에는 아직까지 JRE 1.7 이 설치되어 있는 경우가 많다.

$ java -version
java version "1.7.0_191"
OpenJDK Runtime Environment (amzn-2.6.15.4.82.amzn1-x86_64 u191-b01)
OpenJDK 64-Bit Server VM (build 24.191-b01, mixed mode)

 

다음과 같이 yum 을 이용하여 OpenJDK 8 을 설치한다.

$ sudo yum install -y java-1.8.0-openjdk-devel.x86_64

 

여러 JRE 가 설치된 경우 OS 에서 관리하는 java 를 설정하도록 아래와 같이 수행한다.

$ sudo alternatives --config java

There are 2 programs which provide 'java'.

  Selection    Command
-----------------------------------------------
*+ 1           /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/java
    2           /usr/lib/jvm/jre-1.8.0-openjdk.x86_64/bin/java

Enter to keep the current selection[+], or type selection number: 2

 

불필요한 JRE 7 은 제거한다.

$ sudo yum remove java-1.7.0-openjdk

 

참고자료

 

centos에서 java version관리 (alternatives 사용)

 

blog.seotory.com

 

노하우/Linux | 2019. 4. 12. 15:36 | Posted by 자수씨

머신 환경 상 서버의 기본 포트로 서비스 할 수 없을 경우 

 

서버의 기본 포트를 바꾸는 것 보다는 iptable 로 포트를 리다이렉트하는 것이 편하다.

 

$ sudo iptables -I INPUT 1 -p tcp --dport [외부포트] -j ACCEPT
$ sudo iptables -I OUTPUT 1 -p tcp --dport [외부포트] -j ACCEPT
$ sudo iptables -t nat -A PREROUTING -p tcp --dport [외부포트] -j REDIRECT --to-port [내부포트]

 

UDP 는 아래와 같이 설정

$ sudo iptables -I INPUT 1 -p udp --dport [외부포트] -j ACCEPT
$ sudo iptables -I OUTPUT 1 -p udp --dport [외부포트] -j ACCEPT
$ sudo iptables -t nat -A PREROUTING -p udp --dport [외부포트] -j REDIRECT --to-port [내부포트]

 

 

삭제 시

sudo iptables -D INPUT 1 -p tcp --dport [외부포트] -j ACCEPT
sudo iptables -D OUTPUT 1 -p tcp --dport [외부포트] -j ACCEPT

sudo iptables -t nat -D PREROUTING -p tcp --dport [외부포트] -j REDIRECT --to-port [내부포트]

연구소/Google Docs | 2017. 10. 19. 12:33 | Posted by 자수씨

구글 스프레드 시트에서 스크립트 편집기를 통해 커스텀 함수를 만드는 법은 엑셀에서 VB스크립트와 방식이 유사하여 자주 사용하고 있었다.


이전에는 셀에 변경을 감지하여 작업을 처리하였는데 상단 메뉴바에 커스텀 메뉴를 추가하여 작업을 처리하는 방식을 공유하고자 한다.



스크립트 편집기에 접근하는 방식은 아래와 같다.


[상단 메뉴바] > [도구] > [스크립트 편집기...]



스크립트 편집기가 뜨면 기존에 있던 내용은 지우고 아래의 코드를 삽입한다.




### js


function onOpen() {

  

  var _spreadSheet = SpreadsheetApp.getActiveSpreadsheet();

  var _menuEntries = [];

  

  _menuEntries.push({

    name: "테스트",

    functionName: "test"

  });

  

  _spreadSheet.addMenu("UWO스터디", _menuEntries);

}


function test() {


Browser.msgBox("테스트");

}



Browser.msgBox 는 window.alert 의 개념이라고 보면 되며, 스크립트를 저장한 후 스프레드 시트를 새로고침하면 아래와 같이 커스텀 메뉴가 추가된 것을 확인할 수 있다.




실행하면 권한을 설정하는 부분이 있는데 설정 후에 다시 메뉴를 실행하면 메시지박스를 확인할 수 있다.



참고자료: https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet#addMenu(String,Object)

연구소/TweenMax | 2017. 10. 18. 22:55 | Posted by 자수씨

HTML5 애니메이션 라이브러리로 TweenMax 를 사용할 경우 화면을 최소화 하거나 다른 탭에 의해 가려져 있으면 애니메이션이 동작하지 않는다.


그 이유는 기본적으로 TweenMax 애니메이션이 requestAnimationFrame 이벤트에 의해 동작하게 되는데, HTML5 의 특성인지 브라우저의 특성인지는 알 수 없지만 해당 이벤트가 발생하지 않기 때문이다.


따라서, 다음과 같이 설정을 해주어야 원하는 결과를 얻을 수 있다.


TweenMax.ticker.useRAF(false);


위의 useRAF() 함수는 requestAnimationFrame 의 사용여부를 설정하는 함수인데, 인자를 FALSE 로 넘길 경우 requestAnimationFrame 대신에 setTimeout() 함수를 통해 애니메이션이 처리된다.



관련사이트: https://greensock.com/docs/TweenMax/static.ticker

개발/JavaScript | 2016. 9. 22. 16:46 | Posted by 알 수 없는 사용자

평소에 자주 사용하지 않았던 자바스크립트 연산자를 알아봤다. 


1. 스프레드(...args) 연산자.
"배열 리터럴의 일부를 반복 가능한 식(다른 배열 리터럴 등)에서 초기화하거나 식을 함수 호출에서 여러 인수로 확장할 수 있습니다."

일반적으로 항목을 연결할때 concat메소드를 많이 이용하는데 스프레드 연산자(...args 로 사용)로도 가능하다.
하지만 스프레드 연산자는 반복 개체로만 연결이 가능하다.

var a = "a";
a.concat(["b","c"],"d"); //  "ab,cd"
var b= ["a"];
b.concat(["b","c"],"d"); //  ["a", "b", "c", "d"]

var a = ["a","b","c"];
...a // ---> Uncaught SyntaxError: Unexpected token ...
var b= ["a","b"];
[...b, ...["c"], "d"]; //  ["a", "b", "c", "d"]

concat 연산자와 비슷하게 사용되지만 반복개체로 호출해야만 에러가 발생하지 않는 것을 확인했다.

2. typeof 연산자.
"식의 데이터 형식을 나타내는 문자열을 반환합니다."

요 근래에 자주 사용하기 시작한 연산자이다.
보통 값을 비교할 때, 값과 값의 타입만 비교하는 "===" 나 "!==" 연산자로 사용한다.
내가 자주 사용하는 메소드는 String메소드(split, trim, replace 등)가 많았던 관계로 String 타입이 아니면 에러를 뱉어내곤 했었다.
그럴때 마다 값의 type만 비교하고 싶을때가 가끔 있었다.

typeof로 비교할수 있는 형식은 'number','string','boolean','object','function','undefined'  총 6가지 이다.
typeof 비교 형식은 대소문자를 가리기 때문에 반드시  소문자로만 적용해야 한다.

typeof "A" === 'string' //true
typeof "A" === 'number' //false
typeof 1 === 'undefined' //false
typeof 1 === 'number' //true
typeof bb === 'undefined' //true 변수 선언 X
typeof {} === 'object' // true
typeof "{}" === 'object' //false

3. void 연산자.
"식의 값을 반환하지 않게 합니다."

반환하면 항상 return을 사용하지만 굳이 함수가 아니더라도 값을 반환하지 않고 undefiend를 반환 하는 연산자이다.

function a (){ return "a" }
a() // "a"
void a() // undefined

var b = "b"
console.log(b) // "b"
console.log(void b) // undefined


4. delete 연산자.
"개체에서 속성을 삭제하거나 배열에서 요소를 제거합니다."

배열 삭제 메소드는 Array.splice()를 사용했었다. 하지만 splice는 배열삭제 메소드로 index도 같이 삭제된다.
delete 연산자를 이용하면 index는 그대로고 해당 index에 값만 삭제되는 것을 확인 할 수 있었다.

var ar = new Array (10, 11, 12, 13, 14);
delete ar[1] // true
console.log(ar) // [10, undefined × 1, 12, 13, 14]

var ar = new Array (10, 11, 12, 13, 14);
ar.splice(1,1) // [11]
console.log(ar) // [10, 12, 13, 14]



5. new 연산자.
"새 개체를 만듭니다."
new constructor([args])

new 연산자의 작업 수행은 아래와 같다.
멤버가 없는 개체를 만든다.
해당 개체에 대해 생성자를 호출하고 this포인터로 새로 만든 개체에 포인터를 전달한다.
생성자는 생성자에 전달된 인수에 따라 개체를 초기화한다.

my_object = new Object;
my_array = new Array();
my_date = new Date("Jan 5 1996");





개발/JavaScript | 2016. 9. 8. 13:34 | Posted by 알 수 없는 사용자


### javascript

SELECT lpad(no, 6, 0) AS nums

  FROM (SELECT right(frame_id, 6) num, @N := @N + 1 AS no

          FROM tables, (SELECT @N := 0) AS TBL1

        ORDER BY num) AS TBL2

 WHERE num <> no

 LIMIT 1


이 쿼리문을


### javascript

" SELECT lpad(no, 6, 0) AS nums " + 

"   FROM (SELECT right(frame_id, 6) num, @N := @N + 1 AS no " + 

"           FROM tables, (SELECT @N := 0) AS TBL1 " + 

"         ORDER BY num) AS TBL2 " + 

"  WHERE num <> no " + 

"  LIMIT 1 "; 


String으로 바꾸거나


### javascript

" SELECT lpad(no, 6, 0) AS nums " + 

"   FROM (SELECT right(frame_id, 6) num, @N := @N + 1 AS no " + 

"           FROM tables, (SELECT @N := 0) AS TBL1 " + 

"         ORDER BY num) AS TBL2 " + 

"  WHERE num <> no " + 

"  LIMIT 1 ";  


String을


### javascript

SELECT lpad(no, 6, 0) AS nums

  FROM (SELECT right(frame_id, 6) num, @N := @N + 1 AS no

          FROM tables, (SELECT @N := 0) AS TBL1

        ORDER BY num) AS TBL2

 WHERE num <> no

 LIMIT 1


쿼리문으로 바꾸고 싶었다.


현재 자바의 Mybatis등을 쓰지 않고 있어 소스에서 쿼리문을 작업할때 String 연결을 하고있는데 이 작업이 매우 번거롭다.

좀더 편하게 작업할 수 없을까 하여 위의 이미지처럼 html파일로 간단하게 만들어 버렸다.



정규식으로 문자열 맨 뒤에 [ "+ ] 를 붙이고 맨 앞에 [ " ] 를 붙이고 마지막엔 [ ; ] 를 붙이는 것으로 원하는 것을 해결하였다.


변경하고자 하는내용이 textarea에 담겨있다면


String.replace(/\n/gi, ' " + \n" ').replace(/^/, '" ').replace(/$/, ' "; ');

로 String 문자열을 연결하거나,

위의 정규식을 사용할 것이라면 순서는 반드시 맞춰주어야 한다.


String.replace(/\"\s{0,2}\+{0,1}\;{0,1}/gi, '');

로 연결된 String 문자열을 제거하면 된다.


적용 방법은 아래와 같다.

### javascript

<body>

<textarea id="replace"></textarea>

<textarea id="replaced"></textarea>

</body>

<script>

function replace(){

var value = document.getElementById('replace').value;


// String 문자열 연결

var replaced = document.getElementById('replace').value.replace(/\n/gi, ' " + \n" ').replace(/^/, '" ').replace(/$/, ' "; ');

// String 문자열 제거

var replaced = document.getElementById('replace').value.replace(/\"\s{0,2}\+{0,1}\;{0,1}/gi, '');


document.getElementById('replaced').value = replaced;

document.getElementById('replaced').select();

}

</script>



연구소/electron | 2016. 5. 16. 18:54 | Posted by 자수씨

스마트 개발자 협회 페이스북(https://www.facebook.com/sda.re.kr) 에 Electron 관련 글이 올라왔길래 어떤 용도로 활용이 가능한지 보기 위해서 기본 예제를 돌려보기로 했습니다.



Electron 홈페이지(http://electron.atom.io/) 에 접속하면 아래와 같은 화면이 나옵니다.


현재 주요 버전은 Electron 이 v1.0.1, Node 가 5.10.0 기반입니다.




이제 Electron Quick Start 를 해볼 차례입니다. (사전에 nodejs 와 git 이 설치되어 있어야 합니다.)


E:\Dev\nodejs> git clone https://github.com/electron/electron-quick-start


E:\Dev\nodejs> cd electron-quick-start


E:\Dev\nodejs\electron-quick-start> npm install


E:\Dev\nodejs\electron-quick-start> npm start


엥??? 실행했더니 다음과 같은 오류가 발생합니다.


> electron-quick-start@1.0.0 start E:\Dev\nodejs\electron-quick-start

> electron main.js



npm ERR! Windows_NT 6.1.7601

npm ERR! argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "start"

npm ERR! node v6.1.0

npm ERR! npm  v3.8.6

npm ERR! code ELIFECYCLE

npm ERR! electron-quick-start@1.0.0 start: `electron main.js`

npm ERR! Exit status 3221225781

npm ERR!

npm ERR! Failed at the electron-quick-start@1.0.0 start script 'electron main.js'.

npm ERR! Make sure you have the latest version of node.js and npm installed.

npm ERR! If you do, this is most likely a problem with the electron-quick-start package,

npm ERR! not with npm itself.

npm ERR! Tell the author that this fails on your system:

npm ERR!     electron main.js

npm ERR! You can get information on how to open an issue for this project with:

npm ERR!     npm bugs electron-quick-start

npm ERR! Or if that isn't available, you can get their info via:

npm ERR!     npm owner ls electron-quick-start

npm ERR! There is likely additional logging output above.


npm ERR! Please include the following file with any support request:

npm ERR!     E:\Dev\nodejs\electron-quick-start\npm-debug.log


구글링을 해보니 msvcp140.dll 과 같은 VC++ 14.0 (2015) 재배포 패키지에 포함된 파일이 없어서 발생된 문제였습니다.


VC++ 14.0 (2015) 재배포 패키지 설치 페이지(https://www.microsoft.com/ko-kr/download/details.aspx?id=48145) 에 접속하여 현재 OS 에 맞게 설치합니다.


다시 실행해보겠습니다.


E:\Dev\nodejs\electron-quick-start> npm start



크롬 기반의 웹 페이지가 GUI 어플리케이션 안에 들어가 있습니다.




최근에 nodejs 로 개발자 용 관리 페이지를 만들어볼까 했었는데, Electron 으로 시도를 해봐야겠습니다.





연구소/이것저것 | 2016. 4. 28. 14:11 | Posted by 자수씨


엑셀 시트로 저장된 데이터를 레드마인 위키에 옮길 때 주로 사용하던 컨버팅페이지가 있었는데, 단위가 큰 수를 적용하니 오류가 발생하였습니다.


방법을 궁리하다가 얼마전에 해보았던 Google Sheets Script editor 를 이용하여 포팅을 도전해보았습니다.



#h3 첫번째 시도



위와 같은 데이터가 있을 때 레드마인에서 테이블 형식으로 사용하기 위해서는 다음과 같은 문법으로 작성 되어야 합니다.


|_. 이름 |_. 출생년도 |_. 주급 | 

| 이정주 | 1983 | 500000 |
| 이은호 | 1986 | 480000 |
| 이수진 | 1989 | 450000 |
| 이혜원 | 1900 | 445000 | 


위와 같은 레드마인용 컨텐츠를 작성해주는 Google Sheets 용 script 를 작성해보았습니다.


### js


function toRedmine(input, hasTitle) {

  

  var _redmineContent = '';

  

  for (var i = 0; i < input.length; i++) {

    var _row = input[i];

    for (var j = 0; j < _row.length; j++) {

      var _col = _row[j];

      

      _redmineContent += '|';

      if (hasTitle == true && i == 0)

        _redmineContent += '_.';

      _redmineContent += ' ' + _col + ' ';

    }

    _redmineContent += '|\r\n'

  }

  

  return _redmineContent;

}


커스텀 함수를 사용하게되면 위와 같은 레드마인 문법으로 포팅된 것을 확인할 수 있습니다.


=toRedmine(A1:C5, true)



실제로 레드마인에 붙여보면 내용은 잘 나오지만 시트에서 본 형식이 아니라 만족스럽지는 않습니다.



포맷이 적용된 데이터를 보고싶은데 말이죠...




#h3 포맷팅된 값으로...


구글 시트의 문서를 찾아보니 range 를 이용하여 현재 화면에 보여지는 값을 가지고 올 수 있다고 합니다.

해당 함수를 이용하여 새로운 커스텀 함수를 만들어보았습니다.


### js


function toRedmine2(range, hasTitle) {

  

  var _redmineContent = '';

  var _values = SpreadsheetApp.getActiveSheet().getRange(range).getDisplayValues();

  

  for (var i = 0; i < _values.length; i++) {

    var _row = _values[i];

    for (var j = 0; j < _row.length; j++) {

      var _col = _row[j];

      

      _redmineContent += '|';

      if (hasTitle == true && i == 0)

        _redmineContent += '_.';

      _redmineContent += ' ' + _col + ' ';

    }

    _redmineContent += '|\r\n'

  }

  

  return _redmineContent;

}

새로만든 커스텀 함수는 기존과는 다르게 ```range```  를 문자열 형식으로 전달해야 합니다.


=toRedmine2("A1:C5", true)






처음에 설정했던 목표는 달성했으나 뭔가 정렬되지 않은게 아쉽습니다.




#h3 정렬을 해보자!!


구글 문서를 살펴보니 정렬된 데이터를 가지고 오는 함수가 있었습니다. ```range.getHorizontalAlignments()``` 해당 함수를 이용하여 레드마인의 정렬 문법을 적용시켜보았습니다.


### js


function toRedmine3(range, hasTitle) {

  

  var _redmineContent = '';

  var _range = SpreadsheetApp.getActiveSheet().getRange(range);

  var _values = _range.getDisplayValues();

  var _aligns = _range.getHorizontalAlignments();

  

  for (var i = 0; i < _values.length; i++) {

    var _row = _values[i];

    for (var j = 0; j < _row.length; j++) {

      var _col = _row[j];

      var _align = _aligns[i][j];

      

      _redmineContent += '|';

      if (hasTitle == true && i == 0)

        _redmineContent += '_.';

      else {

        if (_align.indexOf('right') > -1)

          _redmineContent += '>.';

        else if (_align.indexOf('left') > -1)

          _redmineContent += '<.';

        else if (_align.indexOf('center') > -1)

          _redmineContent += '=.';

      }

      _redmineContent += ' ' + _col + ' ';

    }

    _redmineContent += '|\r\n'

  }

  

  return _redmineContent;

}


세번째 커스텀 함수는 사용방법이 두번째와 동일합니다. 헤더 영역은 정렬이 먹지 않으므로 그 부분만 정렬되지 않도록 구성하였습니다.


=toRedmine3("A1:C5", true)






엑셀의 VBScript 는 문법이 손에 익지 않아 불편했는데 Google Sheets 는 주특기로 사용했던 자바스크립트로 개발이 가능하여 훨씬 빠르고 수월하게 원하는 기능을 만들 수 있었습니다.


앞으로도 자주 애용해야겠네요~




#h3 References

 - https://www.joecullin.com/data_converter/

 - https://developers.google.com/apps-script/reference/spreadsheet/range

 - http://webapps.stackexchange.com/questions/10629/how-to-pass-a-range-into-a-custom-function-in-google-spreadsheets

 - http://www.redmine.org/projects/redmine/wiki/RedmineTextFormattingTextile

연구소/AngularJS | 2016. 4. 20. 14:39 | Posted by 자수씨

AngularJS 서비스 상속에 대해 여러 글들을 읽어보고 현재 구성된 부분에 적용을 해보아도 생각했던 결과물이 나오지 않았습니다. 그래도 그 중 에서 가장 도움이 많이 되었던 글을 기반으로 서비스 상속 구조를 구현해보았습니다.




#h5 DaoBaseService.js

### js


"use strict";


myApp.factory('DaoBaseService', function($q) {

return function() {

var conn = null;

var client = new MySQL.Client();

client.setSocketImpl(new MySQL.ChromeSocket2());


this.setConnectionInfo = function(connectionInfo) {


conn = connectionInfo;

};


this.login = function() {


var deferred = $q.defer();

client.login(conn.hostname, parseInt(conn.port), conn.username, conn.password, false, function(initialHandshakeRequest, result) {


if (result.isSuccess()) {

deferred.resolve();

} else {

deferred.reject('Login error: ' + result.errorMessage);

}

}, function(errorCode) {


deferred.reject('Error returned from MySQL server: ' + errorCode);

}, function(result) {


deferred.reject('Cannot connect to MySQL server: ' + result);

});


return deferred.promise;

};


this.logout = function() {


client.logout(function(result) {

console.log('logout');

});

},


this.query = function(sql) {


var deferred = $q.defer();

client.query(sql, function(columnDefinitions, resultsetRows) {


deferred.resolve(resultsetRows);

}, function(result) {


deferred.reject('Never called: ' + result);

}, function(result) {


console.error('Server returned error: ' + JSON.stringify(result));

}, function(result) {


console.error('Cannot send query: ' + result);

});


return deferred.promise;

}

};

});


```DaoBaseService``` 는 클래스 형태로 factory 에 등록합니다. 이러한 형태로 만든 이유는 AngularJS 에서 제공해주는 ```$q``` 서비스를 사용할 때 별도로 파라미터로 넘기지 않고 factory 에 등록하면서 사용할 수 있도록 이런 방식으로 구성하였습니다.



#h5 UserDaoService.js

### js


"use strict";


myApp.service('UserDaoService', function(DaoBaseService) {


var daoService = new DaoBaseService;


daoService.findByUserIdx = function(userIdx) {


var sql = 'select * from tbl_user where useridx = ' + userIdx;

return this.query(sql);

};


return daoService;

});


#h5 TaskDaoService.js

### js


"use strict";


myApp.service('TaskDaoService', function(DaoBaseService) {


var daoService = new DaoBaseService;


daoService.findByUserIdx = function(userIdx) {


var sql = 'select * from tbl_task where useridx = ' + userIdx;

return this.query(sql);

};


return daoService;

});

각 DaoService 에서는 ```DaoBaseService``` 의 객체를 생성하고 해당 객체에 각 서비스에 특화된 함수를 정의합니다. 이 객체를 반환하면 해당 객체가 서비스로 등록됩니다.



컨트롤러에서 사용할 경우에는 기존에 서비스 사용하듯이 선언하고 사용하면 됩니다. AngularJS 에서 service 는 싱글턴으로 유지되기 때문에 이와 같은 방식으로도 상속개념을 사용할 수 있는 것 같습니다.


#h5 MainController.js

### js


"use strict";


myApp.controller('MainController', function($scope, UserDaoService, TaskDaoService) {


...

UserDaoService.login().then(function() {

return UserDaoService.findByUserIdx(userIdx);

}).then(function(resultsetRows) {

$scope.userInfo = resultsetRows;

}).catch(function(fault) {

console.error(String(fault));

}).finally(function() {

console.log('cleanup!!');

UserDaoService.logout();

});

...

});



이러한 방법으로도 가능한 것을 공유하기 위해 포스팅합니다~~



#h3 References

http://blog.revolunet.com/blog/2014/02/14/angularjs-services-inheritance/

http://stackoverflow.com/questions/26642174/angularjs-service-inheritance

http://blog.mgechev.com/2013/12/18/inheritance-services-controllers-in-angularjs/

http://mobicon.tistory.com/329

'연구소 > AngularJS' 카테고리의 다른 글

auth0 & firebase  (0) 2016.04.18
AngularJS 기본 개발 환경 구성하기  (0) 2016.04.14