ETC

2023년을 보내며

partner_jun 2023. 11. 18. 16:23

연말 평가가 다가와 수행한 업무들을 정리하던 중 블로그에도 회고를 적는다. 11월이지만 늦게 적는 것보단 미리 적는 게 더 나을 것 같기도 하고, 하반기에 남은 업무가 많지 않아 한두 달 지나도 차이는 없을 것 같다.
올해 상반기까지는 계속 혼자 작업을 진행했었는데, 하반기부터 팀원이 한분 붙어 함께 작업하기 시작했다. 정/부 개념이 되어 부담은 덜해졌다. 다만 서로 코드 리뷰를 해도 놓치는 부분이 여전히 있었다. 주로 스타일이나 로그 등 상대적으로 중요하지 않은 부분이 그랬는데, 이건 리뷰하는 인원이 늘어난다고 해도 별 차이가 없을 것 같다.
 

몇픽셀 틀린걸 어떻게 알아...

 

주요 업무

서비스 업무

1. 국내 숙소 상세 사이트 개편 (07/20 ~ 11/08)

개요
11월 8일에 런칭한 가장 최근 프로젝트이기도 하지만 중요도와 성과를 생각하면 비중 있는 프로젝트다. 21년 하반기에 개발, 런칭했던 숙소 상세 사이트를 개편한 프로젝트다. 말이 개편이지 새로 개발했다고 보는 것이 낫겠다. 듣기로는 런칭한지 2년도 되지 않은 프로젝트를 전면 개편하는 것은 이례적이라고 한다. IT 업계 자체가 불황이라 그런 것인지 회사 자체가 경쟁에서 밀려나고 있어서인지는 모르겠다.
 
내용
숙소 상세 -> 객실 상세 -> 주문 페이지로 이동하던 흐름숙소 상세 -> 주문 페이지로 줄이는 것, 객실과 요금제의 관계를 1:N으로 노출하는 것(이전에는 요금제별로 객실을 따로 만들었다!)이 주요한 내용이다.
 

요금제별 특성을 한번에 필터링할 수 있는 기능이 마음에 든다

 
요금제와 관련된 것들은 모두 백엔드쪽 작업으로 FE 입장에선 그냥 새로운 사이트 개발이나 다름없었다. 아무래도 작업 내용이 크니 영역을 어느 정도 나누어 개발, 배포하고 AB테스트를 진행했다. 작업 전 내가 가장 강하게 주장했던 것은 '탭 구조의 제거'였다. 
 

이젠 모든 정보가 스크롤로 노출된다.

 
탭 구조는 개발-유지보수 측면에서도 까다롭고, 사용자 입장에서도 끔찍한 UX다. 최근 사용자 추세를 보면 인터랙션을 줄여야 함이 명백하다. 이전 기획 담당자(런칭하기도 전에 퇴사했지만)는 왜 탭구조를 원했는지 모르겠다. 
 
개발
개발 측면에서 중요하게 여긴 점은 코드 정리와 명확한 데이터 흐름이다. 불필요한 recoil 사용을 줄이고, 유지보수에 도움이 된다면 성능을 포기하더라도 중복 컴포넌트를 만들었다.
두 번째는 API 측에 UI로 보여지는 데이터만을 달라고 강하게 요청하는 것이었다. 이전에는 할인 여부라던지 객실의 사진 등을 FE에서 직접 끼워 맞춰야 하는 구조였다. 난 이전부터 FE는 보이는 것에 집중해야 한다고 생각하고 있는데 이 점은 변함없다.
21년에 개발을 진행했을 땐 대타로 들어가기도 했고 입사한지 얼마 되지 않았기에 목소리를 내기 어려웠다. 그래서 FE 개발이나 API, 기획 모두 아쉬움이 많았다. 하지만 지금은 이 프로젝트에 관련된 내용을 어느 정도 결정할 수 있을 정도이기도 하고, 꽤나 오랜 기간 담당해 히스토리도 파악하고 있다. 특히 관련 담당자들과 1년 이상 함께 업무를 수행하며 친해진 것이 컸다.
AB테스트 결과, 진입부터 주문 완료까지의 비율이 0.4%가량 상승했다고 한다. 확실히 프로젝트를 진행하는 사람들이 관심을 기울일수록 더 큰 성과를 얻을 수 있는 것 같다.
 
