우아한테크코스[프리코스] 5주차 회고록

2025. 11. 20. 14:50·우아한테크벨로/프리코스 회고록
728x90

1. 도전의 시작

1.1. 왜 이 프로젝트를 시작했는가

[실제 사용자를 위한 서비스 운영 경험과 문제 해결] 우아한테크코스 8기에 지원하며 제가 가장 깊이 파고들고자 했던 목표는 '실제 사용자가 존재하는 서비스의 운영 경험'이었습니다. 현재 진행 중인 창업 프로젝트는 장기적인 호흡이 필요하여, 단기간에 기획부터 배포, 운영까지의 전체 사이클을 경험하기에는 물리적인 제약이 있었습니다. 그러던 중 마주한 이번 오픈 과제는 규모는 작더라도 서비스의 A to Z를 온전히 경험할 수 있는 최적의 기회라고 판단했습니다. 주제는 제가 근로 장학생으로 일하며 느꼈던 '기자재 관리 및 강의실 예약 시스템의 비효율'로 선정했습니다. 저의 실제 불편함을 기술로 해결하고, 나아가 실사용자의 피드백까지 받아보는 것을 목표로 했습니다.

[타 분야에 대한 이해: 협업을 위한 기술적 시야 확장] 지금까지 백엔드 개발에 집중하느라 프론트엔드 영역을 직접 경험해 볼 기회가 없었습니다. 이로 인해 팀 프로젝트 시 프론트엔드 팀원과 어느 정도의 개발 시간과 비용이 발생하는지 파악하지 못하여 일정 조율을 하는 과정에서 소통의 모호함이 발생하곤 했습니다. 이번 프로젝트에서는 기획부터 디자인, 프론트엔드 개발까지 홀로 수행하며 타 파트가 겪는 기술적 난이도와 고충을 직접 체감해보고자 합니다. 이는 향후 협업 상황에서 더 명확하고 배려 있는 소통을 할 수 있는 밑거름이 될 것입니다.

[성장을 위한 체계적인 개발 프로세스 확립] 기존의 해커톤이나 과제 수행 시에는 시간 제약으로 인해 '빠른 기능 구현'에만 치중하는 주먹구구식 개발을 해왔습니다. 이는 잦은 코드 수정과 예기치 못한 오류로 이어지곤 했습니다. 이번 도전에서는 다릅니다. 기능 명세서, DB 설계, API 명세 등 설계 단계를 탄탄히 다지고 개발에 착수함으로써 문서화의 중요성을 체득하고자 합니다. '작동하는 코드'를 넘어 '유지보수 가능한 시스템'을 만드는 체계적인 개발 습관을 기르는 것이 이번 프로젝트의 핵심 목표입니다.

1.2. 첫 기획과 다짐

[프로젝트 구현 목표 설정]

막연한 아이디어를 실제 서비스로 구현하기 위해 가장 먼저 기능 명세서를 작성하며 프로젝트의 윤곽을 잡았습니다. 이 과정에서 욕심낼 기능과 포기할 기능을 구분하여, 한정된 시간 내에 완성도를 높이는데 집중했습니다. 서비스의 본질인 ‘관리의 효율화’를 위해 다음과 같이 세 가지 메인 비즈니스 로직을 확정했습니다.

  1. 강의실 예약
  2. 기자재 고장 신고 관리
  3. 강의실 사용 가이드라인

핵심 로직을 정한 후에는 각 도메인의 성격에 맞춰 세부적인 CRUD 범위를 조정했습니다. 모든 기능에 CRUD를 적용하기보다, 관리자와 사용자의 권한에 따라 필요한 기능만을 선별하여 개발을 하려고 했습니다.

[완성에 대한 초기 각오]

모든 개발 과정을 경험하면서, 여지껏 경험하지 못했던 다른 파트의 관점에서 프로젝트를 바라보고 좀 더 다양한 기술 스택을 익혀 '어떤 상황에서도 소통이 가능한 개발자', ‘기술 스택에 제한 받는 것이 아닌 문제 해결에 초점을 둘 수 있는 개발자’, '문제를 끝까지 해결해내는 개발자'로 성장하겠다고 다짐했습니다.

