1년 간 개발한 프로젝트 회고

정승훈·2023년 10월 8일
13
post-thumbnail

HI! 👋

나는 대덕소프트웨어마이스터고등학교 취업 관리 시스템 JOBIS 안드로이드 앱 개발을 맡고 있는 2학년 정승훈이고, 약 1년 간 개발해왔던 앱을 얼마 전 배포하면서 그 동안 느낀점을 회고 형식으로 기록하기 위해 글을 써보려 한다.!

팀 소개

https://github.com/Team-return
JOBIS는 Team-return에서 개발하고 있고, 서버 3명, 프론트 3명, 안드 1명, iOS 1명으로 모두 2학년으로 구성되어 있다. 현재 2024년부터 유지보수에 참여할 2기 학생들을 교내 1학년 친구들 대상으로 모집까지 모두 마친 상태다. 그리고 2학년 친구들이 유지보수가 가능할 정도까지 1학년 친구들의 실력을 끌어올리기 위해 일주일에 한 번 다 같이 모여 멘토링을 진행하고 있다.

-> 내가 좋아하는 우리 팀원들 😁

목적

우리 팀은 기존에 수기로 관리되던 모집의뢰서들을 온라인에서 관리하고, 학생, 교사, 기업을 거치는 취업 프로세스를 서비스 하나에서 관리할 수 있도록 기존의 취업 프로세스를 통합하는 것을 목적으로 JOBIS를 개발하게 되었다.

사실 자세한 팀 소개는 여기서 보실 수 있다
https://team-return.notion.site/Team-return-0c0a7ac7c765479fabed003f6adbe5bd?pvs=4

내가 혼자 얘기하는것보단 팀원들하고 다 같이 작성한 팀 소개 페이지가 더 도움이 될 것 같아서 첨부한다.

본론으로 넘어가자

거의 1년 간 개발한 프로젝트를 드디어 배포하게 되었다!!

https://play.google.com/store/apps/details?id=com.jobis.jobis_android

이틀 전 교내 학생들을 대상으로 프로젝트 발표도 진행하였고, 안드로이드, iOS 앱 스토어 링크까지 공유한 결과 약 60명의 사용자도 얻게 되었다. 학교에서 약 1년 6개월 정도를 개발하며 배포를 처음 진행해봤고, 처음 내가 만든 앱에 사용자가 생겼다고 생각하니 너무 뿌듯했다!! 😆

하지만 사용자가 늘었다는 것은 그만큼 앱에서 사용자를 위해 신경 써야 할 부분이 많아졌다는 뜻 이고, 사소한 불편함을 느낄 수 있는 UX 부터 서버 통신 단계에서 발생하는 크고 작은 버그까지... 사용자의 경험을 우선적으로 생각해야할 때가 온 것 같다.. 그래서 도달한 결론은...

사용자가 느낄 수 있는 불편함을 최소화 시키자!

뭘 할 수 있지??...

솔직히 말하면 나는 약 2개월 전부터 앱은 더 이상 손댈 것이 없다고 생각했다. 내 기준 모든 기능들도 다 정상적으로 작동하는 것 같고, 코드는 기능 개발을 하며 수시로 리팩토링을 진행해와서 건들 게 없을 것 같았다. (사실 여기서 더 얘기를 꺼내기 위해선 프로젝트 코드 얘기가 좀 필요할 것 같다.)

‼️주의

쓰고 보니 코드 얘기가 상당히 길다. 만약 본인이 안드로이드를 공부중이라면 재밌게 읽을 수도 있겠지만? 아니라면... 그냥 건너뛰고 읽기 바란다..

사실 안드로이드에서 상태, 이벤트 처리 어떻게 하는지 궁금하면 읽어도 된다.. 아마 이해는 잘 될 것이다 아마??...


프로젝트 구조

안드로이드 공부중인 사람이 한 번이라도 깃허브에서 여러 프로젝트 코드들을 본 적이 있다면 JOBIS 의 안드로이드 아키텍처는 굉장히 익숙할 것이다. 멀티 모듈을 통해 클린 아키텍처를 구현하였다.

물론 앱에 app 모듈 하나만 둔 뒤에 패키지로 클린 아키텍처의 각 계층을 구분하는 방법도 있다. 하지만 이 방식으로 계층을 분리하면 코드를 작성하면서 나도 모르게 계층 간 의존성이 꼬일 것 같아 계층을 모듈 단위로 분리하기로 결정하였다.

아 참고로 100% 컴포즈를 적용하였다. 컴포즈 만세!

Presentation

(패키지 이름에 _가 포함되어 있긴 한데 이 글이 올라갈땐 아마 바뀌어 있을 것이다)

