3.13 모델의 역할

Jay·2025년 2월 6일

Level 3 - SingleView App

목록 보기
13/24

Goal

모델에서 표시되는 시간의 형식을 바꾼다.

Meterials

String Format Specifiers(문자열 형식 지정자)

다음과 같은 폼에 맞추어 문자열의 형식을 지정해 줄 수 있다.

%[argument_index$][flags][width]conversion

[ ] 는 생략이 가능한 옵션이고 conversion 위치에는 출력되는 데이터의 타입을 입력하는데 s(문자열), d(정수), x(16진수), o(8진수), f(실수)가 들어갈 수 있다.
예를들어, “%02d” 에서 ‘0’ 은 빈자리를 ‘0’으로 채우라는 플래그이고 ‘2’ 는 2자리로 지정하는 width 이다. 대부분 언어에서 동일한 형식을 사용하므로 자세한 용법은 검색을 통해 익히길 바란다.

Thinking First

경과한 시간은 초 단위의 Double 타입이다. 예를 들어 65초가 경과했다면 이것은 1분 5초이다.
그러므로 65를 60으로 나눠주면 ‘분'이 되고 그것의 나머지가 ‘초' 가 된다.
이것을 이용해서 시간을 보기 쉬운 형식으로 바꿔보자.

Making Next

분,초,10분의 1초 단위로 상수를 생성하여 알맞은 폼으로 변환해 보았다.

@objc func updateElapsedTimeLabel(timer: Timer) {
      if stopwatch.isRunning {
          let minutes = Int(stopwatch.elapsedTime / 60)
          let seconds = Int(Int(stopwatch.elapsedTime) % 60)
          let tenthsOfSecond = Int(stopwatch.elapsedTime * 10) % 10
          timeLabel.text = String(format:"%02d:%02d.%d",minutes, seconds, tenthsOfSecond)
      }
      else {
          timer.invalidate()
      }
  }

실행해보면 우리가 일반적으로 보는 시간의 형식으로 출력이 될 것이다.

하지만 이 코드는 문제점을 내포하고 있다. MVC 패턴을 다시 떠올려 보면 여기는 컨트롤러 영역이다. 컨트롤러는 모델에게 데이터를 요청만 할 뿐 데이터를 직접 변경하지 않는 것이 좋은데 단편적인 예로, 다른 컨트롤러에서도 이러한 형식이 필요하다면 똑같은 코드를 중복하여 구현해야 한다. 그렇다면 실수로 불일치되는 문제가 발생할 수도 있고 형식이 변경되면 같은 코드를 두번 수정해야 하는 낭비가 발생한다.
그러므로 모델에는 데이터와 그 데이터를 가공하는 내용들이 모두 들어가도록 모델에 새로운 프로퍼티를 만들어 리팩토링 해보자.

class Stopwatch {
...
   var elapsedTimeAsString: String {
       return String(format: "%02d:%02d.%d",
                     Int(elapsedTime / 60), Int(Int(elapsedTime) % 60), Int(elapsedTime * 10) % 10)
   }
...

좀 더 간소화한 문법으로 elapsedTimeAsString 연산 프로퍼티를 정의했다.

그러므로 updateElapsedTimeLabel(:)은 다음과 같이 수정 되어야 한다.

@objc func updateElapsedTimeLabel(timer: Timer) {
    if stopwatch.isRunning {
        timeLabel.text = stopwatch.elapsedTimeAsString
    } else {
        timer.invalidate()
    }
}

Closing

이전과 동일하게 실행되지만 훨씬 깔끔해지고 좀 더 MVC 패턴에 어울리는 코드가 되었다.
이번 챕터는 입문자는 물론 많은 개발자들이 간과하는 부분을 다루었다.
컨트롤러에서 모든 작업을 하면 당시에는 편할지 몰라도 나중에 그만큼 댓가를 치루게 될 것이다.
컨트롤러는 중재자이므로 모든 부담을 지우지 않도록 하자. 데이터와 데이터의 가공은 모델이 책임진다.

profile
Software Engineer Specialized on iOS

0개의 댓글