사실 이번 프로젝트를 시작하는 시점의 제 상황은 녹록지 않았습니다. 창업 프로젝트와 졸업 논문, 학과 수업과 근로, 교과목 튜터, 시스템 관리 튜터 활동까지 병행해야 했기에 절대적인 시간이 부족했습니다. 하지만 '시간이 없어서 못 했다'는 핑계 뒤로 숨고 싶지 않았습니다. 물리적인 시간의 한계를 수면 시간을 줄이는 투지와 철저한 일정 관리로 극복하고, 기획한 모든 기능을 내 손으로 직접 구현하여 배포까지 마치는 '완전한 매듭'을 짓기로 결심했습니다.

단순히 코드를 작성하는 것을 넘어, 낯선 기술이라는 장벽을 넘고, 배포라는 결승선까지 멈추지 않고 달리는 것. 그것이 이번 프로젝트에 임하는 저의 확고한 목표였습니다.

2. 낯선 기술 스택과의 첫 만남

2.1. React를 어떻게 시작해야하는가

[개념 학습: 이론보다 빠른 실행을 선택하다] 처음 프론트엔드 구현을 결심했을 때, 개발 환경 세팅부터 프레임워크 선정까지 모든 것이 미지수였습니다. React, Vue, TypeScript, TSX 등 팀 프로젝트에서 어깨너머로 듣기만 했던 용어들이 쏟아지자, 새로운 도전에 대한 설렘과 동시에 '과연 해낼 수 있을까' 하는 막막함이 앞섰습니다.

하지만 저에게 주어진 시간은 한정적이었습니다. 방대한 공식 문서를 정독하며 완벽히 이해하고 시작하기엔 물리적인 시간이 부족했습니다. 그래서 저는 '빠른 실행과 피드백’을 학습 전략으로 택했습니다. 공식 문서를 통해 React의 핵심 철학인 '컴포넌트'와 '단방향 데이터 흐름' 같은 큰 틀만 빠르게 파악한 뒤, 곧바로 코드를 작성하며 부딪히기로 했습니다. "백문이 불여일타(百聞 不如一打)", 백 번 읽는 것보다 한 번 코드를 쳐보는 것이 가장 빠른 배움의 길이라 확신했기 때문입니다.

[클론 코딩: 아는 것에서 모르는 것으로의 확장] JavaScript와 TypeScript 문법조차 낯선 상태에서 문법을 처음부터 공부하기에는 시간이 턱없이 부족했습니다. 그래서 저는 '맨땅에 헤딩' 대신 '레퍼런스 활용' 전략을 택했습니다. 이전 팀 프로젝트에서 동료들이 작성했던 프론트엔드 코드를 교본 삼아 그대로 따라 쳐보며 구조를 익혔습니다.

이 방법이 유효했던 이유는 제가 해당 프로젝트의 비즈니스 로직을 이미 완벽하게 이해하고 있었기 때문입니다. "이 기능은 이렇게 동작해야 해"라는 흐름을 알고 있는 상태에서 코드를 보니, 낯선 문법들이 어떤 역할을 하는지 빠르게 역추적하여 매핑할 수 있었습니다. 기존 코드로 해결되지 않는 새로운 기능이나 컴포넌트는 구글링과 생성형 AI를 적극 활용하여 코드를 변형하고 응용하며 빈틈을 메워 나갔습니다.

[DFS식 학습: '왜?'라는 질문의 깊이]

클론 코딩이 '어떻게'를 가르쳐 주었다면, DFS식 학습은 '왜'를 깨닫게 해주었습니다. 코드를 수정하려 할 때마다 마주치는 낯선 용어들은 저에게 새로운 학습의 대상이었습니다. 저는 모르는 단어가 나오면 멈추지 않고, 그 단어가 파생된 원점을 찾아 깊이 파고들었습니다.

가장 기억에 남는 것은 비동기 처리에 대한 학습이었습니다. async/await의 편리함 뒤에는 Promise라는 개념이 있었고, 그 뒤에는 Callback 패턴이 존재했습니다. 끝까지 파고든 결과, 왜 개발자들이 Callback 지옥에서 벗어나려 했는지, Promise가 어떻게 코드를 우아하게 만들었는지, 그리고 async/await이 어떻게 비동기 로직을 동기 로직처럼 보이게 하는지 명쾌하게 이해할 수 있었습니다. 이러한 탐구 과정은 단순한 암기보다 훨씬 더 강력한 이해를 선물해 주었습니다.

