You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// 나쁨: 중첩 깊어짐
func sendMessage(to peerNumber:Int, text:String)->Bool{lettrimmed= text.trimmingCharacters(in:.whitespacesAndNewlines)ifvalidateMessage(trimmed){iflet index =conversationIndex(for: peerNumber){ifconversations[index].status ==.active {
// 실제 로직
returntrue}}}returnfalse}
// 좋음: guard로 조기 반환
func sendMessage(to peerNumber:Int, text:String)->Bool{lettrimmed= text.trimmingCharacters(in:.whitespacesAndNewlines)guardvalidateMessage(trimmed)else{returnfalse}guardlet index =conversationIndex(for: peerNumber),conversations[index].status ==.active
else{returnfalse}
// 실제 로직
returntrue}
Result 타입 (복잡한 에러 처리 시):
enumSendError:Error{case invalidMessage
case conversationNotFound
case peerDisconnected
}func sendMessage(to peerNumber:Int, text:String)->Result<DirectMessage,SendError>{guardvalidateMessage(text)else{return.failure(.invalidMessage)}guardlet index =conversationIndex(for: peerNumber)else{return.failure(.conversationNotFound)}guardlet peer =findPeer(peerNumber)else{return.failure(.peerDisconnected)}letmessage=DirectMessage(...)return.success(message)}
# 나쁨: 여러 변경이 한 커밋에
git commit -m "feat: #21 DM 기능 구현 및 코드 정리"# 좋음: 변경 단위로 분리
git commit -m "refactor: #21 payload 생성 헬퍼 함수 추출"
git commit -m "feat: #21 DM 요청 수락/거절 기능 구현"
git commit -m "fix: #21 읽음 처리 누락 버그 수정"
UI/UX 가이드라인
디자인 시스템
Color.background // 앱 배경 (다크)
Color.main // 메인 컬러 (액센트)
Color.flat // 카드/입력창 배경
수치
요소
값
카드 cornerRadius
12
버튼 cornerRadius
10
기본 padding
20 (horizontal), 14 (vertical)
그리드 spacing
12
토스트
위치: 상단 (top: 60)
스타일: Capsule, 검정 배경 80%
지속 시간: 2초
애니메이션: top에서 slide + fade
폰트
.font(.system(size:28, weight:.semibold)) // 헤더 타이틀
.font(.system(size:18, weight:.semibold)) // 서브 타이틀
.font(.system(size:16, weight:.medium)) // 본문
.font(.system(size:14, weight:.regular)) // 보조 텍스트
.font(.system(size:12, weight:.regular)) // 캡션
공용 컴포넌트
MessageInputBar: 메시지 입력창 (Public, Direct 공용)
DMRequestSheet: DM 요청 시트 (Home, Public 공용)
ToastModifier: 토스트 메시지 표시
기능 명세
진입 (EntryView)
랜덤 번호 할당 (#1 ~ #100)
입장 전에도 주변 유저 수 표시
"입장하기" 버튼으로 세션 시작
홈 (HomeView)
3열 그리드로 주변 피어 표시
본인은 상단 좌측에 항상 표시
피어 탭 → DM 요청 시트
활성 대화 중이면 "이미 대화 중인 유저입니다" 토스트
공개 채팅 (PublicChatView)
역순 스크롤 (최신 메시지가 하단)
발신자 칩 탭 → DM 요청 시트
알림 토글 버튼 (bell / bell.slash)
새 메시지 버튼 (스크롤 위치 추적)
1:1 대화 (DirectChatView)
세 섹션: 메시지 요청, 대화, 보낸 요청
카드형 UI (cornerRadius, shadow)
Swipe actions: 나가기
대화방 진입 시 읽음 처리
1:1 채팅방 (DirectRoomView)
상대방 진화 단계 실시간 반영
닉네임 편집 시트
나가기 확인 Alert
키보드 연동 레이아웃
메시지 요청 흐름
요청 전송 (첫 메시지는 선택)
상대방 수락/거절 (햅틱 피드백)
수락 → active 상태로 전환
거절/나간 대화 → 재요청 가능
진화 시스템
단계
이모지
시간
egg
🥚
0초
hatch
🐣
60초
chick
🐥
180초
bird
🕊️
540초
P2P 통신
Info.plist 필수 설정
<key>NSBonjourServices</key>
<array>
<string>_nesty-chat._tcp</string>
<string>_nesty-chat._udp</string>
</array>
<key>NSLocalNetworkUsageDescription</key>
<string>주변 사용자와 연결하기 위해 로컬 네트워크 접근이 필요합니다.</string>
메시지 타입 (P2PPayload.MessageType)
publicMessage: 공개 채팅 메시지
dmRequest: DM 요청
dmRequestAccept: DM 요청 수락
dmRequestDecline: DM 요청 거절
directMessage: 1:1 메시지
dmReadReceipt: 읽음 확인
dmLeave: 대화방 나가기
peerInfo: 피어 정보 교환
stageUpdate: 진화 단계 업데이트
nicknameUpdate: 닉네임 업데이트
Git 컨벤션
커밋 메시지 구조
type: #<issue_number> <subject>
<body (optional)>
커밋 타입
Type
Description
add
리소스 추가 (라이브러리, 컬러, 폰트, 이미지)
feat
새로운 기능 구현
fix
버그 수정
docs
문서 업데이트
style
코드 포맷팅 (로직 변경 없음)
design
UI/UX 디자인 변경
refactor
코드 리팩토링 (기능 변경 없음)
test
테스트 추가 또는 업데이트
chore
빌드 프로세스, 패키지 설정, 환경 구성
rename
파일 또는 폴더 이름 변경
remove
파일 또는 폴더 삭제
Subject 규칙
최대 50자
한글로 작성
이슈 번호 포함 (#)
마침표 없음
명확하고 간결하게
Body 규칙 (선택)
한글로 작성
무엇을, 어떻게, 왜 설명
Subject와 Body 사이 빈 줄
예시
# Body 없이
feat: #24 LoginView UI 구현# Body 포함
feat: #24 로그인 UI 구현
로그인 화면의 초기 UI를 구성하면서 도메인과 프레젠테이션 계층을
명확히 분리한 클린 아키텍처 기반 구조를 도입했습니다.