* 불가피하게 Amazon linux2에서 실행해야 할 상황에서의 대처입니다. 가능하면 ubuntu 사용을 추천드립니다.

 

Amazon linux2에서 node18버전 이상 yum 설치 시 GLIBC 버전 호환 문제로 아래와 같은 에러가 발생합니다.

Error: Package: 2:nodejs-18.20.4-1nodesource.x86_64 (nodesource-nodejs)
           Requires: libc.so.6(GLIBC_2.28)(64bit)
Error: Package: 2:nodejs-18.20.4-1nodesource.x86_64 (nodesource-nodejs)
           Requires: libm.so.6(GLIBC_2.27)(64bit)
Error: Package: 2:nodejs-18.20.4-1nodesource.x86_64 (nodesource-nodejs)
           Requires: glibc >= 2.28

 

Node.js 18.x 설치 방법 (바이너리 다운로드 방식)

이 가이드는 Node.js 18.x을 바이너리 파일을 사용하여 설치하는 방법을 설명합니다. 이 방법은 GLIBC 버전 문제를 피하고 직접 바이너리를 다운로드하여 설치할 수 있습니다. 이 예제에서는 Node.js 18.17.1 버전을 사용합니다.

1. Node.js 바이너리 다운로드

Node.js 18.x 바이너리를 다운로드합니다. 아래 명령어를 사용합니다:

wget -nv https://d3rnber7ry90et.cloudfront.net/linux-x86_64/node-v18.17.1.tar.gz

2. Node.js 바이너리 압축 해제 및 이동

다운로드한 바이너리 파일을 압축 해제한 후, /usr/local/lib/node 디렉토리에 이동합니다:

mkdir /usr/local/lib/node

tar -xf node-v18.17.1.tar.gz

mv node-v18.17.1 /usr/local/lib/node/nodejs

3. 환경 변수 설정

Node.js를 사용할 수 있도록 환경 변수를 설정합니다. NVM이 이미 설치되어 있는 경우, NVM의 환경 설정을 비우고 Node.js의 경로를 추가합니다:

echo "export NVM_DIR=''" >> /home/ec2-user/.bashrc

echo "export NODEJS_HOME=/usr/local/lib/node/nodejs" >> /home/ec2-user/.bashrc

echo "export PATH=\$NODEJS_HOME/bin:\$PATH" >> /home/ec2-user/.bashrc

4. 환경 변수 적용

변경된 환경 변수를 적용하기 위해 .bashrc 파일을 다시 로드합니다:

. /home/ec2-user/.bashrc

5. Node.js 설치 확인

Node.js가 제대로 설치되었는지 확인합니다. 아래 명령어를 실행하여 현재 설치된 Node.js 버전을 확인합니다:

node -e "console.log('Running Node.js ' + process.version)"

node -v

'Dev > Node.js' 카테고리의 다른 글

node.js express docker실행  (0) 2024.08.02
Node.js Express 실행 확인 index.html 포함  (1) 2024.07.30

Node.js 프로젝트 준비

먼저, Node.js 프로젝트를 준비해야 합니다. 프로젝트 루트 디렉토리에 package.json 파일이 있어야 합니다.

 

Node.js Test 코드가 없다면 아래 링크를 통해 간단하게 작성합니다.

https://yes5.tistory.com/45

 

Node.js Express 실행 확인 index.html 포함

Node.js 설치먼저, Node.js를 설치해야 합니다.Node.js 다운로드:Node.js 공식 웹사이트로 이동합니다.LTS (Long Term Support) 버전을 다운로드합니다. 이는 안정적이고 장기적으로 지원되는 버전입니다.Node.js

yes5.tistory.com

 

docker 설치

https://yes5.tistory.com/46

 

Docker 설치 및 설정 deploying WSL2 distributionsensuring main distro is deployed error 해결

1. Docker 설치Docker는 대부분의 운영 체제에서 설치할 수 있습니다. 아래는 주요 운영 체제별 설치 방법입니다.WindowsDocker Desktop for Windows를 다운로드하고 설치합니다.설치 과정에서 기본 설정을 따

yes5.tistory.com

 

Dockerfile 작성

