Firebase 연동을 위한 iOS UI 구현하기: 게시글 작성과 상세보기 화면 구현

호씨·2025년 1월 22일
0

Firebase 연동을 위한 iOS UI 구현하기: 게시글 작성과 상세보기 화면 구현 📱

소개 💡

이번 포스팅에서는 프로젝트 모집/참여 플랫폼의 핵심 기능인 게시글 작성과 상세보기 화면을 구현하는 방법을 정리했다. UIKit과 SnapKit을 사용하여 구현했고, 추후 Firebase 연동을 위한 테스트 용도로 제작했다.

기술 스택 및 개발 환경 🛠

  • iOS: 16.6 이상
  • Xcode: 15.0
  • Swift: 5.9

라이브러리

  • SnapKit: UI 레이아웃 구현
  • Firebase (추후 연동 예정)

1. 게시글 작성 화면 (TestPostUploadVC) 📝

1.1 화면 구성 요소

상단 헤더: "게시글 구분"

  • 선택 가능한 태그 버튼들
    • 구인/구직 선택
    • 직무 선택 (개발, 기획, 디자인 등)
    • 기술 스택
    • 시급성
    • 아이디어 상황
    • 상황 (온라인/오프라인)
    • 경험

입력 필드

  • 경험 설명 텍스트뷰
  • 제목 입력 필드
  • 상세 내용 텍스트뷰
  • 하단 게시글 작성 버튼

1.2 데이터 모델

// 선택된 데이터를 저장하기 위한 속성들
private var selectedPositionType: String?  // 구인/구직
private var selectedJob: String?           // 직무
private var selectedTechStacks: [String] = []  // 기술 스택 (다중 선택 가능)
private var selectedUrgency: String?       // 시급성
private var selectedIdeaStatus: String?    // 아이디어 상황
private var selectedRecruits: String?      // 모집 인원
private var selectedSituation: String?     // 상황
private var selectedExperience: String?    // 경험

1.3 UI 컴포넌트 구현

ScrollView 설정

private let scrollView: UIScrollView = {
    let scrollView = UIScrollView()
    scrollView.backgroundColor = UIColor(red: 1.0, green: 0.97, blue: 0.93, alpha: 1.0)
    scrollView.showsVerticalScrollIndicator = true
    return scrollView
}()

private func setupScrollView() {
    view.addSubview(scrollView)
    scrollView.addSubview(contentView)
    
    scrollView.snp.makeConstraints { make in
        make.top.equalTo(view.safeAreaLayoutGuide)
        make.left.right.equalToSuperview()
        make.bottom.equalTo(view.safeAreaLayoutGuide).offset(-70)
    }
    
    contentView.snp.makeConstraints { make in
        make.edges.equalTo(scrollView.contentLayoutGuide)
        make.width.equalTo(scrollView.frameLayoutGuide)
    }
}

태그 버튼 구현

private func createTagButton(title: String, section: String) -> UIButton {
    let button = UIButton()
    button.setTitle(title, for: .normal)
    button.titleLabel?.font = .systemFont(ofSize: 14)
    button.setTitleColor(UIColor(red: 0.98, green: 0.57, blue: 0.24, alpha: 1.0), for: .normal)
    button.backgroundColor = .white
    button.layer.cornerRadius = 15
    button.layer.borderWidth = 1
    button.layer.borderColor = UIColor(red: 0.98, green: 0.57, blue: 0.24, alpha: 1.0).cgColor
    button.contentEdgeInsets = UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16)
    button.accessibilityIdentifier = section
    button.addTarget(self, action: #selector(tagButtonTapped), for: .touchUpInside)
    return button
}

private func createTagStackView(tags: [String], section: String) -> UIStackView {
    let stackView = UIStackView()
    stackView.axis = .horizontal
    stackView.spacing = 8
    stackView.alignment = .fill
    stackView.distribution = .fillProportionally
    
    tags.forEach { tag in
        let button = createTagButton(title: tag, section: section)
        stackView.addArrangedSubview(button)
    }
    
    return stackView
}

