React밖에 모르는 당신에게. GatsbyJS한 잔, '채용~'

혹시 다들 뱅크샐러드 채용 사이트 보셨나요? 🙋🏻‍♂️

안녕하세요, 이번에 뱅크샐러드 채용 사이트와 기술 블로그를 새롭게 개발한 Web Engineer 이동근입니다.

뱅크샐러드는 마이데이터 서비스 제공을 위해 다양한 직군에서 많은 인원을 채용하고 있습니다. 이에 맞춰 뱅크샐러드의 비전과 이야기, 채용 정보를 더욱 더 잘 전달하기 위해 작년 말부터 새로운 채용 사이트와 블로그를 준비하고 있었습니다.

😎 [대규모 채용 나선 뱅크샐러드… 인재 추천하면 1인당 2000만원]

새롭게 채용 사이트를 만들면서 GatsbyJS를 사용하였는데요. React를 할 줄 알면 매우 쉽게 사용할 수 있지만 직접 배포해 보지 않으면 놓치기 쉬운 문제들도 꽤 있었습니다. 지금부터 채용 사이트 출시까지의 과정에서 어떤 고민과 문제가 있었는지 그리고 어떻게 풀어 나갔는지 이야기 해보려고 합니다.

👋 시작하기 전

뱅크샐러드는 프로젝트를 진행할 때 개발자를 포함 모든 팀원이 함께 문제를 해결하기 위해 기획부터 자유롭게 의견을 내고 참여합니다.

회사 전반적으로 오프라인 커뮤니케이션보다는 문서를 통한 온라인 커뮤니케이션을 지향하고 있는데요. 이번 프로젝트의 경우에도 문제의 원인 파악 및 이를 해결하기 위한 목표와 계획을 하나의 프로덕트 스펙 문서로 정리해 현재 상황과 개발 시 고려해야 할 것들을 빠르게 파악할 수 있었습니다. (이번 채용 사이트 개선은 다른 작업 중 프로젝트 중간에 급하게 투입 되었지만 반나절만에 모두 파악 완료 👍)

프로덕트 스펙

문서는 최고의 커뮤니케이션 도구 입니다.

현재 상황과 고려해야 할 것들

검색엔진 최적화(SEO)

채용 사이트의 가장 큰 목적은 지원자 분들에게 우리 회사의 비전과 채용 관련 정확한 정보를 최대한 자세하게 전달하는 것입니다.

지원자 분들이 검색창에 검색했을 때 원하는 정보를 쉽게 찾을 수 있도록 검색 결과 상단에 노출되게 최적화하는 것이 첫 번째 관문이라 생각했습니다.

뱅크샐러드 채용 사이트 유입 경로

채용 관련 키워드 검색으로 들어오는 비중

요즘에는 CSR(Client Side Rendering) 방식도 SEO(Search Engine Optimization)작업이 충분히 가능하고, 검색엔진이 크롤링하는 데 큰 문제가 없습니다. 그러나 구글 외에 다른 검색엔진에서도 SEO 최적화를 하기 위해 좀 더 유리한 방향을 선택하는 것이 좋다고 생각했습니다. 기본적으로 CSR은 클라이언트 측에서 렌더링(Rendering)이 진행되고 컨텐츠가 만들어집니다. 따라서 미리 완성된 사이트를 훑으며 크롤링 하는 검색엔진에서는 검색이 되지 않을 수 있습니다.

따라서 static 한 페이지SSR(Server Side Rendering)로 개발하는 방향을 고려하였습니다.


누가 관리하지?

관리 포인트를 크게 두 가지로 나누었습니다. 첫 번째는 ’콘텐츠 관리는 누가하지?’, 두 번째는 ’이슈 대응이나 기능 추가는 누가 하지?’ 의 관점으로 나누어 고민하였습니다.

  • 콘텐츠 관리

    현재 뱅크샐러드에서는 90개 직군에서 200명 정도의 인원을 채용을 하고 있습니다. 이러한 채용 정보는 각 직군 및 팀별 채용 여부에 따라 수시로 변경될 가능성이 있습니다. 뿐만아니라 팀원 인터뷰, 뉴스 기사, 블로그 등의 정보도 게시될 예정이었습니다. 때문에 개발자의 도움 없이 자유롭게 콘텐츠를 관리할 수 있어야 한다고 생각했습니다.

    직접 static하게 추가하거나, JSON을 작성하여 추가하는 방식은 인사팀과 개발자 모두에게 매우 고통스러운 일일 것 같았어요. 😇

  • 유지보수의 측면

    향후 공식 블로그나 채용 만 전담하는 팀을 꾸릴 계획은 있으나, 현재는 따로 없습니다. 그래서 누구나 쉽게 이슈에 대응 할 수 있어야 하고, 새로운 스펙을 추가할 때 부담 없이 투입될 수 있어야 합니다.

