라이온하트 iOS 개발자가 된지 2일차!
이틀간 개발한 것들을 정리하고! 기록하고자!! 블로그를 정리해보려 합니다:)
1. 레이아웃 설정 관련

카테고리 컬렉션 뷰를 설계하는 과정에서
처음으로 화면을 기준으로 레이아웃을 잡는 과정을 이해하고 적용했습니다.
기존까지는 Height와 Width를 잡고 기기대응은 전혀 안되는
바보같은 코드를 작성했는데요..
민재형한테 화면에 대한 설명을 듣고 성준이형에게 배운 내용을 전해주며 정확히 저의 것으로 만들 수 있었습니다!

좌우 여백! 그리고 중간 간격을 계산해서 구현을 했습니다.
코드리뷰를 받기 이전에 민재형이 직접 알려준 방식을 적용해보았는데요! 좌우 간격, 그리고 inner 간격에 관한 수를 직접 입력하는 하드 코드 방식이 아닌! enum 선언을 통해 개발자 친화적인?? 코드를 작성했습니다.
//
// ArticleCategoryViewController.swift
// LionHeart-iOS
//
// Created by uiskim on 2023/07/09.
// Copyright (c) 2023 ArticleCategory. All rights reserved.
//
import UIKit
import SnapKit
final class ArticleCategoryViewController: UIViewController {
private enum Size {
static let cellOffset: CGFloat = 51
static let numberOfCellsinRow: CGFloat = 2
static let imageWidth: CGFloat = 162
static let imageHeight: CGFloat = 112
}
private lazy var navigationBar = LHNavigationBarView(type: .explore, viewController: self)
private var dummyCase = CategoryImage.dummy() {
didSet {
self.categoryArticleCollectionView.reloadData()
}
}
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.text = "카테고리별\n아티클 모아보기"
label.numberOfLines = 2
label.font = .pretendard(.head2)
label.textColor = .designSystem(.white)
return label
}()
private lazy var subtitleLabel: UILabel = {
let label = UILabel()
label.text = "똑똑한 아빠들의 비밀 습관"
label.font = .pretendard(.body3R)
label.textColor = .designSystem(.gray400)
return label
}()
private lazy var categoryArticleCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.backgroundColor = .designSystem(.background)
collectionView.showsVerticalScrollIndicator = false
return collectionView
}()
public override func viewDidLoad() {
super.viewDidLoad()
// MARK: - 컴포넌트 설정
setUI()
setNavigation()
// MARK: - addsubView
setHierarchy()
// MARK: - autolayout설정
setLayout()
// MARK: - button의 addtarget설정
setAddTarget()
// MARK: - delegate설정
setDelegate()
}
}
private extension ArticleCategoryViewController {
func setUI() {
ArticleCategoryCollectionViewCell.register(to: categoryArticleCollectionView)
view.backgroundColor = .designSystem(.background)
}
func setHierarchy() {
view.addSubviews(titleLabel, navigationBar, titleLabel, subtitleLabel, categoryArticleCollectionView)
}
func setLayout() {
titleLabel.snp.makeConstraints { make in
make.top.equalTo(self.navigationBar.snp.bottom).offset(28)
make.leading.equalToSuperview().inset(20)
}
navigationBar.snp.makeConstraints { make in
make.top.equalTo(view.safeAreaLayoutGuide)
make.leading.trailing.equalToSuperview()
}
titleLabel.snp.makeConstraints { make in
make.top.equalTo(navigationBar.snp.bottom).offset(28)
make.leading.equalToSuperview().inset(20)
}
subtitleLabel.snp.makeConstraints { make in
make.top.equalTo(titleLabel.snp.bottom).offset(10)
make.leading.equalToSuperview().inset(20)
}
categoryArticleCollectionView.snp.makeConstraints { make in
make.top.equalTo(subtitleLabel.snp.bottom).offset(16)
make.leading.trailing.equalToSuperview()
make.bottom.equalTo(view.safeAreaLayoutGuide)
}
}
func setAddTarget() {
}
func setDelegate() {
categoryArticleCollectionView.delegate = self
categoryArticleCollectionView.dataSource = self
}
func setNavigation() {
NavigationBarLayoutManager.add(navigationBar)
}
}
extension ArticleCategoryViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return dummyCase.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = ArticleCategoryCollectionViewCell.dequeueReusableCell(to: collectionView, indexPath: indexPath)
cell.inputData = dummyCase[indexPath.item]
return cell
}
}
extension ArticleCategoryViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 11
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = (Constant.Screen.width - Size.cellOffset) / Size.numberOfCellsinRow
let height = width * (Size.imageHeight/Size.imageWidth)
return CGSize(width: width, height: height)
}
}
2. TableView의 HeaderView

