로고

프론트엔드 단기 인턴 프로젝트 회고

Jul 2025

어느날 제안을 받아 진행하게 된 단기 인턴.
한 달이라는 짧은 기간이었지만 나에게는 유급으로 진행된 첫 프로젝트 경험이었기 때문에 소중한 경험이자 자산이 되었다.
한 달간 진행한 프로젝트와 일주일정도 추가로 QA에서 넘어온 이슈를 해결하는 것 까지 마무리하고 나니, 이제서야 부족했던 부분과 아쉬운 점이 더 잘 보인다.
내가 성장한 부분 그리고 더 잘 해볼 수 있을 것 같았던 부분과 고민들을 기록해둬야겠다고 생각해서 회고 글을 작성한다.
(사실은... 매일 매일 일지를 작성하다가 중간에 바빠져서 기억이 날아가기 전에 후다닥 붙잡는 중이다^^)


어떤 프로젝트 였는지?

부트캠프를 진행하는 '코드잇'의 'Node.js 백엔드 트랙 고급 프로젝트'에 사용되는 프론트엔드 사이트를 개발했다.
백엔드 부트캠프 수강생들이 작업한 백엔드 부분과 연결해서 사용할 수 있도록 완성도가 있어야 했다.

나는 프론트엔드 개발을 담당했고, 약 5주 조금 넘는 기간동안 진행됐다.
프로젝트를 담당하는 PM분과, 본인 포함 프론트엔드 3명, 백엔드 2명, QA 담당해주시는 1분이 계셨고, 직접적으로 소통하진 않았지만 figma에 디자인을 추가 및 수정해주시는 디자이너 분도 있는 듯 했다.

내가 참여한 프로젝트 중에는 가장 많은 인원이 함께했고, 재택근무였지만 즐거운 부분도 있었고, 도파민 충전한 나날들도 있었다.


무엇을 어떻게 -

CODI-IT이라는 쇼핑몰 사이트를 개발했다. 흔히 볼 수 있는 쇼핑몰 사이트였고, 셀러와 바이어 역할이 구분되어 있었다.

기술 스택
언어는 TypeScript를 사용했다.
core: React, Next.js
style: TailwindCSS
form: react-hook-form, zod
state-management: TanStack Query(React Query), Zustand
code-quality: ESLint, Prettier
를 기본적으로 셋팅하고 사용했고, 이후 몇 가지 필요한 패키지들을 추가해서 사용했다.
협업에는 디스코드와 노션을 사용했다.

우선 figma디자인이 완성된 상태가 아니었고, 요구사항에 맞지 않는 몇몇 부분도 있었다. 우선 요구사항에 부합하는 부분부터 레이아웃을 구현하고, 백엔드 개발이 차차 되면 API 연동하는 것으로 진행하기로 했다.

담당한 부분
GNB (인증 상태에 따른 조건부 렌더링, 알림)
인증(로그인, 회원가입, 로그아웃)
셀러 관련 페이지(스토어 등록 및 수정, 상품 등록 및 수정, 상품 목록 연동 등)

프론트 팀원들이 해당 프로젝트에 있어서는 정보 격차가 발생하지 않도록 노션 셋업도 해두고, 빠르고 편리하게 이슈와 PR을 발행할 수 있도록 템플릿도 설정하고 룰루랄라 개발을 시작했다. 그리고 얼마 가지 않아 삽질을 시작하게 된다.


이슈들 👊👊