위의 두 가지 관점을 고려해 GatsbyJS를 선택하게 되었습니다.


🤷‍♀️ 왜 GatsbyJS죠?

React에 가장 익숙합니다.

현재 뱅크샐러드 내 Web Front-End팀의 경우 React를 가장 활발하게 사용하고 있습니다. 서비스의 성격에 따라 SSR Base의 서비스나, jQuery 등을 사용한 웹 페이지도 존재하나 다수의 팀원들이 부담 없이 참여하기에는 React를 사용하는 것이 더 좋다고 생각했습니다. (컴포넌트 단위로 관리하는 것이 편하다는 판단도 있었고요.)

쉽게 SEO와 성능, 두 마리 토끼를 모두 잡을 수 있습니다.

GatsbyJS는 기존에 블로그 제작에 많이 사용되었던 Jekyll과 같은 정적사이트 생성기입니다. JavaScript가 실행되면 빈 HTML 페이지 안에 마크업을 추가해주는 SPA(Single Page Application)와 다르게, 개발 후 Build 과정에서 마크업이 생성됩니다.

CSR 페이지와 static 페이지

리액트로 만든 SPA 페이지(좌) / GatsbyJS로 만든 static 페이지(우)

둘 다 React를 통해 개발했지만 만들어진 페이지가 다른 것을 볼 수 있습니다. 페이지 내 모든 콘텐츠가 생성 되어있기에 SEO를 잘 챙겨갈 수 있습니다. GatsbyJS는 단순히 static 페이지를 만들어 주는 것으로 끝나는 것이 아니라, 필요에 따라 CSR과 SSR, lazy loading을 적절히 섞어 사용할 수 있어 성능 면에서도 단순 static 페이지보다 큰 이점이 있습니다.

콘텐츠 관리가 쉽다.

기본적으로 GatsbyJS는 JAMstack이라고 하여 콘텐츠를 Markdown으로 관리하며, 빌드 시 정해진 HTML 템플릿에 Markdown으로 작성된 내용들이 하나 하나 담겨집니다. 그렇기 때문에 직접 static하게 콘텐츠를 추가하거나, JSON과 같은 방식을 이용하지 않더라도 비교적 쉽게 콘텐츠를 관리할 수 있습니다. 추가로 마크다운 작성법을 모르더라도 텍스트 에디터가 포함된 CMS를 매우 쉽게 붙일 수 있습니다.

cms


🙃 새로운 Stack을 도입한다는 것

기술 문서를 읽고, 좋은 점과 우려되는 부분을 충분히 파악했음에도 새로운 기술스택을 도입하는 것은 생각보다 쉽지 않은 일 이었습니다. 혹여 내가 선택한 방법보다 더 나은 방법들은 없을까? 놓치고 있는 부분들은 없을까? 등의 고민들로 확신이 서지 않는 경우가 있기 때문인데요.

이러한 상황을 타개하기 위해 뱅크샐러드는 개발하는 이유, 목표, 계획, 우려되는 부분, 질문 등을 테크 스펙이라는 문서로 작성하여 개발 전에 기술 전체 직군에 공유하고, 상황에 따라 피드백을 받거나 팀원들에게 계획을 알리고 있습니다.

그 덕분에 놓치고 있던 부분을 다른 직군의 팀원이 챙겨주기도 하고, 관련 경험이나 지식이 더 많은 팀원이 개선책을 제시하기도 합니다. 이러한 과정 이후에 개발을 할 경우 더욱 안정감 있고 추친력 있게 개발에 집중 할 수 있습니다.

techspec

문서는 최고의 커뮤니케이션 도구 입니다. (2)

👨‍🏭 서비스를 만들면서


관심사의 분리(Separation of Concerns)

GatsbyJS는 기본적으로 React로 개발하는 방법과 매우 유사합니다. 일부 콘텐츠를 관리하기 위한 contents 폴더 또는 Gatsby 빌드 방법이나 설정을 위한 gatsby-OOO.js(node, ssr, browser 등)를 제외하고는 평소 저희 웹 팀이 사용하는 React 구조를 유사하게 가져갈 수 있었습니다.

전체적으로 코드가 복잡하면 다른 사람(팀원 또는 미래의 나자신)이 코드를 파악하는데 시간이 걸리고 유지보수가 힘들어지기 때문에 관심사를 분리해서 최대한 단순하고 직관적으로 가져가려 했습니다.


화면 구조

컴포넌트와 컨테이너 페이지 container 구조

하나의 화면(page)에 비즈니스 로직, 데이터, 컴포넌트를 모두 관리하는 것이 아니라 pages, containers, components로 나누어 화면을 관리하였습니다.

