Skip to content

좋은 코드 유지하기 — 마인드와 코드 습관

좋은 코드 유지하기 — 마인드와 코드 습관
목차




서론

우선, 이 포스팅은 몇년 간 개발을 진행해오며 느낀 저의 생각과,
여러 책, 여러 좋은 개발자분들의 블로그에서 따 온 내용들이 혼합된 것임을 밝힙니다.

저 또한 이 노트들을 최대한 지키려고 노력하지만, 항상 시간에 급급하고 마음이 조급하여
보이스카우트 규칙을 어긴(도착할 때보다 더 지저분해진) 코드를 작성하는 일이 빈번합니다.

하지만 아예 좋은 코드를 아예 모르는 개발자와 좋은 코드를 지키려고 최소한의 노력을 하는 개발자의 코드는 분명히 다르다고 생각합니다.

무의식적으로라도 좋은 코드를 작성하기 위해서, 의식적으로 더 좋은 코드를 위해서,
그리고 또 잊을 본인을 위해서라도 이 포스팅을 남겨보겠습니다.

이 글을 마인드다잡기와, 코드다잡기로 분류해서 작성해보겠습니다.





좋은 코드 유지를 위한 마인드 다잡기



최적화보단 가독성을 먼저

코드는 항상 읽기 쉽고 개발자들이 쉽게 이해할 수 있게끔 작성해야 합니다. 읽기 어려운 코드를 읽는데 낭비되는 시간과 비용은 최적화로부터 얻을 수 있는 것보다 더욱 큽니다. 예를 들자면, 가독성을 위하여 5분간 적절한 변수명 짓는 고민이 차후에 다른 개발자(자기자신도 포함)가 1시간 고민하는 사태를 방지할 수 있습니다.



코드는 최대한 간단하고 단순하게

복잡한 코드는 개발자의 용맹함을 나타내는 지표가 아닙니다.
간단하게 작성한 코드는 버그를 줄이고 디버깅 시간도 줄일 수 있습니다.



주석은 최대한 적게

주석을 많이 사용한다는 것은 다른 사람이 그만큼 이해하기 어려운 코드라는 걸 나타냅니다.
좋은 코드는 주석 없이도 이해될 수 있어야 합니다.
메소드의 정의와 사용법을 설명하는 한 줄로 된 간단한 주석 정도가 좋습니다.



나중에 리팩토링 할거니깐 지금은 대충 짤거야

나중에 리팩토링할 시간은 열에 아홉은 없을 예정입니다. 처음 코드를 작성할 때 최대한 깔끔하고 단정한 코드를 작성하는 습관을 들여야 합니다. 차 후 다시 볼거란 다짐은 평상시 안좋은 습관을 몸에 지고 있다는 이야기와 같습니다.



컨디션이 좋지 않을땐 억지로 코딩하지 말 것

개발자들은 피곤하거나 컨디션이 좋지 않을때 평소보다 2배 이상의 버그를 만들어내곤 합니다. 회사에서 주어진 WBS 상 어쩔 수 없는 경우가 대부분이겠지만, 좋은 컨디션에 더 좋은 코드가 나올 확률이 높습니다.



DRY

Don’t Repeat Yourself - 똑같은 일은 두번 하지 않는다
당연한 얘기겠지만 같은 코드를 중복해서 작성하지 않습니다. 중복되는 함수나 코드는 하나의 공통 컴포넌트로 처리합니다.

저같은 경우도 회사에서 코드를 작성할 때 다른 팀원의 코드를 아무 생각 없이 Copy & Paste 하여 사용한 적이 많습니다. 이런 경우에도 반드시 코드를 합치거나 하나의 함수만 참조하도록 해야 합니다. 또 다음에는 누군가가 제 코드를 Copy&Paste 할 수 있으니깐요.

이러한 DRY 를 어긴 코드를 WET(We Enjoy Typing 혹은 Write Everything Twice) 라고 합니다.



KISS