첫 번째 이슈: TailwindCSS 4.0, 민첩한 n개월을 보내지 못한 대가

  1. 문제 상황
    설마 했던 레이아웃 작업에서 발생하다.. 반응형을 고려하지 않고 pc화면만 작업했기 때문에 큰 문제는 없을거라고 생각했는데, 웬걸.. padding, margin이 원하는 대로 동작하지 않는 것이다.

  2. 원인 파악
    개발자도구도 켜서 이리저리 만져보고 global.css도 평소에 쓰던 방식과 크게 다르지 않아서 삽질하다가, 팀원들에게 화면 공유해서 문제 상황을 공유했다. 다른 팀원들도 비슷한 문제가 있었는데, 알고보니 TailwindCSS 4.0에서 변경된 사항을 반영하지 않아 생긴 문제였다.

  3. 해결책 및 결과
    TailwindCSS 4.0의 변경사항을 반영해 global.css를 수정하였다.
    새로운 import 방식과 함께, CSS의 Native cascade layers 를 직접 사용하도록 변경되었기 때문에,

    @tailwind base;
    @tailwind components;
    @tailwind utilities;
     
    * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    }

    이전에는 Tailwind의 기본 스타일, 컴포넌트, 유틸리티를 각각 순서대로 import 하고, 직접 작성한 전역 CSS를 순서대로 나열해서 작성했다면,

    @import 'tailwindcss';
     
    @layer base {
    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }
    }

    지금은 CSS의 @layer 규칙을 활용하여 * { margin: 0; padding: 0; }와 같은 전역 리셋 스타일은 @layer base { ... } 블록 안에 넣어주어야 한다.
    이렇게 하면 레이어 내에서는 정해진 우선순위 규칙에 따라 작동한다(base < components < utilities)
    위와 같이 수정했더니 padding과 margin을 포함한 전역 스타일과 유틸리티 클래스가 원하는 대로 정확하게 작동했다.

  4. 배운 점

    • 사용 중인 프레임워크나 라이브러리의 버전이 변경되었다면 꼭 확인하고 반영하기.
      TailwindCSS는 정말 많이 쓰는 스택이고 업데이트 당시 이전 버전을 쓰고 있긴 했지만 버전업이 되었다는 사실은 인지했었는데, 변경사항을 짚고 넘어가지 않은 것이 몇 달 후의 프로젝트에서까지 영향을 끼쳤다.
    • CSS를 가볍게 생각하지 말기.
      프론트 개발을 하다 보면 JS에만 집중하고 마크업에는 소홀해지는 경우가 많은데, 사실 CSS야말로 정말 어렵고 중요한 부분이다. 한창 개발 배울 때 멘토님께서 마크업 공부 잘 해야한다고 했는데, 경험으로 뼈져리게 느끼게 됐다.
    • 잘 안 풀리는 부분은 바로바로 SOS 치고, 해결한 이슈는 바로바로 공유하기.
      여러명의 개발 인원이 비슷한 시기에 같은 문제로 삽질하는 것 만큼 생산성 떨어지는 일이 없다. 차라리 함께 고민하는 것이 낫다. 협업의 가치는 이런 데에서 온다고 생각한다.

두 번째 이슈: 항상 빌드 체크 하고 merge하기

  1. 문제 상황
    빌드 에러가 나면 멘붕이 오기 마련이다. 그렇다. 빌드 에러가 났다. 😱

  2. 해결 시도 및 결과

    • 예측가능한 이슈였다. 의존성 파일(package.json)에서 Git 충돌(conflict)가 났고, 수동으로 수정하는 과정에서 콤마가 누락되어 생긴 에러였기 때문에 콤마를 추가해서 해결했다. (package-lock.json은 재생성했던 것 같은데, 이 방법은 동일한 의존성 트리를 보장한다는 lock file의 의도에 맞지 않는 것 같다는 고민이 남았다.)
    • 또한 파일명의 대소문자 변경으로 인해 import 경로가 잘못 들어간것도 문제의 원인이었다. 이 부분도 수정해서 다시 빌드 성공 여부를 확인한 후 하고 merge해주었다.
  3. 배운 점
    해결하기 어려웠던 건 아니지만, main이나 dev 브랜치에서 빌드에 실패하면 아무래도 식은땀을 흘리게 된다.
    가끔 너무 신이 나서 conflict만 안 나면 바로 merge해버리는 경우가 있는데, 차분하게 하나씩 체크하고 올려야겠다는 다짐을 다시 하게 됐다.
    merge하기 전에 꼭 merge될 브랜치를 받아서 로컬에서 빌드가 잘 되는지 확인한 후 merge하는 습관을 가져야겠다고 생각했고, 그 이후로는 항상 이 부분을 체크했다.

    +번외)
    그리고.. 패키지 관리 메커니즘을 더 공부해야 할 필요성을 느꼈다.
    package.json으로 설치 버전을 관리한다는 것만 인지하고 있었는데, 잠금 파일(lock file)에 대해서는 깊게 생각해본 적이 없었다.
    (패키지 잠금 파일은 각 패키지가 최초 설치될 때 정확히 어떤 버전이었는지 등을 기록하여, 팀원 간에 동일한 의존성 버전을 보장하는 역할을 한다. 한마디로 예측가능한 방식으로 의존성을 관리하는것이 목적)

    진짜 문제:
    'package-lock.json conflict가 났을 때 어떻게 하는 것이 좋을까?' 를 생각해보기
    packge-lock.json을 삭제하고 다시 생성해야만 했던 이유는, Git이 자동으로 해결할 수 없는 어마어마한 conflict들이 발생했고, 이미 수동으로 고칠 수도 없이 망가진 파일이 되었기 때문이다.
    각종 블로그나 Reddit 같은걸 참고하다 보면 이 상황이 발생한 경우 어떻게 해결할 것인가 에 대한 갑론을박이 있고, 어떤 사람은 브랜치 다시 파는게 나을 정도라고까지 말한다. (그냥 삭제하고 쓰거나 심지어 ignore에 넣는 사람도 있더라)
    대형 서비스에서 이런 일이 발생하면 얼마나 끔찍할까?
    사전에 방지할 수 있도록 자동화 도구를 사용하거나, 그들만의 git 전략을 사용하거나, 의존성을 주기적으로 업데이트 해준다거나.. 다양한 방식을 사용할 것 같다.
    npm ci를 써서 해결하라는 사람들도 많았다. 아무래도 npm install을 하면 정확히 어떤 일들이 발생할까? 부터 알아야 할 것 같다. npm 명령어들은 어떤 일을 수행할까? 패키지 안정성을 위해 어떤 작업들을 해줘야 할까? 등등..
    생각하지 않고 했던 작업들이 너무나도 많다. 새로운 과제를 기쁜 마음으로 받아들여야지.

