development

Node.js 개발자가 흔히 저지르는 4가지 실수

여름싼타 2023. 3. 29. 19:10
반응형

원문 : https://amplication.com/blog/4-common-mistakes-made-by-nodejs-developers

 

 

실수 1) 로그레벨을 설정하지 않은 상태에서 운영

대부분 로그레벨(DEBUG, INFO, WARN, ERROR 등) 개념을 잘 알고 있다고 생각한다.
제품 팀이 새로운 마이크로 서비스를 제공하기 위해 서두르면서 이러한 로그 수준을 명확하게 정의하는 것을 잊어버리는 경우가 많이 보인다. 이럴 경우 주로 다음 두 가지 단점이 있다:

- 로그에 낮은 수준의 DEBUG 로그 등 관련성이 없는 메시지가 대량으로 표시되면 고객과 팀원들이 실가동 중인 문제를 파악하고 대처하기가 매우 어려워진다. 일반적으로 이것들은 운영 워크로드에 도움이 되지 않는다.
- 로그 서비스의 요금을 극적으로 증가시킨다. 나는 이것을 직접 본 적이 있다. 로그 수집 서비스는 처리량 및/또는 스토리지별로 요금을 청구한다.


위 단점에 모두 대처하려면 로그 수준을 명확하게 정의해야 한다. Node.js(winston, pino, morgan) 용 훌륭한 로거 라이브러리가 많이 있으며 다양한 종류의 로그를 전송하기 위한 간단한 API를 제공한다.

또, 실행시에 환경 변수(LOG_LEVEL)를 사용해 애플리케이션의 로그 레벨을 설정할 수 있는지 확인한다. 이를 통해 로컬에서 작업하고 있는 경우(.env 파일로 설정) 또는 클라우드 환경에서 워크로드를 실행하고 있는 경우(스테징, 운영 등) 필요에 따라 로그 레벨을 조정할 수 있다.

 

 

실수 2)  Docker 파일의 기본 이미지 선택

컨테이너로서 Node.js 애플리케이션을 전개하는 것은 매우 일반적이며, 여기에는 많은 이점이 있다. Docker 파일을 정의할 때는 파일의 선두에 사용할 기본 이미지를 선언한다.

예를 들어

 


이는 이미지가 공식 Node.js 버전 18 이미지를 기반으로 구축된다는 것을 보여준다. 개발자가 주의를 기울이지 않는 경우가 많은 것은 이로 인한 잠재적인 악영향이다.

Node18의 예를 보자. 위 이미지는 Debian 운영 체제를 기반으로 한다. 이것은 Node.js에서 기술된 일반적인 백엔드 API에 대해 많은 오버헤드를 추가하는 완전한 운영 체제이다. 이미지 크기가 매우 크고 빌드에 시간이 많이 걸리고 저장 비용이 증가하며 컨테이너에서 더 많은 리소스가 사용되므로 확장성과 성능에 영향을 미친다.

 

이것을 해결하는 것은 매우 간단하다. 대체 이미지를 사용한다. alpine 및 slim 이미지를 보는 것은 매우 일반적이다. 이것들은 Linux 기반 운영 체제로, 매우 가볍고 풀 기능 운영 체제에 프리 설치되어 있는 이진 및 라이브러리의 대부분은 포함되어 있지 않는다.

 

Docker Hub에서 Node.js 이미지 태그를 브라우즈 하면 alpine flavour와 slim flavour를 모두 이용할 수 있음을 알 수 있다. 이 변경만 하면 다음과 같다:

 


이미지 구축에 상당한 시간을 절약하고 운영 체제 오버헤드를 최소화하여 컨테이너 전체의 성능을 최적화 할 수 있다. 또한 이미지 크기가 크게 작아지기 때문에 빌드와 푸시가 빨라지고 원격 컨테이너 레지스트리에 저장하는 것이 더 저렴해진다.

 


무려 x5 이미지 사이즈가 축소되었다. 여기서 매일 여러 서비스에 대해 여러 CI 파이프라인을 실행하는 팀에서 이것의 영향을 상상해 봐라.

대부분의 경우 이것은 작동하지만 앱 패키지에는 기본적으로 Lightweight 이미지에 포함되지 않은 특정 저레벨 라이브러리가 필요할 수 있다. Docker 파일에 RUN 스테이트먼트로 설치해야 한다. 그래도 이익은 충분히 가치가 있다.

 

 

실수 3) JSON WebToken(JWT)에 서명할 때 비대칭 암호화를 사용하지 않음

JSON Web Tokens는 세상을 바꾸고 있다. 이것은 분산형 인가를 달성하기 위한 마이크로 서비스를 개발할 때 필요한 훌륭한 도구이다. 이 메커니즘은 매우 간단한다. 암호화를 사용하여 토큰에 서명하고 검증한다.

