Node.js는 이벤트 기반 아키텍처를 사용하여 비동기 작업을 처리하는 데 최적화된 환경을 제공합니다.
이벤트 기반 아키텍처는 애플리케이션의 주요 동작을 이벤트로 정의하고, 해당 이벤트가 발생했을 때 적절한 리스너가 동작하도록 설계하는 방식입니다. 이벤트 중심의 설계는 코드의 응집력과 유지 보수성을 높이는 데 큰 도움을 줍니다.
1. 이벤트 기반 아키텍처 장점
- 비동기 처리: 작업을 비동기로 처리하여 효율성과 응답성을 높임.
- 확장성: 새로운 기능을 추가하기 쉽고, 특정 이벤트 처리 로직을 독립적으로 작성 가능.
- 유지 보수성: 모듈화된 설계로 코드 가독성과 유지 보수성을 높임.
2. EventEmitter 소개
이벤트를 생성하고, 리스너를 등록하거나 제거하며, 이벤트를 발생시키는 기능을 제공하는 클래스
EventEmitter 주요 메서드
- on(event, listener): 특정 이벤트에 리스너를 등록.
- emit(event, ...args): 이벤트를 발생시키고, 등록된 리스너 실행.
- once(event, listener): 이벤트에 리스너를 한 번만 등록.
- off(event, listener) 또는 removeListener(event, listener): 등록된 리스너 제거.
3. 프로젝트 구조
project-root/
├── app.js # 메인 애플리케이션 파일
├── events/ # 이벤트 정의 및 리스너 관리 디렉토리
│ ├── userEvents.js # 사용자 관련 이벤트 정의
│ └── ... # 추가 이벤트 정의 파일
├── services/ # 비즈니스 로직 구현 디렉토리
│ ├── userService.js
│ └── ...
├── database/ # 데이터베이스 연동 관련 파일
│ ├── sqlite.js # SQLite 초기화 및 연결 설정
│ └── ...
├── utils/ # 유틸리티 코드 디렉토리
│ ├── dbChecker.js # SQLite 데이터 확인 코드
│ └── ...
├── package.json # 프로젝트 설정 파일
└── README.md # 프로젝트 설명 파일
4. SQLite 연동
- 이벤트 기반 아키텍처에서 데이터베이스 연동은 필수적
- SQLite를 사용하여 데이터를 저장하고 조회하는 기능 구현
SQLite 초기화 및 연결 (database/sqlite.js)
const sqlite3 = require('sqlite3').verbose();
// SQLite 데이터베이스 초기화
const db = new sqlite3.Database('./data.db', (err) => {
if (err) {
console.error('Error opening database:', err.message);
} else {
console.log('Connected to SQLite database.');
}
});
// 사용자 테이블 생성
db.serialize(() => {
db.run(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL
)
`);
});
module.exports = db;
5. EventEmitter로 이벤트 기반 아키텍처 설계하기
- 이벤트 정의: 발생 가능한 이벤트를 정의.
- 리스너 등록: 각 이벤트에 대한 리스너를 설정.
- 이벤트 발생: 특정 상황에서 이벤트를 발생시키고 데이터를 전달.
events/userEvents.js 파일:
const EventEmitter = require('events');
class UserEmitter extends EventEmitter {}
const userEmitter = new UserEmitter();
module.exports = userEmitter;
services/userService.js 파일:
const db = require('../database/sqlite');
const userEmitter = require('../events/userEvents');
// 사용자 등록 서비스
userEmitter.on('userRegistered', (user) => {
console.log(`Saving user data: ${JSON.stringify(user)}`);
db.run(
'INSERT INTO users (name, email) VALUES (?, ?)',
[user.name, user.email],
(err) => {
if (err) {
console.error('Error saving user:', err.message);
} else {
console.log('User data saved successfully.');
}
}
);
});
module.exports = userEmitter;
app.js 파일:
const userEmitter = require('./events/userEvents');
// 사용자 등록 이벤트 발생
const newUser = { name: 'Jane Doe', email: 'jane.doe@example.com' };
userEmitter.emit('userRegistered', newUser);
// 데이터베이스 확인 코드
const db = require('./database/sqlite');
db.all('SELECT * FROM users', [], (err, rows) => {
if (err) {
console.error('Error fetching users:', err.message);
} else {
console.log('Stored users:', rows);
}
});
출력 결과:
Saving user data: {"name":"Jane Doe","email":"jane.doe@example.com"}
User data saved successfully.
Stored users: [ { id: 1, name: 'Jane Doe', email: 'jane.doe@example.com' }
6. 고급 기능: 에러 처리 및 이벤트 제거
1) 에러 처리
userEmitter.on('error', (err) => {
console.error(`Error occurred: ${err.message}`);
});
userEmitter.emit('error', new Error('Something went wrong!'));
출력 결과:
Error occurred: Something went wrong!
2) 이벤트 제거
const listener = (user) => {
console.log(`Temporary listener for ${user.name}`);
};
userEmitter.on('userRegistered', listener);
userEmitter.off('userRegistered', listener);
userEmitter.emit('userRegistered', newUser); // 출력 없음
Node.js에서 이벤트 기반 아키텍처는 비동기 처리를 효율적으로 설계하는 데 필수적인 패턴입니다. EventEmitter를 활용하면 이벤트 흐름을 명확히 정의하고, 유연하고 확장 가능한 애플리케이션을 구현할 수 있습니다.
반응형
'개발정리 (nodeJS)' 카테고리의 다른 글
[nodeJS] Node.js에서 생명 주기 활용하기 (0) | 2025.01.31 |
---|---|
[nodeJS] Node.js에서 DB 프로시저 활용하기 (0) | 2024.12.31 |
[nodeJS] Node.js에서 SQLite를 사용한 로컬 데이터베이스 구축하기 (1) | 2024.12.18 |
[nodeJS] Node.js와 Apache Kafka를 사용한 스트리밍 데이터 처리 (1) | 2024.12.03 |
[nodeJS] Node.js에서 Bcrypt를 사용한 비밀번호 해싱 및 검증하기 (0) | 2024.11.21 |