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

🧠 EmotionCategoryCell 완전 이해하기

by 밤새는 탐험가89 2025. 12. 8.
728x90
SMALL

1️⃣ 이 셀의 목표는 뭐야?

우리가 만들고 싶은 셀은 이렇게 생겼어:

✔ 기본 상태(접힘) — "대분류 감정 보기"

😀 행복

 

✔ 펼쳐진 상태 — "소분류 보기"

# 너무 좋아요  
# 가슴이 설레요  
# 신나요  
...

 

즉,

  • 처음에는 이모지 + 감정 이름(대분류) 만 보이고
  • 셀을 누르면 대분류는 사라지고, 소분류 버튼 리스트가 보이도록 만들고 싶었던 거야.

이걸 위해서 한 개의 UI가 아니라 두 개의 UI 공간을 만든 것이 핵심이야.

 

2️⃣ 왜 baseContainer / subContainer 가 필요한가?

처음 코드는 이렇게 되어 있었어:

  • baseContainer: 이모지 + 감정 이름
  • subEmotionStack: 소분류 버튼들

문제는 baseContainer에다가 subEmotionStack까지 넣으려고 하면서 문제가 터졌어.

⚠️ 문제 발생 이유 — AutoLayout 충돌

baseContainer는
height == 120 같은 구체적인 높이 제약이 있었고,

subEmotionStack은 버튼이 많아질수록
height > 200, height > 300 … 이렇게 커지려 했어.

둘이 같은 parent 안에서 서로 높이가 싸우니까 이런 에러가 터진 거야:

Unable to simultaneously satisfy constraints.
UIView.height == 120
UIView.height == 184

 

즉,

  • baseContainer는 “나 120이어야 해!”
  • subEmotionStack은 “나는 컨텐츠가 많아서 184여야 해!”

서로 말이 안 맞아서 충돌🤯이 나온 거지.

 

3️⃣ 그래서 해결책은?

👉 “두 UI를 같은 뷰에 넣지 말자.”

그래서 우리는 구조를 이렇게 바꿨다:

contentView
 ├─ baseContainer (대분류)
 └─ subContainer (여기에 subEmotionStack 포함)

 

그리고:

  • 접힌 상태 → baseContainer 보임, subContainer 숨김
  • 펼친 상태 → baseContainer 숨김, subContainer 보임

이렇게 두 개를 서로 토글(알파값 0 ↔ 1) 하면 제약 충돌이 완전히 사라짐!

왜냐하면:

  • baseContainer는 고정 높이를 갖고 있을 필요도 없고,
  • subContainer는 내부 버튼 내용 만큼 자연스럽게 늘어남
  • 둘은 서로 간섭하지 않음

이 구조가 아주 중요한 핵심이야.

 

4️⃣ 실제로는 어떻게 숨기고 보여줄까?

정답은 alpha(투명도) 를 이용하는 것!

baseContainer.alpha = expanded ? 0 : 1
subContainer.alpha = expanded ? 1 : 0
 

즉,

  • expanded == false → baseContainer 보임, subContainer 숨김
  • expanded == true → baseContainer 숨김, subContainer 보임

그러면 뷰는 겹쳐있지만 하나는 보이고 하나는 안 보이니까 UI가 자연스럽게 바뀌는 것처럼 보임.

 

5️⃣ 애니메이션은 어떤 역할을 해?

우리가 넣은 애니메이션은 이것:

UIView.animate(withDuration: 0.25) {
    self.layoutIfNeeded()
}

 

  • alpha 값 변경 → 부드럽게 fade-in / fade-out
  • layoutIfNeeded() → subContainer가 커지거나 줄어드는 걸 자연스럽게 애니메이션 처리

이 두 개가 합쳐져서
**“아래로 펼치는 느낌”**이 나게 되는 거야.

애니메이션 없으면 딱딱하게 “딱!” 하고 바뀌기 때문에 UI가 예쁘지 않지.

 

6️⃣ 그런데, 애니메이션을 셀 내부에서 하는 게 맞을까?

사실 100% 정답은 상황에 따라 달라.

지금 방식 (셀 내부에서 애니메이션)

  • 장점: 셀 자체가 알아서 부드럽게 바뀜
  • 단점: 컬렉션뷰 전체 레이아웃이 변경되는 상황에서는 조금 불안정할 수 있음
    (특히 compositional layout + estimated height 조합)

더 안전한 방식 (EmotionStepCell → performBatchUpdates)

EmotionStepCell에서 이렇게 하는 방식:

collectionView.performBatchUpdates(nil)

 

이 방식의 장점:

  • 레이아웃 엔진이 전체 셀의 높이 변화를 고려하고 처리
  • 셀의 height 변화에 아주 안전함
  • 의도치 않은 레이아웃 충돌 방지

그래서 실제로는

🔥 “layoutIfNeeded()는 셀 내부에서 하는 대신, 펼치기/접기 액션은 상위에서 batchUpdates로 처리하는 방식이 더 안정적이다.”

라고 말할 수 있어.

 

728x90
LIST