Nodejs 는 Chrome의 V8 엔진을 기반으로 구축된 platform 입니다. C/C++로 구현 되어 있습니다.


독립적인 platform 이기 때문에 운영체제에 영향을 받지 않습니다. 비슷한 언어로는 Java 가 있는데 JVM(Java Virtual Machine) 이라는 가상 머신이 존재 합니다.


위와 같은 언어는 메모리 관리를 엔진이나 가상 머신 에게 위임 하기 때문에 개발자가 메모리 관리를 하지 않고 비지니스 로직에 집중해서 개발이 가능 합니다.


개발자들이 흔하게 얘기하는 Garbage Collection (GC) 가 메모리 관리를 하는 행위 입니다.


2가지 방법으로 테스트를 해봤습니다. 

약 10분 정도 실행을 했습니다.


자동 GC

Sample Code 

var uuid = require('node-uuid');


function _a() {

  console.log('create _a');

}


function _b() {

  console.log('create _b');

}


while(true) {

  global[uuid.v1()] = new _a();

  global[uuid.v1()] = new _b();

}


메모리 정보

Name:   node

State:  R (running)

Tgid:   4266

Pid:    4266

PPid:   3056

TracerPid:      0

Uid:    1000    1000    1000    1000

Gid:    1000    1000    1000    1000

FDSize: 256

Groups: 4 24 27 30 46 109 124 1000

VmPeak:  2749292 kB

VmSize:  2748676 kB  - (전체 할당된 가상 메모리 크기)

VmLck:         0 kB

VmPin:         0 kB

VmHWM:   1862144 kB

VmRSS:   1827840 kB  - (실제 물리적 메모리 할당된 크기)

VmData:  2721992 kB  - (Heap 영역)

VmStk:       136 kB - (Stack 영역)

VmExe:      8024 kB

VmLib:      4084 kB

VmPTE:      6716 kB

VmSwap:   303584 kB

Threads:        2

SigQ:   0/15889

SigPnd: 0000000000000000

ShdPnd: 0000000000000000

SigBlk: 0000000000000000

SigIgn: 0000000000001000

SigCgt: 0000000188004202

CapInh: 0000000000000000

CapPrm: 0000000000000000

CapEff: 0000000000000000

CapBnd: ffffffffffffffff

Cpus_allowed:   3

Cpus_allowed_list:      0-1

Mems_allowed:   00000000,00000001

Mems_allowed_list:      0

voluntary_ctxt_switches:        5762

nonvoluntary_ctxt_switches:     4740072


수동 GC

Sample Code 

var uuid = require('node-uuid');


function _a() {

  console.log('create _a');

}


function _b() {

  console.log('create _b');

}


while(true) {

  global[uuid.v1()] = new _a();

  global[uuid.v1()] = new _b();

  gc(true);

}


실행 시 --expose-gc 옵션을 줘야 한다.

node --expose-gc test.js


메모리 정보

Name:   node

State:  R (running)

Tgid:   4375

Pid:    4375

PPid:   3056

TracerPid:      0

Uid:    1000    1000    1000    1000

Gid:    1000    1000    1000    1000

FDSize: 256

Groups: 4 24 27 30 46 109 124 1000

VmPeak:   718700 kB

VmSize:   700416 kB  - (전체 할당된 가상 메모리 크기)

VmLck:         0 kB

VmPin:         0 kB

VmHWM:     53492 kB

VmRSS:     53492 kB  - (실제 물리적 메모리 할당된 크기)

VmData:   673732 kB  - (Heap 영역)

VmStk:       136 kB - (Stack 영역)

VmExe:      8024 kB

VmLib:      4084 kB

VmPTE:       288 kB

VmSwap:        0 kB

Threads:        2

SigQ:   0/15889

SigPnd: 0000000000000000

ShdPnd: 0000000000000000

SigBlk: 0000000000000000

SigIgn: 0000000000001000

SigCgt: 0000000188004202

CapInh: 0000000000000000

CapPrm: 0000000000000000

CapEff: 0000000000000000

CapBnd: ffffffffffffffff

Cpus_allowed:   3

Cpus_allowed_list:      0-1

Mems_allowed:   00000000,00000001

Mems_allowed_list:      0

voluntary_ctxt_switches:        68

nonvoluntary_ctxt_switches:     80441


