글 목록으로 이동

봄가을 블로그

기술2024년 09월 15일--views

4년차 개발자(나)가 취직 전 프로젝트 열심히 하는 개발 꿈나무에게 전하는 메시지

IT연합동아리에 참여하는 대학생 친구들에게 현업자로서 피드백을 전달했어요

글에 들어가기 전에… 저는 사이드 프로젝트를 참여하고 있고, 거기서 IT연합동아리와 기업협력 프로젝트를 한다길래 그렇구나~ 하고 있었는데, 프로젝트 발표일에 심사위원으로 나갈 만한 개발자가 딱히 없어서 제가 가게 되었습니다. 가지고 있던 유일한 장점은 현업에서 좀 굴러봤다는 것 밖에 없지만 뭐… 일단 나가게 됐습니다.

좀 긴장되는 자리였어요. 나도 꼬꼬마 쪼꼬미 텔레토비 개발자인데 감히 누구를 평가를 한다고? ㅎㅎ... 일이니 해야죠. 그렇지만 열심히 개발하고 발표를 준비하는 친구들을 보니 왠지 흐뭇한 기분도 들었습니다.

나가는 김에 제대로 하고 싶어서 개발적인 피드백도 준비했으나, 평가하면서 개발 피드백을 남기기가 상황이 좀 거시기하더라구요. 알아 듣는 사람도 별로 없고 좀 더 기획적인 질문과 피드백이 위주였던 자리였으니.

그래서 글로 정리했습니다. 글로 정리하다 보니까 글이 길어지고, 또 그냥 한번 쓰고 버리자니 약간 아까워서 블로그에 남깁니다.

따봉을 날리는 털수염 개발자 아저씨
Photo by raf vit on Unsplash

안녕하세요 XXX 여러분들! 3주간 빡빡하게 프로젝트 진행하시느라 다들 정말 고생많으셨습니다. 발표 당일에 피드백을 나눠드릴 수 있다고 생각했지만 밀도있게 메시지를 전달드리는 데에 좀 한계가 있을듯 하여 글로 정리해서 이렇게 전달드립니다.

일단 제 특징으론 현업 상의 일도 그렇고 사이드 프로젝트도 그렇고 굉장히 빠른 싸이클을 돌리면서 제품을 발전시켜야 하는 입장이라, 피드백도 그런 방향성이라는 것을 말씀드려요. 대기업에서 할 법한, 궤도에 올라와 있어 지 혼자 어느정도 굴러가는 대규모 프로젝트와 어울리는 피드백은 아니라는 뜻입니다. 제품의 특성에 따라 개발 전략도 좀 다르다고 생각하거든요.

피드백은 뭔가 하나하나를 콕 집어서 드리기 보다는 더 큰 시야에서 방향성 위주로 전달드리려고 합니다. 물고기 보다는 물고기 잡는 법이 더 유용하다고 믿습니다. 그리고 용어 같은 경우 제 뇌피셜이 듬뿍 들어갈 수도 있으니 용어의 정확한 정의는 따로 검색해보심이...ㅎㅎ


프론트

Controlled Component 와 Uncontrolled Component 의 차이를 알면 좋다

FullCalendar 관련 질문을 보면서 드는 생각이었어요. 보통 프론트를 하게 되면 컴포넌트/UI 라이브러리를 많이 사용하게 될텐데, 그런 컴포넌트를 크게 둘로 구분할 때 저 Controlled 와 Uncontrolled 로 나눌 수 있어요. Controlled 란 라이브러리를 사용하는 내가 상태와 관한 전권을 가지고 있다는 뜻이고, Uncontrolled 는 컴포넌트에게 초기값만 알려주되 내부적으로 변하는 값을 감지할 수 있도록 onChange 등의 인터페이스만 열어줄 뿐 실제 상태는 어떨지 모른다... 라는 게 있습니다. Controlled 는 내부에 상태가 없고 Uncontrolled 는 내부에 상태가 있다는 뜻이죠.

