IT 성장기 (교육이수)/크래프톤정글 (2025.03-07)

[크래프톤정글] Week14 Toy Project - 개발 일지 (TIL)

eezy 2025. 6. 13. 17:07

Week14 Toy Project - 개발 일지 (TIL)

들어가며

ㅇㅅㅇ

이번 주는 Krafton Jungle 커리큘럼의 일환으로 진행되는 개인 프로젝트 주간입니다. 알고리즘 주차를 지나, CS 지식과 PintOS까지 정말 빠르게 많은 걸 훑고 지나왔네요. 정신없이 달려오다 보니, 아직도 부족한 CS 개념들이 머릿속을 떠나지 않네요.

한편으로는 “좀 더 CS를 파고들고 싶다..”하는 아쉬움도 있고, 또 한편으로는 “이제 진짜 내가 원하는 프로젝트를 완수해보자!”하며 설레이는 마음 반입니다.

곧 다가올 나만무 (나만의 무기 만들기) 프로젝트를 앞두고 코치님이 강조하신건 “개발 지식 자체보단, 팀원들과의 협업 그리고 그 안에서의 나만의 성장기”였어요. 이번 주는 개발 프레임워크를 익히는 준비 운동 기간입니다!

사실 그동안은 주차별로 공부한 내용을 정확하게 정리해 전달하고자 하는 마음에 글 포스팅을 망설였다면, 이제부터는 조금 더 “내 이야기”에 집중한 포스팅을 하려 합니다. 특히 하루하루의 시행착오, 배운 점, 막혔던 순간들을 솔직하게 남겨보려 합니다.

앞으로의 이어질 초보 개발자의 좌충우돌 개발기, 많관부! 🥳


Day 1 : 프로젝트 세팅

🏃‍♀️ 오늘 한 일

9:00 - 정글 크래프톤 티셔츠 오픈런

10:30 - 출근

10:30 ~ 12:00 - PintOS 마무리 정리

14:00 ~ 17:50 - 프로젝트 기반 정립

  • 노션 기획안 정리
  • 프레임워크 선정 및 공부할 내용 정리
  • Git 연동

19:00 ~ 01:30 - React 공부 시작

  • React, Typescript, Tailwind setup
  • React 컴포넌트 및 파일 구조 공부

02:30 ~ 04:00 - 구현 시작

🧠 배운 점

React 프로젝트 구조 이해

  • src, public, App.tsx, index.tsx의 역할을 파악
  • index.tsx는 진입점, App.tsx는 전체 페이지의 루트 컴포넌트

폴더 구조 정리

  • components, pages 등으로 컴포넌트를 역할별로 나누는 폴더링 방식 이해

React Router 도입

  • react-router-dom을 이용해 페이지를 전환하는 방법 학습
  • BrowserRouter, Routes, Route, Link 사용법 익힘

컴포넌트의 Props(속성) 개념

  • 부모 컴포넌트에서 자식 컴포넌트로 값을 전달할 때 사용
  • 읽기 전용이며, 컴포넌트 재사용에 매우 중요
function Welcome(props: { name: string }) {
  return <h1>Hello, {props.name}</h1>;
}

🧩 어려웠던 점

의외로 tailwind에서 계속 알 수 없는 설치 불가 에러가 발생했다. 왜인지는 모르겠으나, 버전 명시를 해야지 설치가 가능했다. 찾아보니 많은 사람들이 동일한 이슈를 겪고 있는듯 하다. 최신 버전의 css와 intellisence가 호환이 되지 않아 생기는 문제 같으나 확실하지 않다.

npm install -D tailwindcss@3.4.17 postcss autoprefixer

Day 2 : React 공부

🏃‍♀️ 오늘 한 일

10:30 - 출근

10:30 ~ 12:00 - 운동

13:30 ~ 15:30 - 이동

15:30 ~ 18:30 - React 공부

18:30 ~ 21:00 - 개인 일정

21:00 ~ 24:00 - Board FE 구현 시작

🧠 배운 점

  • useState: 컴포넌트의 상태를 관리하는 가장 기본적인 훅. 입력값 제어, 버튼 토글 등 사용자 인터랙션에 따라 동적으로 상태를 업데이트할 수 있다.
  • useEffect: 컴포넌트가 마운트되거나 특정 상태가 변경될 때 부수효과(side effect)를 실행할 수 있다. 주로 API 호출, 로컬스토리지 접근, 이벤트 등록/해제 등에 사용한다.
  • useParams (react-router-dom): 동적 URL에서 파라미터 값을 추출할 수 있다. 예: /board/:id 와 같은 경로에서 게시글 id를 가져오는 데 활용됨.
  • 컴포넌트 분리: Pagination, Modal, SearchBar 등 재사용 가능한 UI를 별도의 컴포넌트로 분리하는 방식도 익혔다.
  • props로 데이터 전달: 부모에서 자식 컴포넌트로 상태/이벤트를 전달하여 유연한 컴포넌트 구조 설계 가능

🧩 어려웠던 점

  • 아직 구현을 많이 해보지 않아 스킵