2.2. useEffect와 useState 이해하기

[상태 관리: 변수가 아닌 '상태'로 사고하기] 백엔드 로직에서는 변수에 값을 할당하면 그만이었지만, 리액트에서는 달랐습니다. 처음에는 "왜 변수 값을 바꿨는데 화면은 그대로일까?"라는 의문을 가졌습니다. 학습을 통해 리액트는 일반 변수가 아닌, useState라는 훅을 통해 관리되는 '상태'가 변경될 때만 화면을 다시 그린다는 사실을 깨달았습니다. 즉, 상태 관리는 단순히 데이터를 저장하는 것이 아니라, '데이터의 변화를 감지하고 UI를 능동적으로 업데이트하는 메커니즘'이었습니다.

[의존성 배열: 실행의 타이밍을 제어하는 열쇠] useEffect를 접했을 때 가장 난해했던 것은 '언제 실행되는가'였습니다. 처음엔 API가 무한히 호출되거나, 반대로 갱신되어야 할 데이터가 그대로인 현상을 겪었습니다. 원인은 useEffect의 두 번째 인자인 '의존성 배열'에 있었습니다. 이 배열에 포함된 값이 변할 때만 함수가 재실행된다는 원리를 이해한 후, 컴포넌트의 마운트, 업데이트, 언마운트 시점을 제어할 수 있게 되었습니다.

2.3. API 연동하기

[Axios 라이브러리로 다리 만들기]

처음 Axios를 접했을 때는 단순히 '백엔드랑 통신하는 라이브러리' 정도로만 생각했습니다. 하지만 프로젝트를 진행하며 Interceptor의 강력함, instance를 통한 설정 재사용, 그리고 에러 핸들링의 편리함을 경험하면서 왜 많은 개발자들이 Axios를 선호하는지 이해하게 되었습니다. 특히 response.data를 빼먹어 'Cannot read properties of undefined' 에러를 만났을 때, async/await와 try-catch를 제대로 사용하지 못해 앱이 멈췄을 때의 당황스러움은 개발의 어려움으로 다가왔었습니다.

하지만 이러한 시행착오를 통해 HTTP 통신의 본질, 비동기 처리의 중요성, 그리고 에러 핸들링의 필요성을 깊이 이해할 수 있었습니다. Axios는 단순한 라이브러리를 넘어, 프론트엔드와 백엔드를 연결하는 핵심 다리 역할을 해주는 고마운 존재였습니다.

[꼭 미리 변수명은 문서화 해두자: 유지보수의 시작] 백엔드 API를 프론트엔드에 연동하는 과정은 에러와의 싸움이었습니다. 400 Bad Request나 데이터가 undefined로 뜨는 현상이 반복되었는데, 원인은 허무하게도 '변수명 불일치'였습니다. 백엔드 Entity와 DTO, 그리고 프론트엔드의 타입 정의(Interface)가 미묘하게 달랐던 것입니다.

이는 프론트 개발을 백엔드보다 먼저 진행하는 단계에서 Type 정의에 대한 정확한 이해 없이 무작정 코드를 작성했던 '선 구현, 후 이해' 방식의 부작용이었습니다. Entity별 변수명에 대한 문서화가 되어 있지 않다 보니, 프론트엔드 코드를 짤 때마다 DB 테이블 명세서를 조회하여 컬럼명을 확인했습니다. 그렇게 임의로 변수명을 정하여 프런트 코드를 개발하고 난 후에, 백엔드 개발을 진행하면서 변수명을 평소처럼 고민하며 수정하다보니 변수명은 당연하게 달라졌고, 이 과정에서 치러야 했던 대가는 혹독했습니다.

변수명 하나를 수정하기 위해 연관된 모든 코드를 찾아다니며 수정해야 했고, 이는 막대한 '유지보수 피로 비용'으로 이어졌습니다. 이러한 시행착오 끝에 저는 "문서화는 코드를 작성하기 전, 용도를 정의하고 합의하는 필수 과정"이라는 중요한 사실과 코드를 작성하기 전에 작성하는 코드의 목적이 무엇인지 파악하는 것의 중요함을 깨달았습니다. 전체 코드가 흔들리지 않도록 설계해기 위해서는 문서화를 꼼꼼하게 하고, 작성하는 근거가 있어야 유지보수 비용을 줄일 수 있음을 몸소 체험했습니다. 이제 저에게 문서화는 단순한 기록이 아니라, 미래의 리팩토링을 위한 가장 확실한 투자입니다. 또한 제한된 시간적 상황에서라도 코드를 작성하기 전에는 항상 근거를 생각하는 습관을 가지는 계기가 되었습니다.

