ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 핵심 가치에 집중하니 크기는 줄어도 내용은 견고해졌다
    Today I Learned 2022. 11. 11. 23:51

     

    20주차 금요일 성수 코딩 도장 일과를 진행하면서 느꼈던 점을 정리했다.

     

    오늘의 최소 기능 구현: 참가 신청하기

    오늘은 게시물 리스트를 보고 사용자가 신청 버튼을 누를 경우 참가자 수가 증가하고, 버튼이 신청취소로 바뀌는 기능을 구현했다.

     

    왼쪽은 신청 전, 오른쪽이 신청 후

     

    이전에 작성했던 화면과 작업 계획은 잠시 내려놓고, 핵심 가치에 집중해서 기능을 설계하고 구현을 진행하면서 느낀 점이 몇 가지 있다.

     

    소스코드는 설계를 보면서 작성하고 있다

    지난 주까지는 소스코드를 작성할 때 작업 Task 목록에서 잠깐 구현 방식을 고민한 다음에 소스코드를 작성했는데, 중간중간 멈칫할 때가 많았다. 기능 자체가 너무 크다는 점과 시너지를 일으키면서 인지 부하가 계속해서 일어났다.

     

    반면 설계 문서에서 작성한 API의 내용을 보면서 구현을 진행했을 때는 설계 문서가 일종의 가이드 역할이 되어주는 느낌이 있었다. DTO의 데이터로 주고받기로 한 것이 무엇이었고, 네이밍은 무엇으로 하고, 어떤 레이어를 구현해야 하는지를 결정해놓았기 때문에 가이드를 보고 따라가기만 하면 되었다. 인지 부하가 줄어들자 코드를 치는 중간중간 고민하는 시간이 많이 줄어들었고, 예상했던 스토리 포인트 사용 시간에 맞춰 구현을 진행할 수 있었다.

     

    내용은 적지만 직관적이다

    사용성을 위해서는 참고했던 어플리케이션이나 내가 작성했었던 화면에 나타나는 정보 정도는 나타나야 한다고 생각했다.

    그런데 부수적인 것들을 모두 쳐내고 '종목과 날짜, 시간, 장소를 확인한다' '신청을 한다'에만 집중하는 화면이 생각보다 직관적이고 이해하기 쉽다는 느낌이 들었다.

     

    기능의 크기가 작기 때문에 작성을 견고하게 할 수 있다.

    가장 이점이라고 느꼈던 부분이다. 처음부터 한번에 많은 내용을 리스트로 반환해주는 기능을 만들려고 했던 지난 주차에는 구현 속도가 많이 느렸고, 테스트 코드를 작성하지 못했기 때문에 기능을 구현한다 한들 의미가 없었다. 반면 어제부터 구현했던 최소 기능의 리스트 조회와 참가 신청 기능은 모두 테스트 코드로 동작을 검증하고 있다.

     

    테스트 코드로 정의한 인터페이스에 맞춰서 구조를 짤 수 있기 때문에 해야 할 작업의 세부 단계가 명확해졌고, 안정적인 로직을 갖췄다는 믿음을 줄 수 있게 되었다.

     

     

     

    굳이 미리 분리를 걱정할 필요는 없다

    운동 참가 신청을 구현하기 위해 신청과 관련된 상태와 API 호출을 수행하는 Store와 ApiService를 생성했다. 그러면서 한 가지 마음에 걸리는 부분이 있었다.

     

    Store의 테스트는 msw 라이브러리로 가짜 서버를 만들어 정해진 응답만을 돌려주게 하는 방식으로 실제 서버가 없어도 Store의 동작을 검증하게 할 수 있다. 아직까지는 하나의 테스트 서버 소스코드에 모든 응답 DTO의 형식을 작성하고 있는데, Store와 API가 많아질수록 테스트 서버 소스코드의 길이가 너무 비대해질 것이 우려되었다.

     

    스토리 포인트를 1.5포인트 가량을 들여 테스트 서버 파일을 여러 개로 분리할 수 있을지 실험을 시도해보았다.

     

    먼저 testServer.js 테스트 서버 소스코드와 setupTestServer.js 테스트 서버 제어 소스코드를 분리하고, jest.config.js의 setupFilesAfterEnv 속성에 분리한 파일들의 경로를 추가하는 방식으로 시도해 보았다. 결과는 하나의 테스트 서버는 잘 실행되었지만, 다른 테스트 서버는 실행되지 않아 다른 테스트 서버로부터 응답을 받아야 하는 로직의 테스트가 시간 초과로 실패하는 것을 확인했다.

     

     

    잠시 도장에 내려오신 노아님께 분리를 어떻게 해야 할지 질문을 드렸는데, 이번에도 역시 다른 관점의 답변을 들을 수 있었다. 분리는 가능하지만, 분리할 시점이 아직은 아니라는 것이었다.

     

    아직 오지 않은 상황을 생각하면서 너무 일찍 구조를 짜는 것보다는, 개선이 필요한 시점이라는 판단이 들 때 분리를 시도해야 당위성이 있기 때문에 같은 정보를 찾아도 더 관심있게 집중해서 개선을 시도할 수 있다는 조언을 주셨다.

     

    다시 돌이켜 생각해보니 현재 작업에서 투자해야 하는 비용을 다소 가져와서 투자한 느낌이 있었다. 아직 분리할 정도로 테스트 서버의 크기가 크지 않았기 때문에 정보를 찾는 밀도도 그다지 높지 않았다.

     

    사용할 수 있는 시간이 많이 한정되어 있는 만큼, 작업 효율을 가장 낼 수 있는 시점을 구분할 수 있어야겠다.

     

    // testServer.js
    // 아직은 이 정도가 전부이다.
    
    const postTestServer = setupServer(
      rest.get(`${apiBaseUrl}/posts`, async (request, response, context) => {
        const accessToken = await request.headers.get('Authorization');
    
        if (accessToken) {
          return response(context.json({
            posts: [
              {
                id: 1,
                hits: 334,
                game: {
                  type: '축구',
                  date: '2022년 10월 19일 13:00~16:00',
                  place: '대전월드컵경기장',
                  currentMemberCount: 16,
                  targetMemberCount: 22,
                  isRegistered: false,
                },
              },
              {
                id: 2,
                hits: 10,
                game: {
                  type: '농구',
                  date: '2022년 10월 20일 15:00~17:00',
                  place: '잠실실내체육관',
                  currentMemberCount: 2,
                  targetMemberCount: 12,
                  isRegistered: true,
                },
              },
            ],
          }));
        }
    
        return response(context.status(400));
      }),
    
      rest.post(`${apiBaseUrl}/registers/games/:gameId`, async (request, response, context) => {
        const accessToken = await request.headers.get('Authorization');
        const { gameId } = await request.params;
    
        if (gameId === '1' && accessToken) {
          return response(context.json({
            gameId: 1,
          }));
        }
    
        return response(context.status(400));
      }),
    );

     

     

     

    댓글

Designed by Tistory.