프로젝트 루트 디렉토리에 Dockerfile을 작성합니다. Dockerfile은 Docker 이미지를 빌드하기 위한 설정 파일입니다. 다음은 예시 Dockerfile입니다:

# Node.js 이미지를 기반으로 합니다
FROM node:18

# 작업 디렉토리를 설정합니다
WORKDIR /app

# 패키지 파일들을 컨테이너로 복사합니다
COPY package*.json ./

# 의존성 패키지를 설치합니다
RUN npm install

# 애플리케이션 소스 파일들을 컨테이너로 복사합니다
COPY . .

# 애플리케이션이 실행될 포트를 설정합니다
EXPOSE 3000

# 애플리케이션을 실행합니다
CMD ["node", "index.js"]

 

 

.dockerignore 작성

Docker 빌드 컨텍스트에 포함시키지 않을 파일들을 지정하기 위해 .dockerignore 파일을 작성합니다. 일반적으로 node_modules 폴더와 로그 파일 등을 제외합니다.

node_modules
npm-debug.log

 

디렉토리 위치

 

Docker 이미지 빌드

VSCode 터미널이나 명령 프롬프트를 열고, 프로젝트 디렉토리로 이동한 후 다음 명령어를 실행하여 Docker 이미지를 빌드합니다:

 

docker build -t my-express-app .

 

Docker 컨테이너 실행

이미지 빌드가 완료되면 다음 명령어로 Docker 컨테이너를 실행할 수 있습니다:

docker run -p 3000:3000 my-express-app

 

Docker 컨테이너 내 express 앱 실행 확인

http://localhost:3000 

Node.js 설치

먼저, Node.js를 설치해야 합니다.

  1. Node.js 다운로드:
    • Node.js 공식 웹사이트로 이동합니다.
    • LTS (Long Term Support) 버전을 다운로드합니다. 이는 안정적이고 장기적으로 지원되는 버전입니다.
  2. Node.js 설치:
    • 다운로드한 설치 파일을 실행합니다.
    • 설치 마법사의 지시에 따라 Node.js를 설치합니다. 기본 설정을 사용하면 됩니다.

 

Node.js 설치 확인

설치가 완료되면, Node.js와 npm(Node Package Manager)이 제대로 설치되었는지 확인합니다.

  1. 명령 프롬프트 열기:
    • Windows + R 키를 누르고 cmd를 입력하여 명령 프롬프트를 엽니다.
  2. Node.js와 npm 버전 확인:
    • 다음 명령어를 입력하여 Node.js와 npm이 설치되었는지 확인합니다.
node -v
npm -v

 

Visual Studio Code 설치

  1. VSCode 다운로드:
  2. VSCode 설치:
    • 다운로드한 설치 파일을 실행합니다.
    • 설치 마법사의 지시에 따라 VSCode를 설치합니다. 기본 설정을 사용하면 됩니다.

 

VSCode에서 Node.js 프로젝트 열기

  1. VSCode 열기:
    • 설치가 완료되면 VSCode를 실행합니다.
  2. 프로젝트 폴더 열기:
    • 파일 메뉴에서 폴더 열기를 선택합니다.
    • Node.js 프로젝트가 있는 폴더를 선택하고 열기 버튼을 클릭합니다.

 

터미널에서 Node.js 실행

VSCode 내의 통합 터미널을 사용하여 Node.js 애플리케이션을 실행할 수 있습니다.

  1. 통합 터미널 열기:
    • 보기 메뉴에서 터미널을 선택하거나 Ctrl + ` (백틱) 키를 눌러 통합 터미널을 엽니다.
  2. 프로젝트 폴더로 이동:
    • 터미널에서 프로젝트 폴더로 이동합니다.

 

프로젝트 디렉토리 설정:

mkdir my-express-app
cd my-express-app
npm init -y
npm install express

 

서버 코드 작성:

index.js 파일을 생성하고, 아래의 코드를 추가합니다

const express = require('express');
const path = require('path');

const app = express();
const port = 3000;

// 정적 파일 제공을 위한 미들웨어 설정
app.use(express.static(path.join(__dirname, 'public')));

// 루트 경로에 대한 핸들러
app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

app.listen(port, () => {
    console.log(`서버가 http://localhost:${port}에서 실행 중입니다.`);
});

 

웹 페이지 작성: 