3. 리팩터링

3.1. 프론트 코드 분리

[Hook 분리: 컴포넌트에게 다이어트를] 처음 리액트를 짤 때는 useState와 useEffect가 범벅이 된 거대한 컴포넌트를 만들었습니다. 코드가 길어지니 제가 짠 코드인데도 스크롤을 위아래로 왔다 갔다 하며 길을 잃기 일쑤였습니다. "이건 아니다"라는 생각에 Hook 로직을 뜯어내기 시작했습니다. API를 호출하고 데이터를 가공하는 복잡한 로직들을 밖으로 빼내니, 컴포넌트 파일에는 깔끔하게 UI만 남았습니다. 마치 정리가 안 된 책상을 서랍별로 정리한 기분이었습니다. 이렇게 분리해 두니 가독성이 좋아진 것은 물론, "이 로직을 따로 빼두면 나중에 다른 곳에서도 쓸 수 있겠는데?"라는 재사용의 가능성까지 보게 되었습니다. 이를 통해서 그동안 막연하게만 들렸던 '독립성'과 '확장성'이라는 단어가 실제 개발 생산성을 어떻게 높여주는지, 피부로 느끼며 '좋은 코드'에 대한 기준을 정립할 수 있었습니다.

3.2. 정답이 아닌 '최선'을 찾는 과정

[도메인 경계의 모호함과 구조적 고민] 프론트엔드 개발을 마치고 백엔드로 넘어와 도메인별 패키지 구조를 설계하면서, "이 클래스의 제자리는 어디인가?"라는 근본적인 질문에 봉착했습니다. 도메인 주도 설계(DDD)를 지향하며 기능을 구현했지만, 이론과 실제 코드 사이에는 항상 모호한 경계가 존재했습니다.

[인증/인가 로직의 위치 선정] 가장 큰 고민은 관리자(Admin) 토큰을 다루는 '인증/인가' 기능의 위치였습니다. "이것을 별도의 Auth 도메인으로 분리해야 하는가, 아니면 Member와 Admin을 포괄하는 User 도메인의 인프라(Infra) 계층에 두어야 하는가?"를 두고 고민했습니다. 당장의 프로젝트 규모와 복잡도를 고려했을 때, 과도한 분리는 오히려 복잡성을 높일 수 있다고 판단하여 User 도메인의 하위 인프라로 배치하는 선택을 했습니다. 하지만 프로젝트가 확장되어 인증 방식이 복잡해지거나 Admin의 역할이 비대해진다면, 그때는 분리하는 것이 적합하다는 확장성(Scalability)에 대한 시나리오도 함께 구상했습니다.

[설계에 정답은 없다] 이 과정을 통해 "아키텍처에 만고불변의 정답은 없다"는 사실을 깨달았습니다. 모든 결정은 당시의 상황과 해결하려는 문제에 따른 트레이드오프의 결과여야 함을 배웠습니다. 이 깨달음을 바탕으로, 현재는 다양한 비즈니스 모델을 가정하고 상황에 맞는 최적의 설계를 도출해 보는 모의 설계 연습을 통해 '상황에 유연하게 대처하는 설계 능력'을 기르고 있습니다.

4. 테스트 코드 작성하기

4.1. Mockito 라이브러리

[수동 테스트의 한계를 넘어] 이번 프로젝트에서는 프론트엔드라는 낯선 영역에 도전하는 동시에, 저의 본진인 백엔드에서도 기술적 성장을 이루고 싶었습니다. 그동안은 마감 기한에 쫓겨 Postman을 이용한 API 수동 테스트에만 의존해왔습니다. 하지만 매번 서버를 켜고 API를 직접 호출해야 하는 방식은 반복적인 검증을 어렵게 만들었고, 이는 결과적으로 코드의 안정성을 저하시키는 원인이 되었습니다.