Keep it simple, stupid.
알버트 아인슈타인은 “할머니에게 설명할 수 없다면 당신은 제대로 이해한 게 아닙니다.” 라고 말했습니다.
즉, 소프트웨어 디자인을 간단하고 단순하게 하는 것입니다.
프로젝트가 진행되기 전에 최대한 기반 배경과 추진되는 목적자체를 이해하고 어떻게 구현을 단순화하고 알기 쉽게 설계할 수 있을지 회의를 해서 개선해야합니다. 프로젝트를 단순하게 디자인 하지 못하고 복잡하게만 구현을 한다는 것은 프로젝트를 제대로 이해하지 못했다는 증거입니다.



YAGNI

You Ain’t Gonna Need it
정말 필요할 때까지 그 기능을 만들지 말라는 의미입니다.
현재 필요하지 않지만 나중에 필요할지도 모를 코드를 미리 작성하면 코드 자체가 길어지고, 분석도 어려워지며, 버그가 발생할 가능성이 커집니다. YAGNI(야그니)를 지키지 않으면 야근한다 는 개발자들 사이의 우스갯소리가 괜히 있는 것이 아닙니다.😂
MySql을 연동해야하는 프로젝트이지만 Oracle을 나중에 연동해야 할지도 모르는 상황이더라도, 현재 연동할 DB만 작업해놓는 것이 좋습니다. 미리 구현하는 것이 성실해보이지만, 그만큼 작업시간이 소요되므로 프로젝트의 시간도 늘어나며, 비용적인 부담도 발생합니다.






이제 코드 쪽입니다. 예시들은 Javascript 로 작성하겠습니다.
추가로 발견되는 좋은 코딩 습관은 지속적으로 업데이트해 나가겠습니다.





좋은 코드 유지를 위한 코드 다잡기





네이밍

  1. 변수명에 모든 의미를 충분히 담아두는 것이 좋습니다. 변수명, 함수명만 보고도 의미를 충분히 짐작할 수 있어야 합니다. 너무 과한 함축어 명명습관은 버립시다.
let userFullName = '제임스 아서 고슬링'
  1. 하나의 문자로 된 이름은 사용하지 않습니다. (반복문 제외)
let u = '제임스 아서 고슬링'
let a = 45
console.log('유저의 이름 : ' + u + '유저의 나이 :' + a)

위의 코드는 보기에도 이해하기에도 불편합니다.

  1. Boolean 변수에는 is 접두어를 사용하는 것이 복잡한 코드에서도 보기 편합니다.
let [isFind, isCheck] = [false, true]




함수명

함수는 기본적으로 어떤 일을 처리하는 행위이기 때문에 동사로 이름을 명시해야 합니다.

// O
function setUserName(user)
// X
function userName(user)




위험 요소 피하기

나중에 잘못 이해했을 때 심각한 버그를 만들 가능성이 있는 것들은 변수명에 표현해두는 것이 좋습니다.

  • password => plainTextPassword, encodedTextPassword
  • comment => unescapedComment, escapedComment
  • url => encodedUrl




줄바꿈 재정렬

코드를 훑어보는 데 걸리는 시간이 적을 수록, 더 많은 개발자들이 쉽게 코드를 이해할 수 있습니다.

