ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 프로젝트 설계 문서 공개 리팩터링
    Today I Learned 2022. 11. 7. 21:36

     

     

    아샬님께서 오후에 진행한 내 프로젝트 설계 문서 공개처형 리팩터링 월요지식회를 바로 옆에서 듣고 기록한 내용을 정리했다.

     

    내 사용자 스토리의 문제점

    메인 화면: 사용자는 주요 기능으로 이동할 수 있는 메인 화면을 볼 수 있다.
    헤더 확인하기: 사용자는 운동을 선택하거나 사이드바를 보기 위해 헤더를 항상 확인할 수 있다.
    화면 하단 네비게이터 확인하기: 사용자는 홈, 운동 모집 게시글 보기, 클럽 리스트 보기, 채팅 목록 보기로 이동하기 위해 푸터를 항상 확인할 수 있다.
    ...

     

    일단 요구사항은 화면이 아니어야 한다. (ex. 화면을 볼 수 있다.)

    기능은 영원하지만, 화면은 일시적이다. 기능과 화면이 강하게 결합되면 기능을 개선하는 과정이 필요 이상으로 커질 수 있다.

    화면이 있으면 설계나 요구사항에 활용될 수는 있지만, 화면에 끌려다니지는 않는 것이 중요하다.

     

    내용 상의 문제점

    운동 선택하기:  사용자는 특정 운동에 관련된 주제만을 보기 위해 운동 종류를 선택할 수 있다.
    실시간 개인 채팅: 사용자는 다른 사용자와 직접 실시간으로 채팅하거나 사진, 동영상 등을 공유할 수 있는 실시간 개인 채팅을 할 수 있다.

     

    ~를 위해 ~를 한다가 아니라, ~를 해야 하니까 ~를 위해를 끼워넣자는 느낌이 강하다.

    가치를 바뀌면 소프트웨어의 기능이 바뀌는 것이다. 거기에는 이유가 필요하다.

    진짜로 진짜로 하려는 게 뭐인지 계속 물어야 한다. 우리가 앱을 쓸 때를 잘 생각해보면, 아마 기능이 아니라 앱을 통해 얻을 수 있는 '가치'를 쓰고 있었을 것이다.

     

    게시물 필터링을 생각해보자. 게시물을 운동 종류나 지역으로 필터링을 해야 하는 이유가 있을까?

    시간을 아끼고 빨리 찾기 위해서! (As, I, So에서 So에 해당) 이유와 가치를 찾게 되면, 기능은 그로부터 더 찾아지고 확장될 수 있다!

    (ex. 시간을 아끼기 위한 가치로부터 >> 관심운동을 등록하기, 관심운동 메일 보내기 같은 기능들이 생길 수 있다.)

     

    사용자 스토리는 그걸 보고 개발하는 게 아니라, 질문의 시작점이다.

    스스로에게 계속 질문을 던져 본다. '이걸 왜 봐야 하죠? 이 기능은 왜 이렇게 되야 하죠?'

    계속 질문을 던지고, 대답을 하면서 알아낸 것들이 나오면, 일주일의 시간 동안 딱 알아낸 것들까지만 만든다. 시간은 한정되어 있고, 작업을 지속하기 위해서는 분명 작업의 동력이 있어야 한다. 작업을 계속 하는데도 성취가 없다면 작업과 정신력은 미궁에 빠진다. 처음에는 쉬운 것을 잘 하기 위해 선을 긋는다.

     

    Agile Process는 Incremental과 Iterative의 조합으로 이루어진다. 처음부터 끝까지 반복하는 단계를 작게 시작해서 점진적으로 쌓아올린다. 사용자 스토리 역시 작게 만들기 시작해서 반복해서 다시 보고, 발젼시켜야 한다. 그 순간에 생각나지 않으면 물음표를 치고 넘어가고, 다시 또 보면서 발전시키는 단계를 따라야 한다.

     

    '동시에 하기'

    '기획만', '설계만', '코딩만' 우다다 해서 끝내는 방식은 대표적인 Waterfall 방식이다. Waterfall 방식을 따르면 뒤로 돌아갈 수가 없다. 기획을 하다가, 설계를 하다가, 코딩을 하다가 뭔가 이상함을 느끼면? 언제든 뒤로 돌아갈 수 있어야 한다. 동시에 하는 것은 자연스럽게 하는 것이 가장 좋겠지만, 잘 안 된다면 '시간을 정해 놓고 습관적으로' 하는 방법도 좋다.

     

    어려움을 겪는 것을 공부할 기회로 삼는다.

    어려움을 해결하는 팁을 구하려고 하면 쉬운 해법을 찾게 된다. 제대로 된 쉬운 해법은 찾기 어렵기 때문에 처음부터 제대로 공부한 것보다 훨씬 오래 공부해야 하고, 문제는 그렇게 해도 잘 모른다. 알고 있는 수준 이상의 글을 찾는 것은 그 사람에게는 문제 해결을 위한 마지막 퍼즐일 수 있었겠지만, 찾는 본인에게는 문제 해결을 시작하는 첫 번재 퍼즐이 될 수도 있다.

     

    모르는 것을 그냥 복붙해서 쓰면 어떤 상황에 처하게 될지 모른다. 자주, 가능하면 빨리, 물어봐야 한다.

     

    배민도 처음에는 동 주소를 입력하면 전단지를 화면에 띄우고 전화 기능으로 연결해주는 방식이었다. 더 나은 구조가 존재할지언정, 이번 주 안에 할 수 없는 것을 추구하기보다는 그 순간에 할 수 있는 최선의 것을 하고, 모르는 것은 기를 쓰고 질문하면서 얻어내도록 하자.

     

    설계는 각 계층별로 각각 다르게 분리하자

    REST API는 프론트엔드, 화면에 끌려가서는 안 된다.

    <Route path="/posts/list" element={<PostListPage />} />
    @GetMapping("/posts/list")

    각각 게시물 목록을 출력하는 웹 페이지의 경로와 REST API를 호출하는 경로이다. 화면의 URI를 REST API가 그대로 따라가는 문제가 있다.

    화면에서 게시물 목록을 보여주는 방법에는 여러가지 방법이 있다. 썸네일을 리스트업해서 보여줄 수도 있고, 지도에 마커를 찍어서 보여줄 수도 있다. 이때 이 여러 방법들의 중심 로직은 '게시물 목록'이다. REST API는 Resource를 핵심적으로 나타내야 한다. 게시물 목록을 보여주는 로직을 수행하기 위한 핵심 Resource는 '게시물들'일 것이다. 게시물들을 얻어오는 'GET /posts'로 API를 설계할 수 있을 것이다.

     

    posts의 핵심 Resource를 정의했다. 그렇다면 posts라는 Resource에 집중하는 해당 API는 다른 Resource를 포함하지 않는 것이 좋다.

     

    그런데 내 앱은 게시글에 post를 비롯해 game, team, role, member를 조합해 하나의 post를 구성하는 것이라고 생각했다. 어떻게 문제를 해결할 수 있을까?

     

    컴포넌트도 관심사를 나눌 수 있다.

    화면에 끌려가는 설계를 하다 보니 post가 game, team, role, member를 하위에 모두 포함해야 할 것이라고 생각했다. 그런데 각각의 API가 자신의 Resource에 집중하는 방식이라면 game, team, role, member에 해당하는 API를 생성해 각각을 호출한 뒤, 조합하는 방식을 생각해볼 수 있다.

     

    반드시 조합되어야 할까? 하나의 페이지를 구성하는 컴포넌트의 관심사를 분리할 수도 있을 것이다. 각각의 페이지를 구성하는 컴포넌트의 요소를 각각의 API를 통해 호출해 하나의 페이지 내에서 독립적인 컴포넌트로 구성하는 것을 시도해볼 수 있겠다.

     

    우연에 매몰되지 않는다.

    MVC 계층의 네이밍이 같다고 느껴지는 것은 (PostController, PostService, PostRepository, ...) 단지 우연의 산물일 뿐이다. 우연에 끌려가게 되면 기계적으로, 이유 없이 이름을 짓고, 규칙을 만들게 된다.

    우연이 연속적으로 나타난다고 해서 큰 일이 바로 발생하는 것은 아니지만, 그렇다고 우연에만 흐름을 맡기게 되면 우연으로 대처할 수 없는 상황을 마주했을 때 문제가 된다. '최선이 뭔지는 알고 있다'는 알고 있는 것이 중요하다.

     

    찜찜함 타파

    설령 모든 것을 완성한다고 해도 찜찜함은 남는 게 정상이다. 상위 영역에서 답이 안 나온다고 해도, 상위 영역의 문제를 충분히 고민해야 하위 영역을 이어서 고민할 수 있다.

    잘 완성하는게 가장 좋겠지만, 안 된다면 엉망으로라도 완성하자. 다만 적어도 머릿속에 뭐가 엉망이었는지, 개선은 어떻게 할 수 있을지는 알고 가야 할 것이다.

     

     

    댓글

Designed by Tistory.