위 2가지 상황의 실제 물리적 메모리 할당 크기 를 비교 해보면 약 34배 정도의 차이를 볼 수 있습니다.


실제로 프로그램의 규모가 커지고 Web Application 이라면 접속자가 많아 질수록 메모리 관리의 중요성은 커질 것이라고 생각합니다. 


※ 참고 사이트

 - http://blog.nerds.kr/

 - http://simonmcmanus.wordpress.com/2013/01/03/forcing-garbage-collection-with-node-js-and-v8/

 - http://faq.hostway.co.kr/Linux_ETC/4258



[Java Console 게시판 만들기] - http://blog.whitelife.co.kr/161 


윗 글의 게시판 소스 개선 입니다.


기존 main 함수로 작성 했던 부분을 기능별로 분리하여 작성 하였습니다. 


bbs.java

import java.util.Scanner;

public class bbs {
  
	private static Scanner s = new Scanner(System.in);
	
	private static String[][] bbses = new String[9][];
	private static int seq = 1;
	private static int gindex = 0;
	
	public static void readme() {
		System.out.println("1. 등록, 2. 상세보기, 3. 수정, 4. 삭제, 5. 목록, x. 종료");
	}

	public static void exit() {
		System.out.println("프로그램을 종료 합니다.");
	}

	public static String getInput() {
		return s.next();
	}
	
	public static void create() {
		if (gindex == bbses.length) {
			System.out.println("게시글이 꽉 찼습니다.\n삭제 후 이용해 주세요.");
			return;
		}

		String no = String.valueOf(seq);
		
		System.out.println("input title...");
		String title = getInput();

		System.out.println("input content...");
		String content = getInput();

		String[] bbs = new String[3];
		bbs[0] = no;
		bbs[1] = title;
		bbs[2] = content;

		bbses[gindex++] = bbs;
		seq++;

		System.out.println("등록이 완료 되었습니다.");
	}
	
	private static String[] getSearch(String no) {
		for (String[] bbs : bbses) {
			if (bbs != null && bbs[0].equals(no)) {
				return bbs;			
			}
		}

		return null;
	}

	private static int getIndex(String no) {
		for (int i=0; i<bbses.length; i++) {
			String[] bbs = bbses[i];
			
			if (bbs != null && bbs[0].equals(no)) {
				return i;
			}
		}
		
		return -1;
	}

	public static void read(String no) {
		if (no == null || no == "") {
			System.out.println("잘못 입력 하셨습니다.");
			return;
		}
	
		String[] bbs = getSearch(no);
		
		if (bbs == null) {
			System.out.println("게시글이 없습니다.");
			return;
		}
		
		System.out.println("no: " + bbs[0]);
		System.out.println("title: " + bbs[1]);
		System.out.println("content: " + bbs[2]);
	}

	public static void update(String no) {
		if (no == null || no == "") {
			System.out.println("잘못 입력 하셨습니다.");
			return;
		}
	
		String[] bbs = getSearch(no);
		
		if (bbs == null) {
			System.out.println("게시글이 없습니다.");
			return;
		}

		System.out.println("input title...");
		String title = getInput();

		System.out.println("input content...");
		String content = getInput();

		bbs[1] = title;
		bbs[2] = content;

		System.out.println("수정이 완료 되었습니다.");
	}
	
	public static void delete(String no) {
		if (no == null || no == "") {
			System.out.println("잘못 입력 하셨습니다.");
			return;
		}

		int index = getIndex(no);

		if (index == -1) {
			System.out.println("게시글이 없습니다.");
			return;
		}

		bbses[index] = null;
		gindex--;

		int length = bbses.length;				

		for (int i=0; i<length; i++) {
			
			if (index == 0) {
				break;
			}

			if (index == length-1) {
				break;
			}					

			if (i > index) {
				if (i < length) {
					bbses[i-1] = bbses[i];
					bbses[i] = null;
				}
			}
		}

		System.out.println("삭제가 완료 되었습니다.");
	}

	public static void getList() {
		for (int i=0; i<bbses.length; i++) {
			if (bbses[i] == null) continue;				

			System.out.println("index: " + i);
			System.out.println("no: " + bbses[i][0]);
			System.out.println("title: " + bbses[i][1]);
			System.out.println("content: " + bbses[i][2]);
		}			
	}