fetchBookData().then(()=>{}).catch(()=>{}
fetchBookData().
    then(()=>{}).
    catch(()=>{}




불규칙 로직은 메소드를 이용하여 재정렬

switch (true) {
  case char === `{` || char === `}`:
    char === `{` ? stack.forword({}) : stack.backword()
    break
  case char === `[` || char === `]`:
    char === `[` ? stack.forword([]) : stack.backword()
    break
  case char === 't' || char === 'f':
    const isTrue = input[cursor] === 't'
    stack.setValue(isTrue ? true : false)
    cursor = cursor + (isTrue ? 3 : 4)
    break
  case char === 'n':
    stack.setValue(null)
    cursor = cursor + 3
    break
}

위의 코드는 이해도 어렵고 눈살이 찌푸려집니다.
아래와 같이 고치는 것이 보기 편하고 유지보수도 편해집니다.

switch (true) {
  case isObject(char):
    parseObject(char, stack)
    break
  case isArray(char):
    parseArray(char, stack)
    break
  case isBoolean(char):
    cursor = parseBoolean(input, cursor, stack)
    break
  case isNull(char):
    cursor = parseNull(cursor, stack)
    break
}

const isObject = v => v === `{` || v === `}`
const isArray = v => v === `[` || v === `]`
const isBoolean = v => v === 't' || v === 'f'
const isNull = v => v === 'n'

const parseObject = (char, stack) => {
  char === `{` ? stack.forword({}) : stack.backword()
}
const parseArray = (char, stack) => {
  char === `[` ? stack.forword([]) : stack.backword()
}
const parseBoolean = (input, cursor, stack) => {
  const isTrue = input[cursor] === 't'
  stack.setValue(isTrue ? true : false)
  return cursor + (isTrue ? 3 : 4)
}
const parseNull = (cursor, stack) => {
  stack.setValue(null)
  return cursor + 3
}




조건문에서 인수의 순서

// O
if(100 =< userName.length)
// X
if (userName.length >= 100)

아래쪽이 더 명확하며, 영어에서의 어순과도 맞습니다.
인수의 왼쪽은 타겟을 두고, 오른쪽에 비교대상을 두는것이 가독성이 훨씬 좋습니다.





if-else 에서의 순서

if/else 에서는 긍정(true) 부터 다루는 것이 좋습니다. false를 먼저 다루면, 코드를 이해할 때 한번 부정한 값을 생각해야 하므로 머릿속에서 약간 더 연산의 시간이 지연됩니다.

// O
if (x === y) {
} else {
}
// X
if (x !== y) {
} else {
}




설명변수

복잡하고 긴 코드를 줄이는 방법 중 하나는 바로 작은 하위 표현을 담을 추가 변수를 만드는 것입니다. 변수명으로 코드를 설명하는 방법입니다.

// X
if((temp.substr(1, temp.length).substr(0, temp.length - 2)) === 'root')
// O
const userName = temp.substr(1, temp.length).substr(0, temp.length - 2);
if(userName === 'root')




K-네이밍

일부 개발자들은 필요한 단어를 찾기 힘들다는 이유로 그냥 한국어 발음 그대로 변수명을 짓곤 합니다.

const [yoil, jooso] = ['', '']

이러한 코드는 굉장히 난독화된 코드처럼 보이며, 발음하기 전에는 무슨 코드인지 알기도 어렵습니다. 반드시 지양해야 합니다.







참고 :

https://mingrammer.com/translation-13-simple-rules-for-good-coding/
https://chodragon9.github.io/blog/easy-code/#%EC%9D%B4%EC%A0%9C-%EB%B3%B8%EB%A1%A0%EC%9C%BC%EB%A1%9C-%EB%93%A4%EC%96%B4%EA%B0%80%EA%B2%A0%EC%8A%B5%EB%8B%88%EB%8B%A4
https://rhange.tistory.com/168
클린코드(로버트 C.마틴)




https://mingrammer.com/translation-13-simple-rules-for-good-coding/
https://chodragon9.github.io/blog/easy-code/#%EC%9D%B4%EC%A0%9C-%EB%B3%B8%EB%A1%A0%EC%9C%BC%EB%A1%9C-%EB%93%A4%EC%96%B4%EA%B0%80%EA%B2%A0%EC%8A%B5%EB%8B%88%EB%8B%A4
https://rhange.tistory.com/168
클린코드(로버트 C.마틴)







읽어주셔서 감사합니다.🖐


Ramsbaby
Written byRamsbaby
이 블로그는 직접 개발/운영하는 블로그이므로 당신을 불쾌하게 만드는 불필요한 광고가 없습니다.

#My Github#소개 페이지#Blog OpenSource Github