public 디렉토리를 생성하고, 그 안에 index.html 파일을 작성합니다:

mkdir public

public/index.html 파일에 아래의 코드를 추가합니다:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Simple Express App</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            text-align: center;
            padding: 50px;
        }
        h1 {
            color: #333;
        }
    </style>
</head>
<body>
    <h1>Welcome to My Simple Express App!</h1>
    <p>This is a simple web page served by an Express server.</p>
</body>
</html>

디렉토리, 코드 위치

 

 

서버 실행:

터미널에서 아래 명령어를 실행하여 서버를 시작합니다:

node index.js

 

웹 브라우저에서 확인:

웹 브라우저를 열고 http://localhost:3000으로 접속하면 작성한 웹 페이지가 표시됩니다.

 

'Dev > Node.js' 카테고리의 다른 글

Amazon linux2에 node18 설치 Requires: libc.so.6(GLIBC_2.28)(64bit)  (0) 2024.08.16
node.js express docker실행  (0) 2024.08.02

프로세스 (Process)

정의

운영체제에서 실행 중인 프로그램 인스턴스를 의미. 각 프로세스는 독립된 메모리 공간과 자원을 할당받아 실행된다. 각각의 프로세스는 독립된 실행 흐름을 가지며, 다른 프로세스와는 메모리등의 자원을 공유하지 않는다.

 

자원 할당

각 프로세스는 독립된 메모리 공간을 할당받아 실행되며, 프로세스 간에 메모리나 파일과 같은 자원을 공유하기 위해 별도의 메커니즘이 필요하다. 프로세스는 운영체제로부터 자원을 할당받는 독립적인 개체로 존재한다.

 

동시성과 병렬성(Process) 

각 프로세스는 독립된 실행 흐름을 가지며, 여러 프로세스는 동시에 실행될 수있다. 여러 프로세스가 동시에 실행되는 것을 병렬 실행이라고 한다.

 

스레드 (Thread)

정의

프로세스 내에서 실행되는 작은 실행 단위. 스레드는 프로세스의 자원을 공유하며 실행된다. 한 프로세스 내에서 여러 개의 스레드가 동시에 실행될 수 있다.

 

자원 할당

스레드는 프로세스 내의 자원을 공유하면서 실행되므로, 스레드는 프로세스의 메모리, 파일, I/O등의 자원에 접근할 수 있다. 따라서 스레드 간의 통신과 자원 공유는 상대적으로 간단하게 이루어진다.

 

동시성(Thread)과 병렬성

스레드는 하나의 프로세스 내에서 동시에 실행될 수 있다. 다중 스레드를 사용하면 여러 스레드가 동시에 작업을 처리할 수 있다. 하지만 실제로 동시에 실행되는 것은 여러 스레드의 작업이 CPU의 코어를 번갈아가면서 실행되는 것이고, 스레드는 동시성을 구현하는 데 사용되며, 여러 스레드 간에 작업을 조율하고 자원을 공유하기 위해 동기화 메커니즘을 사용한다.

 

 

 

'Dev > JavaScript' 카테고리의 다른 글

동기 (Synchronous)와 비동기 (Asynchronous)  (0) 2023.05.31
콜백 함수 (Callback Function)  (0) 2023.05.30
이벤트 루프 (Event Loop)  (0) 2023.05.30
데이터 타입의 종류와 메모리 할당  (0) 2023.02.22
JavaScript 설명  (0) 2023.02.13

동기 실행 (Synchronous)

 동기 실행은 코드가 순차적으로 실행되는 방식이다. 한 작업이 끝나기를 기다렸다가 다음 작업을 실행하는 방식. 코드의 실행은 호출된 순서대로 진행되며, 하나의 작업이 완료되기 전까지는 다음 작업이 시작되지 않는다. 동기 실행은 직관적이고 순서가 중요한 작업에 적합하다. 하지만 한 작업이 끝날 때까지 다른 작업을 기다려야 하므로 시간이 오래 걸리는 작업이 있다면 전체 프로그램의 실행이 느려질 수 있다는 단점이 있다.

console.log("첫 번째 작업");
console.log("두 번째 작업");
console.log("세 번째 작업");

위 코드 실행 시 "첫 번째 작업" 부터 차례대로 로그를 출력한다.

 

 