[단위 테스트의 강력한 무기, Mockito] 이러한 비효율을 끊어내고 '지속 가능한 개발 환경'을 구축하기 위해 Java 진영의 대표적인 Mocking 프레임워크인 Mockito를 도입했습니다. Mockito는 실제 데이터베이스나 외부 API에 의존하지 않고, 가짜 객체(Mock Object)를 통해 테스트하고 싶은 비즈니스 로직만을 고립(Isolation)시켜 검증할 수 있게 해줍니다. 이를 통해 외부 환경에 영향을 받지 않는 빠르고 신뢰성 높은 단위 테스트 환경을 구축하고자 했습니다.

4.2. Mockito 적용기

처음 Mockito를 접했을 때는 '가짜 객체'라는 개념 자체가 낯설었습니다. “왜 진짜를 쓰지 않고 가짜를 만들어야 하지?”라는 의문도 들었습니다. 하지만 테스트를 하면서 실제 S3를 띄우고, API를 호출하고, 첨부 파일을 저장하는 테스트 작성이 얼마나 비효율적이고 위험한지 깨달았습니다. Mockito를 통해 의존성을 격리하고, 순수한 비즈니스 로직만 테스트할 수 있게 되면서 테스트 코드 작성이 즐거워졌습니다. 특히 when()으로 원하는 동작을 정의하고, verify()로 메서드 호출을 검증하는 과정에서 “내 코드가 정말 의도한 대로 동작하는구나”라는 확신을 얻을 수 있었습니다. @Mock과 @InjectMocks를 처음 사용했을 때의 신기함, ArgumentCaptor로 전달된 인자를 확인했을 때의 편리함은 Mockito를 단순한 테스트 도구를 넘어, 더 나은 코드를 작성하도록 이끌어주는 가이드로 여기게 되었습니다. 테스트하기 쉬운 코드가 좋은 코드라는 것을, 의존성을 명확히 하는 것의 중요성을 Mockito를 통해 배웠습니다. '테스트 코드를 작성하지 않으면 나중에 후회한다'는 말의 의미를 Mockito와 함께 하며 뼈저리게 느꼈습니다.

5. 새로운 플랫폼을 활용한 배포

5.1. GitHub 연동 배포 Vercel & Railway

[GitHub 푸시가 곧 배포가 되는 마법] 개발의 마지막 관문인 배포. 과거에는 리눅스 터미널과 씨름하며 밤을 새웠지만, 이번에는 더 스마트한 도구들의 힘을 빌렸습니다.

[Vercel: 프론트엔드 배포의 내비게이션] Vercel은 React 프로젝트를 세상에 공개하는 가장 빠른 길이었습니다. "프론트엔드 애플리케이션을 위한 클라우드 배포 플랫폼"이라는 정의답게, 제가 GitHub에 코드를 올리는 순간 Vercel이 이를 감지하여 자동으로 빌드하고 배포해 주었습니다. URL까지 즉시 생성해 주는 편리함 덕분에 실시간으로 결과물을 확인하며 개발할 수 있었습니다.

[Railway: 백엔드의 복잡함을 단순함으로] Railway는 백엔드 배포의 난이도를 획기적으로 낮춰준 서비스입니다. Spring Boot 애플리케이션을 배포하려면 JDK 설정, 환경 변수, 포트 포워딩 등 신경 쓸 게 많았지만, Railway는 이 모든 것을 추상화해 주었습니다. 심지어 MySQL 데이터베이스까지 한 공간에서 관리할 수 있어, 마치 내 컴퓨터에서 개발하듯 편안하게 클라우드 환경을 구축할 수 있었습니다.

5.2. Vercel

[.env 파일의 이해: 민감 정보의 격리] API URL이나 인증 키 같은 민감 정보는 코드 내에 하드코딩할 경우 보안상 심각한 취약점이 될 수 있음을 인지했습니다. 이를 방지하기 위해 .env 파일을 생성하여 환경 변수를 별도로 관리했습니다. 로컬 개발 환경에서는 이 파일을 통해 값을 불러오게 하고, Git에는 .gitignore로 업로드되지 않도록 설정하여 보안 사고를 원천 차단했습니다.

[Vercel Environment Variable 설정] 배포 시에는 .env 파일이 없기 때문에 애플리케이션이 실행되지 않는 문제가 있었습니다. 이를 해결하기 위해 Vercel 대시보드의 Environment Variables 기능을 활용했습니다. 로컬에서 사용하던 변수명(Key)과 값(Value)을 배포 환경에 똑같이 주입(Injection) 해줌으로써, 코드 수정 없이도 로컬과 배포 환경이 동일하게 동작하도록 구성했습니다.

