SW/DevOps

DevOps : 리팩토링 개념과 필요성

얇은생각 2019. 12. 11. 07:30
반응형

리팩토링

 

리팩토링 개념과 필요성

유명한 프로그래머 Kent Beck과 architect Martin Fowler는 소프트웨어 코드 안에서 나오는 여러 문제에 대해 Code Smell이라는 용어를 사용하였습니다. 즉, 코드가 시간이 지나면서 요구사항과 기능들이 추가되면서 추상화, 모듈화, 캡슐화가 되지 않고, 높은 결합성, 낮은 응집성, 낮은 가독성으로 이루어진 코드로 변하면서 점점 유지, 보수 및 확장이 어려운 어플리케이션이 되어가는 상태를 말합니다.

그런 코드를 대상으로 리팩토링이 필요한데, 여기서 코드 리팩토링이란 기존 코드를 재구성하여 외부동작을 변경하지 않고 내부구조를 변경하는 체계적 코딩 기술을 말합니다. 코드 리팩토링을 잘 수행하면 소스 코드의 로직을 단순화하고 불필요한 수준의 복잡성을 제거하게 됩니다.

또한 개발자는 버그나 취약점을 쉽게 발견하고 수정할 수 있어 유지보수 및 확장성이 좋아집니다. 정리하면, 리팩토링은 버그 수정, 기능 추가 등과는 달리 외부에서 보는 프로그램 동작은 변하지 않지만, 프로그램의 내부 구조 개선을 통해 쉽게 버그를 발견하고 기능 추가 및 리뷰하기 쉽게 만듭니다.

 

 

Code Smell

은행에서 융자를 받으면 향후 원금만 지불하는 것이 아니라 대출에 대한 이자를 지불하듯이 Code Smell에 대한 기술 부채가 발생한다고 워드 커닝햄은 말했습니다. 이런 악취 나는 코드, 즉 Code Smell은 가급적 빠른 시간 내에 형상 관리 시스템에 Code Commit을 하기 전에 리팩토링해야 합니다.

물론 개발 중인 코드의 15줄 이상의 메서드나 파라미터가 4개가 넘는 경우 등 약간의 문제가 있는 것은 괜찮지만 변경한 소스를 Commit하기 전에는 리팩토링을 마쳐야 합니다. 개발 툴인 통합 개발 환경에서 대부분 체크해 주기 때문에 잘 활용하여 코드를 반영하기 전에 단위 수준에 코드 악취를 제거하는 습관을 들여야 합니다.

 

 

명명 규칙

명명 규칙에 대해서 알아보겠습니다. 필 칼튼은 컴퓨터 사이언스 분야에서 가장 힘든 두 가지는 캐쉬 무효화와 이름 짓기라고 이야기 했습니다. 클래스 객체 이름은 동사나 명사구가 적합하고, 메서드 이름은 동사나 동사구가 적합합니다.

일반적으로 명명규칙은 프로젝트 또는 팀에서 정한 Coding Convention, 즉 코딩 표준을 따르게 됩니다. 그 중 패키지명, 클래스명, 메서드명 등은 대부분 사전 방법론 등의 가이드라인을 통해 일정 수준의 룰을 기준으로 잘 정의되지만 변수명은 각 개발자가 통일되지 않은 방식을 사용하는 경우가 많습니다. 보통 정확한 기준 없이 축약해서 사용하거나 불분명하게 사용합니다. 그 코드의 개발자는 문제없을 수 있으나, 향후 유지 보수를 다른 사람이 맡게 된다면 전체 소스 코드의 흐름을 파악하는 데 많은 시간이 소요됩니다.

변수는 의미를 명확히 전달하고 짧고 간결한 명칭을 사용해야 합니다. 메서드 이름은 동사나 동사구가 적합하고 화면의 예처럼 일반적으로 많이 사용하는 접두어 및 용어로 정의하는 것이 좋습니다.

 

 

주석

주석의 목적은 코드를 읽는 사람이 작성한 사람만큼 잘 이해하게 도와주는 데 있습니다. 코드에서 빠르게 유추할 수 있는 내용은 주석으로 달면 안 되고, 주석 대신 좋은 이름 짓기로 설명하는 것이 더 좋습니다.

