나 크래프톤 다녀왔다.

tamagoyakii·2022년 9월 15일
3

42gg

목록 보기
3/5
post-thumbnail

42gg 서비스를 크래프톤에서 발표할 수 있는 기회가 생겼다! 한 달 전쯤에 스케줄이 확정이 되면서 코드 리뷰 준비를 정말 열심히 했는데, 드디어 그 결실을 볼 수 있다는 생각에 설레는 마음이 가장 컸던 것 같다. 지금까지 썼던 지식(?) 관련 글과 다르게 이 글은 그냥 멋진 기업에서 발표할 기회가 있었다는 뿌듯함과 드디어 발표가 끝났다는 후련함에 쓰는 자랑글이다.😁

🌠 발표

발표를 준비하는 멋진 김한결

발표는 크게 서비스 소개, Frontend, Backend의 세 파트로 나누어 준비했다. 서비스 소개는 하킴이가, 프론트엔드 파트는 우리의 멋진 리드 재영이가, 백엔드는 허 남준이 발표를 하기로 했다. 내가 맡은 부분에 대해 이야기하기 전에 서비스의 mvp 기능과 프론트의 전체 플로우 차트를 자랑하겠다. 다시 말하지만 이건 자랑글이다.

발표 준비에서 내가 맡은 부분은 시퀀스 다이어그램이었다. 저번에 시퀀스 다이어그램을 만들 때 페이지를 나누어서 각자의 스타일대로 만들었었는데, 내 시퀀스 다이어그램을 팀원들이 좋게 봐주어서 그 스타일을 토대로 발표용 시퀀스 다이어그램을 다시 만들기로 했다. 아래는 그 결과물이다.


발표 시간이 30분으로 제한되어 있었기 때문에 우리는 소개하고 싶은 부분을 명확하게 정해서 간단명료하게 준비해야만 했다. 프론트는 "매칭"이라는 기능이 42gg 서비스에서 가장 주요하다고 생각했기 때문에 매치 페이지를 위주로 발표를 구성했다.

위의 시퀀스 다이어그램과 코드는 유저가 매치 페이지에 접속했을 때의 데이터 요청과, 슬롯을 클릭했을 때의 이벤트 처리 방식을 보여준다. 처음에 멘토님께서 시퀀스 다이어그램에 코드를 매핑해서 발표를 준비해 보라고 하셨을 때는 "시퀀스 다이어그램에... 코드를...? 어떻게..? 너무 복잡하진 않을까...?"라는 생각을 했었는데, 역시 사람이 끝없이 고민하고 노력하면 못할 게 없다는 교훈을 얻었다.🥲


다음은 모달과 관련된 시퀀스 다이어그램이다. 프로젝트 초반에 각자 맡은 페이지에서 개별적으로 모달을 추가하다보니 코드가 중구난방으로 작성되는 바람에 일관성이 떨어지고 반복되는 코드가 많아지는 문제가 발생했는데, 이를 해결하기 위해 우리 팀의 똑순이 수정이가 리팩토링한 부분이다.

Recoil로 관리되는 모달 상태에 modalName이라는 요소로 모달의 보임/안보임을 결정하며, 어떤 모달이 나타날 것인지에 대한 결정은 findModal() 이라는 함수에서 결정하게 된다.

모달 생성기에 대한 내용 다음에 매치 페이지의 대표 모달인 MatchEnrollModal, 즉 매치를 등록해주는 모달에 대한 내용을 추가했다. 매치 등록 모달은 서버에 post 요청을 보낸 뒤 받게 되는 response에 따라 나뉜다.

🌠 피드백

사실 발표를 할 때 프론트 개발자분이 계시지는 않았다. 그러다 보니 코드에 대한 상세한 리뷰는 받을 수 없었다. 하지만 기획팀 PM 분들이 계셔서 서비스에 대한 전반적인 평가와 개선할 부분에 대한 내용들을 들을 수 있었다. 그 중 내가 기억에 남는 내용들을 이렇다.

  1. 서비스를 만들 때 가장 중요한 부분은 아무래도 수익성이다. 아무리 좋은 서비스라도 수익성을 고려하지 않는다면 금방 사라지고 만다. 서비스를 sustainable 하게 유지할 수 있는 장치가 필요하다.

  2. 회사에서 가장 중요한 것 중 하나가 이슈 트래킹이다. 회사에서 많은 인원이 하나의 서비스에 임하는 경우 이슈 트래킹이 잘 되어야 문제에 대한 빠른 인지와 처리가 가능하다. 또, 깃허브 이슈 등이 잘 정리되어 있어야 뉴비가 들어왔을 때 빠른 온보딩이 가능하다. (깃허브 위키 등은 최신화가 잘 되지 않기 때문에!!)

  3. <아마존처럼 회의하라>라는 책을 추천한다. 브레인스토밍 회의는 길어도 좋다. 하지만 그 외의 회의는 짧을수록 좋다. 회의 아젠다를 작성해서 회의 전에 모든 내용을 숙지한 상태로 논의할 내용만 말하도록 하자. "그것도 됩니다." 금지!!!! 번복 금지~~!!~!~!!

  4. 서비스를 어떻게 확장할 것인지가 중요하다. 현재 서버 한 대를 기준으로 운영되고 있는데, 여러 대를 사용하게 될 때의 문제점과 데이터가 많아졌을 때 우리 프로그램이 어떻게 견딜지에 대한 고민을 해보자.

  5. 라이브러리, 프레임워크, 아키텍처 등의 종류에는 끝이 없다. 어떤 게 더 좋은지에 대한 내용은 모두 이론일 뿐이다. 우리가 어떤 걸 사용할지에 대한 끊임 없는 고민하는 자세가 중요하다. 사용해보고 별로일 때 딴 걸 찾아도 된다.