5.3. Railway

[application.yml 파일 분리 및 변수화] Spring Boot 프로젝트의 핵심 설정 파일인 application.yml에는 DB 비밀번호와 같은 중요한 정보가 포함됩니다. 이를 GitHub에 그대로 올리는 것은 위험하다고 판단하여, 민감한 값들은 ${MYSQL_PASSWORD}와 같은 Placeholder 문법으로 대체했습니다. 이를 통해 설정 파일의 껍데기(구조)는 공유하되, 실제 알맹이(비밀번호)는 숨기는 방식을 택했습니다.

[Spring Boot + MySQL 연결과 환경 변수 주입] Railway에 MySQL을 프로비저닝한 후, 제공되는 Host, Port, Username, Password 정보를 Railway의 변수 설정 탭에 등록했습니다. 이렇게 설정해두면 Spring Boot가 실행될 때 Railway가 해당 값들을 application.yml의 Placeholder 자리에 자동으로 주입해 줍니다. 결과적으로 소스 코드에는 아무런 비밀 정보도 남기지 않으면서, 안전하고 유연하게 백엔드 서버와 데이터베이스를 연결할 수 있었습니다.

6. 프로젝트를 마치며 느낀 것들

6.1. React를 배운 소감

[어려웠지만, 그래서 더 재밌었다] 백엔드 개발자로서 로그이나 JSON 응답만 보다가, 화려한 컴포넌트들이 화면을 채우는 모습을 보는 건 정말 신선한 경험이었습니다. 새로운 언어와 라이브러리를 익히며 "이게 되네?"를 연발하던 순간들은 저에게 개발자로서의 초심을 일깨워 주었습니다.

[디자인, 그 넘을 수 없는 4차원의 벽] 하지만 곧 현실의 벽에 부딪혔습니다. 기능은 다 구현했는데, 화면이 예쁘지 않았습니다. 컴포넌트 배치와 색상 조합 앞에서 저는 작아졌습니다. 백엔드 로직은 정답이 명확했지만, UI/UX는 정답이 없는 문제처럼 느껴져 막막했습니다. 이 어려움을 겪으며 프론트엔드 영역이 얼마나 섬세하고 전문적인 감각을 요하는지 뼈저리게 느꼈습니다.

[존경을 담아, 이제야 보이는 것들] 과거에 프론트엔드 동료에게 "버튼 옮겨줄 수 있나요?"라고 쉽게 말했던 저를 반성했습니다. 직접 겪어보니 그 버튼 하나에 수많은 상태 관리와 렌더링 최적화, 그리고 디자인적 고민이 녹아있다는 것을 알게 되었습니다. 이제 저는 "조금은 알 것 같습니다." 그들의 노고를 이해하게 된 지금, 저는 이전보다 훨씬 더 좋은 동료가 될 준비를 마쳤습니다.

6.2. 프로젝트 진행 과정의 교훈

[계획의 중요성: 고민을 앞단으로 옮기다] 이번 프로젝트의 백엔드에서 가장 크게 달라진 점은 '선(先) 설계, 후(後) 코딩'의 실천이었습니다. 과거에는 빈 IDE를 켜두고 "이 엔티티에 무슨 필드가 필요하지?"를 고민하며 시간을 허비하곤 했습니다. 개발 도중 수시로 필드가 추가되고 변수명이 바뀌는 일은 일상이었습니다. 하지만 이번에는 DB 설계와 기능 명세서를 미리 작성해 두고 시작했습니다. 그 결과, 코드를 칠 때는 오직 로직 구현에만 집중할 수 있었고, 변수명이나 구조를 고민하는 '결정 비용(Decision Cost)'이 획기적으로 줄어들었습니다. 꼼꼼한 문서화가 오히려 전체 개발 시간을 단축시키는 가장 빠른 지름길임을 확신하게 되었습니다.