비동기 실행  (Asynchronous)

비동기 실행은 코드의 실행이 순차적이지 않고, 작업이 완료되기를 기다리지 않고 다음 작업을 실행하는 방식이다. 비동기 작업은 별도의 실행 흐름을 생성하여 작업을 백그라운드에서 수행하고, 해당 작업이 완료될 때 결과를 반환하거나 알림을 받는다. 이를 통해 다른 작업을 동시에 수행할 수 있으므로 전체적인 실행 시간을 단축시킬 수 있다. 비동기 실행은 I/O 작업이나 네트워크 요청과 같이 시간이 오래 걸리는 작업에 유용하다.

console.log("첫 번째 작업");

setTimeout(function() {
  console.log("두 번째 작업");
}, 2000);

console.log("세 번째 작업");

위 코드 실행 시 "첫 번째 작업"을 출력한 후, setTimeout 함수는 2초 후에 콜백 함수를 실행한다. 그러나 콜백 함수의 실행을 기다리지 않고, 바로 다음코드 라인으로 넘거간다. 따라서 "세 번째 작업"을 출력 후 2초가 지난 뒤에 "두 번째 작업"을 출력한다.

 

 

파일 읽기 작업 수행 동기와 비동기 차이점

1. 동기적으로 파일을 읽는 작업을 수행한다면, 파일을 읽을 때까지 다음 코드 라인으로 진행되지 않는다.

2. 비동기적으로 파일을 읽는 작업을 수행한다면, 파일 읽기 작업이 백그라운드에서 수행되는 동안 다음 코드 라인을 실행할 수 있다. 파일 읽기 작업이 완료되면 콜백 함수나 promise를 통해 결과를 처리할 수 있다.

'Dev > JavaScript' 카테고리의 다른 글

프로세스 (Process)와 스레드 (Thread)의 차이  (0) 2023.05.31
콜백 함수 (Callback Function)  (0) 2023.05.30
이벤트 루프 (Event Loop)  (0) 2023.05.30
데이터 타입의 종류와 메모리 할당  (0) 2023.02.22
JavaScript 설명  (0) 2023.02.13

콜백함수란?

다른 함수에게 인자로 전달되어 나중에 호출되는 함수

콜백 함수는 비동기적 작업, 이벤트 처리, 데이터 요청 및 처리 등 다양한 상황에서 사용된다.

코드의 유연성과 효율성을 높일 수 있다.

 

콜백 함수의 패턴

비동기 작업의 콜백 함수

  • 다른 함수에게 콜백 함수를 인자로 전달한다. 이때 함수는 비동기적인 작업을 수행으로 콜백 함수를 호출할 수 있다.
  • 작업이 완료되거나 이벤트가 발생했을 때 적절한 동작을 수행할 수 있다.
function asyncOperation(callback) {
  setTimeout(function() {
    console.log('비동기 작업 완료');
    callback();
  }, 2000);
}

function handleCallback() {
  console.log('콜백 함수 호출됨');
}

asyncOperation(handleCallback);
// 2초 후에 '비동기 작업 완료' 출력 후 '콜백 함수 호출됨' 출력

 

이벤트 핸들러의 콜백 함수

  • 이벤트가 발생했을 때 실행될 함수로 콜백 함수를 등록한다.
  • 이벤트가 발생하면 등록된 콜백 함수가 호출되어 특정 동작을 수행한다.
document.getElementById('myButton').addEventListener('click', function() {
  console.log('버튼이 클릭되었습니다.');
});

id가 'myButton'인 버튼을 클릭했을 때 콜백 함수가 실행되며, '버튼이 클릭되었습니다.'를 출력

 

 

배열의 forEach 메소드에 콜백 함수 전달

const numbers = [1, 2, 3, 4, 5];

numbers.forEach(function(number) {
  console.log(number * 2);
});
// 배열의 각 요소에 대해 콜백 함수 실행 후, 2, 4, 6, 8, 10 출력

배열의 각 요소에 대해 콜백 함수를 실행하고, 각 요소에 2를 곱한 결과를 출력

이벤트 루프 설명

JavaScript는 단일 스레드 환경, 동기적으로 이벤트를 처리하는 메커니즘을 갖는다.