여담
런칭 이후 성능이 크게 감소되어 급하게 성능 개선을 진행했다. 아래에도 설명할 내용인데 스크립팅 시간 감소를 위해 Intersection Observer를 이용한 것이 가장 유효했다. Next-React SSR 특성상 컴포넌트가 노출되면 그 자체만으로도 서버 사이드, 클라이언트 사이드 양 측에서의 연산이 필요하니, Swiper와 같은 무거운 것들을 Dynamic으로 처리한 것이다. loading component로 styled component를 거의 그대로 사용할 수 있으니 코드의 수정은 적었지만 효과는 아주 뛰어났다.
 
 

2. 해외 숙소 상세 사이트 리뉴얼 (05/10 ~ 08/02)

개요
기존에도 해외 숙소 상세를 노출하는 웹 페이지가 있었다. 하지만 아무도 안 써서인지 아무도 안 쓰게 만들고 싶어서인지(?) 여러 가지로 끔찍했다. 사소한 버그도 많았지만 그중 으뜸은 끔찍한 속도였다. 서비스 특성상 해외 업체의 데이터를 가져와 보여주어야 하니 그 속도가 엄청나게 느렸는데, 상태가 좋지 않은 UI까지 더해지니 최악이었다. 이번 리뉴얼을 통해 그나마 쓸만한 상태로 만들었으니 괜찮은 성과라고 생각한다.
 
내용
이 프로젝트는 크게 숙소 상세 -> 객실 비교 -> 주문 페이지 흐름으로 이어진다. 특이한 점은 객실 비교 페이지인데, 외부 업체 몇군데의 객실 정보를 가져와 노출하다 보니 같은 객실임에도 가격이 차이나는 경우가 있어 이렇게 기획되었다고 한다. 
 

왼쪽 숙소 페이지와 오른쪽 객실 비교 페이지

 
이 부분이 내가 탐탁치 않은 첫 번째 부분이다. 이 '느린' 객실 비교 페이지에 진입하기 위해 객실 비교 데이터를 미리 가져온다. 가져온 데이터를 가지고 있다가 페이지에 이동할 때 사용하는데, 백엔드 캐시를 이용하면 될 것 같은데 굳이 FE에서 처리했다는 점이 영 신경 쓰인다. 뭐 나름의 이유가 있다고 설명을 들었는데 그래도 납득되지 않았었다. 속도가 느려 소켓이나 그에 준하는 방법으로 응답을 서서히 모아냈다면 그러려니 하겠지만 그런 것도 아니었기에  답답하다.
 
두번째는 인터랙션이다. 페이지의 객실 항목 자체에 바로 예약하기 버튼을 노출하는 것이 아니라, 하단의 버튼을 클릭해 주문 페이지로 이동해야 한다. 이게 무슨 의미가 있는 걸까?
 

객실을 선택하면 오른쪽 아래 버튼이 활성화된다

 
내가 만들면서도 이게 뭔가 싶었다. 근데 다시 봐도 이게 뭔가 싶다. 너무 아쉽다.
 
개발
이 프로젝트는 '국내 숙소' 상세 페이지 프로젝트에 개발되었다. 그러다 보니 개발 중 큰 변경이 있었는데, atomic pattern을 일부 무너뜨렸다는 것이다. atom / molecules 같은 구분만으론 이 구성요소 컴포넌트가 어느 페이지에 영향을 주는지 파악할 수 없었다. 예를 들어 날짜를 선택하는 캘린더 모달은 국내, 해외 양쪽에 사용되는데 해외 숙소의 디자인이 변경되었다고 컴포넌트를 변경하면 작업자는 이 컴포넌트가 '국내 사이트'에서 사용하고 있었는지 알 수 없으니 의도치 않은 변경이 이루어지기 때문이다. 그래서 atomic pattern의 각 요소를 폴더로 구분했다.
 