1.4 태그 선택 로직

@objc private func tagButtonTapped(_ sender: UIButton) {
    sender.isSelected = !sender.isSelected
    
    if let section = sender.accessibilityIdentifier,
       let title = sender.title(for: .normal) {
        
        switch section {
        case "구인/구직 선택":
            selectedPositionType = sender.isSelected ? title : nil
            deselectOtherButtons(in: sender.superview as! UIStackView, except: sender)
            
        case "직무":
            selectedJob = sender.isSelected ? title : nil
            deselectOtherButtons(in: sender.superview as! UIStackView, except: sender)
            
        case "기술 스택":
            if sender.isSelected {
                selectedTechStacks.append(title)
            } else {
                selectedTechStacks.removeAll { $0 == title }
            }
        }
        
        updateButtonAppearance(sender)
    }
}

2. 게시글 상세보기 화면 (TestPostDetailVC) 🔍

2.1 화면 구성

  • 게시글 제목
  • 상태 태그 (온라인, 경력, 실무 경험)
  • 활동 가능 상태 섹션
    • 가능한 시간
    • 시급성
  • 보유 기술 스택 섹션
  • 프로젝트 목적 섹션
  • 프로젝트 가치관 섹션
  • 하단 신고하기 버튼

2.2 UI 컴포넌트 구현

private func createTagView(text: String) -> UIView {
    let containerView = UIView()
    containerView.backgroundColor = .white
    containerView.layer.cornerRadius = 15
    containerView.layer.borderWidth = 1
    containerView.layer.borderColor = UIColor(red: 0.98, green: 0.57, blue: 0.24, alpha: 1.0).cgColor
    
    let label = UILabel()
    label.text = text
    label.textColor = UIColor(red: 0.98, green: 0.57, blue: 0.24, alpha: 1.0)
    label.font = .systemFont(ofSize: 14)
    
    containerView.addSubview(label)
    label.snp.makeConstraints { make in
        make.center.equalToSuperview()
        make.left.right.equalToSuperview().inset(16)
        make.top.bottom.equalToSuperview().inset(8)
    }
    
    return containerView
}

3. 구현시 주의사항 ⚠️

3.1 스크롤뷰 구현

  • SafeArea를 고려한 제약조건 설정이 필요하다
  • contentLayoutGuide와 frameLayoutGuide를 적절히 활용해야 한다
  • 키보드 등장 시 스크롤뷰 조정이 필요하다

3.2 태그 버튼 상태 관리

  • 단일 선택과 다중 선택 구분이 필요하다
  • 상태 변경 시 시각적 피드백을 제공해야 한다
  • 섹션별로 독립적인 상태 관리가 필요하다

3.3 성능 최적화

  • 메모리 관리
    • 큰 이미지나 리소스는 필요할 때만 로드해야 한다
    • 불필요한 뷰는 재사용해야 한다
    • Strong 참조 순환에 주의해야 한다
  • 레이아웃 최적화
    • 복잡한 제약조건을 최소화해야 한다
    • 중첩된 스택뷰 사용 시 주의해야 한다
    • 오토레이아웃 업데이트를 최소화해야 한다

마무리 🎯

이번 포스팅에서는 Firebase 연동을 위한 UI 구현 방법을 자세히 살펴봤다. 특히 재사용 가능한 컴포넌트 설계와 효율적인 상태 관리에 중점을 뒀다.

다음 포스팅에서는 이렇게 구현한 UI에 Firebase를 연동하여 실제 데이터를 저장하고 불러오는 방법을 다룰 예정이다.

참고 자료

  • UIKit Documentation
  • SnapKit Documentation
  • Human Interface Guidelines
profile
이것저것 많이 해보고싶은 사람

0개의 댓글

관련 채용 정보