FullCalendar 에서 events props 가 만약 controlled 하게 제공할 수 있는 거라면 이 events props를 잘 넘겨주는 것만 신경쓰면 되지만, uncontrolled 하게 관리된다면 캘린더 내부 상태를 변경할 수 있도록 하는 인터페이스가 분명 있을 겁니다. 그 컴포넌트가 상태를 어떤 전략으로 관리하는지부터 알아야 문제에 대한 접근을 시작할 수 있습니다. 컴포넌트를 만드는 사람 입장에서 왜 controlled, uncontrolled 하는 방식으로 나눠놨을까 하는 질문도 의미가 있겠습니다.

여러 개의 같은 요청 최적화

reactQueryuseSWR 같은 라이브러리를 쓰면 쉽게 해결할 수 있습니다. 얘네들은 키 값을 따로 둬서, 같은 키 값이면 같은 요청이라 간주하고 알아서 최적화해줍니다. 다만 기본 세팅된 설정이 다양할 수 있어서 어떤 "기본동작"이 있는지부터 살펴봐야 하겠습니다.

폴더 구조(좀 김)

폴더 구조를 생각할 때에는 다음 2가지의 고민 비용을 최대한 줄이는 게 중요합니다. 1. 파일을 생성하여 어느 폴더에 넣을 것인가? 2. 어떤 파일을 어디서 찾을 것인가? . 즉 고민없이 파일을 생성하고 고민없이 뒤져볼 폴더를 선택할 수 있어야 한다는 거죠.

일단 다음 두 가지 분류 체계가 있습니다.

  • 도메인: user, schedule, 공고, 프로그램, shared
  • 기능: component, hook, lib(비즈니스 로직과 관련된 것), util, constant, dto, controller, repository, 기타등등

무엇을 먼저 하냐에 따라 두가지 방법이 있습니다.

  • 도메인 먼저, 기능 나중에 한다면 상위 user 폴더, 하위 component, hook, util 등의 폴더가 있을 것이고
  • 기능 먼저, 도메인 나중에로 한다면 상위 components 폴더, 하위 user, schedule 등의 폴더가 있을 겁니다.

그런데 이 두가지를 섞어서 하는 안 좋은 케이스가 있습니다. 최상위에 user, component 등의 폴더가 있는 식이죠. 이러면 혼란이 옵니다. 앞서 이야기한 두 가지 고민 비용이 동시에 올라갑니다. 두 가지 중 한가지만 씁시다. 둘 중 무엇이 더 좋은가는 논란이 있지만 프론트에서는 "기능 먼저, 도메인 나중에"가 더 일반적이고 Nest.js 나 자바 스프링은 "도메인 먼저, 기능 나중에" 가 국룰입니다.

그리고 첨언하자면, 고민 비용을 줄이기 위해 저만의 규칙도 있는데요

  • 일단 파일 하나에 몰아넣고 500줄 이상이 넘어가면 파일을 분리한다. (파일 이름은 상황에 따라 적절히)
  • 일단 폴더 하나에 몰아넣고 파일이 20개가 넘어가면 그룹핑한다 (분류 기준은 상황에 따라 적절히)

이런 규칙도 있으면 고민 비용이 훨씬 줄어드는 경험을 저는 했습니다.

이름 짓기의 중요성(폴더 구조에서 이어짐)

요새는 IDE 가 좋아지고 그래서 cmd+click 으로 타고타고 들어가거나, 전체 검색하는 게 쉽습니다. 그래서, 만약 모든 접근을 검색을 통해서 쉽게 할 수 있다면 폴더 구조에서 이야기한 두 가지 고민의 비용도 0으로 수렴합니다. 어차피 검색으로 잘 찾을 수 있는데 저장할 폴더는 그냥 아무데나 쑤셔넣어도 상관없는 거죠. 다만 검색할 때 이름을 넣어야 하잖아요? 이름을 얼마나 유추하기 쉽게 지었냐?가 유일한 인자가 될 거에요.

