베스트 프랙티스
프로덕션 환경에서 Sophonz를 가장 효과적으로 활용하는 방법.
Sophonz를 최대한 활용하기 위한 베스트 프랙티스를 소개합니다.
개발 관행
코드 구조
모니터링과 인사이트에 최적화된 프로젝트 구조:
src/
├── components/
│ ├── ui/ # 재사용 가능한 UI 컴포넌트
│ └── features/ # 기능별 컴포넌트
├── hooks/ # 커스텀 React 훅
├── lib/ # 유틸리티 함수
├── pages/ # 페이지 컴포넌트
└── services/ # API 서비스에러 처리
체계적인 에러 처리를 구현하세요:
// 좋은 예: 구조화된 에러 처리
try {
const result = await api.getData();
return result;
} catch (error) {
// 컨텍스트와 함께 에러 로깅
logger.error('데이터 조회 실패', {
error: error.message,
userId: user.id,
timestamp: new Date().toISOString()
});
// 특정 에러 타입 처리
if (error.code === 'RATE_LIMITED') {
// 백오프 전략 적용
await delay(error.retryAfter * 1000);
return retryWithExponentialBackoff(() => api.getData());
}
throw error;
}성능 최적화
지연 로딩
성능 향상을 위한 지연 로딩:
import { lazy, Suspense } from 'react';
const Dashboard = lazy(() => import('./Dashboard'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Dashboard />
</Suspense>
);
}메모이제이션
불필요한 리렌더링을 방지하기 위한 메모이제이션:
import { memo, useMemo, useCallback } from 'react';
const ExpensiveComponent = memo(({ data, onUpdate }) => {
const processedData = useMemo(() => {
return data.map(item => ({
...item,
computed: heavyComputation(item)
}));
}, [data]);
const handleUpdate = useCallback((id, value) => {
onUpdate(id, value);
}, [onUpdate]);
return (
<div>
{processedData.map(item => (
<Item key={item.id} data={item} onUpdate={handleUpdate} />
))}
</div>
);
});모니터링 베스트 프랙티스
커스텀 메트릭
의미 있는 커스텀 메트릭을 정의하세요:
// 비즈니스 메트릭 추적
sophonz.track('user.signup', {
plan: 'premium',
source: 'landing_page',
value: 29.99
});
// 성능 메트릭 추적
sophonz.time('api.response_time', async () => {
return await api.fetchUserData();
});
// 컨텍스트와 함께 에러 추적
sophonz.error('payment.failed', error, {
userId: user.id,
amount: payment.amount,
gateway: 'stripe'
});알림 설정
의미 있는 알림을 설정하세요:
const alerts = [
{
name: 'High Error Rate',
condition: 'error_rate > 5%',
duration: '5m',
severity: 'critical'
},
{
name: 'Slow Response Time',
condition: 'avg(response_time) > 2s',
duration: '10m',
severity: 'warning'
},
{
name: 'Low User Engagement',
condition: 'active_users < 100',
duration: '1h',
severity: 'info'
}
];보안 베스트 프랙티스
API 키 관리
API 키를 안전하게 관리하세요:
// 좋은 예: 환경 변수 사용
const apiKey = process.env.SOPHONZ_API_KEY;
// 좋은 예: API 키 형식 검증
if (!apiKey || !apiKey.startsWith('sk_')) {
throw new Error('Invalid API key format');
}
// 좋은 예: 환경별로 다른 키 사용
const config = {
development: {
apiKey: process.env.SOPHONZ_DEV_API_KEY
},
production: {
apiKey: process.env.SOPHONZ_PROD_API_KEY
}
};데이터 프라이버시
민감한 정보를 보호하세요:
// 좋은 예: 로깅 전 민감 데이터 마스킹
const sanitizedUser = {
id: user.id,
email: user.email.replace(/(.{2}).*(@.*)/, '$1***$2'),
// 비밀번호, 토큰, PII는 절대 로깅하지 마세요
};
sophonz.track('user.action', {
user: sanitizedUser,
action: 'profile_update'
});레이트 리미팅
클라이언트 측 레이트 리미팅을 구현하세요:
class RateLimiter {
constructor(maxRequests, windowMs) {
this.maxRequests = maxRequests;
this.windowMs = windowMs;
this.requests = [];
}
async request(fn) {
const now = Date.now();
this.requests = this.requests.filter(time => now - time < this.windowMs);
if (this.requests.length >= this.maxRequests) {
const waitTime = this.windowMs - (now - this.requests[0]);
await new Promise(resolve => setTimeout(resolve, waitTime));
return this.request(fn);
}
this.requests.push(now);
return fn();
}
}테스트 베스트 프랙티스
유닛 테스트
Sophonz 통합 부분을 테스트하세요:
// 테스트를 위한 Sophonz 모킹
jest.mock('@sophonz/sdk');
test('회원가입 이벤트가 올바르게 추적됨', async () => {
const mockTrack = jest.fn();
Sophonz.prototype.track = mockTrack;
await signupUser({ email: 'test@example.com', plan: 'pro' });
expect(mockTrack).toHaveBeenCalledWith('user.signup', {
plan: 'pro',
source: 'test'
});
});통합 테스트
스테이징 환경에서 실제 통합을 테스트하세요:
// 통합 테스트용 테스트 API 키 사용
const testClient = new Sophonz({
apiKey: process.env.SOPHONZ_TEST_API_KEY,
environment: 'test'
});
test('실제 API 통합', async () => {
const result = await testClient.track('test.event', {
value: 123
});
expect(result.success).toBe(true);
});배포 베스트 프랙티스
블루-그린 배포
무중단 업데이트를 위한 블루-그린 배포:
const deployment = {
strategy: 'blue-green',
healthCheck: {
url: '/health',
timeout: 30000,
expectedStatus: 200
},
rollback: {
onFailure: true,
threshold: {
errorRate: 0.05,
responseTime: 2000
}
}
};기능 플래그
점진적 롤아웃을 위한 기능 플래그:
// 점진적 기능 롤아웃
const useNewFeature = sophonz.feature('new-dashboard', {
userId: user.id,
rolloutPercentage: 10
});
if (useNewFeature) {
return <NewDashboard />;
} else {
return <OldDashboard />;
}환경 일관성
모든 환경에서 일관성을 유지하세요:
// 환경별 설정
const config = {
development: {
logLevel: 'debug',
apiTimeout: 30000
},
staging: {
logLevel: 'info',
apiTimeout: 10000
},
production: {
logLevel: 'error',
apiTimeout: 5000
}
};성능 모니터링
추적해야 할 핵심 메트릭
-
Core Web Vitals
- Largest Contentful Paint (LCP)
- First Input Delay (FID)
- Cumulative Layout Shift (CLS)
-
비즈니스 메트릭
- 전환율
- 사용자 인게이지먼트
- 사용자당 매출
-
기술 메트릭
- API 응답 시간
- 에러율
- 데이터베이스 쿼리 성능
커스텀 성능 추적
// 페이지 로드 성능 추적
window.addEventListener('load', () => {
const perfData = performance.getEntriesByType('navigation')[0];
sophonz.track('page.performance', {
loadTime: perfData.loadEventEnd - perfData.loadEventStart,
domContentLoaded: perfData.domContentLoadedEventEnd - perfData.domContentLoadedEventStart,
firstByte: perfData.responseStart - perfData.requestStart
});
});