[유연함: 문서는 지도가 아닌 나침반] 하지만 계획이 모든 것을 해결해주지는 않았습니다. 완벽하다고 생각했던 설계도 막상 코드로 구현하거나 프론트엔드와 연동하다 보면 불필요한 부분이 발견되거나, 더 효율적인 구조가 떠오르곤 했습니다. 초반에는 문서와 코드를 일치시키기 위해 억지로 코드를 끼워 맞추려 했지만, 이는 주객전도임을 깨달았습니다. "문서는 개발을 돕기 위한 도구일 뿐, 개발을 옥죄는 족쇄가 되어서는 안 된다"는 것을 배웠습니다. 이후로는 설계의 큰 틀은 유지하되, 구현 단계의 현실적인 문제에 맞춰 유연하게 수정하는 '애자일한 태도'를 갖추게 되었습니다.

[작은 단계로 나누어 정복하기] 거대한 기능을 한 번에 구현하려는 욕심은 늘 탈을 불렀습니다. 이번에는 기능을 '작동 가능한 최소 단위'로 쪼개어 진행했습니다. "오늘은 예약 기능의 UI만", "내일은 API만" 식으로 목표를 잘게 나누니, 매일 작은 성취감을 느낄 수 있었고 디버깅도 훨씬 수월해졌습니다.

7. 성장의 발자취

[Zero to One: 막막함에서 확신으로] 프로젝트 시작 전, 저에게 React는 미지의 영역이었습니다. 컴포넌트의 개념조차 생소했고, TypeScript의 엄격한 타입 체크는 거대한 장벽처럼 느껴졌습니다. "한 줄이라도 제대로 짤 수 있을까?"라는 두려움이 앞섰던 것이 사실입니다. 하지만 지금의 저는 스스로 필요한 컴포넌트를 설계하고, Hook을 분리하여 비즈니스 로직을 관리할 수 있게 되었습니다. 단순히 코드를 복사해서 붙여넣는 수준을 넘어, 리액트의 렌더링 원리와 상태 관리의 흐름을 이해하고 주도적으로 코드를 작성하는 개발자로 성장했습니다.

[반쪽짜리 시야에서 전체를 보는 통찰력으로] 이번 프로젝트를 통해 얻은 가장 큰 수확은 '프론트엔드 개발 과정에 대한 온전한 이해'입니다. API 요청을 보내고 응답을 받아 화면에 그리기까지, 데이터가 흐르는 전체 파이프라인을 직접 구축해보며 백엔드와 프론트엔드의 유기적인 관계를 몸소 체험했습니다. 이제 저는 백엔드 로직을 짤 때도 "이 데이터가 프론트엔드에서 어떻게 소비될까?"를 먼저 고민하는, 더 넓은 시야를 가진 개발자가 되었습니다.

[문제 해결 능력의 비약적 도약] 낯선 기술 스택은 매일 새로운 오류와의 전쟁이었습니다. CORS 에러, 비동기 처리의 시점 문제, CSS 스타일링 충돌 등 익숙하지 않은 문제들이 쏟아졌습니다. 하지만 포기하지 않고 원인을 파고드는 집요함으로 하나씩 해결해 나갔습니다. 이 과정에서 "어떤 낯선 환경에 던져져도 결국은 답을 찾아낼 수 있다"는 '문제 해결의 자신감'을 얻었습니다. 이 경험은 앞으로 마주할 그 어떤 기술적 난제도 돌파할 수 있는 단단한 근육이 되어줄 것입니다.

8. 아쉬움과 개선점

[컴포넌트 재사용성: 최적을 고민했으면]

초기에 PageLayout과 PageHeader등의 공통 Layout을 만들어서 사용하였습니다. 하지만 추가로 개발을 하는 과정에서 같은 입력폼을 사용하는 경우가 있었지만, 재사용할 수 있는 컴포넌트로 분리하기보다 복사해서 붙여넣고 쓰는 비효율적인 방식을 택하기도 했습니다. 그래서 조금 더 컴포넌트 단위를 줄여서 설계를 할 수 있었다면 좋지않았을까하는 아쉬움이 남았습니다. 다음에는 앞으로 필요할 확장성까지 고려하여 설계를 하고자합니다.

[문서화: 미래의 나를 위한 친절한 배려] API 명세서는 작성했지만, 프론트엔드 컴포넌트에 대한 문서화는 생각하지 못했습니다. 복잡한 로직이 담긴 Hook이나 컴포넌트는 주석이나 별도의 문서 없이 코드만으로 이해하기 어려웠습니다. 그래서 코드를 다시 열었을 때 "이게 무슨 로직이지?"라는 당황스러움으로 돌아왔습니다. 코드는 컴퓨터가 실행하지만, 읽는 것은 사람임을 잊지 않고 가독성과 설명이 담긴 코드를 작성해야 함을 체감했습니다.