이런 느낌의 구조가 되었다

 
결과적으로 atom/common/Component1과 같은 형태가 되었는데, 이상해 보일 수도 있지만 컴포넌트 관리 측면에선 아주 만족스럽다.
 
여담
개발 기간 중 집에 가려고 하는데 회의에 끌려가 라이브 코딩을 했던 것이 기억에 남는다.
 

이 디자인 요소의 데이터 형식을 정의하는 회의였다

 
API와 FE(웹/앱)에서 사용할 디자인 요소의 타입 정의를 위한 회의였는데, 아무래도 웹 환경이 프로토타이핑하며 논의하는데 가장 유용하니 직접 시연할 수밖에 없었다. 그래도 논의가 꽤 잘 되어 개발 중에 문제 될 것도 없었고, 국내 숙소 작업에도 그대로 사용하게 되었으니 조금은 즐거운 기억이다. 나중에 알게 된 사실이지만, 12월 기준으로 실제 거래액을 목표치 대비 177% 달성했다고 한다. 목표치 액수가 적은 것도 아니었으니 상당한 수준이다. 큰 기대가 없었지만 잘 됐다니 기분이 좋다.
 
 
 
 

3. 숙소 상세 사이트 유지보수

늘 그렇듯 유지보수성 업무는 성과는 없지만 가장 중요한 업무다. 위에서 언급한 사이트 개편과 해외 숙소 상세 사이트 리뉴얼 사이에 계속해서 사이트를 유지보수하고 있다. 간단한 스타일시트 수정부터 로직 개선이나 기능 추가 등이 있었다.
 

  • 라이브러리 및 환경 최신화
    • 작년부터 올해 초까지 문제가 될법한 것들을 모두 정리해 두어 라이브러리 업데이트나(React18, Next13) 인스턴스 환경 업데이트(Node18)에 어려움이 없었다.
  • 크롤러 대응 - RateLimiter
    • 크롤러 관련 이슈가 꾸준히 있었는데, 페이지 접근 양에 따라 응답을 지연하는 RateLimiter를 구현, 적용하여 성과를 측정하고 보고했다. 이를 통해 다수의 접근 시 캡챠를 노출하도록 의사결정 하는데에 큰 역할을 했다고 자부하고 있다.
    • 또 크롤러 특성상 Sentry에 이상한 오류를 자꾸 발생시키는데, 결국 비용 문제로 404와 같이 '정상적인' 오류는 로그를 남기지 않도록 했다. 때때로 잘못된 링크가 있을 수 있어 불안함이 있지만 어쩔 수 없다.

 
여담
올해 초 사용성 개선이라며 윗선에서 아주 촉박한 일정으로 요청된 작업이 기억에 남는다. 기획 자체가 그렇게 된 것을 디자인 한두 개 고친다고 무슨 의미가 있는지 모르겠다. 심지어 배포 이후 지표상으로도 아무런 차이가 없었다. 계속 관심을 가졌으면 열정이 넘친다고 받아들였겠지만 어느 순간 관심이 뚝 끊긴 것을 보면 참 어처구니가 없다.
 
 

기술/챌린지

