본문 바로가기
iOS/개인 출시 프로젝트

첫 개인 출시 프로젝트 회고록...

by iOS rOar 2022. 10. 4.

이번 개인 출시프로젝트를 하면서 아쉬웠던 부분과 어려웠던 부분들

 

그리고 알게된 것들 개발하면서 발생한 이슈들을 어떤식으로 처리하였는지 회고록을 작성해보자..!!

 

1. 처음부터 쉽지않다.....(기획 / 디자인)

우선 가장 처음 마주한 문제점.. 나는 한번도 앱다운 앱을 만들어 본적이 없는데, 개발을 하는것도 어려운데!!!

기획부터 해야한다.. + 디자인..

지금도 사실 볼품없는 디자인 이지만, 음.... 뭐랄까... 쉽지가 않네.

처음 기획의 시작은 내가 관심있는 분야에서 찾아보기로 했다..

신발을 좋아해서 뭔가 신발에 관련된것을 만들어볼까? 뭐하지? 찾아보다가

개인이 그리고 현재의 나로썬 너무 구현하기 어려운 부분..이라패스!!!

그럼 옷으로 시선을 돌려보자.. 나는 내일 뭐입지? 오늘 뭐입지? 하면서 고민하는 시간들이 생각보다 귀찮고 번거로웠다..

그리고 막상 내가 자주입는 옷들만 자꾸 입게되는데, 뭔가 새로운 스타일링을 하고싶다고 하면 옷들을 입고 벗고 이 반복과정이 너무 귀찮다는 생각이 들었다.. 그래서 기획하게 된것이 내가 옷을 입어보지 않아도 간단하게 이런식의 스타일을 하면 어떤 느낌이 나고, 색감은 잘 맞는지 등 내 몸을 움직이지 않고도 할 수 있으면 편하겠다... 라는 귀차니즘에서 기획된 앱이라고 볼 수 있다. ㅎㅎㅎㅎ

 

하지만... 기획을 해서 멘토님들께 피드백을 받았을때, 내가 래퍼런스로 하는 앱의 기능을 넣으려면 기간내에 구현이 힘들것 같다는 답변을 받았다..😭 너무 욕심을 부린걸까^^..

그렇다면 기능을 다른식으로 바꾸고 조금더 심플하게 가보자.. 해서.. 최종 픽스된 기획은

 

1. 날씨태그를 이용하여 아이템이나 스타일을 등록할때 사용자가 선택한 날씨 태그를 기반으로 현재 위치기반 정보에 맞는 날씨에 따른 어떤 아이템이 있고, 어떤 스타일링을 했었는지 등을 한눈에 볼 수 있는 기능.

 

2. 아이템 등록시 큰 카테고리 태그별로 구분하여 정렬해서 볼 수 있는 기능. (ex. 아우터, 상의, 하의 등..)

 

3. 다이어리 작성시 현재 입은 착장 사진을 추가하며, 등록해둔 아이템들을 선택하여 내가 어떤 옷들로 이 스타일링을 했는지.. 추가하는 기능.(다이어리 작성시에 선택된 아이템들은 착용횟수가 올라감)

 

4. 카테고리별로 차지하는 비율을 알 수 있는 기능. (어떤 카테고리의 아이템이 모자란지 알면, 소비방향을 잡을 수 있다고 생각함)

 

5. 다이어리를 작성한것을 기준으로 최근 1주일 동안의 스타일을 한번에 볼 수 있음. (같은 스타일 입는거 지겨우니까~🥲) 

 

대략적으로 요런 기능들이 들어있다.!!

2. 공수기간 그게 뭔데...?

우선 기획해놓은 와이어 프레임을 가지고 UI와 화면전환을 가장 먼저 하기로 했다.

화면 구성을 하는데에 큰 어려움이 있을거란 생각을 못해서 화면구성과 화면전환을 포함하여 이틀(20H)정도의 공수를 산정했다.

