[회고] 기업협업 : 스톡폴리오

i_sy_code·2022년 6월 7일
4

부트캠프 회고

목록 보기
4/4
post-thumbnail

🌱 회사 소개

스톡폴리오(Stockfolio)는 누구나 손쉽게 크리에이팅할 수 있도록 돕고, ‘영상 콘텐츠 제작의 간소화’ 를 진행하고 있는 스타트업이다.
영상 클라우드, 스톡 영상 제공, 편집자 매칭 등의 다양한 서비스를 통해 건강한 콘텐츠 생태계를 만드는 것을 목표로 한다.


🌱 프로젝트 소개

영상 컨텐츠를 검수하기 위한 사내 모니터링툴을 개발했다. 대기중, 반려, 승인으로 나누어 검수 상태를 진단하며 관리자가 반려 사유를 작성하면 반려 기록이 쌓이고, 승인시 승인 영역으로 이동한다.

기술 스택의 경우 다음과 같다.
프론트 : Typescript / React / Mobx / Styled component
백엔드 : Go-lang / Gorm / Mysql

🧷 Frontend Github Repository
🧷 Backend Github Reopsitory
🧷 모니터링툴 시연 영상


🌱 개발 Flow

지난 한달간의 진행 상황이 담긴 우리팀 노션이다.
첫 주차에는 사수님께서 새로운 기술 스택에 대한 세션을 진행해주셨고, 특히 컨벤션 작성과 아토믹 디자인 분석에 많은 노력을 기울였다.
2주차는 레이아웃과 기능 개발을, 3주차엔 API 연결을 진행했으며
4주차에는 전체적인 리팩토링과 QA를 통해 더 클린한 코드를 만들고자 했다.

🎈 협업 방식

- 전체적인 개발은 Figma를 토대로 진행

요구사항에 맞추고자 세세한 기능에 대해서도 디자이너님과 많이 소통했다.

- 협업 Tool로 노션과 github issue 사용

아침마다 데일리 미팅을 진행하고, git flow를 적용해 branch와 이슈를 관리했다.

- 에픽, 스토리, 태스크로 큰 틀을 잡고, 태스크 이슈 넘버로 브랜치명 지정

이슈 넘버와 PR을 연동해 올리면 사수님께서 검토 후 피드백을 거쳐 merge를 진행했다.

크지 않은 기업임에도 체계화가 잘 되어있어 협업하는 방식을 제대로 배운 것이 굉장히 좋았다.




🌱 코드리뷰

본격적인 개발에 들어가고, 매일 6시엔 코드리뷰를 해주셨다. 매일 결과물이 나와야한다는게 부담이었지만,
미처 캐치못한 부분을 지적받은 후 리팩토링 하고나면 코드리뷰의 중요성 아니, 위대함을 느꼈다.
내가 삼항연산자를 비효율적으로 쓴다는 것도 알게 됐고,
왜 그렇게 코드를 짰는지에 대한 이유가 항상 명확해야 함도 깨달았다.

한 번 section 태그를 쓴 이유에 대해 질문 받았을 때, 비슷한 기능을 묶는 단위라 생각했다 답한 적 있다.
하지만, section 태그란 타이틀을 가진, 하나의 의미를 띄는 영역을 나타내는 것이다.
나의 얕은 공부와 자의적 해석이 코드에 개입했음을 깨달은 순간이었다.
논리적 사유를 바탕으로 코드를 짤 수 있어야겠다.

부끄럽지만 내 코드가 리뷰에 따른 리팩토링 후 얼마나 가독성 높아지고, 명료화 됐는지 비교해보려 한다.
버튼 48개에 대한 테마화를 진행한 컴포넌트다.

코드리뷰 전

import * as React from 'react';
import styled, { css, DefaultTheme } from 'styled-components';

export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  btnType: 'highBtn' | 'lowBtn';
  width: string;
  btnTheme: 'red' | 'pink' | 'blue' | 'sky' | 'purple' | 'violet' | 'black' | 'white';
  fontColor: keyof DefaultTheme['colors'];
}

const Btn = styled.button<ButtonProps>`
  ${({ theme, width, btnTheme }) => css`
    width: ${width};
    border: none;
    font-weight: ${theme.fonts.weight.bold};
    text-align: center;
    cursor: pointer;
    &:hover {
      box-shadow: ${btnTheme === 'white' ? '' : theme.hoverShadow[btnTheme]};
    }
    &:active {
      box-shadow: ${btnTheme === 'white' ? '' : theme.pressedShadow[btnTheme]};
    }
  `}
`;

const HighBtn = styled(Btn)`
  ${({ theme, btnTheme, fontColor }) => css`
    height: 56px;
    border-radius: 20px;
    background-color: ${theme.colors[btnTheme]};
    color: ${theme.colors[fontColor]};
    font-size: ${theme.fonts.size.ms};
    line-height: ${theme.fonts.lineHeight.ms};
  `}
`;