기술과 관련된 내용을 문서화하여 공유했다. 연말 평가를 위해서이기도 했지만 개인적으로도 다시 되돌아볼 때에도 정리해 놓는 게 더 나은 것 같다. 내가 작성한 문서이기는 하지만 사내 컨플루언스에 적어두었으니 그대로 가져오기는 뭐해서 내용을 간단하게 적어둔다.
 

  • 코드 클렌징 팁 공유
    • AB테스트나 개편 진행으로 불필요해진 파일을 삭제하는 팁을 공유했다.
      WebStorm(Intellij)의 Inspect Code나 ts-dependency-graph를 이용한 디펜전시 그래프를 이용하는 방법이다.
    • 디펜전시 그래프를 그리면 atomic pattern의 단점이 또다시 부각되는데, 참조 그래프가 끔찍하게 변해버린다는 점이다.
      • atomic pattern의 각 요소 디렉토리가 플랫하게, 좌우로 매우 넓게 표시되어 실제 참조하는 파일의 구조를 파악하기에 매우 어렵다.
  • 프로젝트 성능 개선
    • 국내 숙소 상세 사이트 개편 이후 성능을 개선했다.
      Intersection Observer를 이용해 스크립트 실행을 극단적으로 줄인 것이 가장 유효했다.
    • Http2를 이용함에도 청크 파일의 수를 줄였을 때 페이지 랜딩까지 딜레이를 크게 줄일 수 있었다는 점도 의아했다.
      webpack의 chunk 특성상 순차적으로 실행되어야 해서 그렇지 않았을까라고 예상만 하고 있다.
    • 로컬 퍼포먼스 측정 시 cpu 4x slower, network fast3g 기준으로 min 3231ms -> min 1975ms까지(약 60% 수준) 스크립팅 소요 시간을 줄여냈다. 이것저것 더 손보면 더 빨라질 수도 있겠지만 이 이상은 유지보수에 악영향을 준다고 판단했다.
  • RateLimiter 적용 및 성과 공유
    • 크롤러 대응을 위해 너무 잦은 접근 시 응답이 지연되는 트릭을 적용하고 성과를 공유했다.
    • 접근 자체를 막는다기보단 귀찮게 만드는 것을 목표로 했었고, 크롤러가 시간당 가져가는 데이터의 양을 줄이고 접근 횟수 자체도 줄여내는 등 꽤나 좋은 성과를 냈다.
    • 명확한 수치와 사례를 보고함으로써 Cloudflare captcha 도입의 의사 결정 수단이 되었다.
  • 롤링 배포 설정 정보 공유
    • AWS의 ALB 설정 중 sticky session을 통해 롤링 배포 중 발생하는 404 에러를 줄이고자 했다.
    • 일반적으로는 발생하지 않지만 기존 API 엔드포인트를 변경하는 경우 너무 많은 에러가 로깅되어 적용하자고 공유했는데 다들 별 반응이 없었다. 뭐 동작에 상관없긴 하니까...
  • 썸네일 서버 필요성과 구현 방식 공유
    • 이미지 썸네일은 FE가 주체적으로 가지고 있어야 한다고 생각한다. 이미지 크기를 FE가 지정하니 당연한 일이다.
    • 하지만 아직도 제대로 운영되지 않고 있다. 답답할 뿐이다.
  • SEO 검색 실적 증가 공유
    • 22년 9월 클릭 22.4K, 노출 1.19M이었던 사이트가 23년 10월 기준 클릭 75.K, 노출 3.45M로 클릭, 노출 지표가 약 3배 늘어났다.
    • 코로나 전후 여행 관심도의 차이도 있지만 구글 검색 결과 자체 노출이 크게 늘었다. google structured data를 정리하고 응답 속도나 cls 등 lighthouse 지표를 개선한 것이 긍정적인 효과를 가져온 것으로 보인다.
    • 국내숙소 상세 개편 프로젝트 성과까지 더하면 인센티브 줘야 되는 것이 아닌지...

 

업무 지표