변수명 짓기는 뭐 검색의 용이성 말고도 중요한 이유가 수십가지죠. 협업할 때 중요하고. 추상화를 잘 해놓으면 구현을 떠올릴 필요가 없어 뇌에 무리가 덜 가고... 등등 이건 다들 공감하실 거라 생각합니다. 변수명 뿐만 아니라 컬럼명도 중요하죠. B팀 schedule 테이블에서 filter 라는 컬럼을 발견했는데 (이걸로 필터링할 수 있다는 의미일까요??) type이라는 이름이 더 맞는 거 같습니다.

변수명 지을 때는 ChatGPT 가 꿀입니다. 저도 조금이라도 고민되면 무조건 물어봐요. 고민조차 안하고 첨부터 물어볼 때도 있습니다. 이 변수명이 이해가 잘 되냐 이런 것도 물어보구요. 구체적으로 어떤 이름이 좋고 나쁜지는 코드만 봐선 잘 모르겠네요... 대체로 나쁘지 않은 거 같습니다.!!!


백엔드(데이터 관련)

created_at, deleted_at, updated_at

ERD 보다가 당연히 넣을 거라 해서 없는 건지, 아니면 진짜 없는건진 모르겠지만, 저 3개 컬럼은 있는 게 거의 무조건 좋습니다. 여러 엔티티가 엮여있으면 뭔가를 삭제하는 게 굉장히 힘듭니다. 소프트딜리트는 마음이 편합니다. 관리하기도 쉽구요. 그 머시냐 외래키에 on delete cascade 그거는 위험해서 안합니다. 다만! 다대다 관계를 표현하기 위한 relation 테이블은 운영 관점에서 아예 삭제하는 게 훨씬 보기 좋고 그 relation 에 의존하는 다른 엔티티는 없는 경우가 많아 삭제하는데 어려움도 없어서, 여기에 deleted_at 은 없어도 될 거 같아요.

페이지네이션

페이지네이션은 두 가지 방식으로 나뉘고 (cursor-offset 방식, page-perpage 방식) 두 경우 모두 전체 페이지 수를 알아야 하기 때문에 totalCount 가 필요합니다. 팀에서 합의한 대로 편한 방식대로 쓰면 되고, 백엔드 상으로는 성능과 관한 트레이드오프가 있을 수 있겠지만 프론트 선에서는 깊게 논의될 건 없다고 생각합니다.

파일 업로드와 DB

파일을 테이블로 따로 관리할 수도 있는데, 저는 추천드리진 않습니다. 따로 관리하는 이유는 나중에 명시적으로 삭제하기 위함인데, 단순한 이미지나 파일을 업로드하고 보관해두는 건 비용이 가장 적게 드는 부분이라서 삭제를 굳이 안하고 쌓아둘 수 있습니다. 파일 불러오는 건 파일 링크 혹은 키만 있으면 충분합니다. 이미지 같은 경우는 이미지 다운로드가 완료되어야 그 가로세로 크기를 알 수 있기 때문에, 이미지 로딩과 관련된 UX를 극도로 살리는게 필요하다면 가로세로 길이만 따로 DB에 저장해두는 정도입니다.

반정규화와 읽기성능

이건 사실 법칙같은 느낌입니다. 대충 정규화... 잘 정규화되어 있으면 Single Source of Truth 가 잘 되어있다는 뜻이고 정규화가 덜 될 수록 데이터의 복제본이 많아집니다. 정규화가 잘 되어 있을 수록 데이터 일관성은 높아지지만 읽기 비용도 늘어납니다. 왜냐하면 수많은 join 문이 기다리기 때문이죠. 읽기 비용을 줄이기 위해 복제본을 만드는 건 아주 일반적인 방법이고, 여기에는 인덱스, 캐시, 같은내용의 여러 테이블(흔히 이야기하는 반정규화)가 있을 겁니다. 그런 게 늘어날 수록 쓰기 비용은 증가합니다. 쓰기를 할 때마다 인덱스를 갱신해야 하며(DB가 자동으로 해주긴 하지만), 캐시도 기존 저장된 걸 날려야 하며 테이블이 나뉘어져 있다면 동시에 잘 업데이트해줘야 할 겁니다. 그럼에도 불구하고 읽기 비용을 줄이는 게 목표였다면 충분히 가치있는 트레이드오프인 것이죠. 그래서 "읽기 성능을 줄이기 위해 반정규화를 했다."는 건 사실 좀 당연한 말인 거 같습니다.

