Skip to main content 홈 크리에이터 personamanagmentlayer pcl nodejs-expert
nodejs-expert Expert-level Node.js backend development with Express, async patterns, streams, performance optimization, and production best practices
설치로 이동 Skills Marketplace 커뮤니티가 만든 AI 스킬을 발견하고 탐색하세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/personamanagmentlayer/pcl --skill nodejs-expert명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
Zip 다운로드 다운로드 중... name nodejs-expert version 1.0.0 description Expert-level Node.js backend development with Express, async patterns, streams, performance optimization, and production best practices category languages author PCL Team license Apache-2.0 tags ["nodejs","node","javascript","backend","express","async"] allowed-tools ["Read","Write","Edit","Bash(node:*, npm:*, npx:*, pm2:*)","Glob","Grep"] requirements {"node":">=20.0.0"}
Node.js Expert
You are an expert in Node.js with deep knowledge of async programming, streams, event loop, Express framework, and production deployment. You build scalable, performant backend applications following Node.js best practices.
Core Expertise
Modern Node.js Features
ESM (ES Modules):
{
"type" : "module"
}
import express from 'express' ;
import { readFile } from 'node:fs/promises' ;
import path from 'node:path' ;
import { fileURLToPath } from 'node:url' ;
const __filename = fileURLToPath (import .meta .url );
const __dirname = path.dirname (__filename);
if (condition) {
const module = await import ('./optional-module.js' );
module .doSomething ();
}
const data = await readFile ('config.json' , 'utf-8' );
const config = JSON .parse (data);
Async/Await Patterns:
async function fetchAllData ( ) {
const [users, posts, comments] = await Promise .all ([
fetchUsers (),
fetchPosts (),
fetchComments ()
]);
return { users, posts, comments };
}
async function processItems (items ) {
const results = [];
for (const item of items) {
const result = await processItem (item);
results.push (result);
}
return results;
}
async function safeOperation ( ) {
try {
const result = await riskyOperation ();
return { success : true , data : result };
} catch (error) {
console .error ('Operation failed:' , error);
return { success : false , error : error.message };
}
}
async function fetchMultiple (urls ) {
const results = await Promise .allSettled (
urls.map (url => fetch (url).then (r => r.json ()))
);
return results.map (result => {
if (result.status === 'fulfilled' ) {
return { success : true , data : result.value };
} else {
return { success : false , error : result.reason .message };
}
});
}
Express Framework import express from 'express' ;
import helmet from 'helmet' ;
import cors from 'cors' ;
import compression from 'compression' ;
import morgan from 'morgan' ;
const app = express ();
app.use (helmet ());
app.use (cors ());
app.use (compression ());
app.use (morgan ('combined' ));
app.use (express.json ());
app.use (express.urlencoded ({ extended : true }));
app.get ('/api/users' , async (req, res, next) => {
try {
const users = await getUsersFromDB ();
res.json (users);
} catch (error) {
next (error);
}
});
app.get ('/api/users/:id' , async (req, res, next) => {
try {
const { id } = req.params ;
const user = await getUserById (id);
if (!user) {
return res.status (404 ).json ({ error : 'User not found' });
}
res.json (user);
} catch (error) {
next (error);
}
});
app.post ('/api/users' , async (req, res, next) => {
try {
const userData = req.body ;
if (!userData.email || !userData.name ) {
return res.status (400 ).json ({ error : 'Missing required fields' });
}
const user = await createUser (userData);
res.status (201 ).json (user);
} catch (error) {
next (error);
}
});
app.use ((err, req, res, next ) => {
console .error (err.stack );
res.status (err.status || 500 ).json ({
error : err.message || 'Internal Server Error'
});
});
app.use ((req, res ) => {
res.status (404 ).json ({ error : 'Not Found' });
});
const PORT = process.env .PORT || 3000 ;
app.listen (PORT , () => {
console .log (`Server running on port ${PORT} ` );
});
import express from 'express' ;
import * as userController from '../controllers/users.js' ;
import { authenticate } from '../middleware/auth.js' ;
import { validate } from '../middleware/validation.js' ;
import { userSchema } from '../schemas/user.js' ;
const router = express.Router ();
router.get ('/' , userController.getUsers );
router.get ('/:id' , userController.getUser );
router.post (
'/' ,
authenticate,
validate (userSchema),
userController.createUser
);
router.put ('/:id' , authenticate, userController.updateUser );
router.delete ('/:id' , authenticate, userController.deleteUser );
export default router;
import userRoutes from './routes/users.js' ;
app.use ('/api/users' , userRoutes);
export function authenticate (req, res, next ) {
const token = req.headers .authorization ?.split (' ' )[1 ];
if (!token) {
return res.status (401 ).json ({ error : 'No token provided' });
}
try {
const decoded = jwt.verify (token, process.env .JWT_SECRET );
req.user = decoded;
next ();
} catch (error) {
res.status (401 ).json ({ error : 'Invalid token' });
}
}
export function validate (schema ) {
return (req, res, next ) => {
const { error } = schema.validate (req.body );
if (error) {
return res.status (400 ).json ({
error : error.details [0 ].message
});
}
next ();
};
}
import rateLimit from 'express-rate-limit' ;
const limiter = rateLimit ({
windowMs : 15 * 60 * 1000 ,
max : 100 ,
message : 'Too many requests from this IP'
});
app.use ('/api/' , limiter);
export function requestLogger (req, res, next ) {
const start = Date .now ();
res.on ('finish' , () => {
const duration = Date .now () - start;
console .log (`${req.method} ${req.path} ${res.statusCode} - ${duration} ms` );
});
next ();
}
File System Operations import { readFile, writeFile, appendFile, unlink, mkdir } from 'node:fs/promises' ;
import { existsSync } from 'node:fs' ;
import path from 'node:path' ;
async function readConfig ( ) {
try {
const data = await readFile ('config.json' , 'utf-8' );
return JSON .parse (data);
} catch (error) {
if (error.code === 'ENOENT' ) {
console .error ('File not found' );
}
throw error;
}
}
async function saveConfig (config ) {
const data = JSON .stringify (config, null , 2 );
await writeFile ('config.json' , data, 'utf-8' );
}
async function logMessage (message ) {
const timestamp = new Date ().toISOString ();
await appendFile ('app.log' , `${timestamp} - ${message} \n` );
}
async function ensureDir (dirPath ) {
if (!existsSync (dirPath)) {
await mkdir (dirPath, { recursive : true });
}
}
async function deleteFile (filePath ) {
try {
await unlink (filePath);
} catch (error) {
if (error.code !== 'ENOENT' ) {
throw error;
}
}
}
import { readdir } from 'node:fs/promises' ;
async function listFiles (dirPath ) {
const files = await readdir (dirPath, { withFileTypes : true });
return files
.filter (file => file.isFile ())
.map (file => file.name );
}
import { createReadStream, createWriteStream } from 'node:fs' ;
import { createGzip } from 'node:zlib' ;
import { pipeline } from 'node:stream/promises' ;
function processLargeFile (filePath ) {
const stream = createReadStream (filePath, { encoding : 'utf-8' });
stream.on ('data' , (chunk ) => {
console .log ('Received chunk:' , chunk.length );
});
stream.on ('end' , () => {
console .log ('Finished reading file' );
});
stream.on ('error' , (error ) => {
console .error ('Error reading file:' , error);
});
}
import { Transform } from 'node:stream' ;
class UpperCaseTransform extends Transform {
_transform (chunk, encoding, callback ) {
this .push (chunk.toString ().toUpperCase ());
callback ();
}
}
async function compressFile (input, output ) {
await pipeline (
createReadStream (input),
createGzip (),
createWriteStream (output)
);
console .log ('File compressed successfully' );
}
import readline from 'node:readline' ;
async function processCSV (filePath ) {
const fileStream = createReadStream (filePath);
const rl = readline.createInterface ({
input : fileStream,
crlfDelay : Infinity
});
for await (const line of rl) {
const [id, name, email] = line.split (',' );
await processUser ({ id, name, email });
}
}
HTTP Requests Fetch API (Built-in Node 18+):
async function fetchUsers ( ) {
const response = await fetch ('https://api.example.com/users' );
if (!response.ok ) {
throw new Error (`HTTP error! status: ${response.status} ` );
}
const users = await response.json ();
return users;
}
async function createUser (userData ) {
const response = await fetch ('https://api.example.com/users' , {
method : 'POST' ,
headers : {
'Content-Type' : 'application/json' ,
'Authorization' : `Bearer ${token} `
},
body : JSON .stringify (userData)
});
if (!response.ok ) {
const error = await response.text ();
throw new Error (error);
}
return await response.json ();
}
async function fetchWithTimeout (url, timeout = 5000 ) {
const controller = new AbortController ();
const id = setTimeout (() => controller.abort (), timeout);
try {
const response = await fetch (url, { signal : controller.signal });
clearTimeout (id);
return await response.json ();
} catch (error) {
clearTimeout (id);
if (error.name === 'AbortError' ) {
throw new Error ('Request timeout' );
}
throw error;
}
}
Database Integration import pg from 'pg' ;
const { Pool } = pg;
const pool = new Pool ({
host : process.env .DB_HOST ,
port : process.env .DB_PORT ,
database : process.env .DB_NAME ,
user : process.env .DB_USER ,
password : process.env .DB_PASSWORD ,
max : 20 ,
idleTimeoutMillis : 30000 ,
connectionTimeoutMillis : 2000
});
async function getUsers ( ) {
const result = await pool.query ('SELECT * FROM users WHERE active = $1' , [true ]);
return result.rows ;
}
async function transferMoney (fromId, toId, amount ) {
const client = await pool.connect ();
try {
await client.query ('BEGIN' );
await client.query (
'UPDATE accounts SET balance = balance - $1 WHERE id = $2' ,
[amount, fromId]
);
await client.query (
'UPDATE accounts SET balance = balance + $1 WHERE id = $2' ,
[amount, toId]
);
await client.query ('COMMIT' );
} catch (error) {
await client.query ('ROLLBACK' );
throw error;
} finally {
client.release ();
}
}
import { PrismaClient } from '@prisma/client' ;
const prisma = new PrismaClient ();
const users = await prisma.user .findMany ({
where : { active : true },
include : { posts : true }
});
const user = await prisma.user .create ({
data : {
email : 'alice@example.com' ,
name : 'Alice' ,
posts : {
create : [
{ title : 'First Post' , content : 'Hello World' }
]
}
}
});
const updated = await prisma.user .update ({
where : { id : 1 },
data : { name : 'Alice Smith' }
});
await prisma.user .delete ({
where : { id : 1 }
});
await prisma.$transaction(async (tx) => {
await tx.account .update ({
where : { id : 1 },
data : { balance : { decrement : 100 } }
});
await tx.account .update ({
where : { id : 2 },
data : { balance : { increment : 100 } }
});
});
Testing import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' ;
import request from 'supertest' ;
import app from '../app.js' ;
describe ('User API' , () => {
beforeEach (() => {
});
afterEach (() => {
vi.clearAllMocks ();
});
describe ('GET /api/users' , () => {
it ('should return all users' , async () => {
const response = await request (app)
.get ('/api/users' )
.expect (200 )
.expect ('Content-Type' , /json/ );
expect (response.body ).toBeInstanceOf (Array );
expect (response.body .length ).toBeGreaterThan (0 );
});
});
describe ('POST /api/users' , () => {
it ('should create a new user' , async () => {
const userData = {
name : 'Alice' ,
email : 'alice@example.com'
};
const response = await request (app)
.post ('/api/users' )
.send (userData)
.expect (201 );
expect (response.body ).toMatchObject (userData);
expect (response.body .id ).toBeDefined ();
});
it ('should return 400 for invalid data' , async () => {
const response = await request (app)
.post ('/api/users' )
.send ({ name : 'Alice' })
.expect (400 );
expect (response.body .error ).toBeDefined ();
});
});
});
Environment and Configuration
NODE_ENV=production
PORT=3000
DB_HOST=localhost
DB_PORT=5432
DB_NAME=mydb
DB_USER=admin
DB_PASSWORD=secret
JWT_SECRET=your-secret-key
REDIS_URL=redis://localhost:6379
import 'dotenv/config' ;
const config = {
env : process.env .NODE_ENV || 'development' ,
port : parseInt (process.env .PORT || '3000' ),
database : {
host : process.env .DB_HOST ,
port : parseInt (process.env .DB_PORT || '5432' ),
name : process.env .DB_NAME ,
user : process.env .DB_USER ,
password : process.env .DB_PASSWORD
},
jwtSecret : process.env .JWT_SECRET
};
export default config;
Production Deployment
export default {
apps : [{
name : 'api' ,
script : './app.js' ,
instances : 'max' ,
exec_mode : 'cluster' ,
env : {
NODE_ENV : 'production' ,
PORT : 3000
},
error_file : './logs/err.log' ,
out_file : './logs/out.log' ,
log_date_format : 'YYYY-MM-DD HH:mm:ss Z' ,
autorestart : true ,
watch : false ,
max_memory_restart : '1G'
}]
};
pm2 start ecosystem.config.js
pm2 monit
pm2 logs
pm2 restart api
pm2 stop api
FROM node:20-alpine
WORKDIR /app
# Install dependencies
COPY package*.json ./
RUN npm ci --only=production
# Copy source
COPY . .
# Non-root user
USER node
EXPOSE 3000
CMD ["node", "app.js"]
Best Practices
1. Use Async/Await
async function getData ( ) {
const data = await fetchData ();
return data;
}
function getData ( ) {
return fetchData ().then (data => data);
}
2. Handle Errors Properly
app.use (async (req, res, next) => {
try {
await someAsyncOperation ();
res.send ('Success' );
} catch (error) {
next (error);
}
});
app.use ((err, req, res, next ) => {
console .error (err.stack );
res.status (500 ).json ({ error : err.message });
});
process.on ('unhandledRejection' , (reason, promise ) => {
console .error ('Unhandled Rejection:' , reason);
process.exit (1 );
});
3. Use Environment Variables
4. Validate Input import Joi from 'joi' ;
const schema = Joi .object ({
email : Joi .string ().email ().required (),
password : Joi .string ().min (8 ).required ()
});
const { error, value } = schema.validate (req.body );
5. Use Connection Pooling
6. Implement Rate Limiting import rateLimit from 'express-rate-limit' ;
const limiter = rateLimit ({
windowMs : 15 * 60 * 1000 ,
max : 100
});
app.use ('/api/' , limiter);
7. Use Clustering import cluster from 'node:cluster' ;
import { cpus } from 'node:os' ;
if (cluster.isPrimary ) {
for (let i = 0 ; i < cpus ().length ; i++) {
cluster.fork ();
}
} else {
}
Approach When building Node.js applications:
Use Modern JavaScript : ES modules, async/await
Handle Errors : Try-catch, error middleware
Validate Input : Joi, Zod, express-validator
Secure : Helmet, CORS, rate limiting
Test : Vitest, supertest, high coverage
Monitor : Logging, error tracking
Deploy : PM2, Docker, clustering
Performance : Connection pooling, caching
Always build Node.js applications that are secure, performant, and maintainable.