회사의 업무 수행 도구에 기록된 지표 기록이다. 이게 무슨 의미가 있나 싶지만(특히 PR 개수) 평가에 사용된다니 뭐 할 말이 없다. PR 코멘트를 통해 다른 개발자의 성장을 조금이나마 도왔길 바랄 뿐이다.
 

  • 프로젝트 라이브 배포 47회 이상
    • 핫픽스를 제외하고도 한 주에 한번 이상의 배포를 진행했다.
  • JIRA 티켓 처리 320개 이상
    • 이렇게 보면 참 많은 업무를 했다는 생각이 든다.
  • PR 160개 이상
    • PR 개수가 평가 요소 중 하나라고 하여 몇 달 전부턴 작은 PR을 생성하고 있다.
      defect 같은 것들도 모두 PR로 생성했다면 배 이상으로 늘어났을 것이다.
  • PR comment 270개 이상
    • 내가 주로 담당하는 프로젝트 외에도 간간히 코멘트를 남기곤 했다.
      다만 갑자기 나타나서 헛소리하는 사람으로 보일 수 있다는 것이 무섭다. 회사의 기조는 전혀 다른 팀의 PR에도 코멘트를 달기를 바라는 것 같은데 비즈니스 로직을 매번 설명하기를 바라는 걸까?
    • 개인적으로 PR 코멘트를 남겼을 때 그냥 ok 하고 수정해 버리는 것은 양쪽 모두에게 도움이 되지 않는 것 같다.
      그렇다고 의견을 강요할 수도 없는 노릇이고... 골치 아픈 문제다.
  • 슬랙을 통한 간단한 기술 공유 20회 이상
    • 팀 내 기술 공유 채널에 문서로 만들기에는 별거 없는 간단한 정보들을 공유했다.
    • 주로 partytown 같은 실험 격 라이브러리나 개인 프로젝트를 진행하며 알게 된 팁을 공유했다.
    • 다들 관심이 없는 듯하다. 최근엔 벽 보고 혼자 말하는 채널이 되어버렸다...
  • 신규 입사자 면접 9회
    • 올해 상반기에 신규 채용을 위해 면접을 진행했다.
    • 면접관으로서의 경험이 적어 너무 질문이 많았을 때도, 너무 질문이 적었을 때도 있었다.
    • 특히 기술 질문에 너무 과한(?) 요구를 한 경우도 있었다. 정도를 지키는 게 쉽진 않다.

 

개인 프로젝트

동생과 함께 만드는 사이트도 큰 변화가 있었다. Stable diffusion과 GPT의 공개(출시)로 방향성이 크게 변했고, Stripe를 이용해 유료 서비스를 시작했다.
 

웹 관련 개발

프론트엔드 & 백엔드 개발
여러 기능을 위해 사이트 자체를 리뉴얼했는데, 생각보다 오래 걸리지 않았다. 약 2주 정도 작업하여(5만 라인 정도) Next.js 프로젝트로 완전히 변경했다. 백엔드는 Spring이 괜찮다는 생각에 그렇게 작업했었지만, 개발자가 나 혼자이다 보니 생산성 측면에서 Next 단독 프로젝트인 것이 훨씬 나았다. 이번 기회에 i18n까지 제대로 적용했다. getServerSideProps에서 처리되다 보니 에러 페이지에서 언어 선택이 어렵긴 했지만 큰 문제는 아니었다.
오히려 자주 사용해서 별거 아니라고 생각했던 소켓(Socket.io)을 추가할 때가 문제였다. 프로젝트에 소켓 연결을 추가했더니 갑자기 커넥션이 급증하는 바람에 서버가 죽어 곤란해졌다. AWS beanstalk 특성상 상태가 변하면 명령이 먹히지도 않으니 마냥 기다리는 수밖에 없었다.
 

결국 생산성이 중요하다

 

DB & QUERY
DB 작업이 의외로 많았다. 이전에 백엔드 개발을 맡겼던 녀석이 인덱스를 필드마다 하나씩 만들어둬서 인덱스를 다시 만드느라 굉장히 고생을 했다. 역으로 하지 말아야 할 것을 배우게 되었는데, 필요 없는 인덱스를 만들어두면 쿼리가 그 인덱스를 타서 더 느리게 실행된다. 심지어 where절에 참조하지 않은 필드만을 참조하는 인덱스인데도 말이다. 덕분에 explain 구문만 백여번 확인한 것 같다.

또, full-text 쿼리를 제거했다. 기능 자체에 문제가 있었던 것은 아닌데 피크 타임에 DB의 메모리 사용량이 급증하여 like문으로 바꿔보니 사용량이 줄었다. 스택오버플로 등을 찾아보니 어림짐작은 가는데 정확히 어떤 이유인지는 설명하기 어렵다. like문이 속도가 더 느리긴 하지만 쿼리의 횟수 자체가 많지 않다 보니 문제는 없어 보인다. 이후 DB의 인스턴스를 변경해서 가용 메모리를 크게 늘렸는데 full-text 쿼리로 되돌릴 만큼 메리트가 있진 않아 like문으로 유지하고 있다.
 