이벤트 루프란 이벤트 처리를 위한 주요한 컴포넌트로서, 이벤트 발생과 이벤트 핸들러 실행 사이의 상호작용을 관리한다.

 

일반적으로 JavaScript 코드는 순차적으로 실행되지만, 이벤트 루프를 통해 비동기적인 작업은 바로 반환되지 않고 나중에 완료될 때까지 기다리지 않고도 계속해서 다음 코드를 실행 할 수 있다.

 

이벤트 루프의 역할

1. 비동기 작업을 관리하고 완료되면 이벤트 큐에 해당 이벤트를 넣는다. 이벤트는 이벤트 큐에 순서대로 쌓이게 된다.

2. 현재 실행 중인 코드의 완료 여부를 확인하고, 실행할 다음 이벤트를 이벤트 큐에서 가져와 처리한다.

  •  이벤트 큐(Event Queue) JavaScript에서는 이벤트 루프와 동일어로도 쓰인다.
  •  비동기 이벤트 처리를 위해 사용되는 자료구조. 이벤트를 기록하고, 순차적으로 처리하는 방식으로 동작한다. 일반적으로 이벤트 큐는 이벤트가 발생하는 순서대로 큐에 저장되고, 발생한 순서대로 처리한다.

이벤트 루프의 동작 과정

1. Call Stack에 코드를 추가하여 실행한다.

2. Call Stack이 비어 있으면 이벤트 큐에서 다음 이벤트를 가져와 Call Stack에 추가한다.

3. Call Stack에 추가된 이벤트의 코드가 실행되고 Call Stack이 다시 비워질 때까지 이과정을 반복한다.

 

while(queue.waitForMessage()){
  queue.processNextMessage();
}

queue.waitForMessage() 함수는 현재 처리할 수 있는 메시지가 존재하지 않으면 새로운 메시지가 도착할 때까지 동기적으로 대기한다.

 

런타임 상황의 메모리 동작

런타임 환경에서 메모리 관리

Stack

  • 스택은 메모리의 한 영역으로, 함수 호출과 관련된 정보를 저장하는데 사용된다.
  • 함수가 호출될 때마다 Stack Frame이라는 메모리 블록이 생성되어 스택에 쌓인다.
  • 현재 실행 중인 함수의 정보, 매개변수, 로컬 변수 및 복귀 주소 등이 스택 프레임에 저장된다.
  • 함수가 실행을 완료하면 해당 함수의 Frame이 제거되고 스택의 맨 위에 있는 다음 스택 프레임이 실행된다. 이를 함수 호출 스택 (CallStack)이라고 한다.
function foo(b) {
  let a = 10
  return a + b + 11
}

function bar(x) {
  let y = 3
  return foo(x * y)
}

const baz = bar(7) // 42를 baz에 할당
  1. bar를 호출할 때, bar의 인수와 지역 변수를 포함하는 첫 번째 프레임이 생성됩니다.
  2. bar가 foo를 호출할 때, foo의 인수와 지역 변수를 포함하는 두 번째 프레임이 생성되어 첫 번째 프레임의 위로 푸시됩니다.
  3. foo가 반환하면, 맨 위의 프레임 요소를 스택 밖으로 꺼냅니다. (bar 호출 프레임만 남음)
  4. bar가 반환하면, 스택이 빕니다.

Heap

  • 힙은 동적으로 할당되는 객체 데이터를 저장하는데 사용된다. 객체와 배열 같은 자료구조들은 힙에 저장되며, 이들을 참조를 통해 접근한다.
  • 힙은 가비지 컬렉션에 의해 관리되며, 사용하지 않는 개체들은 자동으로 해제된다.

 

Queue

  • 큐는 비동기 작업의 처리를 위해 사용되는 자료구조
  • 비동기적으로 발생하는 이벤트나 작업은 이벤트 루프를 통해 큐에 추가된다.
  • 큐는 FIFO 원칙에 따라 동작하며, 새로운 이벤트는 큐의 뒤에 추가 되고 실행 할 이벤트는 큐의 앞에서 제거된다.
  • 이벤트 루프는 큐에 있는 이벤트를 순차적으로 처리하고, 해당 이벤트에 할당된 콜백 함수를 실행한다.

 