presetation 모듈은 MVVM + MVI 패턴을 적용하였고, MVI 패턴을 좀 더 손쉽게 적용하기 위해 ORBIT 이라는 프레임워크를 사용하였다. JOBIS에서 사용자가 로그인 하는 과정과 함께 ORBIT을 간략하게 설명해보겠다.

SignInScreen

  • 이메일과 비밀번호 값에 변경이 일어날때마다 viewModel의 setEmail, setPassword 함수를 호출한다.

SignInViewModel

여기서부터 orbit 함수들을 사용하게 된다.

*로 표시된 애들이 orbit 프레임워크 함수들이다.

*intent

  • *SimpleSyntax 스코프를 제공하여 state를 사용할 수 있게 해준다.
  • state, reduce, postSideEffect등의 함수를 사용하기 위해서 반드시 필요하다.

state

  • 모든 뷰모델이 각 한 개의 state를 가지고 있으며 한 스크린에서 보여주는 데이터들을 포함한다.
  • MVVM에서 VM에 해당하는 ViewModel이 가지고 있는 상태라고 생각하면 쉽다.

-> SignInState는 다음과 같은 값들을 포함하고 있다.

  • 참고로 모든 ViewModel은 state data class를 무조건 가지고 있다.

*reduce

  • state를 업데이트 해준다.
  • 기존 stateflow와 다르게 reduce 블록 내에서 state를 copy 하기만 하면 간편하게 state가 업데이트 된다.

-> 서버로 로그인 요청을 보내는 뷰모델 함수이다.

  • SignInUseCase에 SignInParam을 전달하여 요청을 보낸다.
  • SignInParam에는 state의 email, password, autoSignIn 여부가 포함된다.

postSideEffect

  • 로그인이 성공하면 Main 스크린으로 이동하라는 SideEffect를 보낸다.
  • 보낸 SideEffect는 Screen에서 collect 하고 있다.

Domain

아무런 계층에도 의존성을 가지고 있지 않은 최상위 계층이다. Entity들이 포함되며 presentation -> data 사이에 위치하여 둘 간의 상호작용을 돕는다.

서버 통신에서 사용되는 enum들이 위치하고, exception, usecase, repository 인터페이스들이 위치한다.

UseCase

  • ViewModel에 hilt를 통해 주입되며 repository 함수를 호출한다.
  • operator + invoke() 로 클래스 이름으로 바로 함수를 호출할 수 있고, runCatching == Result를 반환하기 때문에 뷰모델에서 runCatching을 사용하지 않고 바로 예외처리가 가능하다.

Param, Entity

  • viewModel -> usecase 호출 시 사용되며, data module에서 SignInRequest로 변환하기 위한 매핑 작업이 이루어진다.
  • SignInEntity는 존재하지 않지만 (signin response가 data module에서만 사용되기 때문에) entity도 마찬가지로 response -> entity 매핑 작업이 data module에서 이루어진다.

Data

UserRepositoryImpl

  • domain에 위치하는 UserRepository 인터페이스를 구현하는 구현체이며 data source를 호출한다.

UserDataSource

  • 실질적인 api 함수를 호출한다.
  • Handler를 통해서 호출하기 때문에 예외를 던지는 시작점이라고 볼 수 있다.

UserApi

  • 서버와 통신하는 역할을 한다.
  • response가 있는 경우 response를 반환한다.

자자 거의 다 왔습니다!

사실 이렇게 대략적인 흐름만 알아둬도 앞으로 얘기할 코드 문제들을 알아듣는데는 큰 지장이 없을 것이다. 만약 앱 코드가 더 궁금하다면 JOBIS 레포지토리를 살펴보는것을 추천한다.

여기까지 읽느라 고생많았다 👏👏


느낀점

이제는 1년간 개발하며 느낀점, 뿌듯했던 일, 발생했던 이슈들을 정리하고자 한다. 그리고 이슈를 해결했다면 해결방법까지 적어볼 생각이다.

1. 혼자 개발하기

사실 이게 제일 힘들었던 것 같다. 위에 팀 소개에서도 언급했듯이 안드로이드는 일단 나 혼자서 개발했었다. 일단 이 이유를 알아보자면 프로젝트 아이디어가 새록새록하고 팀이 막 결성될 2022년 9월로 돌아가야한다..

당시에는 같은 학년에 안드로이드를 공부하는 4명의 친구가 있었다. 모두에게 프로젝트 참여 의향이 있냐고 물어본 결과 한 명의 친구가 좋다고 대답했고, 프로젝트 기획, 웹 와이어 프레임 작업까지는 함께 참여했던 안드로이드 친구가 있었지만.. 앱 개발이 시작될 무렵 타 프로젝트 일정 이슈로 인해서 기획이 한창 진행되던 도중 팀을 탈퇴해버렸다..

