0. 들어가기
그동안 배운 Java의 기본 내용과 진행해본 개인 과제 2개의 경험치로 첫 협업 프로젝트가 진행됐다.
학부에서 데이터베이스 수업시간에 어설픈 협업을 한 것이 협업경험의 전부였던 나로서는 걱정이 되었다. 졸업작품도 빠른시간내에 끝내고 1학기 졸업을 하기 위해 혼자 진행하였고, DB 텀프로젝트로 간단한 CRUD기능이 있는 웹사이트를 만든 것이 전부였다.
(우리가 했던 것은 국세청 홈페이지 불편사항 개선이었다. 기본 국세청 세금신고 자료 저장,관리를 홈페이지에서 하게 되는데 국세청 홈페이지에서 없어서 불편한 품목별 검색, 정렬기능 등을 구현했다)
심지어 그 때 프로젝트도 협업을 경험하기 보다는 막히는게 있으면 그냥 혼자서 풀어 나갔다. Github를 사용하여 각자 분량을 나누어 진행해보려 했지만, 나 포함 조원 전부가 사용해보지 않아 초반에 공부해서 설명하다 반응이 너무 없어 포기하고 진행하였다.
하지만 이번 Toy Project 조원들 중에는 이미 Github로 내가 하고싶었던 협업을 경험한 사람들이 있었고, 생각보다 협업을 편리하게 한 Github의 여러 기능들을 사용해보고 익혀보는 소중한 경험을 할 수 있었다. 막힐때 열심히 설명해 준 조원들에게 감사한 마음이다. 다음 project에서는 내가 알려주는 위치에 있도록 해야겠다.
0.1 ToyProject 개요, 단계별 달성목표
야놀자가 진행하는 과제 답게 구현하려는 것은 "여행 여정을 기록하고 관리하는 SNS 서비스"였다.
Toy project 1, 2, 3을 통해 지속적으로 업그레이드 하며 최종 완성한다.
크게 1단계에서는 콘솔 프로그램으로 틀을 잡고 Java 어플리케이션을 하나 만들어 보기.
2단계에서는 DB를 사용하고, Spring을 사용하며, RESTful한 설계를 지향해 만들어 보기.
3단계에서는 SpringBoot를 사용하고, Spring Security를 활용하고, JPA를 응용해 보기.
이렇게 진행된다. 같은 프로젝트를 업그레이드 하는 형식으로 진행된다.
1단계 프로젝트에서는 파일 입출력, 저장, 예외처리, 객체지향적 클래스 설계가 기본 목표가 되겠다.
0.1 ToyProject1 요구사항 명세
사용자가 콘솔로 메뉴에 숫자를 입력하며 진행되는 콘솔 프로그램으로, 크게 여행 저장과 조회, 종료기능을 구현한다.
여행:여정 = 1:N의 관계를 갖고 여행은 멤버로 해당 여정List를 가진다.
특이사항으로는 JSON파일, CSV파일을 둘 다 저장하고, 조회 시 선택하여 조회할 수 있어야 한다. 이 때 예외처리는 각각 구현한다.
사용자에게 입력받는 여행과 여정의 멤버들은 자세하게 다음과 같이 제시되었다.
평가 기준
그리고 메인 화면 예시도 첨부되어있었다.
요구사항을 만족하는 방법과 클래스 설계, 화면 설계 등은 자유롭게 진행하는 것으로 나왔다.
1. 중점
나는 굉장하게 효율을 추구한다.
추구하는 요율의 기준은 무조건 클라이언트에게 맞춘다.
결국 클라이언트가 사용할 앱을 만드는 것이다. 나는 이것을 1순위로 생각하였고 그 다음으로 요구사항 충족과 평가기준을 두었다.
요구사항 충족은 당연히 완수해야 하는 목표이고, 평가기준을 벗어나지 않는지 확인하는 것은 기본이지만 기준을 거기에 맞추고 진행하는 것을 스스로 지양한다. 앱이나 웹 등을 사용할 때도 항상 같은 기능을 하는 것도 어떻게 사용자가 행동하게 하고 해당 내용을 어떻게 불러오느냐에 따라 만족도가 결정된다고 생각한다.
물론 프로그램이 죽는 일이 있거나, 요구사항 기능이 작동하지 않거나, 속도 문제가 있으면 안 되겠다.
자사의 프로그램이 아닌 프로젝트를 입찰하여 SI회사가 요구사항만 겨우 충족하고 그대로 쓰고있는 기능들을 보면 세금이 너무 아깝고 사용자 입장에서 짜증이 난다.
물론 군대 행정직으로 예산신청을 진행해본 경험으로 보자면 각 지방자치단체에 금액설정을 하고 기획서를 보내고, 중앙 재정부에서 종합하는 등 내년도 예산편성 과정에 1년이 거의 꼬박 걸린다는 사실에 어느정도 이해되기도 한다.
물론 프로그램이 죽는 일이 있거나, 요구사항 기능이 작동하지 않거나, 속도 문제가 있으면 안 되겠다.
하지만 동일 금액으로 자사 솔루션 프로그램을 만들듯이 프로그램을 만든다면 훨씬 사용자가 느끼는 효율도 좋아질 것 같다.
대체로 모로 가도 서울만 가면 된다는 말처럼 정말 요구사항이 가능만 하게 만들어놓은 것이 많다. 마치 내가 처음 만들었던 프로그램처럼 돌아만 가고, 사용자가 결과를 얻어오기까지 굳이 돌아가야 하거나 속도가 느리거나, 결과를 얻으려면 어떻게 진행해야 하는지는 정말 신경을 쓰기는 하는건지 궁금하다. 요구사항을 제한적인 상황에서 충족하려면 그렇게 사용자 편의성을 버려야만 하는지 궁금하다. 세상물정 모르는 취준생이 입사하고 나면 같은 행동을 할 지도 모르겠지만, 나는 내가 만든 프로그램이 클라이언트가 만족할만한 것인지에 중점을 두고 있다.
나의 이러한 성향을 팀원들에게 제대로 설명하고 동의시킨 뒤 진행하기에는 기본적인 Github, MVC패턴과 객체지향 적용에 관한 이해가 너무 부족했다. 제한적인 상황에서 내 목적을 달성하기 위해 나는 MVC에서 Viewer패턴을 맡아 사용자가 상호작용 하는 화면을 맡기로 하였다. 나를 제외한 나머지 조원은 사다리타기로 역할을 결정하였다.
돌아보면 이는 좋은 결정이었던 것 같다. 표 형식으로 콘솔에서 깔끔하게 출력하기가 여간 귀찮은 일이 아닌데, 이를 대충 줄글만으로 출력하거나 하면 우리가 만든 결과가 좋게 보이지 않을 듯 싶었다. 이를 다른 사람이 담당하였을 때 내가 맘에 안드는 것들은 평가기준이 아니기 때문에 요구한다면 부담을 느낄 듯 싶었다.
또 사용자와 상호작용하는 흐름을 내가 결정할 수 있었다. 요구사항에서 제시한 것은 저장과 조회, 종료였다. 화면 구성을 자유롭게 풀어주었기 때문에 이를 어떤 흐름으로 결정할지는 수만가지 경우의 수가 있다.
나는 사용자의 입장에서 최대한 상식적으로 화면마다 원하는 목표를 위해 무엇을 해야 하는지를 쉽게 흐름을 파악하고, 목표를 위해 어떤 것을 입력해야 하는지 바로 알 수 있도록 하였다.
"아 그래서 어쩌라는거야", "이거 할라면 뭐해야돼" 등의 의문이 들지 않도록 하였다. 이 또한 다른 조원이 담당하고 내가 변경을 요구하기보다는 내가 직접 흐름을 구성할 수 있게 하는 것이 좋았다.
1.1 제공해야 하는 기능
우선 만들어야 하는 앱의 전체 흐름을 파악하기 위해 다같이 이야기 해 보았다.
예시로 준 메인화면을 보면 여행기록(1), 여정기록(2), 여행조회(3), 여정조회(4), 종료(5)
DB를 사용하지 않기 때문에 각 여정들을 따로 저장, 조회했을 때 소속 여행과의 관계를 찾을 수 없다.
(RDBMS를 사용한다면 여행의 기본키를 여정의 외부키로 사용하여 연결할 수 있다.)
하여 우리는 여정을 여행 안에 저장하기로 하고 여행이 없는 여정은 존재할 수 없다고 결론지었다.
메인 메뉴에서 우리는 먼저 크게 여행기록, 여행조회, 종료 기능으로 나누기로 하였고, 여정에 관한 내용은 독립되지 않기로 하였으므로 해당 메뉴 내부에서 처리하였다.
메인 메뉴
여행 기록(1), 여행 조회(2), 종료(3)
심플하게 구성하고, 여행과 여정을 여러 개씩 저장하는 등의 세부 내용은 안에서 추가 선택지가 나오도록 하였다.
여행 기록
요구사항
1. 사용자는 한 여행에 여러개의 여정 정보를 입력하고 저장할 수 있다.
2. 사용자는 여행을 여러 번 입력하고 저장할 수 있다.
평가 기준이나 요구사항에 기본키나 멤버 여부가 필수적인지는 명시하지 않았기 때문에 우리는 평가기준을 충족하면서 예외처리를 쉽게 넘어가기 위해 모든 멤버는 필수 입력으로 하였다.
세부 단계
1. 여행 이름, 시작날짜, 종료날짜 입력
2. 여행의 마지막 멤버인 여정리스트를 채우기 위해 여정 정보들 입력
3. [여정 추가여부] 메뉴에서 다른 여정 기록(1)을 선택하면 계속 새 여정을 저장, 여정 기록 종료(2)를 선택하면 완성된 여정기록을 종료하고 완성된 여정을 저장
4. [여행 추가여부] 메뉴에서 다른 여행 기록(1)을 선택하면 계속 새 여행을 저장, 메인으로(2)를 선택하면 메인화면
메뉴에서 여행 기록을 선택하면 반드시 한 번은 여행을 기록해야 한다. 중도 퇴장은 불가하다. 한 여행에 여러 여정들을 저장할 수 있고 이것이 여행 안에 여정List로 포함되기 위해 저장 단위를 여행으로 끊었다.
요구사항에서 사용자는 여러 여행을 기록할 수 있다가 있지만, 사용자 입장에서는 여행 기록 후 세부단계 4를 보면 여러 여행 기록을 수행한다고 생각하게 되므로 굳이 여행까지 몰아서 저장하지는 않고, 내부적으로는 여행 하나당 저장을 수행했다. JSON 파일과 CSV 파일로 저장하는 것은 두 파일 각각 저장되므로 사용자는 알 필요가 없다고 판단하여 자동으로 2가지 파일 형식으로 저장하게 하였다.
여행 조회
요구사항
1. 여행 조회시 JSON파일, CSV파일 중 불러올 파일 형식을 결정한다.
2. 여행 조회를 선택하면 여행의 내용과, 내부 여정 멤버 리스트들이 출력된다.
세부 단계
1. [파일 종류 선택] JSON파일(1), CSV파일(2)
2. 해당 형식으로 저장된 모든 여행들을 이름, id로 화면 출력
3. 사용자는 보고싶은 여행을 이름으로 확인하고 해당하는 id를 콘솔창에 입력
4. 해당 id로 여행을 찾아 세부 내용을 출력
5. 메인화면으로 이동
기본적으로 JSON, CSV파일을 불러올 때, 저장된 여행이 없을 때를 예외처리로 잡고 진행햐였다.
종료
간단한 감사 인사와 종료 멘트를 출력하고 프로그램을 종료한다.
2. 설계
무엇이 필요한지 알았으니 회의에서 필요해보이는 클래스들을 막 던져서 먼저 구조를 짜 보았다. 하지만 MVC패턴을 지키는게 어려워 먼저 다같이 MVC에 대해 정리하고 가기로 했다.
2.1 MVC패턴: 객체지향 설계
프로젝트 평가기준에 "잘 만든 MVC패턴"에 대한 기준이 있었다.
하지만 MVC패턴을 공부해보면 Spring을 통해 구현하는 경우가 많고, Web을 사용하지 않으면 이 구성을 어떻게 적용해야 할지 도대체 감이 잡히지 않았다.
MVC패턴이란 사용자가 Viewer를 통해 상호작용하면 이를 Controller가 필요한 로직을 부르며 Model객체를 주고받는 패턴이다.
이를 어떻게 적용해야 할지 어려움이 있어 출제자와 멘토님에게 질문해 본 결과, Java 콘솔프로그램으로 MVC패턴을 평가기준에 넣은 것은 실제로 MVC패턴을 엄격하게 구현하라는 것이 아니라 "객체지향적으로 프로그램을 설계하라" 라고 이해하면 된다고 했다. 프로그램을 절차지향적으로 코딩하지 않고 역할별 클래스를 분류하여 객체지향적 설계를 해보는 것이 목적이라고 하였다.
요구사항을 제시한 출제자가 이렇게 말 했으니, 우리는 기본적인 구조를 어떻게 가져가야 객체지향 적인지에 대해 고민하기 시작했다. 기본적인 것은 MVC를 따르기로 했다.
3. 완성된 프로그램 결과
프로그램 출력 화면, 파일 출력 결과이다.
3.1 프로그램 출력 화면
여행 기록
- 여행 기록 상황 1 : 여행 하나 - 세부 여정 2개_1
- 여행 기록 상황 1 : 여행 하나 - 세부 여정 2개_2
- 여행 기록 상황 2 : 여행 두 번 기록_1
- 여행 기록 상황 2 : 여행 두 번 기록_2
여행 조회
- 여행 조회 상황 1 : JSON형식 선택하여 조회
- 여행 조회 상황 2 : CSV형식 선택하여 조회
- 여행 조회 상황 3 : 저장된 여행이 없을 때 조회
예외 처리
- 예외 처리 1 : 옵션 선택지 정수 입력, 옵션 범위 확인 후 예외 처리
- 예외 처리 2 : 사용자가 입력한 여행 ID로 여행 조회 불가 시 예외 처리
서비스 종료
3.2 저장된 파일 결과
JSON 파일
CSV 파일
마무리
월-금 프로젝트 후 토요일 SQLD 자격증 시험을 준비해야 해서 나름 시간이 빠듯했다..
혼자 했으면 하루에 했을 것 같은데 협업이 얼마나 힘든 일인지 느낄 수 있었다.
분명 입사하면 내가 혼자 할 스케일이 아닌 프로젝트일 것이다. 해당 프로젝트에서 협업을 통해 잘 만든 객체지향의 모듈들이 상호작용 하듯 매끄럽게 소통하며 업무를 진행하기 위해 협업 경험은 정말 많으면 많을수록 좋은 것 같다.
내 생각을 어떻게 정리해서 이야기 할지, 상대방이 정리하여 말을 하지 않았을 때 내가 어떻게 정리하여 받아들였는지를 알려주고 회의를 진행하고, 지향점이 어딘지를 정확히 설정하고 공감시키는 등 더 치열하게 고민해야겠다.
UML을 거의 기획서용으로 나중에 만들었는데 UML은 원래 소통을 위해 존재하는 친구 아닌가? 다음에는 프로젝트 시작 시에 모두가 이해하고 프로젝트를 진행할 수 있도록 UML을 먼저 만들고 이를 기반으로 소통하는 방식을 내것으로 만들어야겠다.