posted by JakeYeom 2019. 10. 15. 11:02

JavaScript 런타임

"Node.js는 Chrome V8 JavaScript 엔진으로 빌드된 JavaScript 런타임입니다." Node.js는 이벤트 기반, 논블로킹 I/O 모델을 사용해 가볍고 효율적입니다. Node.js 패키지 모듈 매니저인 npm은 세게에서 가장 큰 오픈 소스 라이브러리 생태계이기도 합니다.

런타임은 프로그램을 실행할 수 있게 해주는 환경입니다. 기존에는 javascirpt 프로그램을 인터넷 브라우저위에서만 실행할 수 있엇습니다.

브라우저 외의 환경에서는 속도의 문제때문에 호응을 얻지 못했고 2008년 구글이 V8엔진을 사용하여 크롬을 출시하자 좋은반응을 얻었습니다.

노드는 V8과 더불어 libuv라는 라이브러리를 사용합니다.

V8 과 libuv는 C와 C++로 구현되어 있고 이벤트 기반, 논블로킹 I/O 모델을 구현하고 있습니다.  노드의 내부 구조는 다음과 같습니다.

Node.js Core Library
Node.js Bindings
V8 (자바스크립트 엔진) libuv (비동기 I/O)

 

이벤트 기반

이벤트기반은 이벤트가 발생할 때 미리 지정해준 작업을 수행하는 방식을 의미합니다. 

이벤트 기반 시스템에서는 이벤트가 발생할때 수행할 일들을 미리 등록해 놓아야 합니다. 이런일들을 이벤트리스너, 콜백 함수를 등록한다고 표현합니다. 

 

 

이벤트루프

non-blocking i/o를 위해 사용하는 libuv에서 이벤트 루프를 제공하며 아래와 같이 동작한다.