그렇게 나는 홀로 남겨졌다.

하지만 당시 나는 아주 멍청한 생각을 하고 있었다.

"혼자 개발하면 다 내 마음대로 해도 되겠지?? 오히려 좋아"

아니? 그건 아주 멍청한 생각이었다. 물론 아키텍처링, 디자인 시스템, 기능 구현, 기획에 있어서 안드로이드는 나 혼자 해나가니 확실히 편하긴 했다. 앱 개발에 있어 좋은 생각이 떠오르면 상의하지 않고 코드에 바로 적용할 수도 있었고, 코드 리뷰도 받을 필요가 없어서 개발 속도 역시 단축시킬 수 있었다. 하지만 어느 순간부터 내가 올바른 방향으로 개발을 하고 있는 것인가??.. 라는 생각이 들었다.

코드를 짜도 리뷰해줄 사람이 없으니 PR조차 날리지 않고 브랜치를 바로 머지해버리니 잘못된 코드가 develop 브랜치에 올라가거나, 단순하게 변수명, 오타부터 성능 상의 이슈가 발생할 수 있는 똥 같은 코드들을 그냥 괜찮은 줄 알고 넘어가기 시작했다. 거기에 귀찮다고 초반에 만들어둔 컨벤션을 잘 지키지 않는 일도 점점 증가하기 시작했다.

그래도 이때까지는 나름 혼자서 정신 바짝차리고 문서화 작업을 열심히 해두면 괜찮을 것이라고 생각했다. 하지만 그건 큰 오산이였다.

아니 리컴포지션이 끝없이 일어나고 있잖아!?

-> 대충 리컴포지션은 안드로이드 컴포즈가 화면을 변경된 상태에 따라 새로고침 하는 행위이다. 자세한건 여기를 봐라 (재구성 챕터부터 보면됨)

저 숫자가 리컴포지션이 일어난 횟수이다. 실제로 저게 끊임없이 증가하고 있었다. 리컴포지션이 많이 발생하게 되면 우리도 알게 모르게 앱의 성능이 저하될 수 있다. 그건 곧 내가 가장 중요하게 생각하는 사용자의 경험과 연결된다.

이런 코드가 어쩌다 develop에 올라가게 되었을까?

당연히 내가 짠 로직이 완벽하다고 생각하고 아무 생각없이 브랜치를 머지했을것이다. 코드 리뷰도 하지 않아서 이런 문제가 있을 줄 몰랐겠지...

해결방법

당시 하던 프로젝트가 슬슬 마무리 되어 가던 친구가 한 명 있었다. 그 친구에게 앞으로 JOBIS 개발을 같이 하면 어떻겠냐고 제안했고, 흔쾌히 수락을 하여 QA 를 진행해주던 도중 이런 문제를 발견할 수 있었다.

느낀점

그래서 나는 이 사건을 계기로 혼자 개발하는것이 절대 좋은일만은 아니라고 생각하게 되었다. 하나보단 둘, 둘 보다 셋이 낫고, 좋은 품질의 코드를 짜기 위해서 코드 리뷰는 반드시 필요하다고 생각할 수 있었다. 하지만 만약, 자신이 개발 열정이 좀 식은 것 같다고 느껴진다면 혼자서 규모가 좀 있는 프로젝트의 개발을 맡아보는걸 추천한다. 여러 부분에서 정말 많은 것들을 배울 수 있을 것이다.

2. 아키텍처 이해도

지금 보이는 이 사진은 안드로이드 개발자라면 무조건 봤을 클린 아키텍처 구조도이다. 위에 프로젝트 구조에서 설명했듯이 JOBIS는 클린 아키텍처를 채택하였다. 나는 지금까지 프로젝트를 진행하며 아키텍처 설계를 주도적으로 맡아본 적이 없다. 해봤자 코드 리뷰 해주고.. 의견 제시하고.. 뿐이었다.

그래서 초반 아키텍처를 설계할 때 클린 아키텍처 개념이 부족했던 나는 열심히 삽질하기 시작했다. 실제로 로버트 마틴의 클린 아키텍처도 참고하려고 많이 노력했다.

https://lace-dash-abe.notion.site/Android-Clean-Architecture-dcac3f2d4bcd40eda7caa3c3a28cf7c5?pvs=4
이렇게 노션 정리까지 해가며 정말 열심히 공부한 기억이 난다. 그리고 공부한 내용을 바탕으로 코드에 적용하며 실제 코드에선 클린 아키텍처를 어떻게 적용해야 하는지 고민을 정말 많이 한 것 같다. 물론 클린 아키텍처가 적용된 다른 프로젝트들도 많이 참고했다. (초반엔 전혀 감이 잡히지 않았기에...)

