cs 공부하며 시스템 콜, 커널에 대해 이해가도록 찾아보며 js와 Node.js로 예시로 정리해보았다.
📌 커널 = 운영체제의 핵심, 하드웨어와 소프트웨어를 이어주는 다리
사용자 프로그램이 운영체제(OS)의 커널에게 직접 접근할 수 없으므로, 커널에게 요청을 보내는 방식
1️⃣ 응용 프로그램이 시스템 콜 요청 (예: 파일 열기)
2️⃣ 시스템 콜이 커널 모드로 전환 (유저 모드 → 커널 모드)
3️⃣ 커널이 요청된 작업 수행 (예: 파일을 읽음)
4️⃣ 작업 완료 후, 유저 모드로 복귀 (커널 모드 → 유저 모드)
5️⃣ 응용 프로그램이 결과를 받음
운영체제의 핵심인 커널이 실행되는 모드로, 하드웨어(메모리, 디스크, 네트워크 등)에 직접 접근할 수 있는 권한을 가짐
일반 프로그램(유저 모드)은 직접 하드웨어에 접근할 수 없음
프로그램이 커널의 기능이 필요할 때 시스템 콜을 요청하면 커널 모드에서 실행됨
Dart나 node.js 코드를 보다보면 파일을 다루기 위해 File이나 fs를 사용하는것이 생각나서 내가 이해할 수 있는 예제들로 더 찾아보게 되었다.
Node.js는 서버이므로, 원격으로 클라이언트 PC를 직접 조작할 수 없지만
웹 브라우저 ↔ 백엔드(Node.js) 간 실시간 양방향 통신을 통해 기기 제어(하드웨어 조작) 가능하고,
이게 IoT(사물인터넷) 프로젝트에서 많이 사용하는 방법이라고 한다.
💡 즉, WebSocket, API, 클라이언트 애플리케이션을 활용해 간접적으로 제어 가능!
Next.js의 SSR은 기본적으로 Node.js 환경에서 실행되지만
Vercel, Cloudflare Workers, Deno, Edge Functions 같은 서버리스 환경에서도 실행 가능하다.
API Routes도 마찬가지이다.
📌 즉, Next.js의 SSR을 실행하는 서버가 꼭 Node.js일 필요는 없고, 실행 환경에 따라 다를 수 있다!
서버리스 환경에서는 Edge Runtime을 선택할 수도 있다고 한다.
export const runtime = 'edge'; // Edge Runtime (Deno 기반)
export async function GET(req) {
return new Response("Hello from Edge Runtime!", { status: 200 });
}
✅ 이 코드가 실행되면 Node.js가 아니라 V8 + Deno 환경에서 동작하게 됨
✅ 즉, Next.js의 서버는 실행 환경에 따라 Node.js가 아닐 수도 있음
✅ Node.js는 항상 실행되는 서버 기반 환경
✅ Edge Runtime은 요청이 있을 때만 실행되는 서버리스 환경
Node.js가 파일 시스템, 네트워크, 데이터베이스를 접근하는 과정은 시스템 콜(System Call)을 사용하며, 이때 커널 모드에서 작업이 수행된다.
하지만 Node.js 자체가 커널 모드에서 실행되는 것은 아니고, 시스템 콜을 통해 커널이 대신 실행하는 방식.
const fs = require("fs");
fs.readFile("test.txt", "utf8", (err, data) => {
if (err) {
console.error("파일 읽기 실패:", err);
return;
}
console.log("파일 내용:", data);
});
📌 내부 동작 과정
1️⃣ fs.readFile()이 호출됨 (유저 모드)
2️⃣ Node.js가 내부적으로 시스템 콜 open()을 호출하여 파일을 엶
3️⃣ 파일을 읽기 위해 read() 시스템 콜이 호출됨
4️⃣ 커널 모드에서 파일을 읽고, 데이터를 유저 모드로 반환
5️⃣ Node.js가 데이터를 받아서 JavaScript 코드에서 사용할 수 있도록 제공
💡 즉, Node.js의 fs 모듈을 사용하면 내부적으로 시스템 콜을 호출하여 커널이 파일 시스템을 처리함!
const http = require("http");
http.get("http://example.com", (res) => {
console.log(`응답 코드: ${res.statusCode}`);
res.on("data", (chunk) => {
console.log(`응답 데이터: ${chunk}`);
});
});
📌 내부 동작 과정
1️⃣ http.get()이 호출됨 (유저 모드)
2️⃣ Node.js가 내부적으로 시스템 콜 socket()을 호출하여 네트워크 연결을 생성
3️⃣ 연결이 완료되면 connect() 시스템 콜을 호출하여 서버와 연결
4️⃣ 데이터를 보내기 위해 send() 시스템 콜 실행
5️⃣ 서버에서 응답을 받으면 recv() 시스템 콜을 실행하여 데이터 수신
6️⃣ 받은 데이터를 Node.js에서 JavaScript 코드로 처리
💡 즉, Node.js에서 네트워크 요청을 보내면 내부적으로 커널이 네트워크 소켓을 관리하고 데이터를 처리함!
const mysql = require("mysql");
const connection = mysql.createConnection({
host: "localhost",
user: "root",
password: "password",
database: "test_db"
});
connection.connect((err) => {
if (err) {
console.error("데이터베이스 연결 실패:", err);
return;
}
console.log("데이터베이스 연결 성공!");
});
📌 내부 동작 과정
1️⃣ mysql.createConnection()이 호출됨 (유저 모드)
2️⃣ Node.js가 내부적으로 시스템 콜 socket()을 호출하여 데이터베이스 서버와 연결
3️⃣ connect() 시스템 콜을 호출하여 연결을 설정
4️⃣ SQL 쿼리를 보내기 위해 send() 시스템 콜을 실행
5️⃣ 응답을 받으면 recv() 시스템 콜을 실행하여 데이터 가져오기
6️⃣ 받은 데이터를 JavaScript에서 사용할 수 있도록 반환
💡 즉, 데이터베이스와의 네트워크 통신도 시스템 콜을 통해 이루어짐!
공부하며 정리&기록하는 ._. 씅로그