# 3주차 피어세션
## 🙌🏻 참가자
- S005 김두연 🧑🏻💻
- S018 박영광 👨🏻💻➡️💉
- S021 박정아 👩🏻💻➡️🎤
- S030 오창민 🧑🏻💻
- S044 이정원 🧑🏻💻
- S045 이지수 👩🏻💻
- S046 이진하 👩🏻💻💻
- S051 전여훈 🧑🏻💻➡️📝
</br>
## ⏰ 쉬는 시간
14:20 - 14:30
15:20 - 15:30
16:20 - 16:30
</br>
## 📢 주제
### 이미지 데이터 관리 방법
- S005 : 이미지피커컨트롤러에서 `pngData`로 변환해서 Photo 타입을 만들 때 데이터를 넘겨주었습니다. 팩토리에서 인스턴스를 만드는데, 이때 사각형이랑 사진 타입을 구분할 때 enum의 `associated value`를 사용했습니다.
- 기본 사진중에 하나가 뒤집힌다.. 왜?
- 아무도 모름..
- 우리 피어 캠퍼들 대부분 이 방법을 사용한듯!
- S018, S021, S045, S051 : S005님과 마찬가지로 `pngData`를 사용하여 `Data`타입으로 관리하였습니다.
- S030 : 요구사항에서 바이너리형태로 메모리에 관리한다고 나와있어서 헷갈렸어요.. 저는 이미지를 가져와서 출력을 찍어봤는데 `Any` 타입이길래 `Any`를 썼는데, `pngData`나 `jpegData`를 쓰는게 좋은 것 같아요.
- S044 : 다른 캠퍼분들과 마찬가지로 이미지피커컨트롤러에서 이미지를 `Data`타입의 `pngData`로 변환하였고, Factory에 전달할 때 `enum`의 associated value로 넘겨주었습니다.
`UIImageView`를 생성할 때는 `UIImage(data: photo.data)`를 사용하여 `Data`타입을 `UIImage`타입으로 변환하였습니다.
- S046 : 저도 비슷하긴 한데 팩토리 패턴을 바로 사용하지는 않았고 `if-case`를 사용해서 사각형과 이미지를 구분해서 인스턴스를 만드는 방식을 사용했습니다.
</br>
### 모델과 뷰를 연결 방법
- S005 : 버튼이 눌렸을 때 plane에서 인스턴스를 만들어서 `NotificationCenter`로 인스턴스를 보내주면 뷰 컨트롤러에서 받아서 사용하도록 했습니다.
- 화면을 터치했을 때는 어떻게 하셨나요?
- 터치된 객체가 plane이 보관하는 배열에 몇번째에 있는 인스턴스인지 확인하고 `NotificationCenter`로 인스턴스와 인덱스를 보내주는 방식으로 구현했습니다.
- plane에 쌓여있는 인스턴스의 순서, 개수와 사각형들을 포함하는 뷰의 subview의 순서, 개수가 같다는 점을 이용했습니다.
- S018 : UIView 에 있는 `hitTest()`를 사용해서 뷰를 받아오고, 모델(plane)에서도 hitTest를 사용해서 모델을 받아오도록 했습니다.
- S021 : S005님과 비슷하게 plane과 뷰가 가지고있는 아이템의 순서가 같다는 점을 이용하였습니다. 이를 위해 뷰컨트롤러는 선택된 인덱스를 가지고 있도록 했습니다. 선택되었을 때 `hitTest()`를 해서 plane 인덱스를 Notification을 하게했습니다. 뷰 컨트롤러에서는 Notification을 받으면 받은 인덱스를 사용해서 객체를 가지고 와서 사용하도록 했습니다.
- 인덱스가 꼬이는 문제가 생겼습니다..
- Pan 처리 할 때 문제가 생기는게 아닐까요?
- 임시뷰를 안만들어서 그런게 아닐지..
- S030 : 인덱스말고 다른 방법으로 관리할 수 없을지 궁금해서 주제로 올렸습니다. 저는 여러가지 시도를 하다가 id-UIView가 맵핑되는 딕셔너리를 뷰 컨트롤러에서 사용했습니다.
- id가 중복되는 이슈가 생기면..?
- 이미 있는 Id가 나오면 id를 만들 때 다시 만드는 방법이 좋을 것 같습니다.
- S044 : 모델과 뷰를 따로 맵핑하기보단 각각의 배열에 추가된 순서, 즉 index를 가지고 관리하였습니다.
- S045 : 저도 인덱스를 사용했습니다. `border`까지 `alpha`가 변하는 것을 막기위해 `border`만 가지고 있는 `UIView`를 만들어 이 뷰를 씌워주는 식으로 구현하였습니다. id같은 방법을 사용할 수 있지 않을까 해서 찾아봤는데 자료를 못찾았습니다ㅠ
- S046 : 뷰 컨트롤러에서 뷰를 저장하는 배열을 선언했습니다. hitTest같은 함수를 구현해서 사용했고 String 으로 view의 id를 가져와서 nil일 때는 무시하고 있을 때는 선택하도록 했습니다. delegate 패턴을 해봤다가 `NotificationCenter` 바꿔서 사용했습니다.
- Plane에 `UIKit`? -> 형변환 때문에 사용했어요..
- 모델에는 `UIKit`을 `import`하면 안된다? vs 괜찮다?
- *`모델`에서는 안된다!*
- `DispatchQueue`를 사용한 이유?
- UI작업은 메인 스레드에서 해야된다고 생각해서 사용했어요.
- S051 : 선택된 뷰를 뷰와 모델로 연결된 튜플로 관리하였습니다.
</br>
### 뷰 관련 코드 작성 위치
> 질문의 의도: 뷰를 그리는 코드를 따로 깔끔하게 분리할 수 있는 방법이 있는지 궁금해서 물어봤습니다...
- S005 : `extension`으로 `UIView`를 초기화하는 코드를 다른 파일로 따로 빼서 사용했는데, 이러면 분리가 잘 되는 것 같습니다!
- `extension` 하는 거랑 상속하는 차이?
-> 상속받으면 상속받은 특정한 객체 안에서만 사용할 수 있으니까 더 나을 것 같습니다.
- S018, S021, S030 : `UIView`, `UIImageView`를 상속하는 커스텀 뷰를 만들어서 재사용했습니다.
- S044 : view에 대한 custom class를 생성하지 않아 `ViewController`에서 화면을 그리는 작업을 진행하였습니다. 사각형 뷰와 사진 뷰를 같은 타입으로 관리하고 싶어서 `UIImageView`로 만들고 `UIView`로 감싸는 식으로 구현하였습니다.
- S045, S046, S051 : ViewController에 작성하엿습니다.
</br>
### 사각형과 사진의 구조
#### 1. 프로토콜 채택
S018, S021, S046
#### 2. 클래스 상속
S005, S021, S030, S044, S045, S051
- S005 : 상속을 이용했습니다. 사각형과 사진의 차이점이 내부의 프로퍼티 밖에 없다고 생각을 해서 상속을 선택했습니다. 기본적인 프로퍼티가 겹치고 사각형은 color, 사진은 image만 추가적으로 가진다고 생각했습니다. 프로토콜은 동작이 다른 함수를 만드는데 좋다고 생각해서 프로토콜 보다는 상속을 사용했습니다.
- S018 : 프로토콜을 사용했는데 `Equatable`을 사용하는 것이 다형성을 이용해서 프로퍼티에 접근 하려고 할 때 매번 다운캐스팅을 해줘야해서 클래스 바꿔야 하나 고민됩니다.
- S021 : 처음에 팩토리패턴할 때 프로토콜 밑에 그걸 채택하는 세부 구현이 있다고 알고있어서 무조건 프로토콜을 써야겠다고 생각했습니다. 그러다보니 프로토콜-사각형(프로토콜 채택)-이미지(사각형 상속)의 구조가 되었습니다. 막상 구현해보니 겹치는게 많아서 이게 맞나 싶은 생각이 들었습니다.
-> 추가로 프로토콜을 사용했으니까 또 프로토콜을 채택하는 방법을 사용해보는게 어떻냐는 리뷰어의 의견이 있었습니다.
- S030 : 상속으로 구현했어요. 메서드를 다형성으로 사용하는 것 때문에 상속이 더 낫다고 생가했습니다.
- S044 : 사각형의 프레임에 담을 수 있는 객체를 `Recatngle`로 선언하였고, 배경색이 있는 `ColoredRectangle`과 `Photo`가 `Rectangle`을 상속받도록 하였습니다.
- S045 : 상속을 사용했습니다. 세 번 정도 바꿨습니다.. `extension`에서는 사용하는 변수들이 모두 선언되어 있어야 해서 불필요한 코드들이 생기는 것 같아서 클래스를 사용했습니다.
- S046 : 저는 프로토콜을 사용했습니다.
- S051 : 저는 클래스를 사용했습니다!
</br>
### 팩토리패턴 적용 방법
- S005, S021 : 프로토콜을 두 개를 사용해서 하나는 만들 때, 하나는 만들어 줄 때 사용하도록 했습니다. `enum`으로 타입을 넘겨주고 인스턴스는 팩토리 안에서 만들어지도록 했습니다.
- S030 : 저는 image라는 파라미터를 만들어서 파라미터가 전달되면 image 인스턴스를 주고 아니면 rectangle을 주도록 만들었습니다.
- S044 : 팩토리를 프로토콜로 구현하도록 하는게 더 좋지 않을 까라는 생각을 했습니다. 사각형에 대한, 사진에 대한 구현부를 따로 만들어두는게 좋지 않을까 생각했습니다.
- S045, S051 : 사각형, 사진 뿐만 아니라 랜덤한 값을 가지는 인스턴스들도 팩토리를 통해 만들어주도록 했습니다.
- S046 : 구현 자체는 어렵지 않은데 왜 사용할까라는 의문이 들었습니다. 상속을 다루기 위한 패턴이 아닐까라는 생각을 했습니다.
</br>
### 옵저버 패턴
#### 느슨한 연결의 장점
- S044 : 모델과 컨트롤러의 직접적인 참조를 예방할 수 있습니다.
- S051 : 뷰가 많아지면 직접 다 전달하지 않아도 돼서 편합니다.
#### object? userInfo?
- S005, S051 : `object`는 어디서 오는지를 확인하는 용도라고 생각해서 `userInfo`를 통하여 보냈습니다.
- S051 : 같은 NotificationName을 사용하는 여러 객체가 있을 때 특정한 객체에서 보내는 Noti만 받으려면 `object`를 사용하면 될 것 같습니다.
- S018, S021, S044, S030 : 저는 `object`만 사용했는데 `userInfo`는 어떻게 사용하셨나용?
- S045 : `object`로 보내면 key를 사용하지 않아서 안정적이다 라는 말을 보았습니다.. 저는 `object`를 사용하였습니다.
- S046 : 예전 프로젝트를 진행할 때 `object`는 값을 넘겨줄 때 `userInfo`는 푸시 알림에서 채팅일지 알림일지 구분하는 값을 넘겨줄 때 사용하였습니다.
#### Notification enum? extension?
- S045 : `enum`을 사용하였습니다. Observer가 많아지는 경우 관리가 힘들어지기 때문에 `enum`으로 관리하면 편하다고 합니다.