ETC

2024년 상반기를 보내며

partner_jun 2024. 6. 9. 12:57

벌써 상반기가 지나갔다. 일이 많아서인지 루틴화된 생활 때문인지 시간이 너무 빠르게 흘러가는 것 같다. 반기치고는 꽤 굵직한 일들을 많이 했다. 연말 회고는 평가 자료를 수집할 겸 작성하지만 지금은 평가 기간이 아니다보니 지표나 결과보다는 기억에 남은 것들에 대해 적어두려고 한다. 어떤 작업을 했었고, 아쉬웠던 점이 무엇인지 정도다.
 
 

주요 업무

문서작업

코딩 스타일 가이드

회사의 방침에 따라 팀 별로 언어나 플랫폼에 대해 코딩 스타일 가이드를 작성하라는 지시가 있었다. 웹 개발이니 그에 맞춰 TypeScript, HTML의 코딩 스타일 가이드를 작성했다. 당연히 처음부터 작성한 것은 아니고, 유명 기업들의 가이드를 참고하여 현재 프로젝트에서 사용하고 있는 것들을 문서화하고자 했다. 실제 프로젝트와 비교하면서 적다 알게 되었는데 프로젝트간의 룰 차이도 크고 오래된 프로젝트는 프로젝트 내에서도 컴포넌트마다 제각각의 스타일로 개발되어 있는 경우가 많았다. 이유는 크게 두가지라고 생각된다.
 

lint rule을 고정하는게 중요하다

 
첫번째는 lint의 적용 시기다. 오래된 프로젝트들은 개발 이후에 lint가 적용되었고, 이미 작성된 코드를 모두 수정할 수는 없으니 lint의 룰을 느슨하게 잡아 그대로 유지되었을 가능성이 높아 보인다. 두번째는 담당자의 변경이다. 당연하게도 많은 손을 탄 프로젝트일수록 각자의 개성, 습관이 남아있게 된다. 이런 것들은 lint에 걸리지 않지만(때로는 이 때문에 룰을 제외한다) 코드를 보는 사람에게 혼란을 준다.
코딩 스타일 가이드 문서를 작성하다 보니 문서보다는 lint나 주석이 우선이 아닐까 하는 생각이 더 강해졌다. 문서는 유실되기 쉽지만 프로젝트의 코드는 그대로 유지될테니까.
 

서스테이닝

후기 요약(GPT) 위치 변경

AB 테스트 끝에 숙소 상세 영역 최상단에 넣었던 후기 요약의 위치를 변경했다.(나 개인의 결정은 아니지만) 말도 많고 탈도 많았던 그 영역을 치웠다는 점에서 굉장히 만족스럽다. 재미있는 점은 LLM를 이용해서 만든 이 요약 컨텐츠는 긍정적인 지표가 딱히 없었다는 것이다. 기능 런칭 극초기를 제외하면 매출이나 pv, 체류 시간 등에 긍정적인 영향이 거의 없었다. 내가 생각한 가장 큰 이유는 많은 사람들은 글을 잘 읽지 못하게 되어 버렸다는 것이다. LLM의 특성상 글이 길수록 효과적이지만 길면 읽지 않는다(못한다). 짧게 요약하면 의미가 없고, 길게 요약하면 읽지 않는다.
 

주기적으로 욕먹어서 수명이 좀 늘었다.

 
대신 나쁜 점은 아주 명확하다. 좋지 않은 요약이 메인에 뜬다면 업주는 굉장한 스트레스를 받는다. 10명 중 1명만이 나쁜 경험에 대한 후기를 남겼다 하더라도(심지어 그게 사실인지 아닌지도 모른다) LLM은 그 후기를 중점으로 요약 할 수 도 있다(할 수 도 라는 점이 더 큰 문제다). 업주는 영업 담당자에게 불만을 토로할 수 밖에 없고 영업 담당자는 "이러이러한 일이 있었다" 정도의 의견을 전달하는 방법 밖엔 없다. (ONOFF 기능이 있었지만 모두가 설정해서 제외했다) 심지어 그 의견을 들어도 정치적으로 얽힌 것이 많아 위치를 바꾸는데도 이렇게 긴 시간이 걸렸다. 조만간 아예 다른 지면으로 치워버릴 것 같은데 없어지면 또 아쉬울 것 같다.
 

해외 숙소 sitemap.xml 추가