해당 뷰를 설계하며, 테이블뷰의 헤더에 뷰를 넣고 테이블 뷰를 아래에 넣음으로써 깔끔하게 코드를 작성해야겠다고 생각했습니다! 근데 또 뷰컨에 뷰를 띄우는거에 정신팔려서.. 뷰컨에 단순한 뷰 2개를 넣는 실수를 해버렸습니다..
어라? 이렇게 쉽게 될 일이 없는데.. 역시나ㅋㅋ
지난번! 컬렉션 뷰가 스크롤 뷰를 상속하는 점을 깜빡하고 있다가! 반성했던
저의 모습을 떠올리고!!
해당 테이블 뷰에서는 스크롤 뷰를 구현하는 실수를 하지 않았습니다.
처음으로 헤더뷰를 제대로 알고 사용한 느낌이었습니다.
그치만,, 헤더뷰라고 생각했던 것은 헤더뷰컨트롤러였고,,
결국 제자리로 돌아오긴 했지만 헤더뷰를 뷰에 넣는 과정은 역시나 좋았습니다!
이번에 얻은 것은!
1) 헤더뷰는 “뷰”이기때문에 ! 뷰디드로드를 호출할 필요가 없다는 것!

이렇게 호출해주면 ! 완성!!
2) height값을 설정해주어야 제대로 그려진다는 점이었다.

이렇게 해더뷰헤이트를 직접 지정해주면 된다!
//
// ArticleListByCategoryViewController.swift
// LionHeart-iOS
//
// Created by uiskim on 2023/07/09.
// Copyright (c) 2023 ArticleListByCategory. All rights reserved.
//
import UIKit
import SnapKit
final class ArticleListByCategoryViewController: UIViewController {
private lazy var navigationBar = LHNavigationBarView(type: .exploreEachCategory, viewController: self)
private lazy var tableView: UITableView = {
let view = UITableView()
view.backgroundColor = .designSystem(.background)
return view
}()
public override func viewDidLoad() {
super.viewDidLoad()
// MARK: - 컴포넌트 설정
setUI()
// MARK: - addsubView
setHierarchy()
// MARK: - autolayout설정
setLayout()
// MARK: - button의 addtarget설정
setAddTarget()
// MARK: - delegate설정
setDelegate()
tableView.delegate = self
tableView.register(ArticleListByCategoryHeaderTableView.self, forHeaderFooterViewReuseIdentifier: ArticleListByCategoryHeaderTableView.identifier)
tableView.sectionHeaderHeight = 192
}
}
private extension ArticleListByCategoryViewController {
func setUI() {
view.backgroundColor = .designSystem(.background)
}
func setHierarchy() {
view.addSubviews(navigationBar, tableView)
}
func setLayout() {
navigationBar.snp.makeConstraints { make in
make.top.equalTo(view.safeAreaLayoutGuide)
make.leading.trailing.equalToSuperview()
}
tableView.snp.makeConstraints { make in
make.top.equalTo(self.navigationBar.snp.bottom)
make.leading.trailing.bottom.equalToSuperview()
}
}
func setAddTarget() {
}
func setDelegate() {
}
}
extension ArticleListByCategoryViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
guard let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: ArticleListByCategoryHeaderTableView.identifier) as? ArticleListByCategoryHeaderTableView else { return ArticleListByCategoryHeaderTableView() }
return headerView
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 192
}
}
extension ArticleListByCategoryViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = "Row \(indexPath.row)"
return cell
}
}
3. 라벨 패딩

이전에 사용해보았던 코드이지만... 또 만났습니다.
결국 새로운 익스텐션을 만들어 이전의 코드를 재사용했지만! 쉽게 되지 않았습니다..
알고보니 문제는 라벨의 리딩값을 정해주었지만,, trailing 마저 offset(20)을 지정해주어서 무용지물이 된 것이죠?
오늘의 결론 ! 내가 뭘 하는지 알고 코드를 작성하자!!!!
4. 느낀 점!
4-1. 개발은 생각보다 재밌다는 것
안되던 것들이 되는 순간에 느끼는 희열은 정말 최고입니다.
4-2. 개발자의 협업이 무엇인지 느꼈다.
처음으로 코드리뷰를 제대로 활용했고 깃 크라켄을 단순히 푸시하고 끝내는 도구가 아닌, 내가 무엇을 바꿨고, 어느 파일을 올리는 건지 알아야 한다는 찬미 누나의 말을 통해 "내가 뭘 하는 것"이 얼마나 중요한지 다시금 알게되었습니다. 코드를 작성하며 나만 아는 코드가 아닌 그 누가 보아도 이런 의도구나! 할 수 있는 코드가 좋은 코드라는 것을 꺠달았습니다.
4-3. 디자인 시스템의 중요성을 느꼈다.

.designSystem을 누르고 -> .색상 -> .글자체를 선택하면 굳이 하나하나 값을 입력해주지 않아도, 쉽게 코드를 작성하고 깔끔해지는 걸 보아하니. 참으로 좋았습니다.(디자인 팀들의 노력이 있었기에 가능하지 않았나.. 디자인 여진누나, 솔이, 슬기 모두 고마워!!)
역시나 하나의 프로덕트를 만드는데 있어서, 모두가 각자의 역할에서 충실히 최선을 다하는 것의 중요성을 느꼈습니다.