개발 가이드라인

코딩 스타일

Kotlin 코딩 컨벤션

  • Kotlin 공식 코딩 스타일 가이드 준수
  • 함수형 프로그래밍 우선
  • Null 안전성 활용
  • 확장 함수 적극 활용

Spring Boot 개발 원칙

// 의존성 주입 - Constructor Injection 선호
@Service
class UserService(
    private val userRepository: UserRepository,
    private val cacheManager: CacheManager
) {
    // 구현
}
 
// Coroutines 활용
suspend fun processAsync(): Result {
    return coroutineScope {
        // 비동기 처리
    }
}

API 설계 원칙

  • RESTful API 설계
  • 명확한 HTTP 상태 코드 사용
  • 일관된 응답 구조
  • 버전 관리 전략
// API 응답 구조 예시
data class ApiResponse<T>(
    val success: Boolean,
    val data: T? = null,
    val error: ErrorDetail? = null,
    val timestamp: Instant = Instant.now()
)

아키텍처 패턴

계층형 아키텍처

presentation/
├── controller/
├── dto/
└── mapper/

application/
├── service/
├── usecase/
└── facade/

domain/
├── model/
├── repository/
└── exception/

infrastructure/
├── persistence/
├── external/
└── configuration/

헥사고날 아키텍처 적용

  • 도메인 중심 설계
  • 포트와 어댑터 패턴
  • 의존성 역전 원칙

테스트 전략

테스트 피라미드

  1. 단위 테스트 (70%)

    • 비즈니스 로직 중심
    • Mock 활용
    • 빠른 실행
  2. 통합 테스트 (20%)

    • @SpringBootTest 활용
    • TestContainers 사용
    • 실제 DB 연동
  3. E2E 테스트 (10%)

    • 주요 시나리오
    • API 전체 플로우

테스트 코드 예시

@Test
fun `사용자 생성 시 이메일 중복 검증`() {
    // given
    val existingEmail = "test@example.com"
    every { userRepository.existsByEmail(existingEmail) } returns true
    
    // when & then
    assertThrows<DuplicateEmailException> {
        userService.createUser(CreateUserRequest(email = existingEmail))
    }
}

성능 최적화

데이터베이스 최적화

  • 인덱스 전략 수립
  • N+1 문제 해결
  • 쿼리 최적화
  • 커넥션 풀 설정

캐싱 전략

@Cacheable(value = ["users"], key = "#userId")
suspend fun findUserById(userId: Long): User {
    return userRepository.findById(userId)
        ?: throw UserNotFoundException(userId)
}

비동기 처리

  • Kotlin Coroutines 활용
  • WebFlux 반응형 프로그래밍
  • 이벤트 기반 처리

보안 가이드라인

API 보안

  • JWT 토큰 기반 인증
  • OAuth 2.0 구현
  • Rate Limiting
  • CORS 설정

데이터 보안

  • 개인정보 암호화
  • SQL Injection 방지
  • XSS 방어
  • CSRF 토큰

모니터링 및 로깅

로깅 전략

private val logger = LoggerFactory.getLogger(this::class.java)
 
fun processOrder(orderId: Long) {
    logger.info("주문 처리 시작: orderId=$orderId")
    try {
        // 처리 로직
        logger.info("주문 처리 완료: orderId=$orderId")
    } catch (e: Exception) {
        logger.error("주문 처리 실패: orderId=$orderId", e)
        throw e
    }
}

메트릭 수집

  • Spring Boot Actuator
  • Micrometer
  • CloudWatch 연동

DevOps 실천사항

CI/CD 파이프라인

# GitHub Actions 예시
name: Build and Deploy
 
on:
  push:
    branches: [ main, develop ]
 
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run tests
        run: ./gradlew test
      
  build:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - name: Build application
        run: ./gradlew build

컨테이너화

FROM openjdk:17-jdk-slim
COPY build/libs/app.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

코드 리뷰 체크리스트

기능적 요구사항

  • 요구사항 충족 여부
  • 엣지 케이스 처리
  • 에러 핸들링

코드 품질

  • 가독성
  • 중복 코드 제거
  • 적절한 추상화 수준
  • SOLID 원칙 준수

성능 및 보안

  • 성능 영향도 검토
  • 보안 취약점 확인
  • 리소스 누수 가능성

테스트

  • 충분한 테스트 커버리지
  • 의미 있는 테스트 케이스
  • 테스트 가독성