본문 바로가기
감정일기(가칭)

🧪 DiaryTestManager, 어디에 두는 게 맞을까?

by 밤새는 탐험가89 2025. 10. 20.
728x90
SMALL

❌ Helper 폴더는 NO!

✅ LemonLogTests 폴더가 정답입니다.

 

iOS 앱을 개발하다 보면,
“내가 만든 Core Data나 FileManager 로직이 잘 동작하는지”
직접 확인하고 싶을 때가 많아요.

 

그래서 보통 아래처럼 테스트 전용 클래스를 하나 만들어두죠 👇

final class DiaryTestManager {
    static let shared = DiaryTestManager()
    private init() {}
    
    private let coreDataManager = DiaryCoreDataManager.shared
}

 

이 클래스는 앱 실행 중 사용자에게 보여지는 기능이 아니라,
“개발 중 내가 만든 Core Data 로직이 제대로 동작하는지 검증하기 위한 도구”예요.
그런데… 이걸 어디에 넣어야 할까요?


❌ 잘못된 선택: Helper 폴더

많은 초보 개발자들이 처음엔 이렇게 생각해요 👇

 

“테스트용 클래스니까 Helper 폴더 안에 넣어야지!”

 

하지만 이건 아주 위험한 설계예요.

문제점 설명
⚠️ 앱 번들에 포함됨 앱 빌드 시 사용자 기기에 함께 설치됩니다.
⚠️ 내부 데이터 노출 위험 테스트용 로그나 더미 데이터가 앱 내부에 남을 수 있습니다.
⚠️ 불필요한 용량 증가 테스트 전용 클래스가 릴리즈 버전에 포함됩니다.
⚠️ 유지보수 혼란 Helper 폴더에 테스트 코드가 섞이면 실제 앱 로직과 경계가 모호해집니다.

 

즉, “사용자에게 필요 없는 코드”가 앱과 함께 배포되는 거예요.
테스트 코드는 앱 코드와 완전히 분리된 환경에서만 실행돼야 합니다.


✅ 올바른 선택: LemonLogTests 폴더

테스트 코드는 반드시 테스트 전용 폴더 (LemonLogTests) 안에 넣어야 합니다.

LemonLog/
 ┣ Helper/
 ┃  ┣ LogManager/
 ┃  ┗ DateFormatter/
 ┣ Manager/
 ┣ Model/
 ┣ View/
 ┣ ViewModel/
LemonLogTests/     ✅ 테스트 전용
 ┣ DiaryTestManager.swift
 ┗ DiaryCoreDataTests.swift

 

이 폴더는 앱 타겟과 완전히 분리된 테스트 전용 빌드 환경이에요.
즉, 앱을 실제로 실행할 땐 테스트 코드가 포함되지 않습니다.


💡 DiaryTestManager를 만든 이유

Core Data를 직접 테스트하려면 매번 이렇게 해야 해요 👇

let manager = DiaryCoreDataManager.shared
manager.saveDiary(model: dummy)
let result = manager.fetchDiaries(mode: .all)

 

그런데 이런 코드를 여러 테스트 함수마다 반복하면
중복이 많고 관리가 어려워져요.

그래서 “테스트만 담당하는 관리 객체”로 DiaryTestManager를 따로 만든 거예요.

 

✅ 역할 정리

역할 설명
Core Data CRUD 통합 테스트 save, fetch, update, delete 기능 검증
더미 데이터 생성 테스트용 EmotionDiaryModel을 자동 생성
데이터 초기화 이전 테스트에서 남은 데이터를 삭제
재사용성 확보 다른 테스트 클래스에서도 같은 로직 재사용 가능

⚙️ @testable import를 꼭 추가해야 하는 이유

테스트 코드 상단에는 반드시 이 구문이 필요해요 👇

@testable import LemonLog

 

이건 앱 내부의 internal 코드 (예: DiaryCoreDataManager, FileManager 등)에

접근할 수 있도록 허용하는 키워드예요.


테스트 타겟은 기본적으로 앱 모듈 내부에 접근할 수 없기 때문에
이걸 추가하지 않으면 "Cannot find 'DiaryCoreDataManager' in scope" 오류가 납니다.


🧩 Swift 6 이후의 변화 — MainActor 에러의 등장

DiaryCoreDataManager를 이렇게 선언했죠 👇

@MainActor
final class DiaryCoreDataManager {
    static let shared = DiaryCoreDataManager()
}

 

그런데 Swift 6부터는 MainActor로 격리된 객체(shared)
비동기 아닌 일반 클래스에서 직접 참조할 수 없어요.

 

그래서 아래와 같은 에러가 뜨는 거예요.

 

❌ “Main actor-isolated property ‘shared’ cannot be referenced from a nonisolated context”

 

해결 방법은 간단합니다.
테스트 클래스(DiaryTestManager)에 @MainActor를 붙여주면 돼요 👇

@MainActor
final class DiaryTestManager {
    static let shared = DiaryTestManager()
    private init() {}
    
    private let coreDataManager = DiaryCoreDataManager.shared
}

 

이렇게 하면 MainActor 환경이 일치하기 때문에
Core Data 접근 시 스레드 충돌 없이 안전하게 테스트할 수 있습니다 ✅


🧪 실제 구조 예시

import XCTest
@testable import LemonLog

@MainActor
final class DiaryTestManager {
    static let shared = DiaryTestManager()
    private init() {}

    private let coreDataManager = DiaryCoreDataManager.shared
}

final class DiaryCoreDataTests: XCTestCase {
    private let testManager = DiaryTestManager.shared

    func testSaveDiary() {
        let diary = EmotionDiaryModel(
            id: UUID(),
            emotion: "happy_grade_1",
            content: "오늘은 정말 행복했어요 🌞",
            createdAt: Date(),
            images: nil
        )
        
        testManager.save(diary) // ✅ Core Data에 저장
        let fetched = testManager.fetch(by: diary.id)
        XCTAssertNotNil(fetched)
    }
}

📘 정리 요약

항목 잘못된 방식 올바른 방식
위치 Helper 폴더 ✅ LemonLogTests 폴더
import 방식 import LemonLog ✅ @testable import LemonLog
MainActor 에러 해결 없음 ✅ 테스트 클래스에도 @MainActor 적용
역할 앱 기능 도우미 ✅ Core Data 테스트 관리 전용
결과 앱 번들 포함 ❌ 테스트 환경 전용 ✅

✨ 마무리

“테스트 코드는 앱의 일부가 아닙니다.
앱을 검증하기 위한 별도의 세계입니다.”

 

Helper는 앱 기능을 “돕는 코드”를 담는 곳이고,
Tests는 “앱이 잘 작동하는지 검증하는 코드”를 담는 곳이에요.

 

📌 정비 도구는 공장에, 운전 기능은 자동차 안에.
같은 이유로 테스트 코드는 반드시 LemonLogTests 폴더에 있어야 합니다. ✅

728x90
LIST