코드를 처음 본 개발자가 할 수 있는 질문을 예측하면서 쉽게 빠질 수 있는 함정을 경고해야 합니다. 또한 코드의 의도를 명시하면서 코드 베이스에 대한 큰 그림을 설명하는 데 주력해야 하고, 디렉토리, DB 접속 정보, 비밀번호 등, 보안 관련 정보는 절대 남기면 안 됩니다.

주석은 API 문서화에는 도움이 되겠지만, 틀에 박힌 주석은 사용하지 않는 것이 좋습니다. 개발자는 to do, fix me 등을 남기지 말고 주석 처리한 코드를 바로 고치거나 나중에 고칠 예정이라는 티켓을 등록하든지 아니면 특이한 케이스는 없다고 보고 그냥 넘어갈지 결정해야 합니다.

 

 

Null 처리

NullpointerException은 가장 많이 발생하는 JAVA Exception 중의 하나입니다. 따라서 Null 조건을 체크할 때 end, or, 조건 체크 및 위치를 정확히 알고 사용해야 합니다. Null 반환에 대해서 알아보겠습니다. 반환 값으로 Null 값을 return하기 보다는 비어있는 Collection 또는 배열을 return 하는 것이 좋습니다.

더 나아가 JAVA 8의 Optional이나 Null 객체를 사용하는 것을 고려해 보는 것도 좋습니다.

 

 

매직 넘버를 기호 상수로 치환

매직 넘버를 기호 상수로 치환하는 방법에 대해서 알아보겠습니다. 소스 코드의 특정한 숫자 또는 문자열, 즉 매직 넘버를 직접 사용하는 것은 좋지 않은 코드입니다.

화면의 예처럼 입력 값의 최대 길이가 100인 경우, 100인 매직 넘버 보다는 기호 상수를 이용하여 표현하는 것이 좋습니다. 또한 코드 여러 곳에 매직 넘버를 중복해서 사용하면 나중에 수정이 발생했을 때 대응하기가 쉽지 않고 버그가 될 가능성이 높습니다.

만약 매직 넘버가 분류 코드로 사용된다면 Enum으로 치환하거나 상태 전략 패턴을 사용하는 것이 더 좋을 경우가 있습니다. 매직 넘버를 기호 상수로 치환이 적절하지 않은 경우에 대해서 알아보겠습니다. 하지만 기호 상수로 치환이 적합하지 않은 경우가 있습니다.

첫 번째로 for문 등 반복문 로직 안에서 배열의 길이가 변경되는 경우, 배열 최댓값을 상수로 지정해 놓으면 안 됩니다. 길이 변경이 없을 경우에는 치환해도 괜찮습니다.

두 번째로 바이트 코드에 내장된 상수에 주의해야 합니다. 그 이유는 public static final 클래스 필드로 선언한 경우, 외부 클래스에서 참조하면서 compile이 미리 됩니다. 이후 선언한 클래스의 값이 수정이 된다면, 값을 참조했던 외부 클래스는 이미 변경 전의 값으로 compile이 끝난 상태이기 때문에 재compile해야 문제가 없습니다.

 

 

예외 처리

개발을 진행하다 보면 일반적인 로직 흐름에 집중하기 때문에 예외 처리를 소홀히 하기 쉽습니다. 로직이 어느 정도 완성된 후 예외 처리를 예외일 경우에만 사용하고 빈 catch문으로 두지 않도록 해야 합니다. 또한 범용적인 Exception, RuntimeException 등으로 처리하는 것이 아니라 보다 구체적으로 선언 및 문서화해야 합니다.

마지막으로 보안적인 측면에서 예외메시지를 UI 등 front end로 전달할 때 내부 console 내용이 아닌 일반적인 메시지로 변경해 전달해야 합니다. HTTP일 경우에는 REST API와 HTTP 상태 코드를 참고하시기 바랍니다. 

반응형

'SW > DevOps' 카테고리의 다른 글

DevOps : 리팩토링 기법 (2)  (0) 2019.12.13
DevOps : 리팩토링 기법 (1)  (0) 2019.12.12
DevOps : SonarQube 사용법  (0) 2019.12.10
DevOps : SonaQube 특징, 개요, 기능  (0) 2019.12.09
DevOps : SW 구조 분석 도구 개념 및 종류  (0) 2019.12.08