이러한 메모리 구조와 큐는 자바스크립트의 비동기적인 특성을 관리하고, 함수 호출과 객체 데이터를 저장하며, 이벤트 처리를 순서대로 처리함으로써 프로그램의 실행을 관리한다.

 

참조

 

데이터 타입의 종류

  • 기본형 primitive type
  • 숫자 number
  • 문자열 string
  • 불리언 boolean
  • null, undefined
  • ES6에서 추가된 symbol

 

  • 참조형 reference type
  • 객체 Object
  • 배열 Array
  • 함수 Fuction
  • 날짜 Date
  • 정규표현식 RegExp
  • ES6에서 추가된 Map, WeakMap, Set, WeakSet

 

기본형과 참조형을 구분하는 기준

  • 기본형(불변값) : 값이 담긴 주솟값을 바로 복제 
  • 참조형(가변값) : 값이 담긴 주솟값들로 이루어진 묶음을 가리키는 주솟값을 복제

불변값과 가변값의 의미는 아래 예제를 통해 알아보자.

 

1
2
3
4
var a;
= 'abc';
 
var a = 'abc'; //변수 선언과 할당을 한 문장으로 표현 위 2줄 코드와 같다.
cs

'기본형' 여기선(string)의 선언과 데이터 할당에 대한 메모리 영역

 

-대괄호[]의 숫자는 코드 줄을 의미-

 

[1] var a; // var 예약어로 변수 a 선언

변수 영역에서 빈 공간(@1003)을 확보한다. 확보한 공간의 식별자를 a로 지정한다.

 

[2] = 'abc'; // 변수 a에 데이터 할당

데이터 영역의 빈공간(@5004)에 문자열 'abc'를 저장한다.

변수 영역에서 a라는 식별자를 검색한다(@1003)

앞서 저장한 문자열의 주소(@5004)를 @1003의 공간에 대입한다.

 

[4] var a = 'abc'; // 변수 선언과 할당을 한 문장으로 표현

 

위 예제와 같이 변수영역엔 식별자(a)와 값이 저장된 데이터 영역의 주소(@5004)가 저장된다. 이처럼 변수 영역과 데이터 영역을 분리하면 중복된 데이터에 대한 처리 효율이 높아진다.
기본형 데이터 타입이 불변값인 이유는 'abc' 문자열에 'def'를 추가한다면 'abc'가 저장된 공간에 'def'를 더하는 것이 아닌 새로운 공간(5005)에 'abcdef'를 저장하고 1003주소의 값은 (@5004) -> (@5005)로 변경된다. 이렇게 'abc'는 변하지 않는 성질을 띄고 있다.

 

불변값을 알아 봤으니 이제 가변값도 예제를 통해 알아보자.

 

1
2
3
4
var obj1 = {
    name : 'ohsung',
    age : 26
};
cs

'참조형' 객체의 선언과 데이터 할당에 대한 메모리 영역

 

[1] var obj1 = { // var 예약어로 변수 obj를 선언

변수 영역에서 빈 공간(@1003)을 확보한다. 확보한 공간의 식별자를 obj1로 지정한다.

 

[2] name : 'ohsung'

[3] age : 26

데이터 영역의 빈공간(@5001)에 데이터를 저장하려고 보니 여러 개의 프로퍼티로 이뤄진 데이터 그룹이다.

이 그룹 내부의 프로퍼티들을 저장하기 위해 별도의 변수 영역을 마련하고, 그 영역의 주소(@7103 ~ ?)를 @5001에 저장한다.

@7103 및 @7104에 각각 name과 age라는 프로퍼티 이름을 저장한다.

데이터 영역에서 'ohsung'을 @5003에 저장하고, 26을 @5004에 저장한다.

 

기본형 데이터와의 차이는 '객체의 변수(프로퍼티) 영역'이 별도로 존재한다는 점이다. 예제를 보면 객체가 별도로 할애한 영역은 변수 영역일 뿐 '데이터 영역'은 기존의 메모리 공간을 그대로 활용하고 있다. 데이터 영역에 저장된 값은 모두 불변값이다. 그러나 변수에는 다른 값을 대입할 수 있다. 바로 이부분에 참조형 데이터는 가변값이다라고 한다.

 

+ Recent posts