(사실 이것도 여유롭게 잡았다고 생각했음..) 굉장한 자만이었다고 한다...

하지만 지금까지 이렇게 많은 뷰들과 화면전환이 동반되는 앱을 만들어 본 적이 없기때문에 생각보다 막히는 부분들이 많았고, 기능들을 생각하다 보니 이게 맞을까? 여기서 이렇게 들어가면 불편할것 같은데? 부터 시작해서 네비바를 달아야할까 말아야할까 생각이 많아졌다.. 그리고 와이어 프레임을 잡으면서 생각하지 못했던 재활용되는 뷰들을 조금 디테일하게 생각하지 못해서 고민이 많이 생긴것 같다.

결국은 1.5배 정도의 시간이 들어가게 되었다.. (약 3일정도는 작업한것 같음...)

기획단계에서 더더욱 디테일하게 짜두어야 공수기간을 산정한 일정에 맞게 구현을 할 수 있겠구나.. 라는것을 느끼게 되었다.

 

어쨌든.. 최종 마무리를 생각했던 기간까지 큰 틀에 있어서 구현은 마쳤지만, 조금 더 디테일한 기획으로 많은 시간을 단축시킬 수 있겠다! 라는것이 포인트 였던것 같다.

 

3. 개발의 시작...

1. Realm 설계

나도 디자인에 욕심을 내고 싶었지만, 생각보다 기획해둔 기능들을 구현하려면 시간이 촉박할것 같아서 기능에 초점을 맞추기로 하였다.

(큰 틀의 기능을 마무리하고 시간이 남는다면 UI를 조금 더 손보자.. 라는 마인드로)

앱의 기능을 구현하기 위해서 가장 먼저 해야 할 것은 Realm Table 구조를 설계하는 것이었다..

일단 아이템이 등록이 되어야 다른 기능들도 구현 할 수 있는 기능들 이었기 때문에..

최대한 배운 내용들을 기반으로 확장성들을 고려하다 보니 내가 생각하기에 가장 좋은 구조는 이런 방식이 될 것 같았다.

멘토님들께서 꼭 계절과 카테고리 태그를 테이블로 구성할 필요가 있는지에 대해 생각해보라고 조언을 해주셨고,

긴 토론끝에 처음 구성한대로 4개의 테이블을 가지고 구성을 하기로 하였다.

 

지금까지 Realm을 사용해본것은 하나의 테이블 구조에서 CRUD였지만, 테이블 구조를 보게되면 서로 얽히고 섥혀서 지지고 볶고 난리다.(제 기준🤣)

그래서 처음으로 List라는 Realm에서 제공해주는 배열도 공부를 해보게 되었고, PK와 FK에 대한 개념도 제대로 익히고 넘어 갈 수 있었다.

PK와 FK는 상대적인 개념이며 각각의 테이블에는 PK값이 존재해야 하고, 각 테이블에서 PK값으로 쓰이는것이 다른 테이블에 들어가게 되면 FK가 된다는 것을 알게 되었다.

 

2. Realm 사용하기

결과적으로 프로젝트에 Realm모델은 이런식으로 구성하게 되었다.

업데이트를 하는 방향에 있어서 확장성이 더 좋은 방향이 있겠지만, 우선은? 최선이라는 생각..!!

그리고 Season과 Category는 아이템이나 다이어리를 생성할때 선택을 하는 태그이기 때문에, 앱의 첫 실행에만 레코드가 생성되도록 구성을 해두었다.

UserDefaults의 Bool타입은 초기에 생성을 해주지 않더라도 디폴트 값이 false로 되어있어서 set false로 지정해주지 않아도 된다는것도 알게되었다.

 

개발에 들어가고 나서 2주간은 거의 Realm과의 싸움을 했다..

