basic authentication은 http를 사용하는 agent가 서버에 요청할때 username과 password 제공하는 방법으로, http header Authorization 필드에 username과 password 를 결합하여 base64 encoding 한 값을 value로 설정한다.
웹 리소스에 대한 가장 간단한 인증 기능을 제공하지만, http를 통해 전달되는 텍스트가 base64를 활용하여 누구나 복호화 할 수 있는 기법이므로 basic authentication 만을 사용하는것은 절대로 안전하지 않기때문에 민감정보나 귀중한 정보를 다룰때는 사용하지 않는 것이 좋으며 사용한다고 하더라도 HTTPS / TLS가 함께 사용하여야 한다.
"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에서 이벤트 루프를 제공하며 아래와 같이 동작한다.
A와 B코드를 비동기로 수행할때 A와 B모두 이벤트 기반 시스템 동작으로 실행되는데 A에서 작성된 try-catch 구문이 B에게는 전혀 영향을 주지 않는것을 명심해야합니다. 좀 더 자세히 설명하자면 A가 먼저 호출스택에 들어가서 수행되고 호출스택에서 제거됩니다. A가 제거되고 난후 B가 태스크 큐에 들어간 후 호출스택에 쌓여서 실행되기 때문에 A에서 사용된 context와 B의 context는 독립적인 컨텍스트 환경에서 전혀 영향을 받지 않습니다.
서로 다른 테스트가 종속되지 않아야 하나의 테스트가 실패하더라도 다른 테스트가 영향을 받지 않는다.
테스트는 Atomic한 속성(모두 성공 / 실패)을 따라야하며 중간에 실패를 하는경우가 있으면 안된다.
또한 테스트중인 데이터는 모든 테스트마다 분리하여 적용하지 않으면 테스트를 사용하는 전체적인 결과의 싱크를 보장할 수 없다.
-> 유저의 행동에 초점을 맞춰서 테스트를 설계하고 테스트하며 모든 사건에 대해서 독립적으로 다룬다. 각 테스트 별로 인과관계가 있지 않으며 모듈테스트시 필요한 작업들은 before / after 시점에서 하도록 한다.
테스트 이름에 3가지를 포함해야 한다. V
무엇을 테스트하고 있는지?
어떤 상황과 시나리오인지?
예상되는 결과는 무엇인지?
-> 모듈 / 기능별 테스트를 작성하며 어떤 상황에서 어떤 시나리오로 전개되는지 명확히 작성하고 기대되는 결과를 반드시 적는다.
Assetion을 사용해야 한다. V
Assertion은 프로그래밍시 테스트에 사용되며 테스트를 보기 쉽게 설계하고 참과 거짓으로 결과를 알려준다.
예를들어 expect('age').to.be.equel('32')의 경우 변수의 연령에 따라 32와 같은지 아닌지 참/거짓의 결과를 알 수 있다.
일반적인 테스트 보다 코드라인의 설명이 쉬워서 테스트에 사용하기 용이하고 결과 또한 테스트 설계시 어떤 값을 예상하는지에 대해 명확하게 설계하기 때문에 일반적인 테스트와 같이 결과값에 대해 해석할 필요없이 참/거짓 값으로 테스트의 성공 유무를 알 수 있다.
-> chai를 사용. Should, Expect, Assert 등의 Assertion 모듈을 사용한다. 이는 chain문법이 사용 가능 하므로 읽기 쉽고 표현이 자유로우므로 BDD스타일의 테스트를 설계하는데 이점이 있다. ex) expect.(jake).to.have.property('develoiper');
테스트 러너 사용 V
테스트 러너는 테스트파일을 읽어들어 작성한 코드를 실행하고 결과를 콘솔 또는 로그로 출력해준다. 또 구현코드가 변경될시에 테스트를 재실해주는 Watcher의 기능도 제공한다. 테스트러너가 있으면 설정한 데이터베이스값( dummy/real )으로 테스트를 실행할 수 있다.
-> Mocha를 사용한다. 최초의 테스트도입으로 Mocha, Jest, Jasmine 이 셋 중에 고민이 있었다.
Mocha
Jest
Jasmine
다른 assertion 라이브러리를 지원합니다.
개발자가 개발프로세스를 선택할 수 있습니다 ( BDD, TDD )
비동기 테스트를 쉽게 할 수 있습니다.
Node.js에서 Mocha fremework이 실행되므로 Node.js에서 잘 통합하여 동작합니다.
서버와 클라이언트에서 테스트할 수 있습니다.
여러가지 테스트 리포터가 내장되어있습니다.
No atomic test
초보자에겐 라이브러리선택 및 유틸리티 설정이 어려울 수 있습니다.
facebook에서 추천합니다. React 개발에 사용
문서화가 잘되어 있습니다.
사용하기 쉽습니다.
UI 테스트가 편리합니다.
react unit테스트에 대해 알고 있어야 합니다.
설정이 쉽습니다
공식문서가 어렵습니다.
루비온 레일즈와 잘 통합됩니다.
많은 CI서버에서 지원합니다.
DOM없는 테스트와 비동기 테스트를
모두 허용합니다.
읽기 쉽고 사용하기 쉽습니다.
유연하지 않습니다.
Mocha가 라이브러리, 유틸리티 설정에 있어 어려울 수 있는 단점과, atomic test까지 지원하지 않지만 휴먼스케이프의 프로그램 특성상 전산상의 장애가 엄청나게 치명적인 결과를 일으키지 않는다는 판단과 라이브러리선택과 유틸리티 설정의 경우 그리 단점이 될것 같지 않아서 Mocha를 선택 하였다.
테스트 커버리지에 초점 X
테스트커버리지를 잘 예상해야 한다. 테스트를 반드시 해야 하는지, 아닌지 판단을 해야 한다. 테스트에 들어간는 공수 또한 비용으로 책정되기때문에 테스트전 이를 잘 판단해보고 테스트를 진행해야 한다. 커버리지를 잘 판단하고 효율적으로 운용해야 한다.
-> 커버리지 설정에 고려해야 한다.
테스트 커버리지 플러그인 사용X
테스트 범위를 테스트하는 플러그인 사용할 수 있다. 플러그인은 테스트를 분석하고 테스트를 건너뛰었는지 여부를 알려준다. 모든 테스트 사례가 적용되었는지, 작성된 코드에 테스트가 적용되었는지 백분율을 알 수 있다.
-> 이스탄불 사용 예정.
테스트 커버리지 레포트 분석 X
테스트 커버리지를 분석하고 실패한 테스트의 이유를 분석하고 문제가 있는지 확인한다.
-> 이스탄불 사용 예정.
Mutation Testing X
Mutation testing은 테스트의 조건을 수정하여 의도적으로 fail시키거나 fail의 경우 테스트를 통과시켜 코드내에 존재할 수 있는 애매모호한 부분을 찾는다. stryker와 같은 모듈을 사용하는것을 추천한다.
-> 도입생각 없음.
테스트로 표절 확인 X
코드상에서 표절을 항상 확인해야 한다. 작업자가 인터넷에서 코드를 복사하여 동작시키는것은 흔히 있는 일이며 이는 라이센스상의 문제를 일으킬 수 있다. 이를 해결하기 위하여 plagiarism-checker 를 사용할 수 있다.
-> 라이센스 문제가 있을 수 있으니 도입 예정.
Property 기반 테스트 X
property 기반테스트는 엔터티의 property를 확인하기 위해 사용된다. 예를들어 input a, b가 있을때 b가 항상 짝수property를 가지는지 여부를 확인한다. 속성기반 테스트는 검사해야할 항목이 특정되어 있을때 함수의 임계값을 매우 쉽게 얻을 수 있으므로 예측가능한 장점이 있다.
-> Property 기반인것도 있고 아닌것도 있다.
Chai 라이브러리 사용 V
Assertion라이브러리를 사용하여 테스트코드를 보기쉽게 작성한다.
-> supertest (http 관련 모듈) + chai 사용중이다.
예외적인 시나리오 확인 X
예외적으로 일어나는 상황에 대해서 확인해야 한다. 일어날 수 있는 상황을 만들어서 응용프로그램이 어떻게 동작하는지 확인하고 어떤값이 반환되는지 알수 있어야 한다.
-> 시스템 전반적인 부분에 대해서 아키텍처를 보고 업무와 연관지어 예외적인 시나리오를 설계할 수 있어야 한다.
테스트 피라미드 X
자동화 피라미드
테스트는 단위테스트(독립적인 단위모듈) -> 통합테스트(모듈을 결합하여 테스트) -> 사용자 인터페이스 테스트(Selenium)를 수행한다.
컴포넌트 테스트 X
모든 테스트 계획을 컴포넌트 모듈별로 나누어서 테스트한다. 단위테스트후에 컴포넌트테스트를 수행하며 컴포넌트 테스트는
단위 테스트보다 큰 범위와 빠른속도를 가진다.
-> 단위테스트로 구성한 후에 도입 고려.
인프라문제에 대한 고려 X
테스터들은 보통 코드레벨에서의 테스트만 고려하여 인프라에서 발생하는 문제들을 놓치는 경우가 있다.
인프라에 대해서 테스트를 수행하고 피드백 보고서를 분석해야 한다.
-> 예외적인 시나리오와 동일.
dependency 업데이트 자동화 X
테스트를 수행하기 위해서는 많은 라이브러리와 도구가 필요하다. 종속성이 오래된경우 테스트수행을 올바르게 수행하지 못할 수 있으므로 종속성에 대한 업데이트가 필요하다. 이러한 문제는 업데이트를 자동화하여 해결할 수 있다.
-> 적용해야한다.
Lint를 해라. V
ESLint와 같은 Lint플러그인은 코드 작성시에 오류, 문법을 검사하기 위해 제작되어있다.
Lint는 테스트시에 잘못 작성된 문법들을 catch하는데 도움을 주기 때문에 test시 같이 사용하면 좋다.
-> eslint 5.6.0 사용중 + prettier 적용해야함.
병렬화 X
테스트를 병렬처리 하게 되면 피드백 루프에 대한 범위를 줄일 수 있고 이는 테스트시간을 줄일 수 있으므로 리소스 절약에도 도움이 된다.
단방향성: 원본메시지를 구하면 암호화된 메시지를 구하기는 쉽다. 그러나 암호화된 메시지로 원본 메시지를 구할수는 없다.
단방향 해시함수의 문제점
인식 가능성: 동일한 메시지가 항상 동일한 다이제스트를 갖는다면 해커가 다이제스트를 많이 확보한뒤 결과를 토대로 원본메시지를 유추해거나 악용할 수 있다. 이와 같은 다이제스트 목록을 레인보우 테이블이라하고 레인보우 공격이라 한다.
속도: 해시함수의 목적이 짧은시간에 데이터를 검색하기 위해 설계된것이다. 해시함수의 빠른속도를 이용하여 해커가 다이제스트를 원본문자열과 비교해볼 수 있다(데이터가 충분히 길거나 복잡하지 않은 경우 탈취가능).
단방향 해시함수 보완하기
솔팅(Salting): 솔트(salt)는 단방향 해시 함수에서 다이제스트를 생성할 때 추가되는 바이트 단위의 임의의 문자열이다. 이 원본 메시지에 문자열을 추가하여 다이제스트를 생성하는 것을 솔팅이라한다. 솔트의 길이는 32바이트 이상이어야 솔트와 다이제스트를 추측하기 어렵다.
키 스트레칭(key stretching): 원본메시지를 암호화로 다이제스트를 생성하고, 생성된 다이제스트를 입력 값으로 하여 다이제스트를 생성하고, 이를 반복하는 방법으로 다이제스트를 생성할 수 있다. 이렇게 하면 입력한 패스워드를 동일한 횟수만큼 해시해야 입력한 패스워드 일치 여부를 확인할 수 있다. 이것을 키 스트레칭이라 한다.
Adaptive Key Derivation Functions: 다이제스트를 생성할 때 솔팅과 키 스트레칭을 반복하며 솔트와 패스워드 외에도 입력 값을 추가하여 공격자가 쉽게 다이제스트를 유추할 수 없도록 하고 보안의 강도를 선택할 수 있다.
adaptive key derivation function중 주요한 key derivation function
PBKDF2: 가장 많이 사용된다. 해시 함수의 컨테이너로 솔트를 적용한 후 해시 함수의 반복 횟수를 임의로 선택할 수 있다.
DIGEST = PBKDF2(PRF, Password, Salt, c, DLen)
PRF: 난수, Password: 패스워드, Salt: 암호학 솔트, c: 원하는 반복 수, DLen: 원하는 다이제스트 길이
bcrypt: 패스워드 저장을 목적으로 설계됨. OpenBSD에서 기본적인 암호 메커니즘으로 사용됨.
bcrypt에서 "work factor"인자는 하나의 해시 다이제스트를 생성하는데 얼마만큼의 처리과정을 수행할지 결정한다. "work factor"를 조정하는 것만으로 보안을 높일수도 있다.
String hashed = BCrypt.hashpw(password, BCrypt.gensalt(11)); // gensalt is work factor
PBKDF2나 scrypt와는 달리 입력값으로 72 bytes character를 사용해야 한다.
scrypt: 다이제스트 생성할 때 메모리 오버헤드를 갖도록 설계되어, brute-force attack(모든경우의 수 대입)을 시도할 때 병렬화 처리가 매우 어렵다. PBKDF2보다 안전하다고 평가되며 bcrypt보다 경쟁력이 있다고 여겨진다.
DIGEST = scrypt(Password, Salt, N, r, p, DLen)
Password: 패스워드, Salt: 암호학 솔트, N: CPU 비용, r: 메모리 비용, p: 병렬화(parallelization), DLen: 원하는 다이제스트 길이
코드 단순화 : 코드자체의 분량을 최소화하여 이해하기쉽고 유지가 용이함 ( 코드의 확장하는 작업이 간단해진다 )
CI 라이브러리의 유효 범위와 사용법
CI 라이브러리에서 컨트롤러 리소스에 접근할수 있는 방법 ( CI라이브러리는 컨트롤러 리소스에 접근할 수 있는 권한이 없음 )
=>$ci = &get_intance(); 와 같이 실행한 후 $ci객체를 $this대신 사용해 리소스에 접근할 수 있다.
apllication/libraries폴더에 라이브러리 코드를 추가한다.
config.php를 통한 자동로딩 혹은 컨트롤러를 이용해 직접 객체를 생성한다 ( 전체 : $autoload['libraries'] = array('database', 'my_library'), 특정소스 : $this->load->library('my_library');