Day 3 : 게시판/댓글 FE 개발 및 API 설계

어머!! 일요일에 청.모(청첩장 모임) 다녀오니까 할일이 너무 쌓여버렸다!!! 주말동안 너무 놀아버렸지모야..핳핳..☠️ 하지만 거의 몇년만에 보는 친구도 보고, 친구의 첫째 미니미(!)와의 첫만남을 하고 왔다. 보고 있는것 만으로도 너무 귀여웠다ㅠㅠ 폭풍 수다로 힐링을 제대로 했으니 오늘부터 힘내서 달려 봅시다!

🏃‍♀️ 오늘 한 일

오늘의 목표 : 게시판 CRUD 글 작성, 수정, 댓글 모듈 뼈대 구현

🚀 목표 달성! FE MVP git push 완료

11:00 - 출근

11:00 ~ 12:00 - Board FE 구현 완료

13:30 ~ 18:00 - Auth FE 구현 시작

18:00 ~ 19:30 - 운동

19:30 ~ 24:30 - Auth FE 구현 완료

24:30 ~ 01:30 - 야식타임! 햎피 버스데이

01:30 ~ 03:00 - 댓글 FE 구현 시작

🧠 배운 점

  • React에서 컴포넌트 분리 → Pagination, ForgotPassword 등을 재사용 가능한 컴포넌트로 분리하여 기능별로 모듈화함
  • 클라이언트 사이드 페이지네이션 구현 → 배열 데이터를 slice()로 나누고, useState를 통해 현재 페이지 상태를 제어하는 방식으로 구현함
  • 폼 제출 이벤트 (onSubmit)와 브라우저 새로고침 제어 → e.preventDefault()를 사용해 새로고침을 막고, 유효성 검사 및 상태 처리를 안정적으로 수행
  • 모달 컴포넌트 기본 구조 학습 → 외부에서 onClose 등의 props를 통해 열고 닫는 방식에 익숙해짐

🧩 어려웠던 점

  • 폼에서 새로고침이 발생하는 문제 → button의 type="submit" 기본 동작으로 인해 페이지가 새로고침되며 에러 메시지가 사라졌고, 이를 e.preventDefault()로 해결
  • 상태 변화에 따라 여러 동작이 이어지는 흐름 설계 → 이메일 중복 확인 후 결과에 따라 회원가입을 처리해야 했는데, 이를 Promise와 async/await 구조로 구현하며 상태 제어 흐름에 대한 개념을 익힘

Day 4: DB 연동 & BE 구현

오늘 나만무 팀 결과가 발표되었다! 새로운(?) 사람들과 새로운 여정. 걱정 반 기대 반이다. 나의 몫을 해내야 하는데.. 예상치 못하게 DB 세팅에서 시간이 좀 소요 되었다. 기존에 설치해둔걸 바로 쓸 수 있을것이라 생각했으나, 결국 전부 지우고 재설치했다! 내일까지 서버를 구현할 수 있을지 걱정이다..

🏃‍♀️ 오늘 한 일

12:00 - 출근

14:00 ~ 16:00 - 커리어 특강

16:00 ~ 16:30 - 커리어 특강 블로그 정리

16:30 ~ 18:00 - Node, Express, MySQL 설치

19:00 ~ 04:00 - Express 문법 익히기, 로그인, 회원가입, 마이페이지, JWT 토큰 구현 완료

주요 구현 내용

  1. 유저 정보 불러오기 (GET /api/users/mypage)
  • 로그인 시 발급한 JWT 토큰을 Authorization: Bearer <token> 헤더에 담아 요청
  • 서버에서는 verifyToken 미들웨어로 유저를 인증하고 req.user에 정보 추가
  • 프론트에서는 마이페이지 접속 시 fetchMyInfo() 함수로 사용자 정보를 요청
  • 이름과 프로필 이미지를 불러와 렌더링
  1. 프로필 이미지 수정 (PATCH /api/users/mypage)
  • 클라이언트에서 FormData를 만들어 이미지와 변경된 이름을 함께 전송
  • multer 미들웨어로 서버에서 파일을 업로드하고, 파일 경로를 DB에 저장
  • 성공 시 사용자 정보를 갱신하고 화면에 반영
  1. 기본 프로필 이미지 처리
  • 프로필 이미지가 없는 경우 /uploads/default_profile.jpg를 표시
  • 서버에서 정적 파일 서빙 설정: app.use("/uploads", express.static(path.join(__dirname, "../uploads")))

