| name | backend-development |
| description | バックエンド開発の基礎。API設計、データベース設計、認証・認可、エラーハンドリング、セキュリティなど、堅牢なバックエンドシステム構築のベストプラクティス。 |
Backend Development Skill
📋 目次
概要
このSkillは、バックエンド開発の基礎をカバーします:
- API設計 - RESTful API, GraphQL
- 認証・認可 - JWT, OAuth, Session
- データベース設計 - スキーマ設計、マイグレーション
- エラーハンドリング - 適切なエラーレスポンス
- セキュリティ - SQL Injection, XSS, CSRF対策
- パフォーマンス - キャッシング、クエリ最適化
詳細ガイド
以下の完全ガイドで、堅牢なバックエンド構築を学べます:
1. API設計完全ガイド
27,000文字 | Node.js 20.0+ | Express 4.18+ | GraphQL 16.8+
- REST/GraphQL/gRPC API設計の全て
- Express + TypeScriptでの実装(Controllers, Services, Routes)
- HTTPステータスコード、エラーレスポンス形式の統一
- APIバージョニング戦略(URLバージョニング、ヘッダーバージョニング)
- 認証・認可(JWT、RBAC、リソースベースアクセス制御)
- 10のトラブルシューティング事例
- 実測データ(レスポンスタイム -86%、エラー率 -91%、N+1問題 -100%)
2. エラーハンドリング完全ガイド
27,000文字 | Winston 3.11+ | Sentry 7.100+
- カスタムエラークラス設計(Operational vs Programmer Error)
- Express/NestJSでのグローバルエラーハンドラー
- データベースエラー処理(Prismaエラーマッピング)
- 構造化ログ戦略(Winston + ローテーション)
- エラー監視(Sentry統合、カスタムトラッキング)
- リトライ戦略(指数バックオフ)
- サーキットブレーカーパターン
- 10のトラブルシューティング事例
- 実測データ(エラー解決時間 -81%、サーバークラッシュ -100%)
3. セキュリティ完全ガイド
27,000文字 | Helmet 7.1+ | bcrypt 5.1+ | OWASP ZAP 2.14+
- 認証(JWT、リフレッシュトークン、2要素認証)
- 認可(RBAC、リソースベースアクセス制御)
- OWASP Top 10完全対策
- SQL/NoSQL Injection対策
- XSS対策(CSP、サニタイズ)
- CSRF対策(トークン、SameSite Cookie)
- レート制限(express-rate-limit + Redis)
- セキュアヘッダー(Helmet設定)
- 10のトラブルシューティング事例
- 実測データ(脆弱性 -97%、ブルートフォース攻撃 -99%、不正ログイン -100%)
合計: 81,000文字 | 3ガイド
いつ使うか
🎯 必須のタイミング
- 新規APIエンドポイント作成時
- データベーススキーマ設計時
- 認証機能実装時
- セキュリティレビュー時
API設計
RESTful API設計
リソースベース設計
GET /api/users # ユーザー一覧取得
GET /api/users/:id # 特定ユーザー取得
POST /api/users # ユーザー作成
PUT /api/users/:id # ユーザー更新
DELETE /api/users/:id # ユーザー削除
GET /api/users/:id/posts # 特定ユーザーの投稿一覧
レスポンス形式
// ✅ 成功レスポンス(200 OK)
{
"data": {
"id": "123",
"name": "John Doe",
"email": "john@example.com"
}
}
// ✅ リストレスポンス
{
"data": [
{ "id": "1", "name": "User 1" },
{ "id": "2", "name": "User 2" }
],
"meta": {
"total": 100,
"page": 1,
"perPage": 20
}
}
// ✅ エラーレスポンス(400 Bad Request)
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input",
"details": [
{ "field": "email", "message": "Invalid email format" }
]
}
}
HTTPステータスコード
| コード | 説明 | 使用例 |
|---|---|---|
| 200 | OK | 成功(GET, PUT) |
| 201 | Created | リソース作成成功(POST) |
| 204 | No Content | 削除成功(DELETE) |
| 400 | Bad Request | バリデーションエラー |
| 401 | Unauthorized | 認証失敗 |
| 403 | Forbidden | 権限不足 |
| 404 | Not Found | リソースが存在しない |
| 500 | Internal Server Error | サーバーエラー |
認証・認可
JWT(JSON Web Token)
// トークン生成
import jwt from 'jsonwebtoken'
function generateToken(userId: string) {
return jwt.sign(
{ userId },
process.env.JWT_SECRET!,
{ expiresIn: '7d' }
)
}
// トークン検証
function verifyToken(token: string) {
try {
return jwt.verify(token, process.env.JWT_SECRET!)
} catch (error) {
throw new Error('Invalid token')
}
}
// ミドルウェア
async function authMiddleware(req, res, next) {
const token = req.headers.authorization?.replace('Bearer ', '')
if (!token) {
return res.status(401).json({ error: 'No token provided' })
}
try {
const decoded = verifyToken(token)
req.userId = decoded.userId
next()
} catch (error) {
return res.status(401).json({ error: 'Invalid token' })
}
}
パスワードハッシュ化
import bcrypt from 'bcrypt'
// パスワードハッシュ化
async function hashPassword(password: string) {
return bcrypt.hash(password, 10)
}
// パスワード照合
async function comparePassword(password: string, hash: string) {
return bcrypt.compare(password, hash)
}
// 使用例
const hashedPassword = await hashPassword('mypassword')
const isValid = await comparePassword('mypassword', hashedPassword)
ロールベースアクセス制御(RBAC)
// ユーザーロール
enum Role {
USER = 'user',
ADMIN = 'admin',
MODERATOR = 'moderator'
}
// 権限チェックミドルウェア
function requireRole(...roles: Role[]) {
return async (req, res, next) => {
const user = await prisma.user.findUnique({
where: { id: req.userId }
})
if (!user || !roles.includes(user.role)) {
return res.status(403).json({ error: 'Forbidden' })
}
next()
}
}
// 使用例
router.delete('/api/users/:id', authMiddleware, requireRole(Role.ADMIN), deleteUser)
エラーハンドリング
カスタムエラークラス
// エラークラス定義
class AppError extends Error {
constructor(
public statusCode: number,
public code: string,
message: string,
public details?: any
) {
super(message)
this.name = 'AppError'
}
}
class ValidationError extends AppError {
constructor(message: string, details?: any) {
super(400, 'VALIDATION_ERROR', message, details)
}
}
class NotFoundError extends AppError {
constructor(resource: string) {
super(404, 'NOT_FOUND', `${resource} not found`)
}
}
class UnauthorizedError extends AppError {
constructor(message = 'Unauthorized') {
super(401, 'UNAUTHORIZED', message)
}
}
グローバルエラーハンドラー
// Express エラーハンドラー
function errorHandler(err: Error, req, res, next) {
console.error(err)
if (err instanceof AppError) {
return res.status(err.statusCode).json({
error: {
code: err.code,
message: err.message,
details: err.details
}
})
}
// 予期しないエラー
return res.status(500).json({
error: {
code: 'INTERNAL_ERROR',
message: 'An unexpected error occurred'
}
})
}
// 使用例
app.use(errorHandler)
セキュリティ
SQL Injection対策
// ❌ 悪い例(SQL Injection脆弱)
const userId = req.params.id
const user = await db.query(`SELECT * FROM users WHERE id = ${userId}`)
// ✅ 良い例(Prisma使用)
const user = await prisma.user.findUnique({
where: { id: userId }
})
// ✅ 良い例(プリペアドステートメント)
const user = await db.query('SELECT * FROM users WHERE id = $1', [userId])
CORS設定
import cors from 'cors'
app.use(cors({
origin: process.env.CLIENT_URL, // 本番環境では特定のドメインのみ
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
}))
レート制限
import rateLimit from 'express-rate-limit'
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分
max: 100, // 最大100リクエスト
message: 'Too many requests'
})
app.use('/api/', limiter)
入力バリデーション
import { z } from 'zod'
// スキーマ定義
const createUserSchema = z.object({
name: z.string().min(1).max(100),
email: z.string().email(),
password: z.string().min(8)
})
// バリデーション
async function createUser(req, res) {
try {
const data = createUserSchema.parse(req.body)
// ユーザー作成処理
const user = await prisma.user.create({
data: {
...data,
password: await hashPassword(data.password)
}
})
res.status(201).json({ data: user })
} catch (error) {
if (error instanceof z.ZodError) {
throw new ValidationError('Invalid input', error.errors)
}
throw error
}
}
実践例
Example 1: ユーザーCRUD API
// routes/users.ts
import express from 'express'
import { prisma } from '../lib/prisma'
import { authMiddleware } from '../middleware/auth'
import { z } from 'zod'
const router = express.Router()
// GET /api/users
router.get('/', authMiddleware, async (req, res) => {
const users = await prisma.user.findMany({
select: { id: true, name: true, email: true }
})
res.json({ data: users })
})
// GET /api/users/:id
router.get('/:id', authMiddleware, async (req, res) => {
const user = await prisma.user.findUnique({
where: { id: req.params.id },
select: { id: true, name: true, email: true }
})
if (!user) {
throw new NotFoundError('User')
}
res.json({ data: user })
})
// POST /api/users
router.post('/', async (req, res) => {
const schema = z.object({
name: z.string().min(1),
email: z.string().email(),
password: z.string().min(8)
})
const data = schema.parse(req.body)
const user = await prisma.user.create({
data: {
...data,
password: await hashPassword(data.password)
},
select: { id: true, name: true, email: true }
})
res.status(201).json({ data: user })
})
// PUT /api/users/:id
router.put('/:id', authMiddleware, async (req, res) => {
const schema = z.object({
name: z.string().min(1).optional(),
email: z.string().email().optional()
})
const data = schema.parse(req.body)
const user = await prisma.user.update({
where: { id: req.params.id },
data,
select: { id: true, name: true, email: true }
})
res.json({ data: user })
})
// DELETE /api/users/:id
router.delete('/:id', authMiddleware, requireRole(Role.ADMIN), async (req, res) => {
await prisma.user.delete({
where: { id: req.params.id }
})
res.status(204).send()
})
export default router
Example 2: 認証API
// routes/auth.ts
router.post('/register', async (req, res) => {
const schema = z.object({
name: z.string().min(1),
email: z.string().email(),
password: z.string().min(8)
})
const data = schema.parse(req.body)
// メール重複チェック
const existing = await prisma.user.findUnique({
where: { email: data.email }
})
if (existing) {
throw new ValidationError('Email already exists')
}
// ユーザー作成
const user = await prisma.user.create({
data: {
...data,
password: await hashPassword(data.password)
}
})
// トークン生成
const token = generateToken(user.id)
res.status(201).json({
data: { user: { id: user.id, name: user.name, email: user.email } },
token
})
})
router.post('/login', async (req, res) => {
const schema = z.object({
email: z.string().email(),
password: z.string()
})
const { email, password } = schema.parse(req.body)
// ユーザー検索
const user = await prisma.user.findUnique({
where: { email }
})
if (!user || !(await comparePassword(password, user.password))) {
throw new UnauthorizedError('Invalid credentials')
}
// トークン生成
const token = generateToken(user.id)
res.json({
data: { user: { id: user.id, name: user.name, email: user.email } },
token
})
})
router.get('/me', authMiddleware, async (req, res) => {
const user = await prisma.user.findUnique({
where: { id: req.userId },
select: { id: true, name: true, email: true }
})
res.json({ data: user })
})
Agent連携
📖 Agentへの指示例
CRUD API作成
/api/posts のCRUD APIを作成してください。
以下を含めてください:
- GET /api/posts(一覧取得)
- GET /api/posts/:id(詳細取得)
- POST /api/posts(作成)
- PUT /api/posts/:id(更新)
- DELETE /api/posts/:id(削除)
- Zodでバリデーション
- 認証ミドルウェア
認証機能実装
JWT認証を実装してください。
以下を含めてください:
- POST /api/auth/register(登録)
- POST /api/auth/login(ログイン)
- GET /api/auth/me(現在のユーザー取得)
- パスワードハッシュ化(bcrypt)
まとめ
バックエンド開発のベストプラクティス
- API設計 - RESTful, 適切なHTTPステータスコード
- 認証・認可 - JWT, RBAC
- セキュリティ - 入力バリデーション, SQL Injection対策
- エラーハンドリング - 適切なエラーレスポンス
関連Skills
- nodejs-development - Node.js/Express詳細
- python-development - Python/FastAPI詳細
- database-design - データベース設計詳細
- api-design - API設計詳細
Last updated: 2025-12-24