'항해(航海)'는 선박이나 비행기 등이 먼 거리를 이동하는 것을 의미하며, 특히 바다를 항해하는 것을 지칭하기도 합니다.
상징적 의미:
'떠나다', '사회로의 첫걸음', '새로운 여정' 등을 상징하기도 합니다. 이는 악동뮤지션의 앨범 《항해》에서 나타나는 의미로, 사회에 첫발을 내딛는 청년의 모습을 표현합니다.
항해를 끝 마치고 작성하는 회고 글입니다.
5 주차에서 10 주차까지 느꼈던 점과 배웠던 점들을 중간중간 가볍에 복기하면서 적어보겠습니다.
디자인 패턴은 코드 작성 방법이 아닌 문제 해결 매뉴얼로
'디자인 패턴'이라는 키워드를 보고 많은 걸 배워가고 싶은 마음이 들었다.
하지만 코치님의 발제 자료 중에는 디자인 패턴을 사용하면서 주의해야 할 내용도 있었다.
망치만 있으면 모든 것이 못처럼 보입니다.
많은 초보자는 패턴을 갓 배운 후, 더 간단한 코드로도 문제 해결이 되는 상황에도 모든 곳에 패턴을 적용하려고 합니다. 이것은 최근에 패턴에 익숙해진 많은 초보자를 괴롭히는 문제입니다.
이런 부분들에 유의하면서 적절한 상황에 맞게 디자인 패턴을 사용한다면 더할 나위 없는 좋은 소프트웨어 개발 능력이라 생각한다.
과제 진행은 4 주차의 연장이라고 느꼈고 리액트 개발 패러다임 속에서 좀 더 좋은 코드를 작성하는데 집중했다.
이 때 하필 인도네시아 출장을 다녀와서 아쉽게 진행하지 못 했던 과제이다.
과제는 Feature-Slided-Design(이하 FSD)아키텍처에 대한 내용이었다.
코드로 직접 개선해나가진 못 했지만,
FSD의 개념들에 대해서 여러 자료들을 토대로 공부할 수 있었던 좋은 계기가 되었다.
관련해서 소개하자면,
등이 있는데 위 그림도 이해하는 데 있어서 많은 도움이 되었다.
같은 FSD 라도 여러 개념으로 사용할 수 있어서 팀 협의 하에 공통된 개념을 이해하여 진행하면 좋겠다고 생각했다.
자주 들어본 테스트 코드였지만 직접 작성해보는건 처음이었다.
과제는 정상적으로 제출하진 못 했지만 테스트 코드와의 벽을 허물게 해주는 좋은 과제였다.
관련해서 제출한 PR에 적힌 학습한 내용을 적어보자면,
가장 큰 배움이 있었던 부분:
- 테스트 코드에 대한 전반적인 개념
추가 학습이 필요한 영역:
- e2e 테스트 환경에서 어떤 방식으로 요소를 선택해야 하는지에 대한 학습이 필요할 것 같습니다.
실무 적용 가능성:
- 혼자만의 힘으로 적용하기엔 힘들 것 같지만 AI를 활용해서 작성한다면 해볼만할 것 같습니다.
이었다.
추가로 테스트 환경에서의 모킹(Mocking)을 구성하는 것 또한 중요하다고 생각했다.
모킹에 대한 내용도 정리해봤다.
- 모킹의 대략적인 개념
- 테스트에서 모킹은 실제 객체나 함수, API, DB 같은 외부 의존성을 가짜로 흉내 내는 것을 의미함.
- 왜 모킹을 하는가?
- 외부 환경 의존 제거
- DB, 네트워크, 파일 시스템 같은 건 테스트할 때 항상 준비하기 힘들다.
- 가짜(mock)로 대체하면 테스트가 독립적으로 실행됨.
- 속도 개선
- 실제 API 호출 대신 모킹하면 네트워크 지연 없이 빠르게 테스트가 가능함
- 제어 가능성 확보
- 특정 상황(예: 서버 오류 500, 빈 응답 등)을 직접 시뮬레이션 가능
- 실제 환경에서는 만들기 어려운 상황도 쉽게 재현할 수 있음.
처음 접하는 개념인 만큼 여러모로 배워가는게 많았던 과제였다.
7 주차가 테스트 코드와 친해지기 였다면,
8 주차는 테스트 코드와 협업하기 였던 것 같다.
테스트 주도 개발(TDD)에 대해 깊이 이해하며 TDD가 정말 유용할 지 직접 실험해본 과제였다.
해당 과제를 진행하면서 인상 깊었던 부분들에 대해 공유하자면,
1. RED: 실패하는 테스트 작성
2. GREEN: 테스트를 통과하는 코드를 작성
3. REFACTOR: 작성한 코드 리팩토링
TDD의 세 단계에 대한 내용이 있다.
이런 짧은 사이클을 반복하면서 테스트 주도 개발을 진행하면 생산성 측면에서도 큰 도움이 될 것이라 생각했다.
추가로 페어 프로그래밍을 간접적으로나마 경험해 봤다.
희원님, 아름님과 함께 심화 과제를 진행하면서
특정 기능에 대한 동일한 내용의 테스트 코드를 각자 작성했다.
다만 이 부분에 대해서는 심화 과제에서 요구하는 다양한 수준의 테스트 케이스를 만족하지 못 해서 실패했다(E2E테스트를 더 추가했어야 했음) 그래서 이 부분도 추후 따로 개발하면서 보충해보려고 한다.
이 경험으로 다른 누군가와 같이 개발하는걸 조금이나마 덜 두려워할 수 있게 된 것 같아서 좋았다.
별도로 테스트 전략(피라미드, 트로피 등) 관련해서 팀원들과 토론했던 내용들도 여러 관점에서 생각해볼 수 있어서 유익한 시간이었다.
아래엔 각 전략별 관련 사진을 첨부했다.
- 테스트 피라미드는 단위 테스트의 비중이 제일 높은 피라미드 구조입니다.
- 단위 테스트는 빠르게 모듈의 핵심 기능을 검증할 수 있기 때문에 단위 테스트의 비중을 가장 높게 두고 서비스 특화된 비즈니스 로직이나 UI 검증의 비중은 상대적으로 적게 두는 지표입니다.
- 그림에 있는 것처럼 UI나 서비스 로직은 여러 모듈의 조합을 검증해야 하기 때문에 자연스럽게 테스트 코드 작성 비용과 실행 시간이 오래 걸리기 때문에 다음과 같은 구조를 통해 빠른 피드백을 받고 결함을 정확하게 격리하고 수정하는 방법입니다.
- 상위 수준 테스트에서 실패하는 경우 기능 코드에 버그가 있을 뿐만 아니라 단위 테스트가 누락되거나 부정확한 것을 의미합니다.
- 따라서 높은 수준의 테스트에서 노출된 버그를 수정하기 전에 단위 테스트를 통해 버그를 복제해야 한다고 마틴 파울러는 조언합니다. 그런 다음 단위 테스트를 통해 버그가 죽은 상태로 유지되는지 확인하는 과정을 거쳐 장점을 누리라고 합니다.
- 여기서 Static은 코드를 작성할 때 오타와 타입에러를 확인한다. TypeScript나 ESLint 등을 통해 실행할 수 있습니다.
- 테스트 트로피는 모듈이 조합된 상태에서 비즈니스 로직을 잘 수행하는지 검증하는 통합 테스트의 비중을 가장 높이 두고 있습니다.
- 즉, 컴포넌트 하나 하나의 기능보다는 전반적인 앱의 비즈니스 로직을 실행하는 통합 테스트를 더 중요하게 보고 있습니다.
- 테스팅 트로피가 위로 올라갈 수록 "신뢰도 계수" 즉, 각 테스트 수준에서 상대적인 신뢰성 수준이 올라간다고 보며 통합 테스트를 통해 적절한 비용과 속도의 균형을 갖춘 테스트를 가장 많이 작성하려는 전략입니다.
9, 10 주차는 성능 최적화와 관련된 과제들을 진행했다.
9 주차는 인프라 계층에서의 최적화를
후술할 10 주차에서는 코드 계층에서의 최적화를 할 수 있다.
hydration이라고 하는 용어를 사용하는 이유는 "서버사이드 렌더링으로 만들어진 수분이 없는 정적인 HTML과 State로부터 수분을 보충하는 과정(동적인 상태로 변화)인 hydrate가 일어나기 때문" 이라고 추측한다.
출처: https://simsimjae.tistory.com/389 [104%:티스토리]
라는 글을 보고 나서 떠올린게
인프라 계층에서의 최적화는 마치
한 우물을 파던 사람에게 여러 우물을 파게해줘서 물이 더 잘 나오는 곳을 찾게 해주는 것 같았다.
프론트엔드 개발자라도 서버 지식이 있다면 도움 되는 부분이 많이 있을 거라고 느꼈고,
이후에 풀스택 개발자로 전향함에 있어서도 필요한 지식이라고 생각했다.
해당 과제를 진행하기에 앞서 발제에서는
등등 SSR과 SSG를 이해하기 위해 필요한 지식들에 대해서 소개했다.
각각을 깊게 파보면 좋을 것 같다.
해당 과제는 기본 과제를 거의 다 해가는 과정에서 원인 모를 오류에 부딪혀서 정상 제출은 실패했다..
준일 코치님이 발제 시간 때 했던 말이 있다
이번 과제 하면서 제일 얻어갔으면 하는 점:
아~~ SSR 겁나 짜증나네? 를 얻어가면 좋겠습니다.
이거 잘 하기가 쉽지 않구나!? 조금 고민이 많이 필요하구나!? 등의 인사이트..?
NextJS 사용할 때 “이 기능은 이렇게 만들면 될 것 같은데!?” 라는 생각이 머릿속에 떠올랐으면.
라고 작성해주셨는데.. 첫 번째 부분은 잘 얻어간 것 같고,
덕분에 꼭 한번 더 도전해볼 계획이다 ㅎㅎ
여러모로 새로운 것들을 많이 접하게 되어서 유익했던 과제였다.
아 드디어 대망의 10 주차 과제라는 마음과 코드 관점의 성능 최적화라는 주제 덕분에 조금은 시원 섭섭한 상태로 과제를 진행했던 것 같다.
일 년 전쯤, 초기 단계에서 오버 엔지니어링을 하다가 사수로부터 조언을 들은 적이 있다.
초기 단계에서의 오버 엔지니어링은 독이 될 수도 있어요.
심각하게 중요한 사안이 아니라면, 향후에 최적화 하는게 도움이 될 겁니다.
물론 이 말에 공감했고, 이런 관점으로 개발을 진행하려고 의식했다.
그랬던 나에게 이번 과제 발제는 신선한 접근이었다.
준일 코치님의 발제 자료 중 "성능 최적화는 언제 해야 할까요?" 항목에는 다음과 같은 내용이 있었다.
읽는 사람들에게 번거로울 수 있지만 내가 느꼈던걸 조금 긴 글을 통해 공유하려고 한다.
"성능 최적화는 프로젝트 후반부에 하는 거야"라고 생각하는 개발자들을 종종 봅니다. 하지만 이는 큰 오해입니다. 성능 최적화는 프로젝트의 시작부터 고려해야 할 중요한 요소입니다.
프로젝트 초기부터 성능을 고려하면 나중에 큰 리팩토링 없이도 효율적인 애플리케이션을 만들 수 있습니다. 예를 들어, 컴포넌트 구조를 설계할 때부터 불필요한 리렌더링을 최소화할 방법을 고민하는 것이죠. 또는 상태 관리 라이브러리를 선택할 때 성능 측면을 고려하는 것도 좋은 방법입니다.
최적화를 처음부터 완벽하게 할 순 없습니다. 때로는 "premature optimization"이라는 함정에 빠질 수도 있습니다. 중요한 건 균형입니다. 기능 구현과 성능 최적화 사이의 적절한 균형을 찾는 것, 그리고 이를 프로젝트 전반에 걸쳐 지속적으로 고민하는 것이 핵심입니다.
특히 레거시(기존) 프로젝트에 새로운 기능을 추가할 때는 더욱 주의가 필요합니다. 기존 코드의 성능 이슈를 파악하고, 새로운 코드가 추가됨으로써 발생할 수 있는 성능 저하를 예측하고 대비하는 것이 중요합니다.
결국, 성능 최적화는 일회성 작업이 아니라 지속적인 과정입니다. 코드를 작성할 때마다, 새로운 패키지를 추가할 때마다 "이 방식이 다른 방식 대비 성능에 어떤 영향을 미칠까?"를 고민하는 습관을 들이면, 자연스럽게 최적화된 코드를 작성할 수 있습니다. 그리고 이런 노력은 훌륭한 사용자 경험으로 이어집니다.
요약하자면, 적절하게 최적화의 균형을 잡는 것이 중요하다는 내용이다.
개발을 하면서 자주 느끼는 바이지만 이 균형을 잡는 것이 참 중요하다고 느낀다.
이런 내용들을 머릿속에 넣어두고 과제를 진행했다.
과제 진행에 필요한 리액트 프로파일러를 사용하면서
기법들에 대해서 익숙해질 수 있었다.
캐싱의 경우에는 과제 팁에 적혀있던 내용에 따라 JS의 클로저(closer)를 활용해서 구현해봤는데,
클로저를 잘 쓰고 싶어서 여러 JS 책들을 보면서 익혔던 내용들을 아무런 도움 없이 직접 작성한 코드가 예상한 대로 동작해서 뿌듯했다.
이 외에도
성능 문제를 직접 발견하고 다양한 방법을 시도하며 해결해나가는 과정이 재밌었고 이론으로만 알고 있던 개념들을 실제 코드에 적용하고 성능이 개선되는 것을 눈으로 확인하는 경험이 좋았다.
사람에 따라 이번 항해가 힐링이었을 수도, 혹독한 훈련이었을 수도 있었을 것 같다.
나의 경우에는 중간 정도였던 것 같은데 기회가 된다면 혹독한 훈련으로 진행해 보고 싶다는 생각도 들었다.
지금의 나는 수면과 컨디션을 제일 중요하게 생각하다보니 다른 사람들에 비해 열정적으로 과제에 임하진 못했던 것 같다.
준일 코치님이
“가슴은 뜨겁게, 머리는 차갑게”. 사람을 대할 때는 온 마음을 다해 진심을 표현하는 것이 중요하고, 일을 대할 할 때는 논리와 근거를 기반으로 진행하길 원합니다.
라고 말씀하셨던 적이 있는데 팀원들이 떠올랐다.
고마웠던 팀원들(영서, 지훈, 성진, 정석, 찬규 님)과 페어팀원들(휘린, 은지, 희원, 의찬, 아름, 산들 님) 그리고 석호님과 진솔님 덕분에 무사히 항해를 마칠 수 있었던 것 같다.
다들 감사합니다.
항해 플러스는 짧고도 긴 10 주 동안이었지만 많은 것들을 배우고 즉각 피드백을 받을 수 있어서 매우 만족했던 과정이었다.
유현님 10주동안 고생 많으셨습니다!