components

재사용이 가능한 요소들을 모아 컴포넌트로 구성되어 있습니다. 순수한 데이터 형태를 props로 받아오며, 다양한 container에서 사용 됩니다.

containers

container는 화면을 구성하기 위한 영역에 해당하며 이며 여러개의 section을 가지고 있습니다. (container내 하위 폴더가 section 입니다.) 또한 section은 여러개의 component들의 조합으로 구성되어있습니다.

기본적으로 page와 container는 1:1 매칭 된 구조를 가지고 있으며 데이터를 가져오거나, 비즈니스 로직이 포함됩니다.

pages

pages에 존재하는 파일 이름을 기준으로 서비스의 경로가 생성됩니다. 해당 파일은 경로 이름과 SEO를 위한 title, description 등을 추가하며 콘텐츠들은 모두 container에서 관리하였습니다.

이 이외에도 gatsby-node.js때 사용 될 template들은 templates 폴더에서 관리됩니다.


데이터 호출

기본적으로 GatsbyJS 문서를 보면 아래와 같이 데이터를 호출하여 사용합니다.

const Post = () => {
  const data = useStaticQuery(graphql`
    query {
      site {
        siteMetadata {
          ... {
            frontmatter {
              title,
              description,
              tags,
              ...
            }
          }
        }
      }
    }
  `);
  
  return (
    <article>
      <h1>{data.allMarkdownRemark.nodes[0].frontmatter.title}</h1>
      <p>{data.allMarkdownRemark.nodes[0].frontmatter.description}</p>
    </article>
  );
};

위의 예시 코드는 짧아 매우 단순해 보이지만 실제로는 쿼리의 양이 매우 길며, 비즈니스 로직이 들어가거나, 마크업이 길어질 경우 코드의 복잡도가 매우 높아집니다.

데이터를 호출하는 부분을 react hook으로 만들어 복잡도를 줄였습니다.

const Post = () => {
  const { frontmatter: { title, description } } = useBlogDetail();
  
  return (
    <article>
      <h1>{title}</h1>
      <p>{description}</p>
    </article>
  );
};

놀랍도록 편리한 Gatsby Plugins

GatsbyJS는 다양한 플러그인들을 제공하고 있습니다. 리액트를 사용하면서 자주 사용하는 Package들을 Gatsby에서도 쉽게 사용할 수 있도록 만들어 둔 것인데요, 이러한 플러그인을 활용해 사용자가 더 편하게 웹 페이지를 제작할 수 있습니다. 예를 들면 React에서는 sitemap을 만들기 위해 react-router-sitemap을 설치하고 react-router에 대한 내용을 바꾸는 등의 번거로운 과정이 필요하지만, GatsbyJS에서는 플러그인을 활용하면 단 1줄로 sitemap을 만들 수 있습니다.

gatsby-plugin-sitemap을 설치하고 gatsby-config.js에 연결만 해주면 끝! 🤭

이 이외에도 다수의 설정들을 React보다 더욱 쉽게 추가할 수 있습니다.

GatsbyJS로 프로젝트를 만들면서 유용하게 사용했던 Plugin들을 간단하게 소개하겠습니다.


SEO를 위한 Plugin


그 외


Metadata로 DB를 대체

GatsbyJS는 gatsby-transformer-remark 라는 Plugin을 통해 markdown으로 작성된 콘텐츠들을 HTML 또는 원문, metadata로 가져올 수 있습니다. 보통 이것을 활용해 template에 markdown으로 작성 된 글을 불러와 적용하는 방법으로 블로그를 만드는데, 이 방법을 응용하여 채용 공고 페이지를 구현 하였습니다.

채용공고

채용하고자 하는 조직과 직군, 직군별 세부 카테고리들을 나누기 위해 metadata를 활용 했습니다.

keyword: jd
label: tech
tag: Web Front-End
jd: Junior Web Front-End Engineer
organization: Data Foundation
recruit_url: ''

markdown 상단에 직군(label), 세부직군(tag), 직무명(jd) 과 같이 필터링 할 내용들을 추가하고 key : value 형태로 불러와 필터링해서 하나의 Page에서 여러 채용 정보들을 볼 수 있게 했습니다.


🤦🏻‍♂️ GatsbyJS를 쓰면서 힘들었던 점 없나요?

휴… 전반적으로 매우 만족스러운 개발이었으나, 배포하기 전 까지는 미처 알지 못했던 이슈들이 있었습니다.

대체로 개발 중에 GatsbyJS가 동작하는 과정과 빌드 후 동작하는 과정이 달라서 생긴 이슈들이었는데 꼭 참고하시면 좋을 것 같습니다.

빌드 할 땐 window 객체를 사용할 수 없어요!