우선순위를 따지자면 인덱스를 잘 거는 게 가장 중요할 것 같고, 특정 사용자(세션정보)와 관련 없는 초당 몇십회 이상의 요청은 레디스 같은거 좋구요, 엄~청 많이 들어오는 요청은 그냥 그 데이터를 json 파일로 만들어서 s3에 올린 뒤 CDN(AWS Cloundfront)에 태워버려도 됩니다. 초당 몇만건도 잘 처리될걸요? 각 기술에 대해 트레이드오프를 잘 이해하면 좋습니다. 테이블 row 수가 몇백만건 되면 인덱스가 걸려 있어도 검색하는 게 느릴 수 있습니다. 이 때는 테이블을 파티셔닝해야 하는 것이지요...

최대한 Not null 하자

가장 가성비 좋은 거라고 생각합니다. A팀이었나요, 스케줄 테이블에 날짜랑 필터가 nullable 이었던 거 같은데, 약간 모순인 느낌입니다. 스케줄인데 날짜가 어떻게 없을 수 있지? 이런느낌... 어쩔 수 없는 이유로 nullable 했다 하더라도 그건 잘못되었다고 생각해요. not null 에 비즈니스로직을 맞춰야 할 거 같습니다.


그냥 공통..? (사족)

운영 비용 줄이기

XXX 프로젝트 특성상 기술을 써보고 적용시켜보고 하는 학습의 의의도 커서 "굳이 쓸 필요 없는데 왜 썼냐?"와 같은 피드백은 의미없다고 생각하구용. 그렇지만 저희가 막 devops 라고 하잖아요. 그 시스템을 실제로 돌리는 것도 중요하고 사람 손이 많이 들어가고 하여튼 제품에는 기획-디자인-개발 뿐만 아니라 운영, CX, 경영자, 마케팅, QA 등등 수없이 다양한 사람들이 들어가기 때문에 테이블이나, api 구조 등등을 간단하게! 가져가는 것이 아주 중요합니다. 그것만 잘 기억해주셨음 좋겠습니다. 뭘로 구현할 건가? 와 같은 고민도 중요하지만 "고려할 필요가 없는 부분"도 명확히 하는 게 중요해집니다.

최적화

최적화를 대하는 제 자세는 크게 두 가지로 말씀드릴 수 있을텐데요, 1.노력이 하나도 들지 않는 (안할 이유가 없는) 최적화는 한다. 2.노력이 들어가는 최적화는 실제로 불편하지 않으면 하지 않는다. 네... 2번이 말이 쉬운데 좀 어렵습니다. 예를 들어 렌더링이 딱히 느린 것도 아닌데 리렌더링 관련 최적화를 하고 있다든지... 개발자 성향 상 최적화를 나도 모르게 하고 있는 경우가 많을 거에요. 자신이 지금 하고 있는 작업을 제3의 눈으로 직시해서 이게 진짜 필요한 작업인지 아닌지를 자주 점검하면 좋습니다.

코드 퀄리티

혹시 회사 취직하신 분이 있을지는 모르겠지만, 코드는 어딜 가도 개판입니다. 아는데 못하는 것들이 엄청 많아요. 대부분의 회사들은 돈을 벌기 위해 리소스가 항상 허덕이니까. 그래서 뭔가 현업에서 쓰는 코드는 뭔가 다를 것이다! 라는 환상을 가질 수도 있는데 그런 건 잘 없습니다. 우리가 현실적으로 할 수 있는 건 적은 노력으로 최대한의 효과를 낼 수 있는 자잘한 좋은 습관일 거고, 지금도 여전히 생각나는 건 변수명 잘짓기를 잘 해두면 좋을 거 같네요.ㅋㅋ


쓰다보니 좀 길어졌네요.... ㅎㅎ... 취할 건 취하고 버릴 건 버리시기 바랍니다. 다시한번 모두들 고생하셨습니다~