const LowBtn = styled(Btn)`
  ${({ theme, btnTheme, fontColor }) => css`
    height: 36px;
    border-radius: 12px;
    background-color: ${theme.colors[btnTheme]};
    color: ${theme.colors[fontColor]};
    font-size: ${theme.fonts.size.xxs};
    line-height: ${theme.fonts.lineHeight.xs};
  `}
`;

export default function TextBtn({
  btnType,
  ...props
}: ButtonProps): JSX.Element {
  return btnType === 'highBtn' ? (
    <HighBtn btnType={btnType} {...props} />
  ) : (
    <LowBtn btnType={btnType} {...props} />
  );
}



코드리뷰 후

import * as React from 'react';
import styled, { css, DefaultTheme } from 'styled-components';

export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  btnType: 'highBtn' | 'lowBtn';
  width: string;
  btnTheme: keyof DefaultTheme['pressedShadow'] | 'white';
  fontColor: keyof DefaultTheme['colors'];
}

const Btn = styled.button<ButtonProps>`
  ${({ theme, btnType, width, btnTheme, fontColor }) => css`
    width: ${width};
    height: ${btnType === 'highBtn' ? `56px` : `36px`};
    border-radius: ${btnType === 'highBtn' ? `20px` : `12px`};
    border: none;
    background-color: ${theme.colors[btnTheme]};
    color: ${theme.colors[fontColor]};
    font-size: ${
      btnType === 'highBtn'
        ? `${theme.fonts.size.ms}`
        : `${theme.fonts.size.xxs}`
    };
    font-weight: ${theme.fonts.weight.bold};
    line-height: ${
      btnType === 'highBtn'
        ? `${theme.fonts.lineHeight.ms}`
        : `${theme.fonts.lineHeight.xs}`
    };
    text-align: center;
    transition: ease-in-out 0.15s;
    cursor: pointer;
    transition: ease-in-out 0.15s;

    &:hover {
      ${
        btnTheme === 'white'
          ? `color: ${theme.colors.gray2}`
          : `box-shadow: ${theme.hoverShadow[btnTheme]}`
      }
    }
  
    &:active {
      ${
        btnTheme === 'white'
          ? `color: ${theme.colors.black}`
          : `box-shadow: ${theme.pressedShadow[btnTheme]}`
      }
  `}
`;

export default function TextBtn({ ...props }: ButtonProps): JSX.Element {
  return <Btn {...props} />;
}

  • 필요에 따라 타입을 optional로 줄 수 있음
  • 삼항 연산으로 타입에 제약을 걸 수 있음
  • 단일화할 수 있는 스타일은 최대한 하나로 묶어(테마화) 코드를 줄일 수 있음
  • 복잡한 로직이 들어가지 않는 props는 따로 분리하기보다 삼항 연산으로 처리하는 게 좋음
    등을 해당 코드 리팩토링을 통해 깨닫게 됐다.




🌱 회고

기업협업을 나가기 전 나의 각오는 1인분의 몫은 해내자!였다. 굉장히 잘하는 프론트 두 명과 함께 나가게 되어 부담도 느꼈고, 민폐를 끼칠까 불안했다. 역시 그 두 분에 비해 진도가 늦어졌지만, 주말에 위워크에 나가 모르는 부분을 질문하거나 늘 옆자리에서 끊임없이 물어보며 많은 도움을 받았다.

가장 힘들었던 부분은 바로 공간적인 부분이었는데, 아무래도 작은 스타트업이다보니 공간이 협소해 개인 자리 없이 한 테이블에서 5명이 프로젝트를 진행하게 됐다. 하지만 역시 사람은 적응의 동물이라 나중엔 멀리 떨어져있으면 옆구리 시리다는 농담도 나왔다. 모든건 생각하기 나름이라고 사고를 전환하자 단점이 장점이 됐다. 맨날 같이 붙어 있으니 회의 시간을 따로 잡지 않아도 바로 미팅을 한다거나, 에러도 같이 해결할 수 있었다.

무엇보다 개발을 잘하는 사람은 어떻게 모르는 것을 찾고, 적용하는지 바로 지켜볼 수 있어 좋았다. 코드리뷰를 받으며 사수분께도 정말 많은 걸 배웠지만, 동료를 통해 좋은 개발 태도를 배울 수 있어 너무나 뜻깊은 시간이었다. 나도 그런 동료가 될 수 있도록 멋지게 성장해 나가고 싶다.

profile
삶은 끊임없이 나의 한계와 맞서는 일이다.

2개의 댓글

comment-user-thumbnail
2022년 6월 13일

저도 스톡폴리오에서 기업협업을 했었는데 그 때의 기억이 떠오르네요!! 수고하셨습니다!

1개의 답글