세 번째 이슈: 처음 해보는 알림 기능 연동, Axios는 못 쓴다고?

  1. 문제 상황
    알림 기능을 연동해보는 건 이번이 처음이었다. 다른 API 요청 처럼 axios를 이용해서 똑같이 작성했는데도 알림 연동은 계속 실패했다.

  2. 원인 파악
    우선 원인을 파악하기 위해 네트워크 탭을 확인했다. 왜 안될지 고민해보면서, 알림은 다른 요청들과 조금 다르다는 점에 주목했다.
    백엔드 측에서 준 API 문서를 다시 확인해보니, SSE(Server-Sent Events) 요청이었다.
    그렇다면 서버에서 클라이언트로 보내주는 요청이겠거니 생각한다. 이제 문서를 찾아볼 차례이다.

  3. 해결 시도
    서버로부터 이벤트 수신하는 방법을 체크했다.
    SSE는 한 번 연결되면 서버에서 클라이언트로 지속적으로 이벤트를 스트리밍하는 단방향 통신 방식이기 때문에 클라이언트에서 요청을 보내고 서버로부터 응답을 받는 '요청-응답'의 형태로는 작동하지 않는다. (그래서 axios를 사용할 수 없음)
    서버로부터 이벤트를 받으려면 EventSource(SSE 연결을 위한 웹 표준 API)를 사용해야 한다는 것을 파악했다.
    서버와 연동 시 accessToken을 헤더에 넣는 방식으로 인증했는데, EventSource는 헤더를 직접 추가할 수 없어서, EventSourcePolyfill 라이브러리를 사용하기로 했다.
    패키지를 추가, 선언해주고 코드를 수정했다.

    // SSE 연결
    export const connectNotificationSSE = () => {
      const token = useUserStore.getState().accessToken;
      const baseURL = useApiStore.getState().baseURL;
      return new EventSourcePolyfill(`${baseURL}/notifications/sse`, {
        headers: {
          Authorization: `Bearer ${token}`,
        },
        withCredentials: false, // Authorization 헤더 충돌 방지
      });
    };

    알림 서버와 정상적으로 연결되었고, 실시간으로 ping 이벤트를 받아 알림을 표시할 수 있게 되었다.

  4. 배운 점
    웹 통신의 다양성을 이해하게 됐다.
    일반적인 요청-응답 구조의 HTTP 요청은 만능이 아니며, SSE처럼 지속적인 스트리밍 통신이 필요한 경우에는 전용 API를 사용하기도 한다는 것.
    그래도 '왜 안되는지' 근본적인 원인을 파악하면 대부분 공식 문서에서 해결할 수 있었다.
    대체로 만능이 아니라는 것을 인지하면 많은 문제를 해결할 수 있는 것 같다.
    axios 같은 경우 당연히 요청-응답 통신 방식에 최적화되어 있다는 것을 알고있지만, 그렇다면 다른 통신 방식을 사용해야 할 때에는 어떤 대안책을 찾아나갈 수 있는지, 그것을 적용하는 능력이 중요하다고 생각된다.


배운 점


좋았던 점


아쉬웠던 점


마무리

개인적으로, 끝나고 나서는 '내가 과연 완성도 있고 가독성 좋게 잘 개발했나? 아쉬운 점이 너무 많고 성장했는지도 잘 모르겠다.' 라고 생각했는데, 써두고 보니 이런저런 문제에 직면했었고, 앞으로 탐구하고 시도해볼 과제들이 참 많다는 것을 깨달았다. 즐겁고 소중한 경험이었다.