안녕하세요 !

휴맥스 드림버스 컴퍼니에 지원했고, 서류 및 면접까지 합격해서 후기를 작성하고자 글을 써봅니다.

저는 프론트엔드 개발자를 희망하지만 APP마케팅&광고 직군에 지원해 합격했습니다 ! (SW 개발 직군이 없더라구요 .. )

 

🌝 드림버스 컴퍼니 ?

드림버스컴퍼니는 "고용노동부 미래내일 일경험 지원사업"을 통해 코멘토에서 다양한 기업과 운영하는 인턴십 프로그램입니다.

 

🚘 휴맥스 드림버스컴퍼니는 ?

휴맥스라는 기업이 참여한 드림버스 컴퍼니입니다. 합격하게 된다면 해당 기업에서 공통 교육 + 사전 직무 교육을 받고 남은 기간동안 일경험을 하는 프로그램 입니다.

 

 

📆 휴맥스 드림버스 컴퍼니 3차 모집 일정

2024 휴맥스 드림버스 컴퍼니 3차 일정은 다음과 같았습니다.

 

⏰ 인턴십 상세 일정

인턴십 상세 일정은 다음과 같습니다.

합격한다해서 일을 바로 시작하는 것은 아니고, 공통교육 및 사전직무교육을 수행한 이후 4주간 일 경험을 하게 됩니다.

 

👩‍💻 지원 과정

저는 APP 마케팅&광고 직군으로 지원했습니다.

너.. 개발자면서 왜 ..? 하시겠지만 UIUX를 분석하는 직군이라 도움이 될 것 같기도 하고 ... 호호.. 

📄 서류

드림버스컴퍼니 참여신청서를 다운받아 작성하면 됩니다. 저는 어떠한 경력도 없고, 마케팅과 광고 관련된 활동을 한 적은 더더욱 없습니다 그냥 제가 지금까지 개발자가 되기 위해서 했던 일련의 과정을 작성했습니다. 

 

경력 및 활동사항

경력 및 활동사항의 세부내용은 개조식으로 작성했습니다.

 

자기소개

제가 지금까지 해왔던 활동으로 어필했습니다. 

간단히 요약하자면

 

1. 드림버스컴퍼니 활동 및 해당 직무에 지원하는 이유는 무엇입니까?

저는 과거 프로젝트 중 모빌리티 관련 서비스 기획 및 개발 경험이 있습니다. 기획 과정에서 진행했던 타 모빌리티 서비스 UIUX 분석 경험과, 우리 서비스에 대한 홍보 전략을 세웠던 경험을 토대로 작성했습니다.

 

2. 자신의 강점 한 가지를 바탕으로 희망 직무에서 발휘될 수 있는 성과에 대해 기술해주시기 바랍니다.

1번에서 썼던 경험을 구체적으로 작성했습니다. 기획 단계에서 Figma를 사용해 조사한 정보를 문서화해 팀원들에게 공유한 경험을 적으며 문서화의 강점이 있다는 것을 어필했습니다. 

 

3. 지금까지 살아오면서 타인 또는 공동체를 위해 노력한 경험과 이를 통해 배운 점을 기술해 주시기 바랍니다.

팀 프로젝트 과정에서 팀원이 관련 지식이 없어 힘들어 하기 위해서 관련 지식에 대한 세미나를 열어 도왔었다는 이야기를 했습니다.

 

4. 어려운 환경이나 상황에 부딪혔을 때 이를 극복하기 위해 노력한 경험에 대하여 기술해 주시기 바랍니다.

팀 프로젝트에서 팀원이 본인이 맡은 일을 잘 하지 않아 프로젝트 진행이 느려졌던 경험이 있었는데, 소통과 스크럼 방식을 통해 극복한 경험을 적었습니다.

 

💪 서류 합격

서류 합격 후 2시간정도 뒤에 면접 일정 조율 메일이 옵니다. 보통 한 타임으로 정해져 있는데 해당 시간대에 불가하다면 따로 연락을 취하시면 됩니다.

 

💬 면접 준비

사실 지원분야가 제 전공이 아닌지라 어떤식으로 준비해야할지 막막했습니다. 아무래도 직무가 기술직이 아닌지라, 기술 관련 질문을 할 것 같진 않아서 인성질문 위주로 준비했습니다.

 