가장 처음 막힌 부분은 아이템을 생성할때 태그를 선택하고 저장이나 백버튼으로 화면을 벗어난 후 다시 생성화면에 들어왔을때 태그들이 선택된 상태 그대로 유지가 되어버리는 상황이었다.

내가 가장 먼저 생각한 방법은 뷰가 사라지는 시점에서 모든 태그들을 이니셜라이저 해주는 방법이었다.

사실 좋은 코드는 아니라는 생각이 들지만(태그 자체가 많은것은 아니라서 모두다 돌면서 false로 셋팅해주는것이 크게 비효율이진 않기 떄문에), 이렇게 초기화를 시켜주는 함수를 만들어서 viewWillAppear와 viewDidDisappear에서 init을 시켜주었다.

✅ 사실 여기서 지금 해결하지 못한 문제점이 하나 있는데, 태그를 먼저 선택하고 카메라 버튼을 눌러서 사진을 찍고 돌아오면 태그를 다시 선택해버려야 하는 번거로움이 생기게 되었다. 업데이트시에 조금 더 고민해보고 좋은 방법을 찾아보려고 한다.⭐️

(지금 내 지식에서는 기발한 방법이 떠오르진 않지만...)

 

두번째로 막힌부분은 List타입으로 선언해둔 프로퍼티에 값을 넣어주는것...

계절과 카테고리 태그에서 선택된 태그만 아이템 테이블의 List타입 컬럼에 넣어주는 함수이다.

여기서 꽤나 시간을 많이 보내기도 했다.

값을 넣어주려고 하니까 계속 타입이 맞지않는대..... 나한테 왜그래.. 예민하다 이 녀석.

그래서 최종적으론 이런식으로 태그들중 선택된 아이템의 배열만 받아서 위에 선언해둔 함수에 넣어주는 방식.

음....뭐..... 나름.... 나쁘지 않은것 같아..라고 위안을 삼고 비로소 아이템을 저장할 수 있게 되었다고 한다..

 

그리고 다이어리 생성인데, 조금 다르긴 하지만 비슷한 구조여서 조금의 삽질을 하고나서 문제를 해결 할 수 있었다.

다이어리 생성시 선택한 아이템들의 objectId(PK)가 등록된 아이템의 objectId랑 같은지 비교를 해서 필터를 해주는 함수.

대략 이런식으로 마무리를 하였다.

 

그리고 Realm을 사용하면서 또 한가지 많이 공부된 것이 fetch를 하는 것이었는데, (fetch를 시켜주면 didSet구문에서 reload를 해줌.)

아이템 등록 페이지에서 카테고리별 정렬을 하는 기능과 아이템을 등록하는 두가지 페치가 하나의 뷰에서 이루어 져야 하는데, 이전까지 계속 viewWillAppear시점에서 한가지 방식으로 fetch를 해서 같은 데이터 나열 기준으로 정렬이 되었다.

하지만 이렇게 되면 다른 두개의 뷰에서 이루어지는 fetch에 따른 reload가 불가능해서 이곳에서 클로저를 활용한 fetch를 사용하게 되었다. 코드가 정말 거지같지만...

⭐️ 처음엔 정방향 직접적인 데이터를 전달하듯이 역으로 직접적인 프로퍼티를 통한 값전달을 하려고 했는데,

역방향 전달시에는 이미 깔린 뷰객체가 생성이 되어있어서, 인스턴스를 생성해서 전달하면 메모리 주소값이 달라서 안된다는 것을 알게되었다.⭐️

대략 이런느낌?.. 이 부분도 리펙토링과 폴더링을 다시 하면서 코드를 조금 깔끔하게 정리를 해보고싶다.

 

3. UIBezierPath 복병

데이터 전달을 대부분 끝내고 막바지에 마주하게 된 차트 그리기..

사실 생각보다 큰 틀의 기능 구현이 앞당겨져서 끝나서 Charts라이브러리로 구현하려고 했던 옷장 비율을 하나라도 더 공부해보자 라는 마음가짐으로 UIBezierPath로 그리기로 했다.

 

