🗓️ 오늘 하루 일정
✅ 오전
- 09:00 ~ 11:30 : Craft UI 연결 & 프리뷰 슬롯 NRE 수정(countText 널 가드, 버튼/아이콘 점검)
- 11:30 ~ 12:00 : NPC 대화 타이핑 마무리 점검(스킵/완료 분기)
🍽️ 점심시간
- 13:00 ~ 14:00 : 점심
✅ 오후
- 14:00 ~ 16:00 : 브랜치 머지 정리 및 프리팹/인스펙터 재바인딩 확인
- 16:00 ~ 17:30 : 가공 제한사항(wip) 구현 & 단위 테스트
- 17:30 ~ 18:00 : 버그리스트/체크리스트 업데이트
🍽️ 저녁시간
- 18:00 ~ 19:00 : 저녁
✅ 저녁
- 19:00 ~ 20:00 : 전체 스크립트 검토(전반 구조/의존성 확인)
- 20:00 ~ 21:00 : 팀 회의
✅ 오늘 학습 키워드
- 인벤토리 → 가공(Craft) 1:1 변환 플로우
- Craft UI 미리보기(입력/출력 슬롯)
- NullReferenceException 대응(널 가드, 인스펙터 바인딩)
- NPC 대화 타이핑 효과(스킵/완료 분기)
- 프리팹/인스펙터 재바인딩, 브랜치 머지 전략
✅ 오늘 학습 한 내용을 나만의 언어로 정리하기
- 가공은 “미리보기 → 확정 → 코루틴” 3단 분리가 안정적이다. UI는 미리보기 전용, Mediator는 흐름 제어, CraftSystem은 실제 처리만 맡긴다.
- NRE는 대부분 ‘참조 누락’ + ‘가드 없음’ 조합에서 난다. UI 계층은 필수로 널 가드를 두고, 프리팹/인스펙터 바인딩을 체크리스트로 관리해야 한다.
- 대화 타이핑은 “타이핑 중 스킵 시 전체 출력, 완료 후 다음 액션/선택지 노출”로 UX가 일관된다.
- 머지 이후에는 프리팹/인스펙터 재바인딩 시간이 반드시 필요하다. 코드는 합쳐도 레퍼런스는 자동으로 합쳐지지 않는다.
🧩 학습하며 겪었던 문제점 & 에러
1. 가공 미리보기에서 NRE 발생
- 문제정의: CraftUI의 슬롯 프리뷰에서 InventorySlotUI.Bind 호출 시 countText가 없는 프리뷰 슬롯에서 NRE 발생.
- 시도: 아이콘만 쓰는 프리뷰임에도 기존 슬롯 스크립트를 그대로 사용.
- 해결 방법: countText와 button에 널 가드 추가.
// InventorySlotUI.cs (핵심만)
public void Bind(InventorySlotData slotData)
{
icon.sprite = slotData.itemData.icon; // 프리뷰는 보통 count=1
if (countText)
countText.text = slotData.count > 1 ? slotData.count.ToString() : "";
if (button)
{
button.onClick.RemoveAllListeners();
button.onClick.AddListener(() => onClick?.Invoke());
}
}
- 새롭게 알게 된 점: 프리뷰 슬롯처럼 ‘부분 UI’만 쓰는 케이스가 존재하므로 공용 슬롯 스크립트는 부분 필드 널 가드가 필수.
- 다시 만나게 된다면: Bind()를 세분화(BindIconOnly, BindFull)하거나 슬롯 타입(Enum)로 분기해서 UI 의도를 명시한다.
2. Craft UI에서 출력 아이템 미리보기가 안 뜸
- 문제정의: 가공 UI는 열리지만 우측(결과) 슬롯이 빈 상태.
- 시도: OpenWith(input, recipe)에서 입력 바인딩만 확인.
- 해결 방법: outputSlot.SetActive(true/false)를 분기하고, 레시피가 없을 땐 버튼 비활성화.
// CraftUI.cs (핵심만)
public void OpenWith(ItemData input, RecipeData rcp)
{
inputSlot.gameObject.SetActive(true);
inputSlot.Bind(new InventorySlotData { itemData = input, count = 1 });
if (rcp != null)
{
var outItem = TestManager.Instance.itemDatabase.GetItemById(rcp.outputItemId);
outputSlot.gameObject.SetActive(true);
outputSlot.Bind(new InventorySlotData { itemData = outItem, count = 1 });
processButton.interactable = true;
}
else
{
outputSlot.gameObject.SetActive(false);
processButton.interactable = false;
}
Open();
}
- 새롭게 알게 된 점: **UI 가시성 제어(SetActive)**와 상태 버튼 인터랙션은 동시에 관리해야 사용자가 혼란스럽지 않다.
- 다시 만나게 된다면: 이름/설명 텍스트까지 함께 갱신하고, 레시피가 없을 때 안내 메시지 표시.
3. 가공 버튼이 바로 코루틴을 실행(가공창 무시)
- 문제정의: InventoryMediator.HandleCraft()에서 과거 로직이 남아 있어 CraftUI를 건너뛰고 즉시 CraftCoroutine을 실행.
- 시도: Mediator 내 Handler 정리.
- 해결 방법: “가공 버튼 → CraftUI.OpenWith → CraftUI.OnProcess → 코루틴” 흐름으로 단일화.
// InventoryMediator.cs (핵심 흐름)
private void HandleCraft()
{
if (selectedId == null) return;
var recipe = manager.CraftSystem().GetTransformRecipe(selectedId.Value);
if (recipe == null) return;
var itemData = manager.GetItemDataById(selectedId.Value);
craftUI.OpenWith(itemData, recipe); // 미리보기 먼저
}
private void HandleProcessConfirmed(ItemData input, RecipeData recipe)
{
StartCoroutine(manager.CraftSystem().CraftCoroutine(recipe));
craftUI.Close();
}
- 새롭게 알게 된 점: UI/로직 책임을 분리하면 디버깅이 쉬워지고, UX도 분명해진다.
- 다시 만나게 된다면: Handler에 “즉시 실행” 코드가 다시 섞이지 않도록 테스트 케이스와 코드 리뷰 체크리스트에 항목을 추가한다.
📝 메모
오늘은 UI와 로직의 경계를 다시 세우는 하루였다. 생각보다 작은 널 가드 하나가 전체 흐름을 막기도 한다는 걸 또 체감했다. 모르는 걸 부끄러워하지 말자. 천천히, 정확하게. 팀 회의에서 정리한 기준을 내일 커밋에도 유지하자. 끝은 언제나 정돈이다.
'스파르타 코딩클럽 > TIL작성' 카테고리의 다른 글
| 내일배움캠프 39일차 TIL [3D_Survival_Project] (0) | 2025.08.22 |
|---|---|
| 내일배움캠프 38일차 TIL [3D_Survival_Project] (0) | 2025.08.21 |
| 내일배움캠프 36일차 TIL [3D_Survival_Project] (0) | 2025.08.19 |
| 내일배움캠프 35일차 TIL [3D_Survival_Project] (1) | 2025.08.18 |
| 내일배움캠프 34일차 TIL [NPC&UI 다이어그램] (1) | 2025.08.14 |


