서론
면접에서 "원하시면 코드 리뷰 문화 직접 도입해보세요~"라는 말을 들었었는데, 그것이 현실이 되었다..
책을 보고 혼나는 기분은 처음이었다.
약 9주에 걸친 '클린 코드' 스터디가 끝나간다.
해당 포스트에서는 스터디 후기보다 '클린 코드'라는 책을 본 후기와 실무에서 어떻게 적용했는지 쓰려고 한다.
스터디와 관련된 규칙 및 진행 방식은 아래 링크를 참고 바란다.
내가 쓴 코드를 돌아보며
나는 "가독성 좋은", "직관적인" 코드를 '클린 코드'라고 생각한다.
내가 그동안 기록이랍시고 남겨둔 Repository를 살펴보고 느낀 기분은 딱 이랬다.
"가독성 떨어지는", "직관적이지 않은", "질서 없는"
사실 이 책을 보면서, 내 깃헙에 당당하게 핀을 꽂아둔 레포를 내리고 싶었다.
나름 리더랍시고 늘 팀원을 이끌고 코드 리뷰에 적극적인 협업을 했는데, 정작 뼈대 없는 건물을 짓고 있었기 때문이다.
과거의 나를 대상으로 몇 가지 짚고 가보자.
지금부터는 팀 프로젝트에서 실제로 내가 작성했던 코드들의 일부다.
축약한 변수명
String bres;
이 네이밍을 보고 어떤 데이터를 담는지 유추할 수 있다면 당신은 천재다.
String bres = Base64.getEncoder().encodeToString(outputStream.toByteArray());
내용은 이러하다.
Base64 인코딩을 하기 때문에 "b"를 붙였고
결과물이 담기기에 "result"의 "res"를 합성시켜 "bres"가 탄생했다.
저땐 변수명이 짧으면 좋을 줄 알았나 보다.
통상적으로 쓰이는 아래의 변수명을 보자.
int i;
int cnt;
index를 의미하는 i, count를 의미하는 cnt이다.
이러한 네이밍은 팀 by 팀, 프로젝트 by 프로젝트이니 컨벤션을 따라가는 것이 맞겠지만 개발자들이 보편적으로 이해할 수 있는 단어는 사용될 수 있다고 생각한다.
하지만, 비즈니스 로직을 이해하기 위해 변수명을 해석해야 하는 아래의 경우는 지양하고 있다.
String svcN; // Service Name
String usr; // User
이유 모를 주석처리
@PostMapping("/export")
@ApiOperation(value="기수-프로젝트도메인에 맞는 팀을 가로비 정렬하여 Excel파일로 export한다")
// @ApiResponses({
// @ApiResponse(code = 200, message = "파일을 읽고 Dto화 성공"),
// @ApiResponse(code = 400, message = "잘못된 파일 형식 또는 잘못된 데이터",response = BaseResDto.class)
// })
실제 머지된 코드에 올라가 있는 부분이다.
왜 주석처리했을까?
지금은 안 쓰지만 나중에 쓸 가능성이 있어서?
내가 작성한 코드가 아니라서?
테스트할 때 쓰여서?
모른다..
지금은 불필요한 주석은 제거하고, 필요한 주석이나 이어서 개발해야 하는 경우 todo 주석으로 처리하여 주석을 보고 물음표를 띄우는 상황이 없도록 신경 쓰고 있다.
변경에 취약한 코드
/**
* 0: team_id
* 1: team_name
* 2: stage_name
* 3: track_name
* 4: proejct_name
*/
for(int i =0;i<results.size();i++) {
Object[] o = results.get(i);
long team_id = Long.parseLong(o[0].toString());
String team_name = o[1].toString();
String stage_name = o[2].toString();
String track_name = o[3].toString();
String project_name = o[4].toString();
컬럼 순서가 바뀌거나 컬럼이 바뀌어 버리면 Object에 접근하는 index가 바뀌고 변수명이 바뀐다.
이게 큰 문제가 아닐 수 있다.
하지만, 저런 코드가 사방에 깔려있다면.. (실제로 깔려있다)
index보다 key로 접근한다면 좀 더 직관적인 코드가 될 수 있었을 것이다.
아쉬운 Exception 처리
catch(Exception e) {
log.error("팀 객체에 유저 정보를 채우는 것에 실패했습니다");
e.printStackTrace();
}
Repository의 코드 일부분이다.
Controller -> Service -> Repository 구조인데 Repository에서 Exception을 통째로 잡아 에러를 출력한다.
아마 내 기억으론 Repository, Service, Controller 어디서 Exception을 처리할지 몰라서 중구난방으로 처리를 했던 기억이 있는데, "팀 객체에 유저 정보를 채우는 것에 실패했다"는 예외만 발생하는지는 모른다...
이 부분을 UnCheckedExcpetion인 Custom Exception으로 처리했다면 코드가 훨씬 깔끔해졌을 것이다.
컨벤션
String snake_case;
String lowerCamelCase;
String UpperCamelCase;
변수 선언만 보아도 어떤 곳은 snake_case를 어떤 곳은 lowerCamelCase, UppderCamelCase를 혼용하여 사용했다.
이 뿐만 아니라 코드 작성에 있어서 컨벤션을 통일하고 좀 더 직관적인 네이밍과 Handler를 통한 Exception 처리를 했다면 개발 시간을 단축할 수 있었을 것이다.
결론
이 뿐만 아니라 많은 문제점이 있었다.
여기서 언급되는 "문제점"은 '클린 코드' 저서에서 말하는 문제점뿐만 아니라,
내 코드를 읽는 사람들에게 한번 더 해석을 요구한다는 점에서의 문제점이다.
즉.. 내 코드를 읽기 위해서 이해를 위한 이해가 필요했다.
이런 내 코드를 보고도 열심히 리뷰해주었던 프로젝트 팀원들에게 너무나 감사함을 느낀다.
실무에 적용하는 단계
약 1개월에 걸쳐 팀 Git flow와 코드 컨벤션, PR(MR) 컨벤션을 직접 만들 수 있었고
'클린 코드'를 보며 공감할 수 있었던 내용들을 적용할 수 있었다.
이 과정을 간단히 적어보겠다.
굳이?
협업에 있어 가장 최강의 단어이자 가장 듣기 싫은 단어일 수 있다.
물론 내가 직접 경험한 적은 없으나, 무의식중에 내가 쓰지 않길 바라면서 작성한다.
앞, 뒤 논리 없이 "굳이"라는 단어 하나로 어떤 의견 하나를 묵살시킬 수 있는 끝판왕이다.
절대 절대 쓰지 말자.
특히 남을 설득하거나 상대가 작성한 코드를 리뷰할 때 상대방의 기분이 상하지 않도록 신경 쓰고 있다.
자칫 내 경솔한 단어 하나로 상대방의 작품을 폄하할 수 있기 때문이다.
감히 신입이..
신입이기 때문에 어떠한 컨벤션이 도입되어야 하는 이유와 trade off인 상황을 더 열심히 생각했다.
각 팀마다 보이지 않는 문화가 있을 것이다. 이 문화를 혹여나 해치지 않을까 우려하기도 했다.
또한 설득해야 하는 대상은 나보다 훨씬 고연차의 경험이 많은 베테랑 개발자들이다.
그 앞에서 PPT를 펼쳐두고 이러쿵저러쿵 재롱부리는 격이 되진 않을까 걱정도 되긴 했지만
내 걱정과 달리 Git flow나 Java convention, Merge Request convention 발표를 진행하면서 팀원 분들이 굉장히 귀 기울여 주셨고, 실무에서 경험할 수 있는 불편함을 예측하여 다양한 관점에서 의견을 주셨다.
몇 차례 회의 끝에 팀 컨벤션이 만들어졌고, 적극적으로 적응해가는 팀원분들의 모습이 인상적이었다.
이렇게까지 하는 게 맞을까
실제로 있었던 에피소드이다.
정말 사소한 변수 네이밍에 대해 코멘트를 열정적으로 달아가며 선임 개발자와 토론한 적이 있었다.
아니 그전에,
"변수 네이밍이 사소한가"에 대해 짚고 가자.
사소할 수 있다고 생각하는 사람은 나를 보고 "병이다.", "너무 지나치다."라고 생각할 수 있다.
나도 위 생각을 처음 했었으나, 이런 생각도 해보았다.
이 프로젝트를 처음 보는 사람이(인수인계가 될 수 있고, 담당자가 바뀔 수 있다) 코드를 이해하려고 할 때,
로직을 이해하기도 전에 변수 네이밍이나 메서드 네이밍을 보고 이해하지 못하고 한 Depth씩 따라가며
가장 밑단 로직까지 가서야 이해하고 올라오는 방식이 과연 옳은가?
지금 변수 네이밍 하나 가지고 10분 정도 토론하는 과정으로 이후에 코드를 읽는 사람으로 하여금 1시간을 단축할 수 있다면 이건 효율적인 방식이지 않을까?
결국, 내 스스로 결론을 내렸다.
"변수 네이밍은 사소하지 않다."
장문의 메세지를 주고받으며 해당 Merge Request에 내 의견을 반영할 수 있었다.
짧고 굵은 건설적인 대화였다고 생각하며, 이런 문제에도 적극적으로 의견을 제시해주셨던 선임 개발자분께 참 감사하다.
난 이 과정을 통해 "컨벤션 발표에서 네이밍에 관해 확실하게 정했더라면.." 하는 아쉬움이 있었다.
한편으론 이런 "네이밍까지 관여하는 건 지나치지 않을까..."라는 생각도 들었다.
이건 아직 내 경험이 부족하기에 훗날 답을 내려볼 수 있으면 좋겠다.
마무리
다시 '클린 코드' 저서 얘기로 돌아오자면,
참 유익했고 반성할 수 있었으며 실무에 적용하기도 좋았다.
다만 내가 아직 경험해보지 못한 상황과 예시가 많아서 일정 구간 이후부터는 공감과 깨달음, 반성보다 이론적 이해가 필요한 상황이 많았다.
어릴 때 이해가 잘 안 되던 영화가 나이를 먹으며 이해되는 부분이 있듯이, (인셉션 아직 이해 못 함;)
이 글을 쓰는 이유도 완전 쌩신입때 느낀 점과, 경험이 점차 쌓여가며 느낀 점이 분명 다를 것이라 확신했다.
다음 스터디로는 TDD나 Java에 대해 공부할 수 있는 책을 골라 진행하려고 한다.
당연하게 쓰던 Java에 대해 너무 모르고 쓰고 있다는 생각이 들었고,
이번 프로젝트에서 테스트 코드 작성에 많은 어려움을 겪기도 했고, '클린 코드'에서만 접했던 테스트 코드 작성에 대한 이점으로는 "테스트 코드가 반드시 필요하다!"라는 주장을 하기에 아직 내 지식이 부족하다고 느꼈기 때문이다.
앞으로 공부할게 너무나 많다.. 행복하다.....
'후기 > 경험' 카테고리의 다른 글
글또 8기 참여 (2) | 2023.02.12 |
---|---|
[스터디 회고] 게시판 구현하기 (0) | 2022.06.01 |
프로그래머스 테크 피드 노젓기 (0) | 2021.09.24 |
4개월, 내게 있었던 일들 회고록 (4) | 2021.04.19 |
2020 한국전자통신연구원(ETRI) 하계 인턴(연구 연수생) 합격 후기 (15) | 2020.10.17 |
인프런 지식공유자로 활동하고 있으며 MSA 전환이 취미입니다. 개발과 관련된 다양한 정보를 몰입감있게 전달합니다.