아.. 이 녀석 나에게 굉장히 어려움을 선사해주었다.

사실 UIBezierPath 자체를 그냥 그리는것은 크게 어렵지가 않았다.

응 어려워... 올림픽 당구장 굴렁쇠...

 

이렇게 저렇게 문제점이 뭘까 대체 왜 그려지는데 스택뷰에 넣었는데 너네 말을안들어..?

내가 문제라고 생각한 부분은 커스텀한 UIView와 BezierPath의 인스턴스 생성 시점에서의 시점차이??라는 생각이 들었다.

그래서 처음에 고정값으로 주던 radius를 UIView의 크기에 맞게 그려지도록 비율로 값을 주었고,

비동기를 사용해서 해결할 수 있지 않을까? 해서 이런식으로 해결을 하긴 했다..

좋은 방법인지는 사실 모르겠다. 멘토님들께 조금 더 나은 방향의 조언을 구해보려고 했는데, 깜빡함. ㅎㅎㅎㅎㅎ;;

이 녀석 때문에 이틀동안 삽질을 했다.

 

4. 출시하면 끝난줄 알았지?

출시는 어찌저찌 하였지만, 사실 경험이 많이 없다보니 보는 시각이 좁아서 출시 후 멘토님들께 피드백을 받으면서 여러가지 문제점들을 발견하게 되었다. 나는 어떤 부분에서의 예외처리를 더 디테일하게 해주어야 할까? 생각은 많이 해봤지만 쉽게 찾지를 못했는데..

어.... 음... 결론은 내가 굉장히 수레기처럼 앱을 출시해 버렸다^^.

이 외에도 직접 말씀해주신 부분들이 몇 가지 있는데, 내가 고민하고 있던 부분들도 이런식으로 처리를 해주면 좋지않겠냐며 개선방향을 많이 알려주셨다. 그리고.. 이번에 프로젝트를 하면서 조금 아쉬운 부분은 네트워크 통신이 아직도 미숙한데, 이러한 부분들을 조금 더 다뤄 볼 수 있으면 좋지 않을까 생각이 들었다. 공공데이터 포털에서 데이터를 받아와서 앱을 구현하신 분들은 이번에 되게 경험을 많이 해보셔서 이런저런 고민들을 많이 해보신 것 같았다.

우선 네트워크 통신시에도 여러가지 예외처리를 해야한다는 부분도 피드백을 해주셨고, 이러한 부분들도 업데이트시에 녹여볼까 한다.

그리고 현재 MVC패턴으로 구현되어있는 코드들을 우선 깔끔하게 정리하고, MVVM으로 리펙토링을 해보고자 한다.

 

5. 그 외... 자잘자잘..

그 외의 이슈들은 보통 기기별 사이즈 대응을 할때 레이아웃 문제? 가 있었던 것 같은데,

현재 대응을 해서 해결한 방법들이 올바른 방법인지는 잘 모르겠다.

셀이나 섹션의 높이라던지 조금 더 유동적으로 대응할 수 있는 방법을 공부해 봐야겠다.

 

글을 마치며...

이번에 정말 좋은 경험들도 많이 하게 된 것 같고, 학습을 하면서 문제를 해결해 나가는 과정이 재밌었다.

또한, 개발일지를 작성하는것이 굉장히 중요하다는 것도 느끼게 되었다.

내가 어떤 이슈들이 있었고, 어떤식으로 해결을 했는지 간단하게라도 적어두면 다시 봤을때 기억이 잘 나는것 같다.

지금은 출시 회고록 이지만, 업데이트를 하면서 해결하게 되는 이슈들도 정리를 하면서 학습을 하도록 해야겠다!!!

 

https://apps.apple.com/kr/app/%EC%98%A4%EB%8A%98%EB%AD%90%EC%9E%85%EC%A7%80/id1645004644