티스토리 뷰

사건의 발단

회사 프로젝트에 date를 비교하여 유효한지 체크하는 로직이 있었다.

간단한 로직이고 대부분 유저들에게 잘 작동했는데, 어느 한 유저만 작동하지 않는다고 문의가 들어왔다.

로그를 살펴보니, 당연히 되어야 하는 date 비교 후 결과를 리턴하는 함수에서 false 를 리턴하는 것이였다.

 

본래 로직은 서버에서는 "yyyyMMddHHmmss" 형식으로 시작일과 종료일을 date를 내려주고 있었고,
date 객체로 변환하여 현재 시점이 validate 한지 체크했었다.

 

모든게 정상이였다. 대부분 유저들도 잘 사용했고 내 시뮬레이터와 실기기, 테스트코드 환경에서도 잘 작동해서 실마리를 찾는게 어려웠다.

 

그런데 google 에 'swift dateForamtter issue' 를 검색하니 dateFormatter 가 정상적으로 동작하지 않고있고,

OS 버그로 생각된다는 여러 글들이 있었다.

 

첫번째 수정

그래서 나는 dateFormatter 사용을 최소화 해보자! 해서 int64 로 변환해 숫자끼리 비교하는 것으로 로직을 변경해보았다.

내 모든 테스트 환경에서는 증상 재현이 안되었으므로...

기도메타로 업데이트 일에 맞춰서 배포를 하고 유저에게 확인을 요청하는 수 밖에 없었다.

 

결과는 동일했다. 나는 int끼리 비교 하는 것이 실패하는 것인 줄 알고 세상이 이해되지 않았다.

 

두번째 수정

내 환경에서 재현이 안되는 것이 힘들었다.

로그를 더 자세히 받아볼 수 있도록 guard 문으로 언래핑 하는 쪽에 로그를 심어두었다.

/// 두개의 date 사이에 포함되는지 확인
public static func isCurrentDateBetween(startDay: Int64?, endDay: Int64?) -> Bool {
    // 현재 날짜와 시간 가져오기
    let now = Date()

    // TimeZone 설정
    let timeZone = TimeZone(identifier: "Asia/Seoul")

    // DateFormatter 설정
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyyMMddHHmmss"
    dateFormatter.timeZone = timeZone

    // 날짜와 시간을 지정된 형식으로 변환
    let dateString = dateFormatter.string(from: now)

    // Int64로 변환
    guard let currentDateInt64 = Int64(dateString) else {
    	// 로그찍는 함수!
        return false
    }

    print("CURRENTDATE: \(currentDateInt64)")

    // startDay와 endDay가 nil이 아닌지 확인
    guard let startDay = startDay, let endDay = endDay else {
    	// 로그찍는 함수!
        return false
    }

    // 현재 날짜가 두 날짜 사이에 포함되는지 확인
    let result = currentDateInt64 >= startDay && currentDateInt64 <= endDay
    // 포함 안된다면 로그찍는 함수!
    return result
}

 

코드를 이렇게 수정하여 다시 배포를 진행했고 로그를 기다렸다.

다음과 같이 로그가 날라왔다.

guard let currentDateInt64 = Int64(dateString) 에서 nil 리턴
dateString: 20240804오전 101751
now: 2024-08-04 오전1:17:51+0000
dateFormat: yyyyMMddHHmmss

 

?!

dateString 이 dateFormatter의 dateFormat 을 무시하고 이상한 포맷으로 나온 것이였다.

그러니 Int로 변환이 안되는 것은 당연하다.

(심지어 저건 무슨 형식인가..)

 

문제는 파악했다

왜 이런일이 생겼을까? 심지어 로그에 있는 dateFormat 은 dateFormatter.dateFormat 이다. 

dateFormatter 객체는 이미 'yyyyMMddHHmmss' 형식으로 설정이 되어 있는 것이다.

 

조금 찾아보니 locale 을 고정시켜야 일관적인 날짜 포맷을 얻을 수 있다는 내용이 있었다.

흠. 조금 이해가 되지 않았다. locale 을 고정하지 않으면 자동으로 'KO' 로 locale 설정이 될 것이라 생각되었다.

(그래서 '오전' 도 포함된게 아닌가)

 

일단 아래의 이슈가 너무 동일해서 locale 을 추가해주는 한줄의 코드를 배포일에 맞춰 수정했다.

 

https://forums.swift.org/t/dateformatter-bug/61053

 

DateFormatter bug

Hi, all. I have found a weird result of DateFormatter. Check out the code below. let formatter = DateFormatter() formatter.dateFormat = "yyyyMMdd" formatter.date(from: "20220101") // 2022. 01. 01 formatter.date(from: "") // 2000. 01. 01 formatter.date(from

forums.swift.org

https://developer.apple.com/library/archive/qa/qa1480/_index.html

 

Technical Q&A QA1480: NSDateFormatter and Internet Dates

Technical Q&A QA1480 NSDateFormatter and Internet Dates Q:  I'm using NSDateFormatter to parse an Internet-style date, but this fails for some users in some regions. I've set a specific date format string; shouldn't that force NSDateFormatter to work inde

developer.apple.com

 

결국 고쳐졌다.

업데이트 후 로그를 받아보니, 드디어 내가 의도한대로 로직이 작동됨을 확인했다.

아니 이게 무슨일인가. 정말 locale을 고정하지 않아서 생겼던 이슈였다.

 

많은 우여곡절 끝에.. 이슈가 해결되어서 기분이 너무 좋았는데, 

나와 주변 사람들은 아무리 해도 재현이 안되었었기 때문에 힘들고 오래 걸렸다.

 

다행히 우리 앱에 적극적인 유저가 귀찮을법도 한데 열심히 협조해준 덕분에 버그를 고칠 수 있었다.

심지어 공장초기화까지 진행해서 결과를 알려줬던 유저 덕분에 꼭 고쳐줘야겠다..! 라는 마음을 먹었고,

길었지만 버그가 잡혔다는 소식이 너무 기뻣다.

 

결론

dateFormatter 의 locale 을 고정하지 않으면, 일부 디바이스에서 dateFormat 이 이상하게 설정되는 이슈가 있다.

따라서 locale 을 반드시 고정하여 사용하자.

 

저 swift 포럼에 게시글을 올린 분도 한국인인데..? locale 'KO' 한정 이슈인가.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함