예상 질문 리스트

1. 1분 자기소개
2. 지원 동기 / 지원 직무에 대한 강점
3. 인턴십 과정에서 가장 얻어가고 싶은 부분
4. 경력사항, 활동경험
5. 장단점
6. 도전 경험
7. 갈등 경험
8. 기업에 대한 이해
9. 기업의 미래에 대한 생각
10. 입사 후 포부, 입사 후 기여
11. 마지막으로 하고 싶은 말
12. 질문

 

실제 질문

1. 본인 자기소개 해주세요
2. 팀 활동에서 어려움을 겪고 이를 해결하신 경험이 있나요 ?
3. 본인이 왜 해당 직군에서 강점을 드러낼 수 있나요 ?
4. 마지막으로 할 말 있나요 ?

 

면접 분위기

면접관 1: 지원자 5로 진행되었고 위 4가지 공통 질문만 하고 끝났었습니다.

5명씩 순서대로 돌아가면서 답을 하는데, 1번 지원자가 첫 질문에 맨 처음 대답을 했다면, 2번 질문에는 2번 지원자부터 답변을 하는 방식으로 순서도 돌아가며 대답했습니다.

 

전 사실 프론트엔드 개발자면서 왜 지원했냐는 질문정도는 받을 줄 알았는데 아니더군요 ㅎㅎ 딱히 개인에 대한 특별한 질문은 없었습니다.

 

해당 팀에서 저를 제외하곤 실무 경험이 있는 디자이너, 마케터분도 계셔서 살짝 쫄긴 했습니다..

해당 직무와 딱 맞는 분들이 계셔서 가망이 없겠다 싶었습니다. 그치만 면접 보면서 느낀건데 기본만 준비해도 될 것 같다는 생각이 들었습니다.

 

🎉 최종 결과 - 합격

솔직히 면접 끝나고나서 이거 내가 안 붙으면 이상한데 ? 생각이 들 정도로 잘 보긴 했습니다 ㅋㅋ

면접 이후 결과가 나오는 날까지 2주 정도 기다려야해서 그냥 붙었다 생각하고 살고 있었습니다.

사실 일경험 지원사업 제외하고 개발 관련 부트캠프가 쏟아지고있어서 참여하지 말까 ? 생각도 했지만, 좋은 경험이라 생각되어 참여하기로 결정했습니다. 

 

합격 메일

 

 

참여하며 배운 점에 대해서는 추후 글 써서 올리도록 하겠습니다 !

궁금하신 점은 댓글 주세욥 (◕‿◕)

0. 공부하게 된 계기

  • Hipspot 프로젝트를 진행하면서 상태관리 라이브러리로 recoil을 사용했습니다.
  • 그러나 Hipspot 프로젝트에 참여할 당시에 나는 UI도 겨우 짤 정도의 수준이었고, 기능구현은 구글링해가며 겨우 해냈었습니다.
  • 때문에 상태가 정확히 무엇인지도, 상태관리 라이브러리가 무엇인지도 몰랐고, Recoil의 Atom을 사용하는 방법도 몰랐습니다.
  • Hipspot을 진행하며 눈치껏 팀원들 코드 보며, 문서를 조금 읽으며 어느정도 사용하는 방법을 이해하게 되었습니다.
  • 프로젝트가 마무리되면서 상태관리 및 상태관리 라이브러리에 대해서 정확히 이해하고자 공부를 시작하게 되었습니다 !

 

1. 상태(State)는 무엇인가?

  • State란, 컴포넌트가 기억하는 것이라고 생각하면 편합니다.
  • 예를들어 input에 우리가 타이핑을 하면 그 타이핑된 값이 쳐져야 하고
  • 이미지를 옆으로 넘기는 버튼을 누르면 다음 이미지가 보여져야합니다.
  • 위 예시들에서 컴포넌트는 타이핑된 값을 보여주기 위해선 타이핑 내용을 기억해야 하고, 다음 이미지로 넘어가기 위해선 현재 이미지를 기억해야 합니다.
  • 이렇듯 컴포넌트가 기억해야 하는 값을 우리는 상태라고 부릅니다.
  • 함수형 컴포넌트에서는 ‘useState’라는 Hook을 이용해 state를 다룰 수 있습니다