주석을 풀 일이 없을 것 같다

 
인프라
인프라 작업도 꽤 있었다. AMI를 이용해서 인스턴스 자동 생성을 시도해 봤는데, 그래픽 카드 드라이버를 사용하는 인스턴스에선 이게 제대로 작동하질 않았다. 인스턴스를 생성했을 때 그래픽 카드 드라이버가 미설치되었다고 경고가 나오거나 굉장히 낮은 성능으로 작동되어 그래픽 드라이버를 재설치해야 했다. 쉘 파일을 작성해서 인스턴스가 생성될 때 자동으로 재설치되게 할 수도 있겠지만 관리해야 하는 포인트들을 생각하면 아무런 의미가 없어 보인다. 가상 환경인 eks로 넘어가면 괜찮을 것 같은데 그러기엔 작업이 너무 커져 엄두도 못 내고 있다.
버킷에 올린 파일이 자꾸 바뀌어서 고생한 경험도 있다. API들의 에러가 연거푸 일어나는 아주 특별한 상황에 버킷 파일이 덮어 씌워지는 문제였는데, AWS에 어디서 변경되었는지 문의하니 답변으로 계정이 해킹당한 것 같다는 헛소리를 들었다. 웃겼다.
 

AI 관련

Stable diffusion
기능 중 하나인 Stable diffusion 관련되어서는 webui 프로젝트를 참고해서 작업을 했는데, 파이썬으로 되어 있는 코드를 살펴보느라 고생을 좀 했다. 파이썬 자체가 익숙하지 않기도 하지만 프로젝트 자체의 코드도 품질이 너무 좋지 않아 잔버그가 많았다. 업데이트할 때마다 계속 버그가 생기기도 하고. 오픈 소스 프로젝트의 한계가 아닐까 싶다.
 
GPT
GPT 측면에서는 기능 간의 브리지로써 사용했던 것이 주요했던 것 같다. 여러 가지로 시도해 볼수록 작은 규모에서 만들기 어려운 추천이나 분류 시스템 같은 것, 단순 재미용 챗봇에 사용하는 것이 훨씬 도움 되는 것 같다. 많은 기업들에서 비즈니스에 연동하고 싶어 하는데 부질없어 보인다. GPT 자체는 사용자의 입력이 많아야 원하는 대로 작동하는데, 사용자는 그렇게 많은 텍스트를 입력하지 않는다. 메신저에도 "ㅇㅇ" 보내는 세상에 무슨 입력을 그렇게 하겠나? 
 

여담

AI(웃기는 단어지만)를 이용해 나름 재미있는 기능들을 만들고 있기도 하고, 의외로 지표가 꽤 좋게 나와 고무된다. 서버비로 나가고 있는 금액이 꽤 큰 터라 내년에 큰 성과를 보일 수 있었으면 좋겠다.
 

월간 가입자가 크게 늘진 않았지만 꾸준하다

 
 

마치며

올해는 나름대로 잘 채운 1년이었다. 프로젝트 수행 기간을 잘 조절해 해외여행도 다섯 번가량 갔었고(거의 일본이었다), 회사 프로젝트도 개인 프로젝트도 많은 것을 했고 좋은 성과를 거두었다. 특히 회사 업무는 작년보다 더 많은 업무를 효율적으로 수행했다는 자신이 있다. 회사의 업무 프로세스에 익숙해진 것도 있지만 나 자신이 성장했기 때문이다.
다만 함께 진행하는 팀원의 성장에 기여했는지는 의문이다. 시니어(인지는 모르겠다)급 개발자로서 중요한 것은 나의 개발보다는 팀에 대한 영향이라고 생각된다. 나름 노력해서 전달해도 제대로 받아들였는지, 혹은 제대로 전달했는지도 알 수가 없었다. 이런 부분은 관련된 도서를 읽고 주변 경험을 묻고 배우면서 경험이 쌓일수록 나아질 것이라고 기대한다.

올해 연봉 상승률이 아주 적을 거라는 이야기가 있다. 한 일이 많은데 연봉을 조금 올려준다? 이건 정색할만한 일이다...
 

이직하면 그만이야~