구현의 가장 간단한 형식을 사용하면 비밀(예를 들어 very Secret123)을 사용하여 토큰에 서명할 수 있다. 그런 다음 이러한 토큰을 확인하기 위해 동일한 비밀을 사용한다. 이것은 대칭 서명이다. 이는 토큰의 서명과 확인에 동일한 값이 사용되기 때문이다.

분산 아키텍처에서 이를 수행하는 경우 모든 서비스가 토큰을 확인하기 위해 그 비밀에 액세스해야 한다. 이로 인해 비밀이 도난당할 가능성이 높아지고 공격자가 가짜 토큰에 서명할 수 있다. 이를 통해 공격자는 접근성을 향상하거나 다른 사람을 대신하여 조작을 실행할 수 있다. 이것은 종종 간과되고 심각한 보안 위험을 초래한다.

 


JWTs에 서명하는 최선의 방법은 비대칭 알고리즘을 사용하는 것이다. raw secret 값을 사용하여 토큰에 서명 및 확인하는 대신 키 쌍을 사용한다(openssl 경유로 생성되는 등). 그 결과 토큰 서명에 사용되는 개인 키와 토큰 검증에 사용되는 공개 키가 생성된다.

이 방식은 서명 기관(예를 들어 인증 서비스)이 개인 키를 독점적으로 소유하고 토큰 서명에 사용할 수 있기 때문에 훨씬 안전한다.

API 요구를 수용해야 하는 아키텍처 내의 기타 서비스는 공개 키를 소유하고 토큰 검증에 사용할 수 있다.

이를 통해 접근권을 가진 서비스의 수를 제한함으로써 개인 키가 도난당하고 부정 이용되어 부정한 ID나 특권 토큰이 생성될 위험이 크게 줄어든다.

 

 

실수 4) 고유한 솔팅 없이 비밀번호 저장

일반적으로 이것이 고객의 핵심 비즈니스가 아닌 한(엄격한 규제와 감사를 수반한다), 저는 고객의 시스템에 비밀번호를 저장하는 것을 강력히 반대한다.

그럼에도 불구하고 많은 기업이 자체 시스템에 암호를 저장하는 것을 선택하고 있다. 이것은 백엔드 개발자에게도 중요한 주제이다.

 

이 실수에 대해 이야기하기 전에 비밀번호 인증에 대한 간단한 입문서

패스워드의 검증은 「암호화/복호화」 조작이 아닌 것에 주의해야 한다. raw 비밀번호를 취득하고 해시 알고리즘으로 실행하여 저장한다. 이에 따라 myPassword123은 487753b945871b5b05f854060de151d8과 같이 되어 데이터베이스에 저장된다. 그런 다음 로그인하면 사용자의 입력을 받아 해시한다. 그런 다음 결과 해시와 데이터베이스에 저장된 해시를 비교하고 일치하는 경우 사용자를 인증한다.

 

암호 저장과 관련한 4가지 보안 수준

  1. raw 패스워드 저장이다. 이건 무조건 No이다. 데이터베이스 위반의 경우 공격자는 모든 사용자의 미가공 암호에 액세스 한다.
  2. 해시 패스워드(no salt). 사용자의 비밀번호를 취득하고 위와 같이 해시 알고리즘으로 실행하여 데이터베이스에 저장한다. 이로 인해 공격자는 가공되지 않은 암호에 액세스 할 수 없게 된다. 단, 단순히 비밀번호를 해시하기만 하면 되므로 공격자는 Rainbow Table 공격을 이용할 수 있다. 이 공격에서는 해시된 암호를 각각의 미가공 암호와 비교하여 일치하는 암호를 식별할 수 있다. myPassword123을 단순한 해시 알고리즘으로 실행하면 항상 같은 결과를 얻을 수 있다는 점에 유의해야 한다.
  3. 해시 비밀번호 + global salt. 이 방법은 위 방법과 매우 유사하지만 해시하기 전에 비밀번호에 약간의 salt를 추가한다. 즉, myPassword123을 해시하는 것이 아니라 myPassword123+SOME_SALT를 해시하는 것이다. 즉, myPassword123과 같은 공통 암호는 데이터베이스 내 해시로서 다르게 보이며 레인보우 테이블 공격으로부터 보호한다. 그러나 글로벌 salt가 노출되어 있는 경우 공격자는 데이터베이스에 저장된 일반적인 암호를 식별하기 쉬워진다.
  4. 해시 패스워드 + 패스워드별 고유의 salt. 이것은 현재 가장 견고하고 표준적인 패스워드 저장 방법이다. 데이터베이스에 저장된 모든 암호는 고유 솔트로 해시된다. 이를 통해 데이터베이스를 위반한 경우에도 공격자가 사용자의 미가공 암호에 손을 댈 가능성이 크게 줄어든다. Bcrypt와 같은 패키지를 사용하여 이를 구현하는 것은 매우 간단하다.
반응형