호댕의 iOS 개발

[TIL] 21.11.04 ~05 Today I Learned 본문

Software Engineering/TIL

[TIL] 21.11.04 ~05 Today I Learned

호르댕댕댕 2021. 11. 6. 10:47

 (TDD, Unit Test, Stack, Queue, NotificationCenter, ViewController 간 데이터 전달)

이번 주도 많은 것들을 배웠다. 

프로젝트를 진행하면서 Model의 코드를 작성할 때 이 코드를 어떻게 점검해야되나 고민했었는데 Unit Test를 배웠다.

 

# Unit Test

-> TDD를 위한 보조 수단이다.
정해둔 동작 방향이 정확히 작동하는지 검증하는 절차로 기능별, 단위별 테스트를 해보는 것!

그렇다면 테스트 케이스가 많을수록 좋은 것일까?
적절한 것이 좋다 (최소한 요구사항에 있는 조건은 모두 넣어야 하고 엣지 케이스를 추가해주면 좋다)
다만 테스트 케이스가 많아질수록 요구사항 자체가 변하면 수정하기가 어려워진다.

왜 Unit Test를 해야 할까?
이는 맥북 예가 좋아서 정리해본다.
만약 맥북이 본체와 충전기 어댑터, 케이블이 모두 일체형이라면 충전이 안될 때 어디가 문제인지 파악할 수가 없다. 그러나 본체, 충전기 어댑터, 케이블이 모두 분리될 수 있다면 하나씩 바꿔가며 뭐가 문제인지 찾을 수 있고, 문제를 찾아도 딱 그 부분만 고치면 된다.

코드도 똑같다. Unit Test를 통해 각 메서드를 테스트한다면 문제가 생긴 메서드를 빠르게 찾을 수 있다.
이런 이유로 Unit Test를 하는 것이다.

 

# TDD

-> 하나의 방법론
요구사항을 검증하는 자동화된 테스트 케이스를 작성하고, 테스트 케이스를 통과하기 위해 최소한의 코드를 생성한다.

  1. 요구사항을 먼저 제대로 파악한다.
  2. 요구사항에 맞는 테스트 케이스를 작성한다.
  3. 테스트를 통과할 수 있는 기능을 작성한다.

그렇다면 왜 굳이 실패하는 테스트를 만드는 것일까?
실패할 수 있는 상황도 정확히 알아야 테스트를 신뢰할 수 있다.

그렇다면 테스트를 나중에 작성하면 안될까?

  • 테스트 코드를 먼저 작성하면 테스트를 고려한 코드를 작성할 수 있게 된다.
  • 테스트를 하지 않는다면 코드를 수정(리팩토링)하기도 까다로워진다.

싱글톤을 사용하게 되면 다양한 객체에서 싱글톤 객체를 사용하게 되면서 테스트가 거의 불가능하게 된다. 따라서 이 부분이 바로 싱글톤의 단점이다.

# Stack

쌓아져 있는 순서대로 처리한다.
(접시를 쌓아놓으면 위에 부터 사용하는 것과 동일하다)
나중에 들어온 것이 먼저 나간다. (후입선출)

  • 들어온 것: Push
  • 나가는 것: Pop

# Queue -> 대기열

컴퓨터의 기본적인 자료구조로 먼저 온 순서대로 처리한다. (선입 선출 / First In First Out)
자료의 임시 거처 역할을 한다.

  • 들어온 것: Put
  • 나가는 것: Get

# NotificationCenter

ViewController 간 데이터 전달 방법에 대해 고민을 하다 두번째 View에서 첫번째 View로 데이터를 전달하는 방법으로 NotificationCenter를 사용했다.
활동학습을 통해 NotificationCenter에 대해 배우긴 했지만 아직 이에 대해 정확히 알지 못한다고 생각하여 찜찜했었는데 이번 프로젝트를 계기로 NotificationCenter에 좀 더 가까워졌다.

NotificationCenter도 ViewController 간 데이터 전달에 사용될 수 있었다.
먼저 Notification Center를 생성해주었다.

import Foundation

let notificationCenter: NotificationCenter = .default

extension Notification.Name {
    static let test = Notification.Name("test")
}

(test는 좋지 않은 이름이지만... 임의로 생성한 코드라 이렇게 만들었다.)

여기서 NotificationCenter를 사용하려면 Foundation 프레임워크를 import 해줘야 했다.

데이터를 전달하고 싶은 두번째 ViewController에서 post를 해주었다.

notificationCenter.post(name: .test, object: 전달해주고 싶은 객체)
  • name: 해당 정보를 전달할 NotificationCenter의 이름
  • object: 전달하고 싶은 객체(데이터)

