2026-01-26

1일 1아티클

LY

암묵적 연관성

문제 상황

  class MessageModel(
      val content: MessageContent,
      val timestampMillis: Long,
      val senderUserId: UserId,
      ...
  )

  sealed class MessageContent {
      data object Empty: MessageContent()

      data class Error(val errorType: ErrorType): MessageContent()

      data class Text(val text: String): MessageContent()

      data class Event(val eventType: EventType): MessageContent()
  }

  fun bindToViews(message: MessageModel) {
    val isVisible = isContentValid(message.messageContent)
    layoutContainer.isVisible = isVisible
    if (!isVisible) {
        return
    }

    timestampTextView.text = formatter.format(message.timestampMillis)
    ... // 기타 뷰 업데이트 로직
    contentTextView.text = getMessageText(message.content)
  }

  private fun isContentValid(content: MessageContent): Boolean = when (content) {
      MessageContent.Empty,
      is MessageContent.Error -> false
      is MessageContent.TextMessage,
      is MessageContent.EventMessage -> true
  }

  private fun getMessageText(content: MessageContent): String = when (content) {
      MessageContent.Empty,
      is MessageContent.Error -> error("Invalid message type as `messageText`")
      is MessageContent.TextMessage -> content.text
      is MessageContent.EventMessage -> content.eventType.toMessageString()
  }

문제점

  • getMessageText 구현이 암묵적으로 isContentvalid와 연관
    • isContentValidtrue 반환 시에만 getMessageText를 호출 가능하지만, 이를 위반해도 런타임 에러로만 감지 가능
    • 타입이 추가되거나 업데이트될 때, isContentValidgetMessageText 간의 동작 일관성 확인 필요
    • → 리팩터링이나 기능 확장 시 getMessageText를 오용해도 알아채기 어려움

해결 방법

  • 공통 로직을 하나의 함수로 합하여 해결
    • 단독으로 getMessageText를 사용해도 안전성 확보
    • isContentValidgetMessageText 간의 일관성 보장
  private fun isContentValid(content: MessageContent): Boolean = 
      getMessageText(content) != null

  /**
  * 메시지 콘텐츠[content]를 표시 가능한 텍스트 표현으로 변환하여 반환한다.
  * 단 표시할 수 없는 콘텐츠 유형(error/empty)인 경우 null을 반환한다.
  */
  private fun getMessageText(content: MessageContent): String? = when (content) {
      MessageContent.Empty,
      is MessageContent.Error -> null
      is MessageContent.TextMessage -> content.text
      is MessageContent.EventMessage -> content.eventType.toMessageString()
  }

함수 간에 암묵적인 연관성이 있을 경우 함수를 하나로 합치거나 연관성이 명확한 구현으로 변경할 것

오늘 배운 것

  1. API 고도화 작업
    • 사용자 파라미터 추가
    • 사용자 정의 에러 코드 작성 및 에러 핸들링
    • 로컬 테스팅을 통한 잘못된 로직 수정
    • 입력값 검증 로직 추가
  2. Swagger 고도화 작업
    • 버전 업그레이드
    • JWT Header 설정
    • 담당 API의 명세서 작성

내일 할 일

  1. 기타 업무

참고자료

results matching ""

    No results matching ""