숙소 수가 너무 많아 데이터 인덱싱에 문제로 뒤늦게 추가했다. sitemap 파일 내에 정의할 수 있는 URL의 개수 제한이 있어 조건을 정하고 파일로 생성, 압축하여 업로드하는 식으로 해결했다.
 

페이지가 너무 많아 파일로 나누었다.

 
최종적으로는 인덱싱된 페이지가 40만개에서 100만개 이상으로 늘어났다. 그에 따라 검색 결과 노출이 20만에서 25만 정도로 약 25%정도 상승했다. 구글에서 이정도이니 네이버에서도 비슷한 정도로 상승하지 않았을까 예상하고 있다. 다만 여전히 아쉬운 것은 평균 검색 결과 순위가 10위대로 너무 낮다는 것이다. 현재로써는 API 응답 속도나 각종 기능으로 인한 코드 자체의 무거움으로 순위를 끌어올리는데 한계가 있다.(물론 압도적인 페이지 진입이 있다면 오르겠지만) Server Component를 사용한다던지 SEO 툴을 이용한 점검 등이 필요한 시점이다. 그나마 지금 당장 손쉽게 가능한 것은 google structured data를 추가하는 것이다. 해외쪽은 다른 작업에 밀려 아직까지도 추가하지 못했는데 이 작업이 된다면 순위가 조금 오르지 않을까 기대하고 있다.
 

불필요한 코드 제거

별거 아닌 것처럼 보이지만 이건 생각보다 어려운 일이다. 전통적인(이라기엔 얼마 안 됐지만) 컴포넌트 아키텍처링인 도메인/용도에 따라 묶는 방식이라면 간단하게 삭제해 나가면 된다. 하지만 atomic 패턴은 문제가 커진다. 사용하지 않는 컴포넌트의 확인이 어렵다. 그리고 사용한다고 하더라도 논리적으로 노출되지 않는 경우도 많다. 예를 들면 페이지 이관이 그렇다. 실제로 페이지는 남아있지만 라우팅 단계에서 다른 페이지/사이트로 리다이렉션 시키는 경우다. 참조를 하긴 하는 코드이기에 트리쉐이킹 단계에서 제거되지 않아 성능에도 악영향을 미친다. 이전 회고에 적은 것처럼, 이런 경우 코드 그래프 생성 툴을 이용하거나 IDE의 inspection을 이용해 사용되지 않는 코드를 제거한다. 귀찮아서 기록으로 남겨두지는 않았지만 이 작업으로 청크 파일의 크기가 꽤나 줄었고 JS 실행 속도에도 영향을 미쳤다.
 

회원 등급제 적용

난 이 작업을 진행하며 놀랐다. 아직도 회원 등급이 없었다고? 내 입장에서는 특별히 할 일이 많지는 않은 작업이었다. 단순히 회원 특가라는 배지를 노출하는 정도였다. 이게 생각보다 효과가 좋았는지 연계된 작업들이 계속 논의되고 있다. 이번 작업보다는 다음 작업들이 많을 것이라 생각된다.
 

사원 특가도 좀...

 
 

모노레포 이관

유행에 따르기 위해서인지 "실 단위"의 모노레포로 이관하는 작업이 있었다. 각자 담당하던 프로젝트를 pnpm + turbo로 관리하는 프로젝트로 이관했다. 배포와 관련된 몇가지 사소한 문제가 있었지만 큰 어려움은 없었다. 
 

프로젝트는 pnpm으로 관리된다.

 
개인적으로는 FE는 모노레포가(TBD가) 어울리지 않는다고 생각한다. 이유가 몇가지 있는데, 첫번째로는 package-lock 파일이다. FE는 다양한 이유(특히 개발 단계에서)로 패키지 참조가 변하게 된다. 참조된 패키지가 변할 때마다 lock 파일이 변경되고 충돌이 일어난다. 브랜치마다 lock 파일이 다른 경우가 많고, 배포조차도 ci 명령어를 이용하기 때문에 lock 파일이 제대로 생성된 파일이 아니라면 배포도 불가능하다.
 