1.1 State를 사용하는 이유, 지역변수의 값을 바꿔주는거로는 안되나?

export default function Count() {
  let index = 0;

  function handleClick() {
    index = index + 1;
  }
  return (
    <>
      <button onClick={handleClick}>
        +1
      </button>
      <h3>  
        {index}
      </h3>
    </>
  );
}
  • 이렇게 지역변수의 값을 바꿔주는 것으로는 우리가 의도한 것처럼 숫자가 올라가지 않습니다. 그 이유로는 두 가지가 있습니다.
  • 첫 째, 지역변수는 렌더링 되면 유지되지 않습니다. 따라서 리액트가 이 컴포넌트를 두 번 렌더링 한다면, 렌더링 이전에 변경된 지역변수를 고려하지 않고 처음부터 다시 렌더링 합니다.
  • 둘 째, 지역변수가 변경된다고 해서 렌더링이 이뤄지지 않습니다. 리액트는 새로운 데이터와 함께 컴포넌트를 렌더링할 필요를 느끼지 못합니다.

 

위와 같은 이유로 우리는 버튼 클릭시 숫자가 업데이트 되도록 하려면

  1. 버튼 클릭시 리렌더링 되어야 합니다.
  2. 리렌더링 되면서도 컴포넌트가 숫자 값을 기억하고 업데이트 할 수 있어야 합니다.

2. useState은 뭔데 ?

  • React Hook이란 React 버전 16.8부터 제공하는 요소이며, 기존 class 바탕의 코드를 작성할 필요 없이 여러 기능을 사용할 수 있습니다.
  • useState는 이러한 Hook 중 하나이며, 상태 관리할 때 사용되는 Hook입니다.

2.1 useState 사용하기

  • useState는 두 가지 요소로 구성된다고 볼 수 있다.
    • 첫 째로 상태변수(위 예시에선 index)인데, 상태변수는 렌더링시에도 데이터를 잃지 않고 유지합니다.
    • 둘 째로 setter함수(위 예시에선 setIndex)인데, setter 함수를 업데이트 하면 리액트도 리렌더링 되고, 상태변수를 업데이트 합니다.
  • 지역변수로 작성했던 코드 useState로 바꿔보자
    • 위 코드를 실행하면 버튼 클릭 시 onClick 이벤트가 실행되어 handleClick함수가 호출됩니다.
    • handleClick함수가 실행되면 setIndex가 실행되는데, 이 setter 함수가 실행됨에 따라 index 변수의 값은 1 더해지고, 컴포넌트가 리렌더링 됩니다.
    • index 변수는 상태변수이기에 렌더링시에도 값을 유지하기에 화면에는 초기값 0에 1이 더해진 1이 표시됩니다.
import {useState} from 'React'

function App() { 
	const [상태변수, setter함수] = useState(상태의 초기값);
    const [index, setIndex] = useState(0);
 }

 

2.2 상태 넘겨주기

  • 리액트에서 상태를넘겨줄 땐 Props를 이용합니다.

2.2.1 State vs Props

State

부모 컴포넌트에서 자녀 컴포넌트로 데이터를 보내는 것이 아닌 해당 컴포넌트 내부에서 데이터를 전달할 때 State를 이용합니다.

  • 예를들어 검색 창에 글을 입력할 때 글이 변하는 것은 State을 바꿉니다.
  • State는 변경 가능합니다.
  • State가 변하면 re-render 됩니다.
State = {
    message: ' ',
    attachFile : undefined,
    openMenu : false,
};

 

Props

  • Properties의 줄임말입니다.
  • Props는 상속하는 부모 컴포넌트로부터 자녀 컴포넌트에 데이터등을 전달하는 방법입니다.
  • Props는 읽기 전용으로 자녀 컴포넌트 입장에서는 변하지 않습니다. 변경하고자 하면 부모 컴포넌트에서 state를 변경시켜주어야 합니다.

2.2.2 Props로 전달

const [todoData, setTodoData] = useState({title: 'todo1', time : 1});
<Lists todoDatas={todoData}/> // 이런식으로 props를 넘겨준다
<자녀컴포넌트 이름 자녀컴포넌트에서 사용할 이름 = {부모컴포넌트에서의 이름} />