9. 마치는 글

창업가, 학생, 근로 장학생, 튜터... 저에게 주어진 역할은 너무나 많았고, 하루 24시간은 턱없이 부족했습니다. 솔직히 포기하고 싶은 순간도 있었습니다. 하지만 제가 느꼈던 '강의실 관리의 비효율'을 제 손으로 해결하고 싶다는 열망, 그리고 우아한테크코스라는 새로운 목표가 저를 다시 책상 앞에 앉게 했습니다. 잠을 줄여가며 완성한 이 프로젝트는 저에게 단순한 과제가 아닌, 제 한계를 시험하고 극복해 낸 승리의 기록입니다. 낯선 React와 씨름하고, 배포 에러와 싸우며 깨달은 것은 '기술은 도구일 뿐'이라는 사실입니다. 중요한 것은 그 도구로 무엇을 만들어내고, 어떤 가치를 전달하느냐였습니다. 저는 이번 경험을 통해 혼자서도 서비스를 A부터 Z까지 만들 수 있다는 자신감과 함께, 타 직군을 이해하는 넓은 마음을 얻었습니다. 이제 저는 다음 단계로 나아갈 준비를 마쳤습니다. 이번에 겪은 시행착오들을 밑거름 삼아, 다음 프로젝트에서는 더 견고한 설계와 더 효율적인 코드로 대답하겠습니다. 혼자 빨리 가는 개발자가 아니라, 동료와 함께 멀리 가는 개발자. 기술적 깊이와 인간적 배려를 겸비한 '대체 불가능한 개발자'가 되기 위해, 저의 도전은 멈추지 않을 것입니다.

 

Notion: https://versed-music-9b1.notion.site/2a1242c6313480c3900cd502271b3527
GitHub: https://github.com/ClassRoomManager-Woowa-Tech-Course
배포링크: https://front-eosin-rho.vercel.app

728x90

'우아한테크벨로 > 프리코스 회고록' 카테고리의 다른 글

우아안 테크코스[프리코스] 최종 코딩 테스트 회고록  (1) 2026.01.23
우아한 테크코스[프리코스] 4주차 회고록  (0) 2025.11.12
우아한 테크코스[프리코스] 3주차 회고록  (0) 2025.11.04
우아한 테크코스[프리코스] 2주차 회고록  (0) 2025.10.28
우아한 테크코스[프리코스] 1주차 회고록  (0) 2025.10.21
'우아한테크벨로/프리코스 회고록' 카테고리의 다른 글
  • 우아안 테크코스[프리코스] 최종 코딩 테스트 회고록
  • 우아한 테크코스[프리코스] 4주차 회고록
  • 우아한 테크코스[프리코스] 3주차 회고록
  • 우아한 테크코스[프리코스] 2주차 회고록
Bello's
Bello's
개발하는 벨로
  • Bello's
    벨로의 개발일지
    Bello's
  • 전체
    오늘
    어제
    • 분류 전체보기 (199) N
      • 노예 일지 (7)
        • 스타트업 노예일지 (3)
      • CS 이론 (81)
        • 학과 수업 (4)
        • 알고리즘 (64)
        • 시스템 프로그래밍 (3)
        • 데이터 통신 (1)
        • 운영체제 (2)
        • 데이터베이스 (1)
      • project (3)
      • 나는 감자다. (4)
      • Spring (27)
      • 모각코 (45)
        • 절개와지조(모각코) (7)
        • 어쩌다보니 박준태가 조장이조 (11)
        • 어쩌다보니 박준태가 또 조장이조 (12)
      • LikeLion🦁 (20)
      • 캘리포니아 감자 (4)
      • OpenSource Contribute (1)
      • 우아한테크벨로 (1) N
        • 프리코스 회고록 (6) N
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    프리코스
    Spring
    JPA
    DFS
    그래프 순회
    백준
    8기
    티스토리챌린지
    오블완
    모각코
    타임리프
    감자
    BFS
    자바
    나는 감자
    누적합
    어렵다
    절개와지조
    뛰슈
    회고록
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
Bello's
우아한테크코스[프리코스] 5주차 회고록
상단으로

티스토리툴바