본문으로 건너뛰기

보안 모범 사례

Connect Base 애플리케이션의 보안을 강화하기 위한 가이드입니다.

API 키 보안

1. 환경 변수 사용

typescript
// ❌ 하드코딩 금지
const cb = new ConnectBase({ secretKey: 'cb_sk_actual_secret_key_here' })

// ✅ 환경 변수 사용
const cb = new ConnectBase({
    secretKey: process.env.CONNECT_BASE_SECRET_KEY
})

2. .gitignore 설정

# .gitignore
.env
.env.local
.env.production
.env.*.local
*.pem
*.key

3. 클라이언트와 서버 분리

환경사용 키노출 위험
브라우저 / 모바일 앱cb_pk_*노출되어도 권한이 제한적
Node.js 서버 / Cloud Functioncb_sk_*노출되면 전체 권한 탈취

입력 검증

클라이언트 측 검증 (UX 개선용)

typescript
import { z } from 'zod'

const userSchema = z.object({
    login_id: z.string().min(3).max(30),
    password: z.string().min(8),
    nickname: z.string().min(1).max(50)
})

const validated = userSchema.parse(formData)
await cb.auth.signUpMember(validated)

서버 측 검증 (보안)

서버리스 함수에서 외부 입력을 처리할 때:

typescript
// fn_user_action.js
export default async function handler(request, context) {
    const { user_id, action } = request.body

    if (typeof user_id !== 'string' || !user_id.startsWith('member_')) {
        return { error: 'invalid user_id', status: 400 }
    }

    if (!['like', 'unlike', 'report'].includes(action)) {
        return { error: 'invalid action', status: 400 }
    }

    // ... 검증된 입력으로 처리
}

XSS 방지

typescript
// React 는 기본적으로 XSS 방지 (JSX 의 자동 escape)
// dangerouslySetInnerHTML 사용 시 DOMPurify 로 sanitize
import DOMPurify from 'dompurify'

const sanitized = DOMPurify.sanitize(userInput)
return <div dangerouslySetInnerHTML={{ __html: sanitized }} />

인증 보안

안전한 비밀번호 정책

회원가입 폼에서 클라이언트 측 검증:

typescript
import { z } from 'zod'

const passwordSchema = z.string()
    .min(12, '최소 12자 이상')
    .regex(/[A-Z]/, '대문자 포함')
    .regex(/[a-z]/, '소문자 포함')
    .regex(/[0-9]/, '숫자 포함')
    .regex(/[^A-Za-z0-9]/, '특수문자 포함')

세션 / 토큰 관리

SDK 는 access_token 만료 시 자동으로 refresh_token 으로 갱신을 시도합니다. 앱 코드에서는 콜백만 등록하면 됩니다.

typescript
const cb = new ConnectBase({
    publicKey: 'cb_pk_...',

    // 토큰이 갱신될 때마다 호출 (localStorage 에 저장 등)
    onTokenRefresh: ({ accessToken, refreshToken }) => {
        localStorage.setItem('cb_access_token', accessToken)
        localStorage.setItem('cb_refresh_token', refreshToken)
    },

    // refresh_token 까지 만료된 경우 (재로그인 필요)
    onTokenExpired: () => {
        localStorage.removeItem('cb_access_token')
        localStorage.removeItem('cb_refresh_token')
        window.location.href = '/login'
    }
})

네트워크 보안

HTTPS 강제

Connect Base API 는 HTTPS 만 허용합니다. SDK 의 기본 baseUrl (https://api.connectbase.world)을 그대로 사용하세요.

자체 호스팅 서버에서 SDK 를 사용한다면 reverse proxy 에서 HTTPS 강제 리다이렉트:

typescript
// Express 예시
app.use((req, res, next) => {
    if (req.header('x-forwarded-proto') !== 'https') {
        return res.redirect(`https://${req.header('host')}${req.url}`)
    }
    next()
})

CSP 헤더 설정

typescript
// Content Security Policy
app.use((_, res, next) => {
    res.setHeader('Content-Security-Policy',
        "default-src 'self'; " +
        "script-src 'self' 'unsafe-inline'; " +
        "style-src 'self' 'unsafe-inline'; " +
        "img-src 'self' data: https://cdn.connectbase.world; " +
        "connect-src 'self' https://api.connectbase.world https://socket.connectbase.world"
    )
    next()
})

보안 헤더 (helmet)

typescript
import helmet from 'helmet'
app.use(helmet())

데이터 보호

민감 데이터 마스킹

typescript
function maskEmail(email: string): string {
    const [local, domain] = email.split('@')
    return local.slice(0, 2) + '***@' + domain
}

function maskPhone(phone: string): string {
    return phone.slice(0, 3) + '-****-' + phone.slice(-4)
}

로그에서 민감 데이터 제외

typescript
const SENSITIVE_FIELDS = ['password', 'publicKey', 'secretKey', 'access_token', 'refresh_token', 'ssn', 'credit_card']

function sanitizeForLogging(data: Record<string, unknown>): Record<string, unknown> {
    const sanitized = { ...data }
    for (const field of SENSITIVE_FIELDS) {
        if (field in sanitized) {
            sanitized[field] = '[REDACTED]'
        }
    }
    return sanitized
}

console.log('Request:', sanitizeForLogging(requestData))

필드 레벨 암호화

특히 민감한 컬럼(주민번호, 카드번호 등)은 컬럼 생성 시 encrypted: true 로 설정하세요. 데이터 암호화 → 필드 레벨 암호화 를 참고하세요.

감사 및 모니터링

콘솔 로그 활용

콘솔의 로그(Logs) 메뉴에서 다음을 확인할 수 있습니다:

  • API 호출 이력
  • 인증 시도 (성공/실패)
  • 함수 실행 로그
  • 에러 발생 빈도

에러 트래커 (cb.errorTracker)

클라이언트 에러를 자동 수집해 콘솔로 전송합니다.

typescript
const cb = new ConnectBase({
    publicKey: 'cb_pk_...',
    errorTracker: {
        // 콘솔에서 발급한 트래커 설정
        enabled: true
    }
})

보안 체크리스트

개발 단계

  • 환경 변수로 시크릿 관리 (.gitignore 확인)
  • 입력 검증 구현 (zod 등)
  • 에러 메시지에 민감 정보 노출 방지
  • 의존성 보안 취약점 스캔 (npm audit)

배포 전

  • 클라이언트 빌드에 cb_sk_* 미포함 확인
  • 콘솔 CORS 허용 도메인 검토
  • 모든 환경(dev/staging/prod)별 별도 키 사용
  • HTTPS 강제

운영 중

  • 정기적인 키 로테이션
  • 콘솔 로그 모니터링 (이상 패턴 탐지)
  • 보안 업데이트 적용
  • 침투 테스트 수행