  public static void main(String[] args) {
	while(true) {
		readme();		

		String choice = getInput();

		if (choice.equals("1")) {
			create();
		} else if (choice.equals("2")) {
			System.out.println("번호를 입력해 주십시오.");
			read(getInput());
		} else if (choice.equals("3")) {
			System.out.println("번호를 입력해 주십시오.");
			update(getInput());
		} else if (choice.equals("4")) {
			System.out.println("번호를 입력해 주십시오.");
			delete(getInput());
		} else if (choice.equals("5")) {
			getList();
		} else if (choice.equals("x")) {
			exit();
			break;
		} else {
			System.out.println("잘못 입력 하셨습니다.\n다시 입력해 주십시오.");
		}
     }	
  }
}



vim 입력 모드로 전환 한다.


:%s/old/new/g


old: 기존 문자열

new: 변환 할 문자열


위와 같이 실행 시 변환 된다.


'Linux' 카테고리의 다른 글

Ubuntu rar 압축 풀기  (0) 2014.09.21
Ubuntu 고정 IP 설정 하기  (0) 2014.09.21
gcc 컴파일 시 pcap.h no such file and directory 해결 방법  (0) 2013.11.08
find 명령어 사용하기  (0) 2013.11.07
Ubuntu 방화벽 설정 하기  (0) 2013.07.28


최근 들어 자바란 아이에게 신경을 별로 쓰지 못 했다. ㅎㅎ

생각 없이 코딩을 하던 중 String 비교를 하는데 비교가 되지 않아서 equals 함수를 써서 해결을 했다. 무심했던 것 일까...


test.java

public class test {
  public static void main(String[] args) {

    String a = "test";
    String b = "test";
    String c = new String("test");
    String d = new String("test");

    System.out.println("a: " + System.identityHashCode(a));
    System.out.println("b: " + System.identityHashCode(b));
    System.out.println("c: " + System.identityHashCode(c));
    System.out.println("d: " + System.identityHashCode(d));

    System.out.println("a == b: " + (a == b));
    System.out.println("a equals b: " + a.equals(b));
    System.out.println("c == d: " + (c == d));
    System.out.println("c equals d: " + c.equals(d));
  }
}

실행 결과

a: 1579880541
b: 1579880541
c: 1564441079
d: 1918924532
a == b: true
a equals b: true
c == d: false
c equals d: true

c == d 부분을 보면 hash 값이 다른 것을 볼 수 있다. 당연히 주소 값을 비교 하기 때문이다. 뻘짓을 하다니 완전 좌절 했다. ㅋ


게시판을 만들어 보자 


기능 정의

게시글의 최대 수는 9개로 제한 한다. 아래는 세부 기능 이다.


1.  등록

2.  상세 보기

3.  수정

4.  삭제

5.  리스트 보기

6.  종료


Sample

게시 글 항목은 번호, 제목, 내용 간단하게 3가지로 간다.


no: 1

title: title

content: content

 

Code

bbs.java

import java.util.Scanner;

public class bbs {
  
