이 게시물은 HolyBean 프로젝트의 2024년 5월 ~ 8월에 진행된 업데이트에 관련된 내용입니다.
거의 모든 기능은 유지되었지만, 코드상으로는 거의 대부분 변경되어서 따로 기록으로 남기고자 합니다.
시작 배경
Maintenance Nightmare
소프트웨어공학 시간에 배운 용어로, 유지보수하느라 매일 악몽 같은 시간을 보낸다는 뜻입니다.
HolyBean 프로젝트는 개발 경험이 거의 전무한 시절 시작한 프로젝트였습니다. 덕분에 수많은 오류와 최적화 이슈가 발생했고, 약 6개월간 실사용한 앱 치고는 꽤 많은 시간을 유지보수에 투자해야 했습니다.
소프트웨어공학 수업에서 배웠듯이, 소프트웨어 개발 예산을 잡을 때 개발:유지보수를 1:9로 잡을 정도로 유지보수는 소프트웨어 생명주기에서 상당한 비중을 차지합니다. 이러한 유지보수를 효율적으로 하기 위해 클린코드로 작성하고, 리팩토링을 꾸준히 해야 한다는 말을 상당히 많이 들었습니다.
하지만 제 앱은 그런 지식조차 전무할 때 무작정 ChatGPT와 함께 개발했던 프로그램이었기 때문에, 사용자 요구사항 변경이나 디버그 과정은 하나의 Maintenance Nightmare로 다가왔습니다.
리팩토링 결정의 계기
특히 이번에 쿠폰 판매 관련하여 카페 담당 집사님께서 수정을 요구하셨는데, 그 기능은 현재 상태로는 도저히 감당되지 않아 리팩토링 및 DB 개선 작업을 먼저 진행하게 되었습니다.
목적 & 의도
1. 객체지향 원칙 적용
유지보수 및 개발에 용이하도록 각 클래스 간의 의존도를 낮추고, 객체지향 프로그래밍의 SOLID 법칙을 어느 정도 적용하기
2. 데이터베이스 최적화
데이터베이스 시간에 배운 Normalization(정규화)를 현재 DB 스키마에 적용하여, 메모리가 작은 태블릿에 최적화 시도
3. 코드 품질 개선
지금까지 유지보수하면서 생겨난 스파게티 코드들을 정리하고 클린코드화
주요 개선 사항
1. DB 스키마 변경
기존 문제점 최초 DB 설계 당시, Query를 작성할 줄 몰랐기에 DB의 각 테이블에 목적에 맞는 대부분의 정보를 담았습니다. 따라서 Redundant Data가 굉장히 많았고, 이는 데이터베이스의 불필요한 크기 증가로 이어졌습니다.
개선 결과 2024년 8월 28일 DB 업데이트를 위해 백업 당시 약 4,000여 개의 행이 DB에 들어있었는데, 스키마 설계를 다시 하면서 확인한 결과 30% 정도는 중복 데이터였습니다.
과거 DB 설계:
변경된 DB 설계:
2. Controller-Service-Repository 패턴 적용
기존 구조의 문제점
기존 프로젝트 구조는 Fragment와 DatabaseManager만으로 이루어져 서로 데이터를 주고받는 구조였습니다. 그 결과:
- 비즈니스 로직이 각각에 섞여있음
- 6개월간의 유지보수 동안 스파게티 코드로 변질
- 점점 코드 수정이 어려워짐
개선 방안
최근 Spring을 공부하며 객체지향의 SOLID 원칙도 함께 공부했고, 이를 통해 현재 구조의 문제점을 명확히 인식했습니다. SOLID 중 SRP(단일 책임 원칙)을 지키는 보편적인 기법 중 하나인 Controller-Service-Repository 패턴을 적용했습니다.
구체적 변경사항
- DatabaseManager 클래스 → Service(비즈니스 로직) + Repository(데이터베이스 접근)로 분리
- 각 Fragment들 → Controller(UI, UX) + Service(비즈니스 로직)로 분리
- Database 싱글턴 객체 신규 생성으로 DB 연결 관리
- Repository 클래스들 구분하여 단일 책임 원칙 준수 및 데이터베이스 동시 접근 문제 예방
3. 의존성 주입(DI) 적용 - Hilt
Controller-Service-Repository 패턴을 적용하면서 자연스럽게 Dependency Injection을 고려했고, 구글에서 공식적으로 권장하는 Hilt 라이브러리를 적용했습니다. Spring Boot처럼 Annotation만으로 의존관계 주입이 가능하다는 점이 인상 깊었습니다.
4. Printer 관련 기능 추상화
기존 문제점 Printer를 사용하는 부분들에서 각각의 함수들로 POSPrinter 객체를 생성하도록 구성되어 있어 코드 중복이 심했습니다. 개선 방안 추상 클래스 및 상속을 적용하여:
- Printer 추상 클래스 생성
- 인쇄 설정, 출력, 연결 해제 기능 통일
- 기능별 출력 양식은 Printer 추상 클래스를 상속받은 개별 클래스로 구현
- 유지보수성 향상 및 기능 통일성 확보
마무리
이번 리팩토링을 통해 단순히 기능을 추가하는 것을 넘어서, 지속 가능한 코드를 작성하는 것의 중요성을 체감했습니다. 비록 개발 초기에는 시간이 더 소요되지만, 장기적으로는 훨씬 효율적인 개발과 유지보수가 가능해졌습니다. 앞으로도 새로운 기능을 추가할 때마다 이러한 원칙들을 지켜나가며, 더 나은 코드를 작성해나가겠습니다.