코드스테이츠 교육과정을 수강하며 팀 프로젝트를 진행할 때에는 제한된 시간에 맞춰 기능을 구현하느라 제대로 신경 못 썼던 것이 있습니다. 상대방도 읽기 편한 깔끔한 코드를 작성하지 않았던 것인데요. 나름 코드 규칙을 세워가며 프로젝트를 진행하긴 했지만 각자의 코딩스타일이 너무나도 다른 것 때문에 나중에 리팩토링할 때에 조금 더 힘들었던 경험이 있습니다.
제 코드를 읽는 팀원들도 많이 애먹었을 것을 생각하며.. 요즘에는 최대한 남이 읽기 편한 코드를 작성하기 위해 노력 중입니다. 항상 머릿 속에 생각하고 실행하려 하고 있지만 언제든 잊어버릴 수 있기에 유튜브에서 봤던 클린 코드에 관련된 좋은 영상들의 내용을 정리하여 기록해보려 합니다.
좋은 코드란 무엇인가?
좋은 코드란 것은 일단 돌아가기만 하면 되는 코드가 아닙니다. 좋은 코드란 그 자체로 설명이 다 되는 코드입니다. 만약 팀으로 일한다면, 좋은 코드는 팀원들이 읽었을 때 읽기만 해도 무엇인지 이해가 되고 코드가 무엇을 하는지 물어볼 필요도 없이 이해가 되는 코드를 말합니다. 그게 가장 이상적인 코드의 모습일 것입니다.
코드가 당연히 작동도 잘 되고 부연설명이 필요없는 상태
또한 혼자서 작업시 오랜 시간 후에 다시 코드를 확인하더라도 예전에 내가 하던 고민이 무엇인지 코드만으로 이해가 되는, 부연설명 없이 코드로 설명이 되는 상태일 것입니다. 위의 상태의 코드가 가장 이상적이고 훌륭한 코드의 모습이라고 생각하고, 클린 코드 작성 팁을 설명해보겠습니다.
🔍 첫번째 팁 - 검색이 가능한 이름을 쓰자.
코딩을 하다보면 랜덤하게 값을 추가해야 할 때가 있습니다. 예를 들면 하루가 총 몇 초인지, 하루가 총 몇초인지를 요구하는 함수가 있다면 해당 숫자를 변수(variable)로 해두는 것이 좋습니다.
❌ Bad
setInterval(eatKimchi, 86400) // X
✅ Good
const SECONDS_IN_A_DAY = 86400;
setInterval(eatKimchi, SECONDS_IN_A_DAY); // O
그 이유는 다른 팀원이 봤을 때 그 함수가 무엇을 하는지 이해를 못할 수 있기 때문입니다. 그 숫자가 무엇을 의미하는지 모를 수 있기 때문이죠. 그래서 해당 숫자(하루가 총 몇초인지)를 변수로 해두면 사람들은 읽고 이해할 수 있을 것입니다.
🏃🏻♂️ 두번째 팁 - 함수명은 반드시 동사를 쓰자.
❌ Bad
function userData() {
// ...
}
const data = userData();
✅ Good
function loadUserData() {
// ...
}
const data = loadUserData();
예를 들면 userData(유저 데이터)는 함수명으로 좋은 이름이 아닙니다. loadUserData(유저 데이터 불러오기)가 좋은 이름이죠. 이 규칙은 꽤나 심플하고 중요한 것을 알려줍니다. 이렇게 이름을 짓다보면 함수가 너무 많은 역할을 하는 것은 아닌지 알게 되기도 합니다.
함수는 딱 한개의 역할만 잘해야 합니다. 함수를 그들이 하는 역할, 동사로 짓기 시작하면 액션 중심으로 이름을 짓다보면 구분의 필요성을 느끼게 될 것입니다. 예를 들면 유저 데이터를 불러오는 함수는 불러오는 역할만 해야합니다.
❓왜 함수는 딱 한개의 역할만 잘해야 할까요?
본 영상에는 이에 대한 자세한 설명이 없어서 설명을 덧붙여보겠습니다.
대부분의 시스템은 복잡하게보다는 심플하게 만들어졌을 때 최고로 잘 동작한다. 그러므로 시스템을 디자인할 때 심플함이 주 목표가 되어야 하고, 불필요한 복잡성은 피해야 한다.
by Kelly Johnson
위와 같은 말이 있습니다. KISS원칙(Keep It Simple, Stupid)에 따라 함수의 이름, 매개변수, 구현된 사항의 코드를 읽었을 때 한번에 이해할 수 있도록 한가지의 기능을 수행하는 함수를 심플하게 작성하는 것이 좋습니다.
실무에서 클린 코드의 의의는 유지보수 시간의 단축이라고 합니다. 동료 혹은 과거의 스스로 짠 코드를 빠르게 이해할 수 있다면 유지보수할 때 드는 개발 시간이 짧아집니다.
함수에 무작정 기능을 여러개 추가하다보면 나중에 본인이 보기에도 알아보기 힘들 뿐더러 다른 사람은 건드릴 수 조차 없게 되는 코드가 만들어지게 됩니다.
결국 추후에 유지보수 시간을 단축시키기 위해 함수를 심플하게 한가지의 기능만 수행하도록 만든다고 생각하시면 됩니다. (단일책임 원칙)
위의 KISS원칙과 단일책임 원칙에 대한 자세한 내용은 아래의 영상들을 통해 더 알아보시면 좋을 것 같습니다.
참고: https://www.youtube.com/watch?v=jafa3cqoAVM
참고: https://www.youtube.com/watch?v=edWbHp_k_9Y&t=269s
본론으로 돌아가보겠습니다.
❌ Bad
function loadUserData() {
const value = `; ${document.cookie}`;
const parts = value.split(`; user_id=`);
if (parts.length === 2) {
const cookie = parts.pop().split(';').shift();
// load data using the cookie
}
}
const userData = loadUserData();
위처럼 해당 함수가 유저 데이터를 불러오는 것 뿐만 아니라 다른 것도 한다면?
✅ Good
function getCookie() {
const value = `; ${document.cookie}`;
const parts = value.split(`; user_id=`);
if (parts.length === 2) {
return parts.pop().split(';').shift();
}
}
function loadUserData() {
const cookie = getCookie();
// load data using the cookie
}
const userData = loadUserData();
해당 함수를 쪼개야할 수도 있는 것입니다.
따라서 두번째 팁은 2가지 파트로 나눌 수 있습니다. 첫번째는 함수는 무조건 한가지 액션만 수행해야 한다는 것이고, 두번째는 함수명은 동사를 사용해라. 라는 것입니다.
🪺세번째 팁 - 함수의 인수는 2~3개가 적당, 그 이상은 configuration object를 사용하자.
이번엔 함수의 인수에 대해서 이야기 해볼 것입니다. 몇개의 인수를 함수가 가져야할까요? 가장 좋은 숫자는 3개 혹은 그 이하입니다.
❌ Bad
function makePayment(price, productId, size, quantity, userId) {
// process payment
}
makePayment(35, 5, 'xl', 2, '니꼬');
만약 함수가 너무 많은 수의 인수를 필요로 하면, 다른 사람이 봤을 때 어떤 인수가 무엇을 하는지 혼란스러울 수가 있습니다. 대신 함수가 많은 숫자의 인수를 요구한다면?
✅ Good
function makePayment(price, productId, size, quantity, userId) {
// process payment
}
makePayment({
price: 35,
productId: 5,
size: 'xl',
quantity: 2,
userId: '니꼬',
});
한 개의 configuration object를 보내는 것을 추천합니다. 이렇게 정리하는 것이 함수의 역할을 파악하기 좋고 또한 총 몇개의 인수를 필요로 하는지도 파악하기 좋습니다. 2~3개까지의 인수는 이해하기 좋지만 그 이상은 너무 복잡하므로 configuration object 사용을 추천합니다.
🙅🏻♂️ 네 번째 팁 - boolean 값을 인수로 함수에 보내는 것을 최대한 방지하자.
boolean 값은 참 혹은 거짓을 의미하는 데이터 타입입니다. 왜 boolean 값을 인수로 함수에 보내지 않아야 할까요?
❌ Bad
function sendMessage(text, isPrivate){
if (isPrivate) {
// send private message
} else {
// send public message
}
}
sendMessage('hello', false)
sendMessage('this is a secret', true)
boolean 값을 함수에 보낸다는 것은 그 함수 안에 if-else가 있다는 뜻입니다. 허나 이는 좋지 않은 방법이므로 if-else 값을 각각의 다른 함수로 분리하는 것을 추천합니다.
✅ Good
function sendPublicMessage(text){
// send public message
}
function sendPrivateMessage(text){
// send private message
}
sendPublicMessage('hello');
sendPrivateMessage('this is a secret');
함수는 단 한개의 액션만 해야한다는 것을 기억하실 것입니다. 함수는 단 한개의 액션만 해야한다는 원칙에 따라야 하므로 boolean(참/거짓) 값을 인수로 보내는 것이 아니라 위와 같이 함수를 분리하시기를 추천드리는 것입니다.
📏 다섯 번째 팁 - 짧은 변수명이나 축약어 쓰는 것을 피하자.
짧은 변수명이나 아무도 이해 못하는 축약어 쓰는 것을 피합시다. 예를 들면 'u'라고 쓰지 말고 'user'라고 써야 하는 것입니다. 아래의 예시를 봐주시길 바랍니다.
❌ Bad
allUsers.forEach((u,i) => {
sendEmail(u);
addToCount(i);
});
'user'를 'u', 'index'를 'i' 라고 자신만 아는 의미로 축약하여 사용한 잘못된 예시입니다.
✅ Good
allUsers.forEach((user, currentNumber) => {
sendEmail(user);
addToCount(currentNumber);
})
한눈에 봤을 때도 변수의 의미를 알 수 있는 좋은 예입니다.
예를 들면 'email'이라고 써야 하는 것을 'e'라고 제멋대로 줄이거나 하면 안된다는 것입니다. 이것만 잘 준수해도 우리의 코드를 읽는 것이 편해질 것입니다. 다른 팀원이 쓴 코드 'e'를 본다면 우리는 뭘 알 수 있을까요? 그러니 줄여쓰지 말고 그냥 'email'이라고 풀어서 쓰면 됩니다.
❗️ 주의사항
위까지가 깨끗한 코드를 작성하는 5가지 팁인데, 그전에 하나 알아둬야 할 것이 있습니다.
우리가 코딩을 할 때에는 약간 미친(?) 모드가 되어서 뭔가 작동이 되게끔 애를 쓰곤 하는데, 초기 시작점에서 코드를 이쁘게 쓰려고 하지 말라는 것입니다. 못생겼더라도 코드를 일단 쓰고 나서 작동이 되는 것을 확인하고 클린 코드로 다듬어주면 됩니다.
처음부터 이쁘장한 코드로 쓰는건 어렵기 때문입니다. 처음 쓸 때는 새롭게 만들고 있는 단계이므로 어떻게든 되게 하려는 상태라서 혼란의 도가니가 되곤 합니다. 처음부터 클린 코드를 쓰려 하지말고 마지막에 작업하도록 합시다. 코딩하는데 시간을 들인 만큼, 깔끔하게 다듬는 데에도 시간을 들이길 바랍니다.
이 글은 유튜버 '노마드 코더 Nomad Coders' 님의 유튜브 영상을 참고하여 작성되었습니다.
코딩에 관련된 더 좋은 영상들이 많으니 코딩에 관심이 있으신 분들은 구독하여 많은 정보를 얻어가시면 좋겠습니다!
참고 : https://www.youtube.com/watch?v=Jz8Sx1XYb04
'Studying Web Development > Free Memo' 카테고리의 다른 글
ES6에서 Arrow 함수를 언제, 왜 쓸까? (0) | 2022.06.22 |
---|---|
CORS에 대처하는 방법과 우회하는 방법 (0) | 2022.06.17 |
[Error Handling] TS2307: Cannot find module '.png' or its corresponding type declarations. (이미지 import 에러) (0) | 2022.06.06 |
var, let, const의 차이점 (0) | 2022.05.10 |
크롬 개발자도구에서 디버깅하는 방법 (debugger) (0) | 2021.09.05 |
댓글