| name | backend-expert-advisor |
| description | Backend expert guidance for API/DB/Security/Architecture |
Backend Expert Advisor
Version: 1.0.0
Last Updated: 2025-01-24
Specialization: Professional Backend Development (API/DB/Security/Architecture)
Target Audience: Intermediate to Advanced Backend Developers
Language Support: Korean + English
๐ Overview
Backend Expert Advisor is a comprehensive skill that provides expert-level guidance for backend development challenges. Built on 45+ research papers in prompt engineering and curated from authoritative sources including RFC standards, OWASP guidelines, and enterprise engineering blogs (Netflix, Uber, Kakao, Naver), this skill delivers production-ready solutions with security and performance best practices.
Core Strengths
- API Design: REST/GraphQL/gRPC with industry standards (OpenAPI 3.1, RFC 9110)
- Database Optimization: Query tuning, indexing, sharding strategies for SQL/NoSQL
- Security: OWASP Top 10 compliance, authentication/authorization patterns
- Architecture: Microservices, event-driven, domain-driven design
- Korean Regulations: KISA, PIPC compliance for payment/personal data
Knowledge Base
- Official Documentation: PostgreSQL, MongoDB, Redis, Kubernetes, Docker
- Standards: RFC (HTTP, OAuth), ISO (SQL), OWASP (Security)
- Academic Research: ACM SIGMOD, IEEE ICDE, USENIX papers
- Industry Practices: Netflix, Uber, Slack, Kakao, Naver engineering blogs
- Korean Specifics: ๊ฐ์ธ์ ๋ณด๋ณดํธ๋ฒ, ์ ์๊ธ์ต๊ฑฐ๋๋ฒ, CSAP guidelines
๐ฏ When to Use This Skill
Use Backend Expert Advisor when you need to:
API Development
- Design RESTful APIs following best practices (versioning, pagination, HATEOAS)
- Implement GraphQL schemas with optimal resolver patterns
- Choose between REST/GraphQL/gRPC based on use case
- Set up API gateway patterns (Kong, AWS API Gateway, NGINX)
- Handle rate limiting and throttling strategies
Database & Performance
- Optimize slow queries and design efficient indexes
- Choose between SQL and NoSQL databases for your use case
- Implement connection pooling and transaction management
- Design database sharding and partitioning strategies
- Set up caching layers (Redis, Memcached, CDN)
Security & Authentication
- Implement OAuth 2.1 and OpenID Connect flows
- Design JWT-based authentication with refresh tokens
- Set up RBAC (Role-Based Access Control) or ABAC systems
- Prevent common vulnerabilities (SQL injection, XSS, CSRF)
- Comply with Korean regulations (๊ฐ์ธ์ ๋ณด๋ณดํธ๋ฒ, KISA standards)
Architecture & Scalability
- Design microservices architecture with proper boundaries
- Implement event-driven patterns (message queues, pub/sub)
- Choose between monolith, SOA, and microservices
- Design for horizontal scaling and load balancing
- Implement circuit breaker and saga patterns
Monitoring & Operations
- Set up structured logging with ELK or Loki
- Implement metrics collection (Prometheus, Grafana)
- Design distributed tracing (OpenTelemetry, Jaeger)
- Create effective alerting rules and SLA monitoring
- Build CI/CD pipelines with Docker and Kubernetes
Korean Market Specifics
- Integrate with Korean payment systems (KG์ด๋์์ค, NHN KCP, ํ ์คํ์ด๋จผ์ธ )
- Implement personal data protection (๊ฐ์ธ์ ๋ณด๋ณดํธ๋ฒ ์ค์)
- Handle electronic financial transactions (์ ์๊ธ์ต๊ฑฐ๋๋ฒ)
- Use government frameworks (์ ์์ ๋ถ ํ์คํ๋ ์์ํฌ)
- Deploy to Korean cloud platforms (Naver Cloud, KT Cloud)
๐ก Core Capabilities
1. Architecture Design & Review
- Evaluate existing architecture and suggest improvements
- Design scalable, maintainable backend systems
- Identify bottlenecks and single points of failure
- Recommend appropriate patterns (microservices, event-driven, etc.)
- Create architecture decision records (ADRs)
2. API Design & Best Practices
- Generate OpenAPI 3.1 specifications
- Design consistent REST API naming and structure
- Implement versioning strategies (URL, header, content negotiation)
- Set up pagination, filtering, and sorting patterns
- Handle error responses with RFC 7807 Problem Details
3. Database Optimization
- Analyze and optimize slow queries
- Design indexes for specific query patterns
- Recommend database schema improvements
- Suggest sharding/partitioning strategies
- Provide ORM best practices (Prisma, TypeORM, SQLAlchemy)
4. Security Hardening
- Audit code for OWASP Top 10 vulnerabilities
- Design secure authentication flows (OAuth 2.1, OIDC)
- Implement proper token management and rotation
- Set up rate limiting and DDoS protection
- Encrypt sensitive data at rest and in transit
5. Performance Tuning
- Identify and resolve N+1 query problems
- Implement multi-level caching strategies
- Optimize API response times
- Design asynchronous processing patterns
- Profile and optimize resource usage
6. DevOps & Deployment
- Create Dockerfiles following best practices
- Design Kubernetes deployments with proper resource limits
- Set up CI/CD pipelines (GitHub Actions, GitLab CI)
- Implement blue-green or canary deployments
- Configure monitoring and logging infrastructure
7. Code Review & Quality
- Review backend code for common issues
- Suggest refactoring opportunities
- Identify code smells and anti-patterns
- Recommend testing strategies (unit, integration, e2e)
- Ensure adherence to SOLID principles
8. Korean Compliance & Integration
- Guide personal data protection implementation
- Integrate payment gateways (Korean providers)
- Handle resident registration numbers securely
- Comply with cloud security standards (CSAP)
- Use Korean-specific APIs (๊ณต๊ณต๋ฐ์ดํฐํฌํธ, etc.)
๐ Usage Guide
Quick Start
Basic Query Format
"I need help with [specific problem].
Context:
- Tech stack: [e.g., Node.js + PostgreSQL + Redis]
- Current issue: [describe the problem]
- Constraints: [performance requirements, regulations, etc.]"
Example
"I need help optimizing a slow API endpoint.
Context:
- Tech stack: Express.js + PostgreSQL + Redis
- Current issue: /users endpoint takes 3-5 seconds
- The query joins 4 tables and returns 10,000+ rows
- Need to reduce to under 500ms"
Advanced Usage Patterns
Pattern 1: Architecture Review
"Review my microservices architecture:
Services:
1. User Service (Node.js + MongoDB)
2. Product Service (Java + PostgreSQL)
3. Order Service (Python + PostgreSQL)
4. Payment Service (Go + MySQL)
Communication: REST APIs
Message Queue: RabbitMQ for async events
Issues:
- Frequent timeouts between services
- Difficulty maintaining data consistency
- Deployment takes 30+ minutes
Suggest improvements with Korean cloud deployment in mind."
Pattern 2: Security Audit
"Audit my authentication system for security issues:
[PASTE YOUR CODE OR ARCHITECTURE DIAGRAM]
Requirements:
- OAuth 2.1 compliance
- JWT with refresh tokens
- OWASP Top 10 compliance
- ๊ฐ์ธ์ ๋ณด๋ณดํธ๋ฒ ์ค์ (for Korean users)"
Pattern 3: Database Optimization
"Optimize this query:
```sql
SELECT u.*, p.*, o.*
FROM users u
LEFT JOIN profiles p ON u.id = p.user_id
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.created_at > '2024-01-01'
ORDER BY u.created_at DESC
LIMIT 100;
Current performance:
- Execution time: 4.2 seconds
- Rows scanned: 1.2M
- Database: PostgreSQL 15
Target: <500ms"
#### Pattern 4: API Design
"Design a REST API for a blog system with:
Entities:
- Users (authentication required)
- Posts (public + private)
- Comments (nested, max 3 levels)
- Categories & Tags
Requirements:
- RESTful design
- Pagination
- Filtering by category/tag/date
- Search functionality
- Rate limiting (100 req/min per user)
Generate OpenAPI 3.1 spec."
---
## ๐ ๏ธ Framework & Tool Specific Guides
### Node.js + Express.js
```javascript
// โ
Best Practice: Async Error Handling
const asyncHandler = (fn) => (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
app.get('/users/:id', asyncHandler(async (req, res) => {
const user = await User.findById(req.params.id);
if (!user) throw new NotFoundError('User not found');
res.json(user);
}));
// โ
Best Practice: Structured Logging
const logger = winston.createLogger({
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [new winston.transports.Console()]
});
app.use((req, res, next) => {
logger.info('Request', {
method: req.method,
path: req.path,
ip: req.ip,
userId: req.user?.id
});
next();
});
// โ
Best Practice: Connection Pooling
const pool = new Pool({
host: process.env.DB_HOST,
database: process.env.DB_NAME,
max: 20, // max connections
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
});
Python + FastAPI
from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.get("/users/{user_id}")
async def get_user(
user_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
user = db.query(User).filter(User.id == user_id).first()
if not user:
raise HTTPException(status_code=404, detail="User not found")
return user
from pydantic import BaseModel, EmailStr, Field
class UserCreate(BaseModel):
email: EmailStr
password: str = Field(..., min_length=8)
name: str = Field(..., max_length=100)
class Config:
json_schema_extra = {
"example": {
"email": "user@example.com",
"password": "SecurePass123!",
"name":
}
}
Java + Spring Boot
@Service
@Transactional
public class UserService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
@Autowired
public UserService(UserRepository userRepository,
PasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
public UserDTO createUser(UserCreateRequest request) {
if (userRepository.existsByEmail(request.getEmail())) {
throw new DuplicateEmailException("Email already exists");
}
User user = User.builder()
.email(request.getEmail())
.password(passwordEncoder.encode(request.getPassword()))
.name(request.getName())
.build();
User savedUser = userRepository.save(user);
return UserDTO.from(savedUser);
}
}
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound {
ErrorResponse.builder()
.status(HttpStatus.NOT_FOUND.value())
.message(ex.getMessage())
.timestamp(LocalDateTime.now())
.build();
<>(error, HttpStatus.NOT_FOUND);
}
}
๐ Examples
Example 1: API Rate Limiting Implementation
Scenario: Prevent API abuse with Redis-based rate limiting
Problem:
- Public API receiving 10,000+ requests per second
- Need to limit to 100 requests per minute per user
- Must return proper HTTP 429 status with retry-after header
Solution (Node.js + Express + Redis):
const Redis = require('ioredis');
const redis = new Redis(process.env.REDIS_URL);
async function rateLimiter(req, res, next) {
const userId = req.user?.id || req.ip;
const key = `rate_limit:${userId}`;
const limit = 100;
const window = 60;
try {
const current = await redis.incr(key);
if (current === 1) {
await redis.expire(key, window);
}
if (current > limit) {
const ttl = await redis.ttl(key);
res.set('Retry-After', ttl);
return res.status(429).json({
error: 'Too Many Requests',
message: `Rate limit exceeded. Try again in ${ttl} seconds.`,
: ttl
});
}
res.(, limit);
res.(, limit - current);
();
} (error) {
.(, error);
();
}
}
app.(, rateLimiter);
Result:
- Reduced server load by 70%
- Proper HTTP 429 responses
- User-friendly retry-after headers
- Fail-open design (continues if Redis is down)
Example 2: N+1 Query Optimization
Scenario: Optimize blog post listing with author and comment counts
Problem (Bad Code):
@app.get("/posts")
async def list_posts(db: Session = Depends(get_db)):
posts = db.query(Post).limit(20).all()
result = []
for post in posts:
author = db.query(User).filter(User.id == post.author_id).first()
comment_count = db.query(Comment).filter(
Comment.post_id == post.id
).count()
result.append({
"id": post.id,
"title": post.title,
"author": author.name,
"comment_count": comment_count
})
return result
Solution (Optimized):
from sqlalchemy.orm import joinedload, selectinload
from sqlalchemy import func
@app.get("/posts")
async def list_posts(db: Session = Depends(get_db)):
posts = db.query(
Post.id,
Post.title,
Post.created_at,
User.name.label('author_name'),
func.count(Comment.id).label('comment_count')
).join(
User, Post.author_id == User.id
).outerjoin(
Comment, Post.id == Comment.post_id
).group_by(
Post.id, User.name
).limit(20).all()
return [
{
"id": post.id,
"title": post.title,
"author": post.author_name,
"comment_count": post.comment_count
}
for post in posts
]
Key Techniques:
- Use
JOIN instead of separate queries
- Aggregate functions (
COUNT) in single query
- Proper indexing on foreign keys
- Result: 95% faster (2.3s โ 45ms)
Example 3: Secure JWT Authentication (OAuth 2.1 Compliant)
Scenario: Implement secure authentication with refresh token rotation
Requirements:
- JWT access tokens (15 min expiry)
- Refresh tokens (7 days, rotation on use)
- Secure cookie storage (HttpOnly, Secure, SameSite)
- CSRF protection
- ๊ฐ์ธ์ ๋ณด๋ณดํธ๋ฒ ์ค์ (Korean regulation)
Implementation (Node.js + Express):
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');
const crypto = require('crypto');
function generateTokens(userId) {
const accessToken = jwt.sign(
{ userId, type: 'access' },
process.env.ACCESS_TOKEN_SECRET,
{ expiresIn: '15m' }
);
const refreshToken = jwt.sign(
{ userId, type: 'refresh', jti: crypto.randomUUID() },
process.env.REFRESH_TOKEN_SECRET,
{ expiresIn: '7d' }
);
return { accessToken, refreshToken };
}
app.post('/auth/login', async (req, res) => {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user) {
return res.status(401).json({ error: 'Invalid credentials' });
}
isValid = bcrypt.(password, user.);
(!isValid) {
res.().({ : });
}
{ accessToken, refreshToken } = (user.);
.({
: user.,
: refreshToken,
: (.() + * * * * )
});
res.(, refreshToken, {
: ,
: ,
: ,
: * * * *
});
res.({
accessToken,
: ,
:
});
});
app.(, (req, res) => {
{ refreshToken } = req.;
(!refreshToken) {
res.().({ : });
}
{
payload = jwt.(
refreshToken,
process..
);
storedToken = .({
: payload.,
: refreshToken
});
(!storedToken) {
.({ : payload. });
res.().({ : });
}
.({ : storedToken. });
tokens = (payload.);
.({
: payload.,
: tokens.,
: (.() + * * * * )
});
res.(, tokens., {
: ,
: ,
: ,
: * * * *
});
res.({
: tokens.,
:
});
} (error) {
res.().({ : });
}
});
() {
authHeader = req..;
(!authHeader?.()) {
res.().({ : });
}
token = authHeader.();
{
payload = jwt.(token, process..);
req. = { : payload. };
();
} (error) {
res.().({ : });
}
}
app.(, authenticate, (req, res) => {
user = .(req..);
res.(user);
});
Security Features:
- โ
Short-lived access tokens (15 min)
- โ
Refresh token rotation (prevents replay attacks)
- โ
HttpOnly cookies (prevents XSS)
- โ
Secure & SameSite flags (prevents CSRF)
- โ
Token reuse detection (invalidates all tokens)
- โ
Database-backed refresh tokens (revocable)
Korean Compliance:
- ๊ฐ์ธ์ ๋ณด (์ด๋ฉ์ผ) ์ํธํ ์ ์ฅ
- ๋ก๊ทธ์ธ ์๋ ๋ก๊น
(์ ๊ทผ ๊ธฐ๋ก)
- ๋น๋ฐ๋ฒํธ bcrypt ํด์ฑ (๋จ๋ฐฉํฅ ์ํธํ)
Example 4: Microservices Circuit Breaker Pattern
Scenario: Prevent cascading failures between microservices
Problem:
- Order Service calls Payment Service
- Payment Service occasionally times out (3-5% of requests)
- Timeouts cause Order Service to hang, affecting all users
Solution (Node.js with opossum library):
const CircuitBreaker = require('opossum');
const axios = require('axios');
function createPaymentClient() {
async function processPayment(orderId, amount) {
const response = await axios.post(
'http://payment-service/api/payments',
{ orderId, amount },
{ timeout: 3000 }
);
return response.data;
}
const options = {
timeout: 3000,
errorThresholdPercentage: 50,
resetTimeout: 30000,
rollingCountTimeout: 10000,
rollingCountBuckets: 10,
fallback: (orderId, amount) => {
console.log();
messageQueue.(, { orderId, amount });
}
};
breaker = (processPayment, options);
breaker.(, {
.();
metrics.();
});
breaker.(, {
.();
metrics.();
});
breaker.(, {
.();
metrics.();
});
breaker.(, {
.();
metrics.();
});
breaker;
}
paymentClient = ();
app.(, (req, res) => {
{
order = .({
: req..,
: req..,
: req..
});
payment = paymentClient.(order., order.);
(payment. === ) {
res.().({
: ,
: order.,
:
});
}
order.({ : , : payment. });
res.().({
: ,
: order.,
:
});
} (error) {
.(, error);
res.().({ : });
}
});
Circuit Breaker States:
CLOSED (Normal)
โ (50% errors in 10s window)
OPEN (Reject all requests)
โ (After 30 seconds)
HALF-OPEN (Allow 1 request to test)
โ (If successful)
CLOSED (Resume normal)
Benefits:
- Prevents cascading failures
- Automatic recovery detection
- Graceful degradation (fallback to queue)
- Real-time metrics and alerting
- User experience maintained (202 Accepted vs 500 Error)
Monitoring Dashboard (Grafana):
Circuit Breaker Status:
- State: CLOSED โ
/ OPEN โ / HALF-OPEN โ ๏ธ
- Success Rate: 95.2%
- Average Response Time: 245ms
- Fallback Triggered: 12 times (last hour)
Example 5: Database Connection Pooling (PostgreSQL)
Scenario: Optimize database connections for high-concurrency API
Problem:
- API handles 1000+ concurrent requests
- Each request creates new DB connection
- Connection limit reached (max 100)
- "Too many connections" errors
Solution (Node.js + pg library):
const { Pool } = require('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,
query_timeout: 10000,
statement_timeout: 10000,
ssl: process.env.NODE_ENV === 'production' ? {
rejectUnauthorized: false
} : false
});
pool.on('connect', () => {
.();
});
pool.(, {
.(, err);
});
() {
start = .();
{
result = pool.(text, params);
duration = .() - start;
(duration > ) {
.(, {
duration,
: text,
params
});
}
result;
} (error) {
.(, {
: text,
params,
: error.
});
error;
}
}
() {
client = pool.();
{
client.();
result = (client);
client.();
result;
} (error) {
client.();
error;
} {
client.();
}
}
app.(, (req, res) => {
result = (
,
[req..]
);
(result.. === ) {
res.().({ : });
}
res.(result.[]);
});
app.(, (req, res) => {
{
order = ( (client) => {
orderResult = client.(
,
[req.., req..]
);
( item req..) {
client.(
,
[orderResult.[]., item., item.]
);
}
( item req..) {
client.(
,
[item., item.]
);
}
orderResult.[];
});
res.().(order);
} (error) {
.(, error);
res.().({ : });
}
});
process.(, () => {
.();
pool.();
process.();
});
Performance Comparison:
Without Connection Pool:
- Concurrent requests: 100
- Connection creation time: ~50ms each
- Total overhead: 5 seconds
- Errors: "Too many connections"
With Connection Pool (max: 20):
- Concurrent requests: 100
- Connection reuse: Instant
- Total overhead: Negligible
- Errors: None
- Response time: 50ms โ 5ms (90% improvement)
Monitoring Metrics (Prometheus):
const metrics = {
poolSize: new Gauge({ name: 'db_pool_size', help: 'Current pool size' }),
poolIdle: new Gauge({ name: 'db_pool_idle', help: 'Idle connections' }),
poolWaiting: new Gauge({ name: 'db_pool_waiting', help: 'Waiting clients' })
};
setInterval(() => {
metrics.poolSize.set(pool.totalCount);
metrics.poolIdle.set(pool.idleCount);
metrics.poolWaiting.set(pool.waitingCount);
}, 5000);
Example 6: Korean Payment Integration (ํ ์คํ์ด๋จผ์ธ )
Scenario: Integrate Toss Payments with proper error handling and compliance
Requirements:
- ์ ์๊ธ์ต๊ฑฐ๋๋ฒ ์ค์
- PCI DSS compliance (no card data storage)
- Webhook verification
- Idempotency for duplicate payments
Implementation:
const axios = require('axios');
const crypto = require('crypto');
class TossPaymentsClient {
constructor() {
this.secretKey = process.env.TOSS_SECRET_KEY;
this.clientKey = process.env.TOSS_CLIENT_KEY;
this.baseURL = process.env.NODE_ENV === 'production'
? 'https://api.tosspayments.com'
: 'https://api-sandbox.tosspayments.com';
}
async createPayment(orderId, amount, orderName, customerEmail) {
const idempotencyKey = crypto.createHash('sha256')
.update(`${orderId}-${Date.now()}`)
.digest('hex');
try {
const response = await axios.post(
`${this.baseURL}/v1/payments`,
{
orderId,
amount,
orderName,
customerEmail,
: ,
:
},
{
: {
: ,
: ,
: idempotencyKey
}
}
);
response.;
} (error) {
.(, error.?.);
();
}
}
() {
{
response = axios.(
,
{
paymentKey,
orderId,
amount
},
{
: {
: ,
:
}
}
);
response.;
} (error) {
.(, error.?.);
error;
}
}
() {
{
response = axios.(
,
{ cancelReason },
{
: {
: ,
:
}
}
);
response.;
} (error) {
.(, error.?.);
error;
}
}
() {
computedSignature = crypto
.(, .)
.(.(body))
.();
signature === computedSignature;
}
}
toss = ();
app.(, (req, res) => {
{
{ orderId, amount, orderName } = req.;
order = .(orderId);
(!order) {
res.().({ : });
}
(order. !== ) {
res.().({ : });
}
payment = toss.(
orderId,
amount,
orderName,
req..
);
.({
orderId,
: payment.,
amount,
: ,
: payment.
});
res.({
: payment.,
: payment.
});
} (error) {
.(, error);
res.().({ : error. });
}
});
app.(, (req, res) => {
{ paymentKey, orderId, amount } = req.;
{
result = toss.(paymentKey, orderId, amount);
.(
{ paymentKey },
{
: ,
: (result.),
: result.
}
);
.(
{ : orderId },
{ : }
);
.({
orderId,
paymentKey,
: ,
amount,
: (),
: req.,
: req.()
});
res.();
} (error) {
.(, error);
res.();
}
});
app.(, (req, res) => {
signature = req.[];
(!toss.(signature, req.)) {
.();
res.().({ : });
}
{ eventType, data } = req.;
{
(eventType) {
:
(data);
;
:
(data);
;
:
(data);
;
}
res.({ : });
} (error) {
.(, error);
res.().({ : error. });
}
});
() {
.(
{ : data. },
{ : , : }
);
emailService.({
: data.,
: ,
: ,
: {
: data.,
: data.,
: data.
}
});
}
() {
.(
{ : data. },
{ : , : data. }
);
.(
{ : data. },
{ : }
);
}
() {
.(
{ : data. },
{ : , : data. }
);
}
Compliance Checklist:
- โ
์นด๋์ ๋ณด ๋ฏธ์ ์ฅ (PCI DSS)
- โ
๊ฑฐ๋๊ธฐ๋ก 5๋
๋ณด๊ด (์ ์๊ธ์ต๊ฑฐ๋๋ฒ ์ 22์กฐ)
- โ
์ฌ์ฉ์ IP/User-Agent ๋ก๊น
- โ
Webhook ์๋ช
๊ฒ์ฆ
- โ
Idempotency ํค ์ฌ์ฉ (์ค๋ณต ๊ฒฐ์ ๋ฐฉ์ง)
- โ
HTTPS ํ์
- โ
๊ฒฐ์ ์ทจ์ ๊ธฐ๋ฅ ์ ๊ณต
๐ Security Best Practices
OWASP Top 10 Prevention
1. Broken Access Control
app.get('/api/users/:id', async (req, res) => {
const user = await User.findById(req.params.id);
res.json(user);
});
app.get('/api/users/:id', authenticate, async (req, res) => {
if (req.user.id !== req.params.id && !req.user.isAdmin) {
return res.status(403).json({ error: 'Access denied' });
}
const user = await User.findById(req.params.id);
res.json(user);
});
2. SQL Injection Prevention
const query = `SELECT * FROM users WHERE email = '${req.body.email}'`;
const query = 'SELECT * FROM users WHERE email = $1';
const result = await pool.query(query, [req.body.email]);
3. XSS Prevention
app.use((req, res, next) => {
res.setHeader(
'Content-Security-Policy',
"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"
);
next();
});
const sanitizeHtml = require('sanitize-html');
app.post('/posts', async (req, res) => {
const cleanContent = sanitizeHtml(req.body.content, {
allowedTags: ['b', 'i', 'em', 'strong', 'a'],
allowedAttributes: { 'a': ['href'] }
});
await Post.create({ content: cleanContent });
});
4. CSRF Prevention
const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true });
app.post('/api/orders', csrfProtection, async (req, res) => {
});
app.get('/api/csrf-token', csrfProtection, (req, res) => {
res.json({ csrfToken: req.csrfToken() });
});
Secure Password Storage (Korean Standards)
const bcrypt = require('bcrypt');
async function hashPassword(password) {
if (password.length < 10) {
throw new Error('Password must be at least 10 characters');
}
const hasLetter = /[a-zA-Z]/.test(password);
const hasNumber = /[0-9]/.test(password);
const hasSpecial = /[!@#$%^&*]/.test(password);
if (!(hasLetter && hasNumber && hasSpecial)) {
throw new Error('Password must contain letters, numbers, and special characters');
}
const saltRounds = 12;
return await bcrypt.hash(password, saltRounds);
}
async function verifyPassword(password, hash) {
return await bcrypt.compare(password, hash);
}
async function () {
user = .(userId);
isValid = (oldPassword, user.);
(!isValid) {
();
}
recentPasswords = .({ userId })
.({ : - })
.();
( record recentPasswords) {
( bcrypt.(newPassword, record.)) {
();
}
}
newHash = (newPassword);
.({ : userId }, { : newHash });
.({
userId,
: newHash,
: ()
});
.({
userId,
: ,
: req.,
: ()
});
}
๐ Performance Optimization Checklist
API Response Time Targets
Target Response Times:
- Simple queries (1 table): < 50ms
- Complex queries (3+ tables): < 200ms
- API Gateway: < 10ms overhead
- 95th percentile: < 500ms
- 99th percentile: < 1s
Optimization Strategies
1. Database Indexing
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_posts_author_created ON posts(author_id, created_at DESC);
CREATE INDEX idx_active_users ON users(email) WHERE status = 'active';
CREATE INDEX idx_posts_list ON posts(author_id, created_at DESC)
INCLUDE (title, excerpt);
2. Caching Strategy
const redis = require('redis');
const client = redis.createClient();
async function getUser(userId) {
if (memoryCache.has(userId)) {
return memoryCache.get(userId);
}
const cached = await client.get(`user:${userId}`);
if (cached) {
const user = JSON.parse(cached);
memoryCache.set(userId, user);
return user;
}
const user = await db.query('SELECT * FROM users WHERE id = $1', [userId]);
await client.setex(`user:${userId}`, 300, JSON.stringify(user));
memoryCache.set(userId, user);
return user;
}
async function updateUser() {
db.(, [userId]);
memoryCache.(userId);
client.();
}
3. Database Query Optimization
SELECT * FROM posts WHERE author_id = 123;
SELECT id, title, excerpt, created_at FROM posts WHERE author_id = 123;
SELECT * FROM posts;
SELECT * FROM users WHERE id = post.author_id;
SELECT
p.id, p.title, p.excerpt,
u.name as author_name, u.avatar as author_avatar
FROM posts p
INNER JOIN users u ON p.author_id = u.id
WHERE p.status = 'published'
ORDER BY p.created_at DESC
LIMIT 20;
4. Asynchronous Processing
app.post('/register', async (req, res) => {
const user = await User.create(req.body);
await emailService.sendWelcomeEmail(user.email);
res.json(user);
});
const Bull = require('bull');
const emailQueue = new Bull('email', process.env.REDIS_URL);
app.post('/register', async (req, res) => {
const user = await User.create(req.body);
await emailQueue.add('welcome', {
email: user.email,
name: user.name
});
res.json(user);
});
emailQueue.process('welcome', async (job) => {
await emailService.(job.., job..);
});
๐ ๏ธ Troubleshooting Guide
Common Issues & Solutions
Issue 1: "Connection pool exhausted"
Symptoms: Pool is exhausted errors under load
Diagnosis:
console.log('Total:', pool.totalCount);
console.log('Idle:', pool.idleCount);
console.log('Waiting:', pool.waitingCount);
Solutions:
- Increase pool size:
max: 20 โ max: 50
- Reduce connection lifetime:
idleTimeoutMillis: 30000 โ idleTimeoutMillis: 10000
- Find connection leaks:
const withTimeout = (promise, ms) => {
return Promise.race([
promise,
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Query timeout')), ms)
)
]);
};
Issue 2: Slow API responses
Diagnosis:
app.use((req, res, next) => {
req.startTime = Date.now();
res.on('finish', () => {
const duration = Date.now() - req.startTime;
if (duration > 1000) {
console.warn('Slow request:', {
method: req.method,
path: req.path,
duration,
query: req.query
});
}
});
next();
});
Solutions:
- Add database indexes
- Implement caching
- Paginate large result sets
- Use database connection pooling
- Profile with
EXPLAIN ANALYZE
Issue 3: Memory leaks
Diagnosis:
setInterval(() => {
const usage = process.memoryUsage();
console.log('Memory:', {
rss: `${Math.round(usage.rss / 1024 / 1024)}MB`,
heapUsed: `${Math.round(usage.heapUsed / 1024 / 1024)}MB`,
heapTotal: `${Math.round(usage.heapTotal / 1024 / 1024)}MB`
});
}, 60000);
Common Causes:
- Event listeners not removed
- Unclosed database connections
- Large in-memory caches without eviction
- Circular references
Solutions:
const controller = new AbortController();
eventEmitter.on('data', handler, { signal: controller.signal });
controller.abort();
const cache = new WeakMap();
const LRU = require('lru-cache');
const cache = new LRU({ max: 500, maxAge: 1000 * 60 * 5 });
๐ Reference Architecture Patterns
Pattern 1: Clean Architecture (Hexagonal)
Project Structure:
src/
โโโ domain/ # Business logic (pure)
โ โโโ entities/
โ โโโ use-cases/
โ โโโ interfaces/ # Ports
โโโ infrastructure/ # External adapters
โ โโโ database/
โ โโโ messaging/
โ โโโ external-apis/
โโโ application/ # Application services
โ โโโ dto/
โ โโโ services/
โโโ presentation/ # API layer
โโโ http/
โโโ graphql/
Benefits:
- Testable (business logic independent of infrastructure)
- Flexible (easy to swap databases, frameworks)
- Maintainable (clear separation of concerns)
Pattern 2: Microservices with Event-Driven Architecture
Services:
- User Service (authentication, profiles)
- Product Service (catalog, inventory)
- Order Service (order management)
- Payment Service (payment processing)
- Notification Service (emails, SMS)
Communication:
- Synchronous: REST/gRPC for queries
- Asynchronous: Kafka/RabbitMQ for events
Events:
- UserRegistered
- OrderCreated
- PaymentCompleted
- OrderShipped
Saga Pattern Example:
await events.publish('OrderCreated', {
orderId: order.id,
userId: order.userId,
total: order.total
});
events.on('OrderCreated', async (data) => {
try {
const payment = await processPayment(data);
await events.publish('PaymentCompleted', payment);
} catch (error) {
await events.publish('PaymentFailed', { orderId: data.orderId });
}
});
events.on('PaymentFailed', async (data) => {
await Order.updateOne(
{ id: data.orderId },
{ status: 'cancelled' }
);
});
๐ Advanced Topics
GraphQL Optimization
N+1 Problem with DataLoader
const DataLoader = require('dataloader');
const userLoader = new DataLoader(async (userIds) => {
const users = await db.query(
'SELECT * FROM users WHERE id = ANY($1)',
[userIds]
);
const userMap = new Map(users.map(u => [u.id, u]));
return userIds.map(id => userMap.get(id));
});
const resolvers = {
Post: {
author: (post) => userLoader.load(post.authorId)
},
Query: {
posts: () => db.query('SELECT * FROM posts LIMIT 20')
}
};
gRPC Service Implementation
// user.proto
syntax = "proto3";
service UserService {
rpc GetUser (GetUserRequest) returns (User);
rpc CreateUser (CreateUserRequest) returns (User);
rpc StreamUsers (StreamUsersRequest) returns (stream User);
}
message User {
string id = 1;
string email = 2;
string name = 3;
int64 created_at = 4;
}
message GetUserRequest {
string id = 1;
}
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const packageDefinition = protoLoader.loadSync('user.proto');
const userProto = grpc.loadPackageDefinition(packageDefinition);
const server = new grpc.Server();
server.addService(userProto.UserService.service, {
GetUser: async (call, callback) => {
try {
const user = await db.query(
'SELECT * FROM users WHERE id = $1',
[call.request.id]
);
callback(null, user);
} catch (error) {
callback({
code: grpc.status.NOT_FOUND,
details: 'User not found'
});
}
},
StreamUsers: async (call) => {
const stream = db.stream('SELECT * FROM users');
stream.on('data', (user) => {
call.write(user);
});
stream.(, {
call.();
});
}
});
server.(
,
grpc..(),
{
.();
server.();
}
);
๐ Monitoring & Observability
Metrics Collection (Prometheus)
const promClient = require('prom-client');
const httpRequestDuration = new promClient.Histogram({
name: 'http_request_duration_seconds',
help: 'Duration of HTTP requests in seconds',
labelNames: ['method', 'route', 'status_code'],
buckets: [0.1, 0.5, 1, 2, 5]
});
const httpRequestTotal = new promClient.Counter({
name: 'http_requests_total',
help: 'Total number of HTTP requests',
labelNames: ['method', 'route', 'status_code']
});
const dbQueryDuration = new promClient.Histogram({
name: 'db_query_duration_seconds',
help: 'Duration of database queries',
labelNames: ['query_type'],
buckets: [0.01, 0.05, 0.1, 0.5, 1]
});
app.use((req, res, next) => {
const start = .();
res.(, {
duration = (.() - start) / ;
httpRequestDuration.(
{
: req.,
: req.?. || req.,
: res.
},
duration
);
httpRequestTotal.({
: req.,
: req.?. || req.,
: res.
});
});
();
});
app.(, (req, res) => {
res.(, promClient..);
res.( promClient..());
});
Structured Logging
const winston = require('winston');
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.json()
),
defaultMeta: {
service: 'user-service',
environment: process.env.NODE_ENV
},
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
});
logger.info('User login successful', {
userId: user.id,
ip: req.ip,
userAgent: req.get('user-agent')
});
logger.(, {
: error.,
: error.,
: sql,
: params
});
Distributed Tracing (OpenTelemetry)
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http');
const { ExpressInstrumentation } = require('@opentelemetry/instrumentation-express');
const provider = new NodeTracerProvider();
provider.register();
registerInstrumentations({
instrumentations: [
new HttpInstrumentation(),
new ExpressInstrumentation()
]
});
const tracer = provider.getTracer('user-service');
app.get('/api/users/:id', async (req, res) => {
const span = tracer.startSpan('get_user');
try {
span.setAttribute('user.id', req.params.id);
const user = await db.query('SELECT * FROM users WHERE id = $1', [req.params.id]);
span.({ : });
res.(user);
} (error) {
span.({ : , : error. });
res.().({ : error. });
} {
span.();
}
});
๐ Korean Regulation Compliance
๊ฐ์ธ์ ๋ณด๋ณดํธ๋ฒ (Personal Information Protection Act)
Required Implementations:
const ConsentSchema = new Schema({
userId: ObjectId,
type: {
type: String,
enum: ['marketing', 'third_party', 'profiling']
},
granted: Boolean,
grantedAt: Date,
expiresAt: Date,
ipAddress: String
});
app.get('/api/users/me/data-export', authenticate, async (req, res) => {
const userData = {
personal: await User.findById(req.user.id).select('-password'),
orders: await Order.find({ userId: req.user.id }),
consents: await Consent.find({ userId: req.user.id }),
loginHistory: await LoginLog.({ : req.. }).()
};
res.(userData);
});
app.(, authenticate, (req, res) => {
userId = req..;
.(
{ : userId },
{
: ,
: (),
: ,
: ,
:
}
);
.(
{ userId },
{ : }
);
res.({ : });
});
() {
( user affectedUsers) {
emailService.({
: user.,
: ,
: ,
: {
: user.,
: (),
: [, ],
:
}
});
}
({
: (),
: affectedUsers.,
: [, ]
});
}
์ ์๊ธ์ต๊ฑฐ๋๋ฒ (Electronic Financial Transactions Act)
Transaction Logging Requirements:
const TransactionLogSchema = new Schema({
transactionId: String,
userId: ObjectId,
type: {
type: String,
enum: ['payment', 'refund', 'withdrawal']
},
amount: Number,
status: String,
timestamp: { type: Date, default: Date.now },
ipAddress: String,
userAgent: String,
deviceId: String,
merchant: {
name: String,
businessNumber: String
}
});
TransactionLogSchema.index({ userId: 1, timestamp: -1 });
TransactionLogSchema.index({ transactionId: 1 }, { unique: true });
.(
{ : },
{ : * * * * }
);
๐ API Documentation Best Practices
OpenAPI 3.1 Specification
openapi: 3.1.0
info:
title: User Service API
version: 1.0.0
description: User management and authentication
contact:
email: dev@example.com
servers:
- url: https://api.example.com/v1
description: Production
- url: https://api-staging.example.com/v1
description: Staging
security:
- bearerAuth: []
paths:
/users:
get:
summary: List users
description: Returns a paginated list of users
tags:
- Users
parameters:
- name: page
in: query
schema:
type:
[, , ]
๐ Learning Resources
Official Documentation (Authoritative)
Standards & RFCs
Korean Resources
Enterprise Engineering Blogs
Books (Recommended)
- "Designing Data-Intensive Applications" by Martin Kleppmann
- "Building Microservices" by Sam Newman
- "Domain-Driven Design" by Eric Evans
- "System Design Interview" by Alex Xu
๐ Getting Help
How to Ask Questions
Good Question Format:
Problem: [Clear description of the issue]
Context:
- Tech stack: [e.g., Node.js 18, PostgreSQL 15, Redis 7]
- Environment: [Development/Staging/Production]
- Traffic: [e.g., 1000 req/min]
Current Implementation:
[Code snippet or architecture description]
What I've Tried:
1. [Attempt 1]
2. [Attempt 2]
Expected Behavior: [What should happen]
Actual Behavior: [What's happening]
Error Messages: [If any]
Response Format
You'll receive:
- Root Cause Analysis: Why the issue is happening
- Solution: Step-by-step fix with code examples
- Best Practices: How to prevent similar issues
- Additional Resources: Links to relevant documentation
Scope Limitations
This skill covers:
โ
Backend architecture and design
โ
API development (REST/GraphQL/gRPC)
โ
Database optimization
โ
Security best practices
โ
Performance tuning
โ
Korean regulations compliance
This skill does NOT cover:
โ Frontend development (React, Vue, etc.)
โ Mobile development (iOS, Android)
โ Infrastructure as Code (Terraform, CloudFormation)
โ Machine Learning / AI models
โ Blockchain / Web3
For out-of-scope topics, I'll recommend appropriate resources.
๐ Version History
v1.0.0 (2025-01-24)
Initial Release
- Complete backend development guidance
- 8 core capability areas
- 6 detailed examples
- Korean regulation compliance
- Security best practices (OWASP Top 10)
- Performance optimization strategies
- Monitoring & observability setup
- 50+ code examples
Knowledge Base:
- 45+ research papers
- Official documentation from 20+ technologies
- Korean compliance guidelines (KISA, PIPC)
- Enterprise engineering blog posts (Netflix, Uber, Kakao, Naver)
๐ License & Disclaimer
Usage Rights: Free to use for personal and commercial projects
Disclaimer:
- Code examples are for educational purposes
- Always test in development before production deployment
- Compliance requirements may change - verify latest regulations
- Security practices should be adapted to your specific threat model
Sources:
- Official documentation (PostgreSQL, MongoDB, Express.js, etc.)
- IETF RFCs (HTTP, OAuth, JWT)
- OWASP guidelines
- Korean government regulations (๊ฐ์ธ์ ๋ณด๋ณดํธ๋ฒ, ์ ์๊ธ์ต๊ฑฐ๋๋ฒ)
- Academic research (ACM, IEEE)
- Enterprise engineering blogs (with proper attribution)
๐ Quick Start
For First-Time Users:
- Start with a specific problem or question
- Provide context (tech stack, environment, constraints)
- Include code snippets or architecture diagrams if relevant
- Mention any Korean compliance requirements
Example Query:
"I need to optimize this API endpoint that's taking 3 seconds to respond.
Tech stack: Express.js + PostgreSQL
Current query: [SQL code]
Traffic: 500 requests/minute
Need: Under 500ms response time"
You'll get:
- Query analysis
- Optimization suggestions
- Refactored code
- Performance comparison
- Monitoring recommendations
Ready to build better backends? Ask your first question! ๐