효율적인 협업 체계 만들기
업무 환경 만들기
로마에 가면 로마법을 따르라길래 잘 따르려고 했는데, 로마가 무정부 상태라면 어떻게 해야 할까? 빨리 짐 싸서 튀는게 정답일까? 아니면 끝까지 남아 정부 수립에 기여해야 하는 걸까? 나도 사실 잘 모르겠다. 그래도 한 가지 확실한 건, 어딘가에 소속되어 있고 시간에 대한 보상을 받고 있다면 적어도 그 기간에는 최선을 다해야 한다.
다음주에 개선된 코드 작성 방안에 대해 발표를 하려고 했는데, 다른 내용들을 먼저 말하는 게 좋을 것 같다. 디자인 패턴이나 패키지 구조, 코드 작성 규약과 같은 방법론들의 끝점에 있는 건 결국 사람인데, 이 엔드포인트를 사람이 아닌 시스템으로 변경하지 않는 이상 지속시키기는 어려울 것 같았다.
무턱대고 그냥 ‘코드 갈아엎고 이런 방식으로 다시 짜보자!’ 라고 말한다면 나홀로 지키는 룰이 될 것이기 때문에, 일단은 뭐가 문제인지부터 서로 파악을 하고, 공감대 형성에 성공한다면 이를 바탕으로 시스템적인 제약을 거는 방향으로 설정했다.
일단 문제 파악부터 해보자. 갈길이 멀다… ㅠㅠ
문제 1. 라우터 몰빵 코드
대부분의 서비스 로직이 컨트롤러 하나의 메서드에 작성되고 있다. 여기에 하나 더 추가로 db 엔티티도 하나의 단일 파일에서 관리되고 있는데, 그 파일에 컨트롤러 요청, 응답 모델도 같이 존재한다. 회사 코드를 공개할 수는 없고, 이런 분리되지 않은 코드들이 가지고 온 결과를 설명해 보자면 다음과 같다.
문제 정리
일단 당장 해결 가능해 보이는 문제들은 동글뱅이, 시간이 꽤 걸릴것 같은 문제들은 X를 쳐놨다. 세모는 나도 당장은 판단이 안되는 아리송한 문제들이다.
심각한 코드 중복
- 수없이 반복되는 권한 체크 코드 (O)
- 진행 불가능한 유닛 테스트 (X)
- 끊임없이 반복되는 동일 쿼리문 (O)
- 그 외 계속해서 등장하는 서비스 로직들 분리 (△)
난독화 수준의 알쏭달쏭 코드
- 추상화가 되어 있지 않은 날것 그대로의 조건들 (O)
- url을 호출하면 어떤 동작을 할 지 예측 힘듬 (X)
수많은 기능이 중첩된 단일 메서드
- 특정 url은 관리자가 수정, 삭제 그리고 유저가 생성하는 기능을 다 같이 수행 (X)
분리되지 않은 요청, 응답 모델
- 이곳 저곳에서 다쓰이는 모델들 (X)
- 값 수정시 어디서 무슨 문제가 터질지 모르는 짜릿함 (X)
수없이 반복되는 깃 컨플릭트
- 같은 파일을 서로 수정하다 보니 충돌은 다반사 (△)
해결책
결국 코딩 컨벤션이나 공통 가이드라인이 없어서 생기는 문제다. 이런걸 xml 파일로 만들어서 pr 날릴때 파이프라인으로 잡아주거나 코드 리뷰 문화라도 있으면 해결해 볼 수 있을것 같은데, 지금 우리 팀이랑은 너무 거리가 먼 얘기같다. 솔직히 정상적으로 작동 안 할 것 같다. 유의미한 문화가 될 수 있는지도 모르겠고… 차라리 소나큐브같은 외부 인프라를 땡겨쓰는것도 좋을 것 같은데, 결재 올릴만큼 공감대를 얻을 수 있을지 모르겠다. 그렇다고 손 놓고 있을 수는 없으니, 일단 최대한 실현 가능한 해결책들을 생각해보자.
수없이 반복되는 권한 체크 코드 (O)
그나마 가장 간단한 문제다.
해당 코드는 어드민이 아니면 예외를 던지고 접근을 막는 기능밖에 하지 않기 때문에, FastAPI에서 제공해주는 의존성 함수로 빼주거나 미들웨어쪽에서 잘 만지면 될 것 같다.
이리저리 잘 섞어가며 진행해야 할 것 같은데, 어드민 기능도 하면서 유저 기능도 하는 괴상한 컨트롤러들이 있어서 일괄적으로 빼지는 못할 것 같다. 하나 걱정되는건 의존성 주입이 낯선 팀원들이 있는 것 같아서 가벼운 사용법이나 원리 같은 소개와 함께 진행하면 좋을 것 같다.
당장 확인해본 특정 메서드 중복 작성건만 40개가 넘는다. 최대한 빨리 쳐내보자.
진행 불가능한 유닛 테스트 (X)
이건 단언할 수 있다. 지금은 힘들다.
팀원들이 테스트 코드의 존재 자체를 잘 모르기도 하고, 실험삼아 내가 작성한 테스트들을 pr로 성공 여부, 커버리지 표시되게 했더니 오히려 거부감을 가지더라. 사실 이 작업은 충분한 설명과 공감대를 얻는 선행작업이 크게 필요하지 않을 것이라 생각해서 빠르게 진행한 것이었는데, 나도 힘빠지더라. 그렇다고 테스트 하나 없이 계속 프로젝트를 진행하는건 아무리 생각해도 말도 안되서, 이건 진지하게 고민중이다.
정답을 모르겠다 나도…
끊임없이 반복되는 동일 쿼리문 (O)
컨트롤러단에서 코드가 늘어지는 가장 큰 주범이다. 이건 쿼리들만 그대로 별도 메서드로 모아주면 되니까 가능하지 않을까 생각중이다.
다만 그 방식에 있어서 고민을 했는데, 루비나 파이썬쪽에서 많이 사용하는 액티브 레코드 방식이 있고 스프링 진영에서 많이 사용하는 데이터 매퍼, 레포지토리 방식 중에 고민했는데 팀의 숙련도나 사용의 익숙함을 고려해서 액티브 레코드 방식으로 가면 좋지 않을까 생각중이다. 지금 우리 코드 방식에서 레포지토리, 서비스 이런 계층은 너무 갭이 큰 구조일 것 같아서 최대한 익숙하게 보일 수 있는 구조로 고민했다.
간략하게 생각한 방식은 다음과 같다.
1
2
3
4
5
6
7
8
class IAmQuery(Document):
i_am_속성: str
@classmethod
async def 추상화된_로직이에여(cls, id: PydanticObjectId) -> bool:
return await IAmQuery.find(IAmQuery.id == id).exists()
기존 몽고 odm인 beanie와 유사한 쿼리 사용 방식으로 하기 위해 정적 메서드로 선언하고, 클래스명을 통해서 바로 메서드에 접근하는 방식이다. 이거랑 나중에 코드가 잘 응집화되면 하나 더 제안하고 싶은게 함수를 바로 임포트 해서 써오는 방식 말고, 파일명.함수() 이런식으로 사용하면 좋을 것 같다. 함수명만 띡 임포트해서 쓰니까 얘가 저쪽놈인지 이쪽놈인지 구별이 안된다. 위에 임포트문도 뭐가 계속 늘어나서 별로 보기 안좋다. 나 혼자만의 생각인가??
1
2
3
4
5
# 요런 방식으로 쓰고 싶어요 ㅠㅠ
permission_manager.grant()
# 이런거 싫어요 ㅠㅠㅠㅠ
grant()
그 외 계속해서 등장하는 서비스 로직들 분리 (△)
이건 코딩 컨벤션이 정해지면 해결 가능할 문제 같다. 가능하겠지?
사실 이거 말고도 기준점 정해야 할게 수두룩 빽빽이다. 당장 네이밍 룰만 봐도 눈물이 흐른다. 역할에 따른 명사 동사 이런거 따질 때가 아니라 뱀과 낙타가 공존중이다. 코드 볼때마다 내가 파이썬 백단 코드 보는중인지 타입스크립트 프론트 코드인지 헷갈릴 때가 있다.
이런 기준점이 서비스 로직 분리에는 크게 무리가 없으리라 생각한다. 사실 대부분의 복잡도를 올리는 코드가 산개된 쿼리문들이고, 복잡한 자체 서비스 로직은 사실상 거의 없기 때문에 가능하지 않을까 짐작할 뿐이다.
추상화가 되어 있지 않은 날것 그대로의 조건들 (O)
이건 함수로 빼면 나름 가독성 있는 조건 분기가 되지 않을까 기대중이다.
예를 들자면,
1
2
3
4
5
6
7
8
# ....
if model.value_1 and model.value_2:
do_something()
# ...
if model.value_1 and model.value_3 and not model.value_2:
do_something_other()
이런 코드들을
1
2
3
4
5
6
7
8
# ....
if is_condition_1():
do_something()
# ...
if is_condition_2():
do_something_other()
이런 식으로만 빼줘도 훨씬 낫지 않을까??
예측 불가 url, 기능 중첩 url, 분리되지 않은 요청, 응답 모델 (X)
이건 당장은 힘들다.
나 혼자 날뛰어서 될 파트가 아닌게 가장 큰 이유같다. 프론트 쪽도 다 같이 수정이 들어가야 되고, 기존 문서들도 새로 정리해야 되고, 합의가 상당히 필요한 부분일 것이라 생각한다.
수없이 반복되는 깃 컨플릭트 (△)
이건 결국 단일 파일에서 모든걸 작업해서 생기는 부수적인 문제라고 생각한다.
클래스를 나누고, 패키지를 나누고, 파일들을 잘 정돈하다 보면 서서히 해결되리라 기대한다.
한 가지 더 바라는 바가 있다면 작업의 단위를 최대한 작게 쪼개서 빠르게 머지하는 방식으로 가고 싶은데, 가능할지 모르겠다. 지금은 컨플릭이 안 나는게 신기한 구조다. 브랜치 하나 빼서 작업을 30일 가까이 하는데 메인에 머지할 때 충돌 안나길 바라는게 GTA 심보 아닌가 싶다.
다음 이 시간에
사실 초안에 문제 6까지 써놨는데 하나의 글에 전부 담을 사이즈가 아닌 것 같다.
차후 문제별로 하나씩 포스팅하고, 개인적으로 소망하는 개선 방안을 쓰려한다. 남은 주제들은 다음과 같다.
- 문제 2. 찾을 수 없는 로그와 히스토리
- 문제 3. 테스트? 그게 뭔데?
- 문제 4. 지금 내가 짜는게 곧 표준
- 문제 5. 제약 없는 배포 프로세스
- 문제 6. 작성한 코드의 대략적인 영향력 생각하기
문제 1부터 부디 잘 설득이 되면 좋겠다…