여기서 userinfo와 object가 어떤 차이가 있는지 궁금증이 들었다. 이에 대해선 공부도 해보고 다른 캠퍼들에게 질문을 드려봐야겠다…

그리고 이 데이터를 받을 첫번째 뷰에는 addObserver를 해주고 옵져버가 할 행동을 정해줬다.

notificationCenter.addObserver(self, selector: #selector(신호를 받았을 때 해줘야 할 일), name: .test, object: nil)

selector에 #selector를 통해 무조건 @objc 메서드를 넣어야 하는 것이 아니라 일반 메서드를 넣어도 된다는 것을 알게됐다. 이 부분에 대해선 조금 더 공부를 해봐야겠다.

아직 NotificationCenter에 대해 정확히 알진 못했지만 이번 프로젝트를 계기로 그나마 NotificationCenter에 가까워진 기분이 들었다.

# ViewController 간 데이터 전달

사실 이 부분에 대해선 아직 정확히 모르겠다. 프로젝트에선 NotificationCenter, performSegue, prepare를 활용했는데 정확하게 알고 썼다는 말은 못하겠다… 😢

일단 이해한 내용에 대해 정리해보자.

# performSegue

performSegue(withIdentifier: , sender: )
  • withIdentifier: segue의 identifier를 String으로 적어주는 매개변수이다.
  • sender: segue를 실행하기 위해 사용하길 원하는 객체를 적어주는 매개변수이다.

# prepare

prepare는 새로운 ViewController를 만들게 되면 주석에 있는 메서드이다.

In a storyboard-based application, you will often want to do a little preparation before navigation.

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "segue" {
        let destinationController = segue.destination as! StockModificationViewController

        destinationController.2번째_뷰에서_값을_넣어줘야_할_변수 = 첫번째_뷰에서_넣어줄_값
}

아직 prepare의 경우 유튜브 영상도 찾아보고 구글링도 해봤지만 정확히 이해는 하지 못했다. 다만 두번째 ViewController에 데이터를 받을 변수를 생성해주고 원하는 segue를 통해 첫번째 ViewController의 데이터를 전달해주는 방식으로 이해했다.

여기서 변수를 생성해주지 않고 바로 두번째 ViewController의 label.text에 넣어주지 않는 이유는 무엇일까?
아직 두번째 View가 생성되지 않았기 때문에 label은 생성이 되지 않은 상태이다. 즉, 아직 메모리에 올라와 있지 않은 상태인 것이다. 따라서 바로 label.text에 넣어줄 수 없다.

# AutoLayout

프로젝트를 진행하며 아이폰 SE 같은 화면이 작은 디바이스로 시뮬레이터를 돌리니 버튼에 있는 titleLabel이 일부 생략되어 보이는 문제가 있었다.
따라서 화면이 작아도 버튼의 text를 모두 볼 수 있는 방법에 대해 찾다 다음과 같은 메서드를 찾았다.

# adjustsFontSizeToFitWidth

폰트 사이즈를 넓이에 따라 맞춰주는 label 관련 메서드이다. 이 메서드를 true로 주니 버튼의 크기에 맞춰 글자가 조정되었고 모든 글씨가 다 보였다.

하지만 문제는 또 있었다… 프로젝트 참고 그림에선 분명 버튼이 줄바꿈이 되어 있었는데 adjustsFontSizeToFitWidth 메서드를 사용해도 줄바꿈이 되지 않았다.

.titleLabel?.lineBreakMode = .byWordWrapping

따라서 이렇게 단어 기준으로 줄바꿈을 할 수 있도록 설정해주었고

.titleLabel?.textAlignment = .center

텍스트 정렬이 가운데로 올 수 있도록 해주었다.

 

 

# 새롭게 알게 된 내용


  1. @discardableResult: Return 값을 사용하지 않아도 경고창이 뜨지 않게 된다.
  2. ViewController 간 데이터를 전달하는 방법으로 prepare와 performSegue를 사용해봤다. 아직 ViewController 간 데이터를 전달하는 방법이 익숙하지 않은데 이에 대해 공부를 해야겠다.
  3. Unit Test를 할 때 테스트 함수에 test_를 붙이지 않으면 테스트를 할 수 있는 마름모가 생성되지 않는다. 잊지 말고 꼭 작성하자!!
  4. View와 Window의 차이
  • Window: 자체적으로 보이는 컨텐츠를 가지고 있진 않지만 앱의 view를 담을 수 있는 기본 컨테이너를 제공함. → 일반적으로 Window는 앱에서 하나만 가지고 있다.
  • View: 컨텐츠로 window의 일부를 채울 수 있다.

 

Comments