🧠 배운 점

  • JWT 인증 흐름과 미들웨어 구조에 대한 이해
  • multer를 활용한 이미지 업로드 및 서버 저장 방식
  • FormData를 통한 파일 업로드 처리법
  • React에서 이미지 미리보기 처리 방식 (FileReader

🧩 어려웠던 점

  • MySQL 설치 과정에서 기존에 설치해둔 XAMPP 와 충돌이 발생하며 socket을 찾지 못함
    • → homebrew 가 아닌 mysql 웹사이트에서 다시 다운로드 받아 해결.
  • JWT 구현 시 Authorization 헤더만 설정하고 Content-Type을 누락함
    • → 토큰은 localStorage에 잘 저장되었지만 서버로 전달되지 않았고, Bearer null로 인식되어 인증 실패. 헤더를 올바르게 설정하여 해결.
  • verifyToken에서 req.user를 정의했지만 타입 충돌 발생
    • → 컨트롤러 함수의 반환 타입을 Promise<Response>로 지정했으나 실제로는 res.json() 호출만 하므로 Promise<void>로 변경하여 타입 오류를 해결.
    • → 구현 초기 타입 에러는 express 5.0.0-beta 사용 시 타입 호환 오류로 인해 express 4버전으로 다운그레이드 하여 해결.
  • 기본 프로필 이미지가 렌더링되지 않음
    • → 서버에서 정적 파일로 /uploads/default_profile.jpg를 서빙하도록 했지만, 프론트에서 경로가 일치하지 않아 이미지가 로드되지 않음. 서버 정적 경로 설정과 프론트의 이미지 src 경로를 명확히 일치시켜 해결.
  • 프로필 이미지 변경 시 이미지가 저장되었지만 브라우저에서 보이지 않음
    • → 서버에 이미지가 정상 저장되었지만, 클라이언트에서 경로를 상대적으로 처리하거나 ${user.profileImageUrl}로 직접 문자열을 만들지 않아 src 경로가 제대로 생성되지 않았음.
  • PATCH 요청을 보냈지만 서버에 핸들러가 없다는 오류 발생
    • → 서버 코드에는 핸들러가 존재했지만, 변경 사항을 반영하지 않고 서버를 재시작하지 않아 발생한 문제. 서버를 재시작하여 해결.
  • useEffect()alert()가 두 번 실행됨
    • → React의 Strict Mode로 인해 개발 환경에서 컴포넌트가 두 번 마운트되며 발생. 실제 배포 환경에서는 발생하지 않음.

Day 5: DB 연동

댓글을 모듈화 해둔 것이 발목을 잡게될 줄 몰랐다.. 게시판과 동일하게 CRUD를 구현하려 했으나, 생각보다 api의 흐름이 헷갈려서 오히려 어디서 에러가 터졌는지 이해하는 시간이 오래 걸렸다!! 결론은 모듈화도 적당히 해야 가독성이 좋다. 너무 기능을 다 나뉘버리면 오히려 헷갈린다.

🏃‍♀️ 오늘 한 일

10:00 ~ 18:00 - AWS 특강

19:30 ~ 04:00 - 백엔드 CRUD 마무리 구현

04:00 ~ 04:30 - 발표 준비

주요 구현 내용

  1. 게시판 CRUD 구현
    • 게시글 등록, 수정, 삭제, 조회 API 구현
    • 게시글 상세 조회 시 작성자 인증 처리 및 예외 처리 적용
  2. 댓글 CRUD 구현
    • 댓글 등록, 수정, 삭제, 조회 기능 구현
    • 게시글과 댓글 간의 관계 설정 및 외래키 제약 대응
  3. 토큰 인증 적용
    • JWT를 이용한 로그인 인증을 통해, 유저별 CRUD 권한 분리
    • 인증된 사용자만 댓글/게시글을 작성, 수정, 삭제할 수 있도록 제한

🧠 배운 점

  • JSON 형식의 데이터 구조화와 통신 방식에 익숙해졌다.
  • 프론트와 백엔드 간에 명확한 데이터 구조가 통신의 핵심임을 체감했고, 이를 기반으로 TypeScript 타입 선언과 매핑을 시도하며 구조적인 코드를 작성하는 연습을 했다.
  • RESTful API 설계 원칙을 따르려 노력했다.
  • 리소스 중심의 URL 설계와 HTTP 메서드의 의미를 구분해서 사용하는 연습이 실제 구현에 큰 도움이 되었다.
  • 파일 구조 기획을 통해 API 모듈화를 고민했다.
  • controller, service, routes 계층을 분리하고 책임을 명확히 하면서, 유지보수성과 가독성을 개선하는 구조를 설계할 수 있었다.

🧩 어려웠던 점

  • TypeScript의 엄격한 타입 시스템
  • 특히 백엔드 응답 객체를 프론트에서 처리할 때, 타입 충돌이나 undefined 예외를 자주 마주쳤다. 이러한 부분을 해결하기 위해 공통 인터페이스를 분리하거나, optional chaining 등을 적극 활용하게 되었다.
  • 댓글 삭제 시 외래키 제약 오류 발생
  • 게시글 삭제 전에 연관된 댓글을 먼저 삭제하지 않으면 DB에서 제약 오류가 발생하는 상황을 겪었다. 이 문제를 해결하기 위해 TypeORM의 관계 설정과 cascading 옵션을 다시 학습하고 적용했다.
  • 프론트와 백엔드의 데이터 동기화
  • 댓글 등록이나 삭제 후 새로고침 없이 UI를 즉시 반영하는 작업이 의외로 까다로웠다. 상태 관리와 useEffect를 적절히 활용해 비동기 처리와 렌더링 타이밍을 조율해야 했다.