//List.js todoDatas 객체 통째로 받고
function List (todoDatas) {
    return (
        <>
            //컴포넌트 내에서 직접 접근
            <div>할 일 : {todoDatas.name}    </div>
            <div>걸리는 시간 : {todoDatas.time}    </div>
        </>
    )
}

//List.js, 애초에 받을 때 구조분해 할당으로 받아버려
function List ({name, time}) {
    return (
        <>
            <div>할 일 : {name}    </div>
            <div>걸리는 시간 : {time}    </div>
        </>
    )
}

 

3. 그래서 뭐가 문제야 ? (Props Drilling)

 

  • 해당 그림은 Root에서 state를 만들고, 이를 Props Drilling 방식으로 하위 컴포넌트에게 state를 내려주고있습니다.
  • 만일 G 컴포넌트에서 상태가 변경되었고, 이를 J 컴포넌트에서 사용해야한다면
  • G → E → C → A → Root → H → J 순서로 상태가 전달이 것입니다.
  • 코드를 통해서 보면 (참고자료) App > FirstComponent > SecondComponent > ThirdComponent > ComponentNeedingProps
  • ComponentNeedingProps 컴포넌트에서 해당 Props를 사용하기 위해선 이렇게 전달하는 과정을 거쳐야 합니다.
import React from "react";
import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <FirstComponent content="Who needs me?" />
    </div>
  );
}

function FirstComponent({ content }) {
  return (
    <div>
      <h3>I am the first component</h3>;
      <SecondComponent content={content} />
    </div>
  );
}

function SecondComponent({ content }) {
  return (
    <div>
      <h3>I am the second component</h3>;
      <ThirdComponent content={content} />
    </div>
  );
}

function ThirdComponent({ content }) {
  return (
    <div>
      <h3>I am the third component</h3>;
      <ComponentNeedingProps content={content} />
    </div>
  );
}

function ComponentNeedingProps({ content }) {
  return <h3>{content}</h3>;
}

 

3.1 Props Drilling

3.1.1 Props Drilling이란?

  • Props Drilling이란 props를 ‘하위 컴포넌트로 전달하는 용도로만 쓰이는’ 컴포넌트를 거치며 React Component 트리의 한 부분에서 다른 부분으로 데이터를 전달하는 과정이다.
  • 이는 컴포넌트가 3~4개일 때는 문제가 되지 않지만, 여러 개의 컴포넌트가 있을 때는 문제가 될 수 있다.

3.1.2 Props Drilling의 장점

  • 컴포넌트 간에 데이터를 가장 쉽고 빠르게 전달할 수 있다.
  • 작은 규모의 application일 경우, 컴포넌트를 잘게 분해해서 props drilling을 한다면, 코드를 실행하지 않고 정적으로 따라가는 것만으로도 어떤 데이터가 어디서 사용됐는 지 파악하기 쉽고 수정도 용이하다

3.1.3 Props Drilling의 문제점

  • 필요보다 많은 props를 전달하다가, 컴포넌트 분리하는 과정에서 필요하지 않은 props가 계속 남거나 전달되는 문제
  • props 전달을 누락했는데 default props가 사용되어 props의 미전달을 인지하기 어려운 문제
  • props의 이름이 전달중에 변경되어 데이터를 추적하기 어려워지는 문제

3.1.4 Props Drilling을 피하려면

  • 렌더링 될 컴포넌트를 불필요하게 여러 컴포넌트로 나누지 않는다.
    • React는 단 하나의 컴포넌트에 application 전체를 작성하더라도 기술적인 제약이 없다.따라서 불필요한 컴포넌트 쪼개기를 할 필요가 없다.컴포넌트를 재사용해야할 상황을 기다렸다 분할해도 괜찮으며, 불필요한 props drilling을 방지할 수 있다.
  • defaultprops를 필수 컴포넌트에 사용하지 않는다.
    • deafultProps를 사용하면 필요한 props가 전달되지 못한 상황임에도 오류가 가려지게된다. 따라서 defaultProps를 필수적이지 않은 컴포넌트에만 사용하면 props drilling으로 인한 문제를 막을 수 있다.
  • 가능한 관련성이 높은 곳에 state를 위치한다.
    • 어떤 데이터가 application의 특정 위치에서만 필요하면 최상위 컴포넌트에 state를 위치시키는게 아닌, 해당 state를 필요로하는 컴포넌트들의 최소 공통 부모 컴포넌트에서 관리하는 것이 효율적이다.
  • 상태관리 도구를 사용한다.
    • 데이터를 필요로하는 컴포넌트가 props drilling의 깊숙히 위치한다면, React의 Context API를 사용하거나, Redux, Recoil 등의 외부 전역 상태관리 라이브러리를 사용해서 문제를 해결할 수 있다.
  • Children을 사용한다. (Legacy API)
    • children을 사용하여 리팩토링을 진행하면, 하나의 컴포넌트에서 값을 관리하고, 그 값을 하위요소로 전달할 때 코드추적이 어려워지지 않게됩니다.
    • 그러나 리액트 공식문서에도 나와있듯, children은 잘 사용되지 않고 빈약한 코드 (fragile code)로 이어질 수 있습니다.

 