두번째는 배포 시기의 조정이다. 모노레포는 TBD를 기본으로 하는데, 이는 항상 배포되어도 되는 API 백엔드에서 유리한 방식이다. UI/UX의 변경은 대부분 그렇지 않다. AB 테스트 혹은 플래그로 노출 여부를 결정한다면 그나마 낫지만(이것도 코드 용량이 커져 비효율적이다) 테스트 없이 QA 이후 바로 배포해야 하는 경우 브랜치를 따로 관리해야 한다. QA 서버에 배포하는 브랜치와 "지금" 배포를 위한 브랜치. 브랜치 관리 포인트가 늘어났을 뿐더러 메인 브랜치가 변경될 때마다 QA 브랜치의 lock 파일과 충돌이 발생한다. 
 
세번째로는 공용 패키지다. UI 구성을 위한 패키지는 npm이나 nexus 등을 이용해 배포하고 버전 관리하는 것이 기본이다. 하지만 공용 패키지를 모노레포 안에 옮긴다면 버전 관리에 문제가 발생한다.
예를 들어 아이콘 컴포넌트가 있고 파라미터로 아이콘의 이름을 입력하는 컴포넌트가 있다고 치자. 아이콘들이 추가/변경되어 호출하는 이름도 변경해야 할 때, 공용 패키지가 작업되었다고 곧바로 병합한다면 작업되지 않은 프로젝트에는 아이콘이 없거나 일부만 변경되는 등 문제가 발생한다. 기존 아이콘을 남겨도 문제고, 새로운 아이콘으로 한번에 바꿔버려도 크기나 색상 등 문제가 생길 확률이 높아 전수 조사가 필요해진다. 이런 경우는 공용 패키지 작업자가 한번에 모두 처리해야 하겠지만, 여러 지면, 혹은 여러 사이트에서 참조하는 것을 변경하는 작업에는 큰 리소스가 들어간다. 심지어 일정이 정해져 있다면 메인 브랜치로의 병합 자체를 미루는 수 밖에 없다.
 
네번째로는 용량 측면에서의 문제다. 실 단위 모노레포에 많은 프로젝트를 넣어버리니 용량이 어마어마하게 커진다. 개발 기기의 성능이 향상되었다곤 하지만 코드를 검색하기 위해 매번 범위를 지정해야 한다. 지정하지 않으면 모든 프로젝트에서 코드를 찾기 시작하니까. 이를 해결하려고 sparse checkout을 하곤 한다. 하지만 브랜치가 분리되거나 정작 필요할 때 또다시 checkout 받아야 하는 등 한계가 있다. 심지어 배포할 때도 마찬가지다. 흔히 젠킨스 서버에서 checkout을 받는데 이러면 너무 많은 파일을 받게 된다. 더군다나 pnpm-turbo로 빌드하면 필요 없는 패키지도 빌드하여 시간이 더 소요된다(캐시 설정은 문제 발생 여지가 많아 더 골치아프다)
 

일정적 여유가 있는 회사에서나 가능하지 않을까

 
주저리 주저리 적었지만 물론 해결할 수 없는 문제는 없다. 하지만 FE에 어울리는지 고민했었는지 의문스럽기도 하고, 의도 자체가 불순해보인다. 실제로 커밋 횟수가 어쩌고 하고 있기도 하고...
 

프로모션 - 놀먹보

몇가지 업체들과 연계하여 서로의 사이트에서 쿠폰을 발급받는(주고받는?) 프로모션 페이지와 그 페이지에서 요청하는 BFF 서버(API aggregation)를 개발했다. 생각보다 어렵지 않겠거니 했지만 기술 외적인 문제가 꽤 많았다. 그 중 가장 고통스러웠던 에셋 관리다. 50여개 이상의 이미지가 들어가다 보니 구분할 수 있게 파일명도 바꾸고 디렉토리로 정리해서 버킷에 업로드했다. 여기까진 괜찮았지만... 개발 기간 중 이미지가 계속 변경되어 몇번이나 업로드하려니 분노가 머리 끝까지 치밀어 올랐다. 같은 이미지를 몇 번이나 다시 올린건지...