누군가 공유한 채용 정보를 클릭해 사이트에 들어왔을 때는 보통 해당 채용 정보를 바로 보여주게 됩니다.

공유하기
URL Params를 분석하여 알맞는 내용을 보여준다.

공유된 URL에는 조직(organization)이나 직무(category) 등의 정보들이 parameter로 담겨져 있는데요. 해당 정보들을 가져오기 위해 window.location 정보들을 접근해서 사용하고 있었습니다. (이 이외에도 화면 사이즈나, 스크롤 이벤트에서도 사용)

개발 중에는 React와 동일하게 CSR과 동일한 환경에서 동작하기 때문에 window 객체가 존재 하지만 빌드 중 에는 브라우저 환경이 아닌 Node 환경에서 빌드를 하기 때문에 window 객체가 존재하지 않습니다. 만약, window객체를 사용해야 한다면 아래와 같은 방법들을 사용하여 우회해야 합니다.

  1. window가 존재하는지 확인

    const isClient = typeof window !== 'undefined';
    
    if (isClient) { window.~~~ }
  2. useEffect hook이나 componentDidMount 와 같은 곳에서만 사용

사이트 최초 진입 페이지 Render와 그 이후 Render가 달라요!

위에 window 이슈에서 언급한 것 처럼 개발 중에는 React와 동일하게 동작합니다. 하지만 빌드 이후에 만들어진 페이지의 경우에는 다릅니다. SSR로 빌드한 경우에는 상황이 다르지만 SSR을 사용하지 않았다면 다음과 같이 동작하게 됩니다.

개츠비 라이프 사이클

최초 진입 시에는 이미 마크업이 다 그려진 상태에서 내려오기 때문에, JS등을 통해 Dom Render를 할 경우 의도와 다르게 동작할 수 있습니다.

예를 들면, PC와 모바일에서 각각 다른 화면들을 보여줘야 하는 경우들이 있습니다. 직무 선택 화면

처음엔 해당 화면을 다음과 같이 구현 하였는데요.

const { isMobile, setIsMobile } = useState(false);

useEffect(() => {
  setIsMobile(화면 size 체크);
}, []);

<div>
  {isMobile ? <MobileNav /> : <DesktopNav />}
</div>

페이지 내 이동 중 해당 코드를 직면하였을 때에는 의도한 대로 잘 동작하겠지만, 최초 진입 시에는 다른 화면을 맛보실 수(?) 있습니다. (짜릿해! 🌶)

결과

위 문제는 최초 진입 시 에만 문제가 되며 그 이후 이벤트(스크롤, 화면 사이즈 변경 포함)에는 의도한대로 JS 코드가 동작하기 때문에 ‘static HTML를 보여준 뒤 JS가 동작’하는 GatsbyJS의 동작 원리를 생각하고 구현 하거나, 미디어 쿼리를 사용 할 수 있는 상황이라면 반드시 미디어 쿼리를 사용 하는 것이 좋습니다.


👍 마무리

기술 블로그와 채용 사이트를 개선하면서 GatsbyJS를 사용한 건 매우 좋은 선택이었다고 생각됩니다.

팀원들에게 쉽고 익숙한 구조와 개발 언어(React)를 선택한 덕분에 소소한 버그가 발생하거나 기능 개선을 할 때, 웹 팀뿐 아니라 다른 팀원들도 모두 직접 참여하고 있습니다. 또한 채용 정보 등의 콘텐츠도 CMS를 통해서 인사팀에서 편하게 수정하고 있고요.

아마, React를 사용했다면 채용 정보를 담은 DB를 설계하고, 데이터를 주고받을 Server를 개발하는 등 지금보다 더 많은 리소스를 사용했을 거라 생각됩니다.

React와 GatsbyJS를 비유한다면 마치 레고와 듀플로 블록과 같은 느낌입니다.

리액트와 개츠비

레고(좌)와 듀플로 블록(우)

GatsbyJS는 복잡한 로직을 구현하기에는 정적 사이트 생성기라는 한계가 존재하지만, 단순한 로직으로 구성된 서비스를 만들 경우에는 리액트보다 더 쉽고 빠르게 무언가를 만들 수 있는 좋은 대안이 됩니다.

새롭게 만들어진 채용 사이트와 블로그가 배포된 이후로 지원자의 비율이 두 배나 늘었으며, 잘 된 웹사이트를 소개하는 곳인 굿디자인 웹에서 Winner prize 수상을 하였습니다.🎉

🧐 아직 구경안해보셨다면! 한번 들어와 구경해주세요. 지원하기 버튼을 통해 보실 수 있습니다. 😁

보다 빠르게 뱅크샐러드에 도달하는 방법 🚀

지원하기