  public static void main(String[] args) {
   
  	Scanner s = new Scanner(System.in);

	String[][] bbses = new String[9][];
	int seq = 1;
	int gindex = 0;

	while(true) {
			
		System.out.println("1. create, 2. read, 3. update, 4. delete, 5. list, x. exit");

		String choice = s.next();

		if (choice.equals("1")) {
				
			if (gindex == bbses.length) {
				System.out.println("게시글이 꽉 찼습니다.\n삭제 후 이용해 주세요.");
				continue;
			}

			String no = String.valueOf(seq);
				
			System.out.println("input title...");
			String title = s.next();

			System.out.println("input content...");
			String content = s.next();

			String[] bbs = new String[3];
			bbs[0] = no;
			bbs[1] = title;
			bbs[2] = content;

			bbses[gindex++] = bbs;
			seq++;

			System.out.println("Complete...");
		} else if (choice.equals("2")) {
				
			System.out.println("input no...");
			String no = s.next();					
				
			boolean flag = false;		

			for (String[] bbs : bbses) {
				if (bbs != null && bbs[0].equals(no)) {
					System.out.println("no: " + bbs[0]);
					System.out.println("title: " + bbs[1]);
					System.out.println("content: " + bbs[2]);
					flag = true;
					break;
				}
			}

			if (!flag) {
				System.out.println("게시글이 없습니다.");
			}
		} else if (choice.equals("3")) {
				
			System.out.println("input no...");
			String no = s.next();					
				
			boolean flag = false;		

			for (String[] bbs : bbses) {
				if (bbs != null && bbs[0].equals(no)) {
					System.out.println("input title...");
					String title = s.next();

					System.out.println("input content...");
					String content = s.next();

					bbs[1] = title;
					bbs[2] = content;

					flag = true;
					break;
				}
			}
				
			if (flag) {
				System.out.println("Complete...");
			} else {
				System.out.println("게시글이 없습니다.");
			}
		} else if (choice.equals("4")) {

			System.out.println("input no...");
			String no = s.next();					
				
			int index = -1;			
			boolean flag = false;		
				
			if (gindex == 0) {
				System.out.println("입력된 게시글이 없습니다.");
				continue;
			}

			for (int i=0; i<bbses.length; i++) {
				String[] bbs = bbses[i];

				if (bbs != null && bbs[0].equals(no)) {
					bbses[i] = null;
					index = i;
					gindex--;
					flag = true;
					break;
				}
			}
				
			if (flag) {
					
				int length = bbses.length;				

				for (int i=0; i<length; i++) {
						
					if (index == 0) {
						break;
					}

					if (index == length-1) {
						break;
					}					

					if (i > index) {
						if (i < length) {
							bbses[i-1] = bbses[i];
							bbses[i] = null;
						}
					}
				}

				System.out.println("Complete...");
			} else {
				System.out.println("게시글이 없습니다.");
			}

		} else if (choice.equals("5")) {
			for (int i=0; i<bbses.length; i++) {
				if (bbses[i] == null) continue;				

				System.out.println("index: " + i);
				System.out.println("no: " + bbses[i][0]);
				System.out.println("title: " + bbses[i][1]);
				System.out.println("content: " + bbses[i][2]);
			}			
		} else if (choice.equals("x")) {
			System.out.println("프로그램을 종료 합니다.");
			break;
		} else {
			System.out.println("잘못 입력 하셨습니다.\n다시 입력해 주십시오.");
		}
	}	
  }
}

실행 결과


1. create, 2. read, 3. update, 4. delete, 5. list, x. exit

1

input title...

111

input content...

222

Complete...

1. create, 2. read, 3. update, 4. delete, 5. list, x. exit

1

input title...

333

input content...

444

Complete...

1. create, 2. read, 3. update, 4. delete, 5. list, x. exit

1

input title...

555

input content...

666

Complete...

1. create, 2. read, 3. update, 4. delete, 5. list, x. exit

5

index: 0

no: 1

title: 111

content: 222

index: 1

no: 2

title: 333

content: 444

index: 2

no: 3

title: 555

content: 666

1. create, 2. read, 3. update, 4. delete, 5. list, x. exit

x

프로그램을 종료 합니다.


심플한 게시판이 실행 되는 것을 확인 할 수 있다.


긴 글을 읽어 주셔서 감사합니다. 



최근 itworld 기사들을 자주 보는 편 입니다.


공감이 많이 가고 머리 속에서 계속 떠올라서 적어 봅니다.





  1. "그 업체가 가장 싼 가격을 제시했어요!"
  2. "기능 한 개만 더 추가할 수 있어요?"
  3. "이 솔루션에는 온갖 기능이 다 있어요!"
  4. "그걸 테스트할 시간도 돈도 없어요."
  5. "테스트 환경에서 문제 없었으니까 실무 환경에서도 아무 문제 없을 겁니다"
  6. "항상 이렇게 했는데요!"
  7. "프로젝트에 더 많은 프로그래머들을 투입하고 있어요."
  8. "문서화는 작업 속도를 늦출 뿐입니다"
  9. "IT 부서가 책임지고 하세요."
  10. "이걸 왜 다시 하죠?"

공포에 떨게 되는 10가지 입니다. 그 중에서도 4번, 7번, 8번 말이 제일 공감이 갑니다.

 

8번 한마디의 설명 입니다. 


 물론 코드의 기능에 대한 문서를 작성하는 일보다 실제 코드를 작성하는 데 더 많은 시간을 쓰고 싶겠지만 작업을 역추적할 수 있는 문서화를 게을리할 경우 필히 재앙으로 이어지게 된다. 실제로 무엇을 구축하는지 모두가 알 수 있도록 하는 요구 사항 문서부터, 작성자가 떠나고 오랜 시간이 지난 뒤에도 코드를 어떻게 사용해야 하는지 사람들이 알 수 있도록 하는 코드 문서화에 이르기까지, 문서화는 프로젝트가 뒤죽박죽 무질서한 상태로 진행되지 않도록 해주는 귀중한 요소다.