(출처: http://stackoverflow.com/questions/10680601/nodejs-event-loop)

이벤트큐 (태스크큐)는 콜백들이 대기하는 큐(FIFO)형태의 배열이고, 이벤트 루프는 호출스택이 비워질 때마다 큐에서 콜백함수를 꺼내와 호출스택에 넣고 실행하는 역할을 해줍니다.  

 

+ 태스크큐는 nextTick(우선순위 1)과 promise(우선순위 2)를 다루는 마이크로태스크 큐와 타이머(우선순위 2보다 낮음)등의 콜백을 지원하는 태스크 큐로 나뉩니다.

 

이벤트기반 시스템의 실행 예시

동작주체

이벤트루프: 이벤트 발생시 호출할 콜백 함수들을 관리, 실행순서를 결정. 서버 종료시 까지 루프

태스크 큐: 이벤트 발생후 콜백함수들이 실행되기전 대기하는 배열

백그라운드: 타이머나 I/O작업 콜백 또는 이벤트 리스너들이 대기하는 곳

코드: 

function test() {
	console.log('3초 후 실행');
}
console.log('start');
setTimeout(run, 3000);
console.log('end');

 

(참조: Node.js 교과서 조현영 지음 )

 

1. 호출스택에 main함수, setTimeout함수 순서로 쌓입니다 (LIFO)

2. setTimeout이 먼저 실행되고 호출스택에서 집니다. 그리고 run + 타이머 3초 가 백그라운드로 보내집니다.

3. 백그라운드에서 3초가 지난뒤에 run은 태스큐 큐에 보내집니다.

4. 호출스택에서 main함수가 실행이되고 호출스택이 모두 비워지면 이벤트큐가 태스크큐에 있는 작업중 가장 첫번째로 할 작업인 run함수를 호출스택으로 보냅니다.

5. 호출스택에서 run함수가 실행되고 실행 완료 후 호출 스택에서 비워집니다.

6. 이벤트 루프는 태스크 큐에 함수가 들어올때 까지 계속 대기하게 됩니다.

 

 

비동기 API의 컨텍스트 실행

$('.btn').click(function() { // (A)
    try {
        $.getJSON('/api/members', function (res) { // (B)
            // 에러 발생 코드
        });
    } catch (e) {
        console.log('Error : ' + e.message);
    }
});

(출처: https://meetup.toast.com/posts/89)

node.js 환경에서는 비동기 함수 사용에 대해 유의해야 합니다.

A와 B코드를 비동기로 수행할때 A와 B모두 이벤트 기반 시스템 동작으로 실행되는데 A에서 작성된 try-catch 구문이 B에게는 전혀 영향을 주지 않는것을 명심해야합니다. 좀 더 자세히 설명하자면 A가 먼저 호출스택에 들어가서 수행되고 호출스택에서 제거됩니다. A가 제거되고 난후 B가 태스크 큐에 들어간 후 호출스택에 쌓여서 실행되기 때문에 A에서 사용된 context와 B의 context는 독립적인 컨텍스트 환경에서 전혀 영향을 받지 않습니다.

 

 

논블로킹 I/O

(출처: https://medium.com/prod-io/understanding-the-basics-of-node-js-99e01c5d844f)

논블로킹이란 이전작업이 완료될때까지 멈추지 않고 다음 작업을 수행하는것을 말합니다.

이벤트루프, 태스크큐에서 논블로킹 방식으로 작업을 처리하게 되면 오래걸리는 작업들을 나중에 수행하고 먼저 수행할 작업들을 빠르게 숭행할 수 있기때문에 작업을 효율적으로 수행할 수 있습니다.

 

 

싱글 스레드

싱글 스레드는 주어진 작업을 혼자서 처리하는것을 말합니다. 싱글스레드를 블로킹 방식으로 처리하게 되면 현재작업을 완료할때 까지 다음 작업은 무기한 대기해야하는 상황이 생겨서 비효율적입니다. node.js 에서는 싱글스레드에서 논블로킹 방식을 사용하고 있기 때문에

이전작업이 끝날때까지 기다리지 않고 작업을 요청받고 순서를 정한뒤 수행합니다.

 

'백엔드 > Node.js' 카테고리의 다른 글

Best Pratices of Node.js Error Handling  (0) 2019.09.17
posted by JakeYeom 2019. 9. 17. 18:16

1. Use Async-Await or promises for async error handling

비동기식 콜백 오류를 다루는것은 매우 어려운 일이므로 reputable promise library를 사용하거나  async-await 에 try-catch 와 같이 친숙한 구문을 사용하는 것이 좋다.

 

2. Use only the built-in Error object

error object는 내장객체만을 사용하는것이 통일성이 향상되고 정보손실을 방지할 수 있어 좋다. custom 객체를 사용하는경우 상호 운용성이 복잡해진다. ( ex: stack trace 정보가 손실될 수 있음 )

 

3. Distinguish operational errors vs programmer errors

운영상의 오류와 프로그래머가 내는 오류를 분류한다. 

운영상의 오류는 프로그래머가 이해할 수 있는 내의 범위의 오류를 말한다.

프로그래머 오류는 알 수 없는 코드장애로 응용프로그램을 다시 시작하는 오류를 말한다.

( 알려지지 않은 오류로 응용프로그램을 다시 시작해야한다면 다중사용자에 대응도가 매우 떨어지기 때문에 상황에 대한 대처법을 적용해야 한다. )

 

4. Handle errors centrally, through but not within middleware

모든엔드포인트의 에러는 캡슐화를 잘해서 메일 또는 로그로 중앙에서 관리할 수 있도록 해주어야 한다.

 

5. Document API errors using Swagger

스웨거에 에러에 대한 가이드를 명시한다. 사용자가 에러에 대한 대처를 작성할 수 있다.

 

6. Shut the process gracefully when a stranger comes to town

알 수 없는 오류가 발생할 경우. 애플리케이션 운영 상태에 대한 보장을 할 수 없으므로 Forever 나 PM2 같은 restarter를 사용하여 프로세스를 다시 시작한다.

 

7. Use a mature logger to increase errors visibility

Winston, Bunyan, Log4J 와 같은 로깅 도구를 사용하면 오류 발견을 쉽게할 수 있다.

console.log를 사용하는 것보다 오류 디텍팅 비용을 아낄수 있다.

 

8. Test error flows using your favorite test framework

코드가 작성자가 의도한 시나리오를 충족하는지, 올바른 오류를 처리하고 있는지 확인한다.

 

9.  Discover errors and downtime using APM products

모니터링 및 성능측정 제품을 사용하여 오류 및 다운타임을 검색한다.

 

10. Catch unhandled promise rejections

unhandled promise rejections을 catch 한다. 오류에 대해 기록을 남기고 처리할 수 있는 방법을 생각해 본다.

 

11. Fail fast, validate arguments using a dedicated library

arguments에 대해 검증할 수 있는 library를 사용한다.

'백엔드 > Node.js' 카테고리의 다른 글

Node.js 핵심개념정리  (0) 2019.10.15
posted by JakeYeom 2017. 11. 17. 16:33

4장. 라이브러리


라이브러리 사용시의 장점

  • 효율성 : 최소한의 리소스만을 로딩한다 ( 실행시간의 오버헤드 최소화 )
  • 코드 재사용성 : 프로젝트전반에 걸쳐 재사용이 가능 
  • 코드 분리 : 프로젝트의 다른장소에서 우연히 이름이 겹치는 현상을 방지
  • 코드 단순화 : 코드자체의 분량을 최소화하여 이해하기쉽고 유지가 용이함 ( 코드의 확장하는 작업이 간단해진다 )
CI 라이브러리의 유효 범위와 사용법
CI 라이브러리에서 컨트롤러 리소스에 접근할수 있는 방법  ( CI라이브러리는 컨트롤러 리소스에 접근할 수 있는 권한이 없음 )
 =>$ci = &get_intance(); 와 같이 실행한 후 $ci객체를 $this대신 사용해 리소스에 접근할 수 있다.
  • apllication/libraries폴더에 라이브러리 코드를 추가한다.
  • config.php를 통한 자동로딩 혹은 컨트롤러를 이용해 직접 객체를 생성한다 ( 전체 : $autoload['libraries'] = array('database', 'my_library'), 특정소스 : $this->load->library('my_library');
  • 라이브러리 메소드를 사용한다 $result = $this->my_library->called_method($param1, $param2);
  • 라이브러리의 유효범위를 제한한다


'백엔드 > CodeIgniter' 카테고리의 다른 글

CI. 3_컨트롤러 사용법과 유효 범위  (0) 2017.11.17
CI. 2_설정과 명명 규칙  (0) 2017.11.15
CI. 1_입문  (0) 2017.11.13
posted by JakeYeom 2017. 11. 17. 13:26

3장. 컨트롤러 사용법과 유효 범위


컨트롤러 


=> 기능 : 애플리케이션의 전면에서 의사를 결정하는 주체 ( 요청처리, 라우팅, 브라우저에 렌더링 뷰 전송, 데이터베이스 업데이트 등등 )

     컨트롤러는 자신을 호출하는 주체에게 결과를 리턴한다 ( 모델, 헬퍼, 라이브러리 ,뷰를 통해 호출자에게 결과를 리턴 )

     

     사용시 지켜야할 것 : 사용자의 컨트롤러는 내장 CI컨트롤러를 반드시 상속하여 사용해야 한다.

      

     동작의 예시 : 1. 브라우저를 통해 URL을 참조, 2. AJAX 비동기요청을 처리




CI 컨트롤러의 유효 범위





사용자 정의 CI 컨트롤러


[컨트롤러의 작성]

  • 모든 컨트롤러는 프로젝트 디렉토리의 application/controller 에 위치힌다.
  • 컨트롤러가 사용할 수 있는 리소스 : application/helper ( 내장헬퍼, 사용자 정의헬퍼, 제3자 정의 헬퍼 ), application/models ( 테이블을 위해 작성한 사용자 정의 모델 ), application/libraries ( 내장, 사용자, 제3자 라이브러리 )
[컨트롤러 확장]
  • 헬퍼, 모델, 라이브러리 같은 리소스 로딩 : 모든 리소스에서 로딩할 수 있음. 성능 최적화를 위한 리소스로딩을 생각해야한다. ( 리소스로딩 예시 : $this->load->model('example_model');, $this->load->library('example_library', $example_array);, $this->load->helper('example_helper'); )
  • public과 private 메소드 추가 : PHP OOP의 원칙을 지키기 위해 사용
  • 컨트롤러 호출 : 컨트롤러는 CI 코어가 자동으로 생성한다. 메소드는  HTTP URL을 통해 호출한다. ( 호출방법 4가지 : index, 매개변수없음, 매개변수있음, AJAX)
[CI 컨트롤러의 용도]
  • 뷰 렌더링 : 데이터와 함께 뷰를 생성한 후 웹 어플리케이션에서 현재 세션에서 다음페이지 옮겨갈 수 있도록 뷰를 보여준다. ( 앵커태그를 이용해 다른 페이지로 이동 )
  • 브라우저의 AJAX 요청을 처리하는 컨트롤러 
  • 리눅스 크론 스케쥴러 서버의 요청을 처리하는 컨트롤러 ( 크론탭으로 원하는 반복작업을 설정할 수 있음 )


'백엔드 > CodeIgniter' 카테고리의 다른 글

CI. 4_라이브러리  (1) 2017.11.17
CI. 2_설정과 명명 규칙  (0) 2017.11.15
CI. 1_입문  (0) 2017.11.13
posted by JakeYeom 2017. 11. 15. 11:11

2장. 설정과 명명 규칙


CI 설정

CI의 설정

=> CI를 설치한후 처음해야할일 : 프로젝트 요구사항에 맞게 데이터베이스, 세션, 자동 로딩이 필요한 헬퍼, 라이브러리 등을 설정하는 작업

=> 주요설정파일 : config.php, database.php, autoload.php


CI 디렉터리구조


새로운 프로그인이나 리소스를 추가하기위해 새로운 디렉토리를 추가하는 경우

=> CI의 BASEPATH에 상대적인 위치로 참조한다. ex) CI/application/bootstrap의 경로는 $path = BASEPATH. "application/bootstrap/" 이다.


[config.php]

$config['base_url']

=> CI의 최상위 디렉토리를 기본 URL로 계산한다. 

     코드사용예시 $base_url = base_url(); // base_url()함수는 URL헬퍼에 정의되어있다.


$config['index_page']

=> CI컨트롤러나 메소드에 대한 URI 경로 문자열에 인덱스 페이지를 포함시키고 싶다면 $config=['index_page'] 에 'index.php' 값을 할당한다.

     index.php는 모든 URI 요청을 처리하는 CI의 최상위 서비스다. URI처리에서 index.php를 제거하고 싶다면 다음과 같은 설정 작업을 해야한다.


1. phpinfo()메소드를 통해 mod_rewrite 모듈이 로드되어있는지 확인하고 (안되어있으면 mod_rewrite부터 해결)

   APACHE서버내의 conf/httpd.conf파일의 <Directory> 태그를 찾아 AllowOverride None을 AllowOverride All로 변경한다.

2. $config['index_page'] = 'index.php'의 값을 $config['index_page'] = '' 로 변경한다.

3. BASEPATH 하위에 .htaccess파일을 작성하고 

<IfModule mod_rewrite.c>

  RewriteEngine On

  RewriteBase /

  RewriteCond $1 !^(index\.php|images|captcha|data|include|uploads|robots\.txt)

  RewriteCond %{REQUEST_FILENAME} !-f

  RewriteCond %{REQUEST_FILENAME} !-d

  RewriteRule ^(.*)$ /index.php/$1 [L]

</IfModule>

위와 같이 입력시켜준다.


위의 3가지를 만족하게 되면 http://localhost:8080/example2/more/1/2/3 과 같이 index.php가 URI에 포함되어있지 않아도 원하는 페이지출력결과를 얻을수 있다.

[ URI에서 index.php를 없앤 결과 ]



손대지 않기를 추천하는 설정변수들 

$config['language'] = 'english'; // 언어설정

$config['charset'] = 'UTF-8' // 문자인코딩, HTML파일 metatag에도 추가를하기를 추천한다.

$config['enable_hooks'] = FALSE // 후크설정

$config['subclass_prefix'] = 'MY_' // 사용자라이브러리의 프리픽스

$config['permitted_uri_class']  = 'a-z 0-9~$.:_\-' //  URI로 CI리소스를 호출할 때 사용할 수 있는 문자

$config['allow_get_array'] = TRUE // 컨트롤러 클래스의 메소드를 매개변수와 함께 호출가능하게 설정

$config['enable_query_strings'] = FALSE // GET방식의 URL 질의 문자열을 사용할 수 있는지 설정

$config['log_path'] // 로그경로설정

$config['log_threshold'] // 로그기준점 설정 0 : 로그기능 비활성, 1 : 에러 메시지, 2 : 디버그 메시지, 3 : 정보성 메시지, 4 : 모든 메시지

$config['log_date_format'] // 기본 날짜 시간 포맷

$config['cache_path'] // 캐시 파일 경로

$config['encryption_key'] // 세션 클래서의 서비스를 이용할때 설정


사이트 신뢰를 높일 수 있는 설정들

$config['global_xxs_filtering'] // XSS필터링 활성화, 악의적인 XSS필터링  타입 공격으로부터 URI요청을 보호

$config['csrf_protection'] // 사이트간 위조 공격을 막음( 위조된 폼을 전송했을때 위험하다, AJAX요청시에는 별도의 추가적인 코드가 필요함 )



[database.php]

database는 2차원 배열의 형식으로 설정변수를 할당하고 있으며 다음과 같이 이용할 수 있다.

$db['default'] = array(
    'dsn'   => '',
    'hostname' => 'localhost',
    'username' => 'root',
    'password' => 'adminpw',
    'database' => 'aliendatabase',
    'dbdriver' => 'mysqli',
    'dbprefix' => '',
    'pconnect' => FALSE,
    'db_debug' => (ENVIRONMENT !== 'production'),
    'cache_on' => FALSE,
    'cachedir' => '',
    'char_set' => 'utf8',
    'dbcollat' => 'utf8_general_ci',
    'swap_pre' => '',
    'encrypt' => FALSE,
    'compress' => FALSE,
    'stricton' => FALSE,
    'failover' => array(),
    'save_queries' => TRUE
);

위처럼 한개의 DB이외에 다른 DB의 설정을 하고 싶다면

$db['anotherdb'] = array( 설정값 ); 과 같이 다른 설정값을 입력하면 된다.


연결할 데이터베이스를 직접 지정해 로딩하고 싶을때

=> $this->load->database('default');


기본이 아닌 다른 데이터베이스를 직접 지정해 로딩하고 싶을때

=> $this->load->database('anotherdb', TRUE);


기본 database연결시 쿼리문작성 방법

=>  $query = $this->db->query("select * from users");


기본이 아닌 database연결시 쿼리문작성 방법

=>  $query = $this-> anotherdb->db->query("select * from users");



[routes.php]

이 파일은 프로젝트의 기본 URI를 요청하면 실행항 기본 컨트롤러를 정의한다

$route['default_controller'] = 'welcome';

위와같이 default_controller를 설정하게 되면 서버의 최상위 디렉토리에 진입하게 될때 http://도메인/welcome을 호출하는것처럼 컨트롤러를 실행한다.


$route['404_override'] = 'notfound';

URI에 알지못하는 경로값을 입력하였을때에는 위에 해당하는 컨트롤러를 실행한다.


[사용자설정파일.php]

예를들어 나만의 설정정의를 사용하기위해 설정파일을 my_config.php라는 파일을 만들었다고 하자

해당 파일에는 아래와 같은 값이 정의되어 있다.

$userparam = 'value1';


다른파일에서 my_config.php 파일의 모든 변수를 배열에 로딩하여 손쉽게 접근할 수 있다.


해당파일에 작성 

$array = $this->config->load('my_config' ,TRUE);


사용

$userparam = $this->config->item('userparam', 'my_config'); 

$userparam = $array('my_config', 'userparam');


CI 명명 규칙의 이해와 사용

http://codeigniter.com/user_guide/general/styleguide.html에서 살펴볼 수 있다.


주요 리소스 명명규칙

CI는 하나의 클래스마다 하나의 파일이라는 규칙을 정해 모든 CI컨트롤러나 모델은 각자 한 파일에 담도록 규정한다. ( 헬퍼도 이와 같다 )


컨트롤러 사용

1. 컨트롤러의 index 메소드 호출

2. 매개변수 없이 컨트롤러의 calc 메소드 호출

3. 매개변수와 함께 컨트롤러 메소드 호출

4. AJAX를 통해 AJAX처리 메소드를 매개변수와 함꼐 호출하기


라이브러리, 모델, 헬퍼 로딩

사용자의 컨트롤러에서 라이브러리나 모델, 헬퍼 등의 기능을 사용하려면 컨트롤러나 모델 클래스에서 로딩해야 한다.

자동로딩을 하기 위해서는 application/config에 위치한 autoload.php 파일에 지정할 수 있다.


그 밖의 코딩 명명 규칙

  • 사용자의 클래스, 함수, 매개변수는 짧은 이름을 이용해야 한다. 여러 단어로 이를 정의할 경우에는 _(언더스코어, ex: source_code)를 이용한다.
  • 문자열 내에 변수가 들어있다면 큰 따옴표를 사용한다 ex: $my_str = "This is $clause";
  • 불리언 값은 대문자로 쓴다.




'백엔드 > CodeIgniter' 카테고리의 다른 글

CI. 4_라이브러리  (1) 2017.11.17
CI. 3_컨트롤러 사용법과 유효 범위  (0) 2017.11.17
CI. 1_입문  (0) 2017.11.13
posted by JakeYeom 2017. 11. 13. 15:28

코드이그나이터 MVC 프로그래밍


CI(코드이그나이터)란?

=> Ellis 랩에서 개발한 PHP기반의 객체지향적 MVC(모델-뷰-컨트롤러) 개발 플랫폼


이 강좌의 목표

=> CI로 프로그래밍 된 웹사이트의 유지보수를 할 수 있다.


강좌수강조건

=> PHP 객체지향프로그래밍, MySQL의 기본지식정도는 알아야 함




MVC의 개념

정보의 표현과 이 정보와 상호작용하는 사용자를 분리하는 사용자 인터페이스를 지원하는 개발패턴


M(Model) : 애플리케이션 데이터로 구성, 이를 조작하는 서비스를 제공

V(View) : 최종적으로 처리된 결과를 브라우저에 출력, 사용자 입력 로직과 표현할 대상을 정의

C(Controller) : 웹브라우저를 이용하는 사용자로부터 받아들이는 입력을 처리, 비즈니스 관련 계산을 수행, 모델, 데이터베이스 업데이트


CI의 폴더 살펴보기

  • application/config : CI 어플리케이션에 관한 모든 설정파일
  • application/controllers : CI 어플리케이션에 있는 모든 컨트롤러 파일 ( 사용자의 요청을 처리하고 사용자에게 보여줄 데이터를 제공, 클래스의 메소드는 URI를 통해 실행 또는 호출 가능 )
  • application/views : 모든 뷰 파일을 갖고 있다. ( 뷰의 형식 : 웹페이지, RSS )
  • application/models : 모든 모델파일 ( 데이터베이스에 담긴 데이터를 처리한다 )
  • application/helpers: CI 내장 헬퍼를 제외한 모든 추가적인 헬퍼 파일을 포함 ( 각 함수는 특정작업을 위해 작성한 독립적인 함수의 집합이며 다른 함수와 의존성이 없다)
  • application/libraries : CI 어플리케이션 프로젝트상에서 개발자가 생성한 모든 라이브러리를 포함한다
  • system : CI 코어의 최상위 디렉토리, 하위에는 시스템 핵심 요소들 core, database, embedded helper, embedded library등을 포함한다 


위의 내용은 CI버전에 따라 다를 수 있습니다.



1장. CI 기본 다루기


1-1 HelloWorld


컨트롤러 : application/controllers/hello.php



뷰 : application/views/helloview.php


예제 확인 URI : http://localhost:8080/index.php/hello



1-2 GET방식으로 View에 매개변수 전달하기


컨트롤러 : application/controllers/example2.php



뷰 : application/views/example2more.php


예제 확인 URI : http://localhost:8080/index.php/example2/more/1/2/3


1-3 모델을 이용해 데이터베이스에 질의한 후 결과값 뷰에 렌더링하기


config 설정 : application/config/database.php에 데이터베이스 설정정보를 입력해야 한다.


컨트롤러 : application/controllers/user.php


모델 : application/model/usermodel.php


뷰 : application/views/userview.php


예제 확인 URI :http://localhost:8080/index.php/user/users




'백엔드 > CodeIgniter' 카테고리의 다른 글

CI. 4_라이브러리  (1) 2017.11.17
CI. 3_컨트롤러 사용법과 유효 범위  (0) 2017.11.17
CI. 2_설정과 명명 규칙  (0) 2017.11.15