4. Context

  • Context란 application에서 사용할 상태들을 context 내에서 관리하여 보다 컴포넌트들이 편하게 접근 가능하게 합니다.
  • 그림으로 알 수 있듯 Context를 사용하면 Props Drilling을 막을 수 있습니다.

4.1 Context 사용방법

  1. createContext 메서드를 사용해 context를 생성합니다.
  2. 생성된 context를 가지고 context provider로 컴포넌트 트리를 감쌉니다.
  3. value props를 사용해 context provider에 원하는 값을 입력합니다.
  4. context consumer를 통해 필요한 컴포넌트에서 그 값을 불러옵니다.

 

5. 상태관리 라이브러리란 ?

  • 리액트에서 사용하는 데이터를 담는 변수인 State를 전역적으로 관리하는 툴입니다.
  • 상태관리 라이브러리에 대한 자세한 설명은 추후 포스팅하도록 하겠습니다.

 

cf ) 공식문서 보면서 알게된 어휘인데 ‘from scratch’가 처음부터라는 뜻이었다. 그래서 ‘render from scratch’라 하면 ‘처음부터 렌더링된다’ 라고 해석가능합니다.

 

 

참고자료

https://devowen.com/459

https://react.dev/learn/scaling-up-with-reducer-and-context

https://react.vlpt.us/basic/22-context-dispatch.html

https://redux.js.org/tutorials/essentials/part-1-overview-concepts

https://slog.website/post/13

https://codingpracticenote.tistory.com/56

0. MSW 공부 계기

  • 취뽀스테이션(졸업작품)을 개발할 땐 firebase를 이용해 개발을 진행했기 때문에 MSW를 이용하고싶어도 굳이 ? 싶은 생각이 들었었다.
  • 그러나 이번 세론 프로젝트를 진행하며 MSW가 필요할 것 같아 공부하게 되었다.

1. Mocking REST API

동작원리

1.1 기본 설정

  • React 프로젝트 설치 및 msw 설치
yarn create vite msw_study --template-react-ts
cd msw_study
yarn 
yarn add msw --dev
yarn run dev

1.2 Mock Definition

  • src폴더 안에 mocks 폴더 만들기
  • mocks 폴더 안에 handler.js 파일 만들기

1.3 API 고르기

  • 보통 REST API를 사용하므로 REST API로 가자
  • 공식문서에서도 고민되면 REST API 쓰라고 나와있음

1.4 Request handler

  • 우리가 REST API request를 다루고 싶으면 그에 대한 method, path 그리고 mocking할 response를 반환하는 함수를 정해주어야한다.
  • 이 튜토리얼에서는 우리는 유저의 로그인 흐름을 모킹할 것이다.
    • POST/login : 유저가 로그인 가능하도록 하는 것
    • GET/user : 로그인된 유저의 정보를 리턴하는 것
    • // src/mocks/handlers.js import { rest } from 'msw' export const handlers = [ // Handles a POST /login request rest.post('/login', /*response resolver*/), // Handles a GET /user request rest.get('/user', /*response resolver*/), ]

1.5 Response resolver

위에서 request handler를 작성하였는데, rest.post('/login', **여기**)**,** 이 코드에 여기 부분에는 req, res, ctx를 인자로 갖는 response resolver 콜백함수가 들어가야 한다.

  • req : 서버로 요청이 전송되다 붙잡힌 request
  • res : 모킹된 response
  • ctx : 모킹된 response의 status code, headers, body 등
