베스트 프랙티스

프로덕션 환경에서 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
  }
};

성능 모니터링

추적해야 할 핵심 메트릭

  1. Core Web Vitals

    • Largest Contentful Paint (LCP)
    • First Input Delay (FID)
    • Cumulative Layout Shift (CLS)
  2. 비즈니스 메트릭

    • 전환율
    • 사용자 인게이지먼트
    • 사용자당 매출
  3. 기술 메트릭

    • 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
  });
});