🌠 진짜 피드백

마지막은 크래프톤에 다녀온 후 이호준 멘토님께서 코드에 대해 리뷰해 주신 내용이다. 큰 주제는 컴포넌트나 함수의 의존성에 대한 것이었다. 코드를 만드는 것보다 삭제하는 것이 가장 어려우며, 코드를 삭제했을 때 사이드 이펙트가 어디까지 가는지를 잘 봐야 한다고 하셨다.

가장 기본적인 예시는 if, else 문이었다. 아래의 예시는 42gg 매치 페이지에 있는 슬롯을 클릭했을 때의 이벤트를 처리하는 코드다.

  const enrollHandler = async () => {
    if (status === 'mytable') {
      try {
        const res = await instance.get(`/pingpong/match/current`);
        if (res?.data) {
          const { slotId, time, enemyTeam } = res.data;
          setModalInfo({
            modalName: 'MATCH-CANCEL',
            cancelInfo: { slotId, time, enemyTeam },
          });
        }
      } catch (e) {
        setErrorMessage('JH08');
      }
    } else if (userLive.event === 'match') {
      setModalInfo({ modalName: 'MATCH-REJECT' });
    } else {
      setModalInfo({
        modalName: 'MATCH-ENROLL',
        enrollInfo: { slotId, type, startTime, endTime },
      });
    }
  };

위와 같이 if(), else if(), .... else 로 깊이 들어가 버리면 각 스코프 간의 의존도가 높아져 버린다. 이를 해결하는 방법은 간단하다.

  const enrollHandler = async () => {
    if (status === 'mytable') {
      try {
        const res = await instance.get(`/pingpong/match/current`);
        if (res?.data) {
          const { slotId, time, enemyTeam } = res.data;
          setModalInfo({
            modalName: 'MATCH-CANCEL',
            cancelInfo: { slotId, time, enemyTeam },
          });
        }
      } catch (e) {
        setErrorMessage('JH08');
      }
      return;
    }
    if (userLive.event === 'match') {
      setModalInfo({ modalName: 'MATCH-REJECT' });
      return;
    }
    if (userLive.event === null) {
        setModalInfo({
        modalName: 'MATCH-ENROLL',
        enrollInfo: { slotId, type, startTime, endTime },
      });
	  return;
    }
  };

이렇게 if()return; if()return; 으로 끊어버리는 것이다. 굉장히 쉽다! 또 다른 방법은 조건문 전체를 배열 또는 객체로 만들어주는 것이다.

if (status === 조건a) {
	functionA
}
if (status === 조건b) {
	functionB
}
if (status === 조건c) {
	functionC
}

위와 같은 조건문을 어떻게 객체로 만들 수 있을까?

status = {
	"조건a" = functionA,
    "조건b" = functionB,
  	"조건c" = functionC,
}

이것도..? 쉽다! "이게 바로 객체지향 oop다!"라고 멘토님께서 말씀해 주셨다. 또, 코드를 만드는 코드를 짜야한다며 config 파일을 활용해 코드 제너레이터를 만들라는 이야기와 함께 예시도 보여주셨다. 우리는 c언어를 기초로 배우고 있기 때문에 위와 같은 방식이 익숙하지가 않아서 그렇다며... 어쩔 수 없다고 하셨지만, 아무래도 내가 너무 바보였다는 뉘우침과 함께 앞으로 꼭 저렇게 사고해 봐야지라는 오기가 생겼다.

🌠 마무리

정말 다시는 없을 좋은 경험이었다. 발표를 하면서 현직자 분들께 직접적으로 배운 것들도 있지만, 발표 준비를 하면서 스스로 배운 것들도 많다고 생각한다.

우리 팀에게 좋은 기회를 주신 42서울과 이호준 멘토님, 그리고 크래프톤 관계자분들께 너무너무 감사하다는 말씀을 드리고 싶다. 우리 팀원들도 고생 많았다!!!💘

2개의 댓글

comment-user-thumbnail
2022년 9월 16일

정말 좋은 경험하셨네요! 너무너무 부럽습니다!! 시퀀스 다이어그램도 잘 만드셨네요. 많이 배우고 갑니다~!!!

답글 달기
comment-user-thumbnail
2022년 9월 19일

글을 읽으면서 크래프톤 발표 준비하며 고민했던 것들을 다시금 리마인딩할 수 있었습니다! 정리 너무 잘하셨고 좋은 글 감사합니당~

답글 달기