프로젝트는 혼자 하는 것이 아닙니다.  여러 사람들과 협업을 합니다. 그릇이 모자라는 사람, 넘치는 사람, 적당한 사람 등 다양한 사람들이 있습니다. 다양한 사람들과 프로젝트를 진행 하기 때문에 기능, 소스 등 History 관리가 되지 않으면 지금 당장은 아니지만 추후 위 설명과 같이 재앙으로 이어질 수 있습니다. 다 비슷한 사람들 이라고 한다면 서로 호흡이 잘 맞아서 진행이 수월 하겠지만, 보통 그게 아니기 때문에 문서화는 그 기준점이라고 생각 합니다. 

개발 일을 하면서 한번 쯤은 되돌아 봐야 한다고 생각 합니다.


※ 참고 사이트: http://www.itworld.co.kr/t/62082/IT%20%EA%B4%80%EB%A6%AC/84341

※ 참고 이미지: http://cfs13.tistory.com/image/35/tistory/2009/02/04/09/28/4988e12478fc8


'IT' 카테고리의 다른 글

개발자에 대한 고찰  (0) 2017.05.02
Windows 7 최대 절전 모드 해제 하기  (0) 2014.10.20
Windows 8, 8.1 에서 파티션 설정 하기  (0) 2014.10.11
씨게이트 통큰 이벤트~~  (0) 2013.05.27
야근은 스포츠...  (0) 2013.03.14


Step 1.  ubuntu 인 경우


sudo apt-get install libpcap0.8-dev


Step 2.  centos 인 경우


yum install libpcap*


한 후 컴파일 하면 해결 된다.


'Linux' 카테고리의 다른 글

Ubuntu 고정 IP 설정 하기  (0) 2014.09.21
vim 문자열 replace 하기  (0) 2013.11.10
find 명령어 사용하기  (0) 2013.11.07
Ubuntu 방화벽 설정 하기  (0) 2013.07.28
VirtualBox 폴더 공유 하기  (0) 2013.07.28


find 명령어는 시스템 관리자, 프로그래머는 필수로 알아야 한다. 원하는 파일을 계속 필터링 하면서 찾아볼 수 있고, 잘못 수정 된 파일 등 추적할 때 유용하게 사용 된다.


사용 방법


Step 1.  파일 찾기


whitelife@whitelife:~/work$ find . -name 'pattern'


현재 위치에서 해당 파일을 찾는다. 파일 이름은 아래와 같은 형태로도 적용이 가능 하다.


형태

표현 방법

 전체 표현

 * 

 확장자

 *.log 


Step 2.  변경된 파일 찾기


whitelife@whitelife:~/work$ find . -name 'pattern' -mtime n -print


현재 시간 기준 n*24 시간 으로 계산 하여 변경된 파일인 경우 찾는다. mtime 이외에 atime, ctime 이 옵션 값으로 있다.

access, change, modify를 추적 한다고 생각하면 쉽다.


Step 3.  찾은 파일을 실행 하기


whitelife@whitelife:~/work$ find . -name 'pattern' -mtime n -print -exec [command] {} \;


command 에 실행하고 싶은 명령어를 작성 한다. 파일을 찾은 후 추가적인 작업이 가능 하다.


Step 4.  부정 연산자 사용 하기


whitelife@whitelife:~/work$ find . -name 'pattern' \! -mtime n -print


옵션 앞에 \! 을 넣어주는 경우 반대로 출력 하게 된다.


'Linux' 카테고리의 다른 글

vim 문자열 replace 하기  (0) 2013.11.10
gcc 컴파일 시 pcap.h no such file and directory 해결 방법  (0) 2013.11.08
Ubuntu 방화벽 설정 하기  (0) 2013.07.28
VirtualBox 폴더 공유 하기  (0) 2013.07.28
CentOS 방화벽 설정 하기  (0) 2013.04.26


Query 사용 시 Rownum 이 필요 할 때가 있다.


사용 방법.


select

  @row_number:=@row_number+1, data.*

from

  (select @row_number:=0) as rownum, data


임시 변수를 만들어 놓고, 매 회 추가 되는 방법을 사용 한다.


+ Recent posts