그만바꿔

 
API 사용에도 아쉬움이 있었다. 기존 사용하던 API를 어떻게든 재사용하자는 의견이 모였고, 새로운 기능을 제공하려다 보니 내가 직접 BFF 서버에 이벤트 참여 시간, 날짜 구분이나 에러 메시지 처리 등 별 잡다한 기능들을 추가해야만 했다. 여러 업체들과 연계하는 프로젝트라는 것도 꽤 큰 관리 포인트였다. 업체별 이벤트 페이지가 당일에 정상적으로 작동하지 않는 것은 물론이고, 쿠폰 발급에 문제가 있어 담당자들이 진땀을 빼기도 했다. 업체 문제로 이미 광고비를 집행했던 푸시를 못 보내기도 했는데 어떻게 해결했는지는 모르겠다.
URL 인코딩과 관련되어 꽤 골치아픈 문제도 있었다. 앱의 딥링크는 특정 URI 파라미터를 추가 입력했을 때 웹뷰로 보여주는 기능이 있는데, 아래 같은 경우에 문제가 발생했다.

// 기본 URL. 
// IOS는 google.com 이후의 "?name=" 부터 인식하지 못한다.
testApp://webview?title=테스트&url=https://www.google.com?name=google

// URL 부분 인코딩
testApp://webview?title=테스트&url=https%3A%2F%2Fwww.google.com%3Fname%3Dgoogle

 
딥링크 자체가 쿼리 파라미터 룰을 따르고 있기 때문에 쿼리 파라미터로 전달되는 URL에도 쿼리 파라미터가 있는 경우 구문이 모호해진다. 이를 해결하기 위해 URL만 인코딩하여 전달해야 했는데 외부 링크 담당자가 이 구문을 인코딩하지 않고 삽입한다던가, 업체에서 이미 인코딩된 URL을 사용하는 경우 링크에 문제가 발생했다. 특히 모바일에서 다른 URL을 사용하는 경우는 파악하기 어렵다보니 찾는데도 꽤나 긴 시간이 걸렸다.
이런저런 이슈가 있긴 했지만 다 지나고 나니 생각보다 재미있었던 프로젝트였다. 일단 여기저기 마케팅 자료를 뿌려 검색하면 내가 만든 페이지가 뜨는 것도 재미있고, 제공하는 상품이 꽤 많다보니 커뮤니티 사이트에서 반응을 보는 것도 재미있었다. 물론 난 출석도 한두번 하고 안해서 받은게 없다.

누르면 고장날까봐 안누름

 
DAU나 신규, 이탈 회원 등 성과 지표는 목표대비 90% 남짓으로 큰 성공을 거두었다고 보기는 어려울 수 있지만, 업체들로부터 좋은 반응을 얻어 아마 지속적으로 진행할 것 같다고 공유받았다.
 

Protobuf 로그 자동화

이건 이전에 글을 썼던 내용이다. protobuf로 작성된 통계(클라이언트 로그) 명세를 각 언어별 전송 함수로 생성되도록 일종의 툴을 만들었다. 생각보다 결과물이 만족스러웠다. 의도한대로 타입 체크도 명확하게 이루어지고 실제로 입력해야 하는 값도 많이 줄어들었다. 기존에는 고정된 문자열을 계속 입력하면서 이게 뭐하는 짓인가 싶기도 했는데 그런 면에서 모두가 편해졌다고 믿는다.
평가 측면에서는 다른 팀의 구성원들과 이슈를 제기하고 회의하며 맞췄던 과정이 꽤 좋게 평가받고 있는 것 같다. 개인적으로 이런 평가 측면의 중요성보다 다른 플랫폼의 코드를 만들어내는 일종의 크로스 플랫폼 툴 개발 경험이 유의미하다고 생각된다. 폴리글랏의 유행은 지난 것 같지만 그래도 여러 언어에 대한 친숙함은 큰 강점이 될 것이다.

물론 아직도 왜 protobuf를 썼는지는 모름

 
 

마치며

상반기에는 팀 외부의 인원과 논의하고 맞춰나가는 작업이 많았다. 여러 측면에서 큰 도움이 되는 것을 느끼지만 그만큼 기술 측면에 관심이 줄어들어 가는 것을 느낀다. 기술은, 특히 변화가 빠른 FE는 계속 관심을 가지고 학습해야 하지만... 쉽지 않다.
여러 취미를 가져보려고 노력하고 있다. 경량비행기 자격증을 목표로 삼고 운전 연수를 했고, 얼마 전 조종 체험을 했다. 상당히 재미있었지만 자격증을 따기까지 최소 600만원이 들어간다고 하여 고민중이다. 이 돈이면 여행을 가도 몇 번을 간다는 생각이 든다. 이어서 공 3개 저글링에 도전해보려 한다. 10여년 전 한발 자전거는 결국 실패했었지만 이건 꽤 가능성이 보인다.