import {rest} from 'msw';

export const handlers = [
    rest.post('/login', (req, res, ctx) => {
        sessionStorage.setItem('is-authenticated', 'true);
        return res(
            ctx.status(200)
        )
    }

    rest.get('/user', (req, res, ctx) => {
        const isAuth = sessionStorage.getItem('is-authenticated');
        if(!isAuth){
            return res(
                ctx.status(403),
                ctx.json({
                    errorMessage : "Not Authorized",
                })    
            )    
        }    
        return res(
            ctx.status(200),
            ctx.json({
                usename: 'admin',
            })
        )

    })
] 
  • HTTP POST 요청 처리를 위해 rest.post 함수를 사용하여 요청을 보낸다.
  • 핸들러 함수의 첫 번째 파라미터로 ‘/login’ 이라는 요청 경로를 넣었고, 두 번째 파라미터로는 response resolver라는 콜백함수를 넣어주었다.
  • response resolver 함수는 res, req, ctx를 인자로 갖는다.
  • req, res, ctx를 사용하여 원하는 조건에 따라 모의 응답을 작성한다.
    • 위 POST 요청에선 요청이 전송되면 sessionStorage에 ‘is-authenticated’라는 키에 true 값을 넣어준다.
    • 이후 200번 상태코드를 넣어준다.
    • user 정보를 가져오는 GET 요청에선 조건에 따라 응답을 다르게 설정해주었다.
      • sessionStorage에 'is-authenticated' 키의 값을 가져온다.
      • 만일 값이 false라면 상태코드 403번 (Forbidden, 서버가 요청을 이해했지만 승인 거부함)과 에러메시지를 전송하고
      • 만일 값이 true라면 상태코드 200번과 username을 함께 리턴해준다

2. MSW 직접 적용하기 (브라우저에서)

2.1 MSW 라이브러리 설치

  • 이건 맨 처음 프로젝트 설정에서 했으니 넘어가겠음
  • yarn add msw --dev

2.2 브라우저에 서비스 워커 등록

브라우저에서 사용하기 위해선 MSW를 서비스 워커에 등록하는 과정이 필요하다. 아래 명령어를 입력하면 서비스 워커 등록을 위한 파일이 public 폴더에 추가된다

npx msw init <PUBLIC_DIR> --save

npx msw init public/ --save
  • public/ 폴더는 주로 프로젝트의 정적 리소스를 담는 폴더이다. CRA, Next.js, Vite에서 기본적으로 셋팅 되어있다.
  • 다른 프로젝트의 경우 public 디렉토리가 다를 수 있는데, 해당 링크에서 참고할 수 있다.

2.3 Worker 설정

  • scr/mocks 폴더 내에 brower.js 파일을 만든다.
  • 생성한 browers.js 안에서 worker 인스턴스를 생성하고, request handles를 인자로 넣어준다.
import { setupWorker } from "msw";
import { handlers } from "./handlers";

export const worker = setupWorker(...handlers);

2.4 Worker 실행

  • 우리가 mocking 한 코드를 어플리케이션에 적용하고 실행하려면 우리 어플리케이션에 import해와야한다.
  • 그러나 mocking은 개발시에만 사용되는 기술이기 때문에 mocking이 필요할 때만 해당 파일을 가져오면 된다.
  • 우리는 지금 mocking이 필요하기 때문에 worker을 실행하는 코드를 추가해주면 된다.
// src/index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'

// 아래 if문이 worker을 실행하는 코드
if (process.env.NODE_ENV === 'development') {
    // 공식문서에선 아래 코드를 이용하라 하였다.
    const { worker } = require('./mocks/browser')
    // 그러나 Vite를 이용하여 개발하는 경우 require를 사용하지 않으므로 await import를 해주면 된다.
    const { worker } = await import("./mocks/browser");
  worker.start()
}

ReactDOM.render(<App />, document.getElementById('root'))


[MSW] Mocking enabled라는 문구가 콘솔창에 뜨면 mocking이 활성화 된 것이다 !

2. 실습해보기 with TodoList (추후 추가예정)

  • 로그인 기능이 있는 TodoList를 실습하여 추가할 예정이다.

+ Recent posts