그리고 무엇보다 MVI를 적용한게 정말 뿌듯했다. ORBIT은 성빈랜드 성빈님의 블로그를 보고 알게 되었다. 참고할 코드도 ORBIT 레포지토리 밖에 없어서 삽질 할 것도 없었다.. MVI는 상태 관리를 정말 손쉽게 할 수 있는 방법 중 하나 인 것 같다. 최고!!

느낀점

혼자서 주도적으로 무언가를 설계해보는 경험은 개발자에게 반드시 필요한 것 같다. 개념적인 부분으로는 완벽하게 알고 있다고 생각해도 막상 코드로 구현하려고 하면 막막한 경우가 많은 것 같다. 이러한 부분에서 설계를 위해 깊게 공부해보고 또 코드로 적용하는게 성장에 굉장히 큰 경험이 되는 것 같다고 생각할 수 있었다.

3. 디자인 시스템

디자인 시스템을 한 번도 들어본적 없는 개발자는 없을것이다!
있다면 미안합니다..

나름 혼자 개발했지만 디자인 시스템까지 따로 개발해서 배포도 하였다.
코드는 깃허브에서 볼 수 있고 사용 방법은 문서화가 덜 되어서 나중에 공개할 수 있을 것 같다!.

디자인 시스템 역시 컴포즈 100%이고 기존에 내가 디자인 시스템 유지보수에 참여했던 우리학교 기숙사 관리 시스템 DMS의 디자인 시스템과 대구소프트웨어마이스터고 도담도담 팀의 DUI를 참고하였다.

참고로 난 한 번 꽂히면 제대로 하는 성격이기 때문에 릴리즈 노트도 꾸준히 작성하고 있다. 써놓길 참 잘한 것 같다. 유지보수를 하며 이 코드는 대체 언제 짠거야?? 하면서 궁금해질 때 한 번씩 보기도 하고, 전 버전에 어떤 작업들을 했나 보기도 편한 것 같다. 물론 깃허브 릴리즈 노트가 있긴 하지만 그냥 노션에 써놓은게 더 끌린다.

4. 앱 배포

실제로 나는 앱을 처음 배포해봤다. 그래서 심사 통과 기준도 잘 몰랐고, 플레이 콘솔에 뭐가 많아서 앱을 올리기까지 굉장히 많이 고생했다. 큰 고생 끝에 큰 행복이 찾아온다 그랬나. 지금은 사용자도 늘어났고, 실제로 쓰기까지 진짜 얼마 안 남은것 같아서 굉장히 행복하게 유지보수를 진행하고 있다. 아 그리고 앱 역시 릴리즈 노트를 작성하고 있다.

실제로도 메뉴가 너무 많다. 거기에 심사 통과 기준도 몰라서 리젝을 7번 먹고 8번째때 앱을 출시했다.나! 고생많았어 ㅎㅎ~

왜 리젝을 7번이나 먹었는지는 나중에 관련된 글을 올릴 생각이다. 거기에 심사를 요청할 때 어떤점을 주의해야 하는지, 안되는건 뭐가 있는지 등... 많은 관심 부탁한다.

느낀점

최근 취업 공고를 보면서 앱 배포 경험을 우대사항으로 작성해놓은 기업이 많은 것 같다. 만약 배포를 해본적이 없다면 한 번 해보는걸 적극적으로 추천하고, 배포를 하고 실제 서비스를 하는 과정에서 어떤 부분이 유저에게 불편함을 안겨줄 수 있는지, 어떤 점이 보안적으로 취약한지 등 배울 부분이 많다고 말해주고 싶다.


마무리!

긴 글 읽느라 고생많았다!! 나도 이렇게 긴 글은 저번에 쓴 글 이후로 처음 쓰는 것 같다. 하지만 이렇게 회고를 간단하게 몇 마디가 아닌 자세하게 긴 글로 남겨보는게 프로젝트를 하며 진행했던 일, 들었던 생각들을 정리하는데 큰 도움이 되는 것 같다.

이 글을 보시는 분들도 언젠가 한 번씩 긴 글로 회고를 작성해보는 것을 추천하며 1년 간 개발한 프로젝트 회고 글은 여기서 마치겠다! 🚀

그리고 혹시나 글에서 틀린 부분이 있거나 그 밖의 피드백이 있다면 댓글로 남겨주길 바란다!

4개의 댓글

comment-user-thumbnail
2023년 10월 8일

1년동안 수고 많으셨습니다!! 자! 이제 유지보수 집중해야합니다!

1개의 답글
comment-user-thumbnail
2023년 10월 14일

아 이거 회고임 개웃기네요진짜 팀리턴화이팅

1개의 답글