Lecture

레거시와 리팩토링

빈코 2022. 5. 23. 11:56

개발 관련 유튜브나 서적을 보면 레거시(legacy)라는 단어를 자주 접하게 됩니다. 사전적인 의미로 유산이라는 뜻인 건 알았지만, 개발 문화에서는 정확히 어떤 의미로 사용하는지 궁금하게 되어 공부하게 되었습니다. 레거시에 대해 찾다 보니 자연스럽게 리팩토링(refactoring)도 접하게 되었고, 보다 자세히 알고 싶어 강의를 수강하게 되었습니다. 

 

로고
레거시 & 리팩토링

 

레거시 코드(Legacy Code)

레거시 코드란 나를 포함한 모든 개발자가 기존에 개발했던 코드를 일컫습니다. 어떠한 코드이든 간에 기술의 변화가 많은 이 시점에서 시간이 흐르면 낡은 기술이 될 것입니다. 이밖에도 코드의 가독성이 떨어지는 경우, 코드의 규약이 없는 경우, 코드의 결합도가 높은 경우, 테스트 코드가 없는 경우 등의 여러가지 원인들을 가진 코드들을 말합니다.

 

레거시 코드 특징📙

  • 긴 메서드, 긴 클래스
  • 복잡한 코드
  • 이상한 이름
  • 많은 중복
  • 테스트 없음


개발의 악순환💢

레거시 코드를 이해하는데 많은 노력과 시간이 필요 ➙ 이해가 부족한 상태에서 코드를 수정해야 하는 상황이 많아진다 ➙ 레거시 변경에 대한 두려움 ➙ 코드 덧대기로 두려움을 회피한다 ➙ 다음 사람에게 레거시 투척

 

 

악순환을 줄이기 위해선?

첫 번째로, 변경하기 쉬운 구조로 점진적으로 리팩토링하여 코드 변경 비용을 낮춰야 합니다.

두 번째로, 이전과 동일하게 동작하는지 테스트를 진행해야 합니다.

세 번째로, 테스트를 만드려면 기능이 어떻게 동작하는지 분석해야 합니다.

 

즉, 악순환을 줄이려면 레거시를 분석하고 테스트를 만들어 리팩토링 해야 합니다.

 

 

코드 분석에 도움이 되는 보조 수단

코드 시각화👀

여러 다이어그램을 사용해서 코드 흐름을 시각화 할 수 있다. 종류로는 액티비티 다이어그램, 시퀀스 다이어그램, 의존/호출 관계 그래프 등이 있다.

 

1. 액티비티 다이어그램 - 단계적인 코드 실행 흐름을 알 수 있으며, 조건 분기 추적에 용이하고 논리적인 코드 블록을 도출할 수 있다.

액티비티
출처:https://fastcampus.co.kr/dev_red_bcr

 

2. 시퀀스 다이어그램 - 구성 요소간의 연동 흐름을 파악할 수 있으며, 요소 간 호출 관계와 시간 흐름에 따라 실행 순서를 알 수 있다.

시퀀스
출처:https://fastcampus.co.kr/dev_red_bcr

 

3. 의존/호출 관계 그래프 - 구조와 영향력 파악에 도움이 된다.

의존/호출
출처:https://fastcampus.co.kr/dev_red_bcr

 

코드 출력📃

코드 출력
출처:https://fastcampus.co.kr/dev_red_bcr

 

코드를 출력해서 본다면 여러 메서드의 코드를 한 번에 펼쳐 놓고 볼 수 있고, 형광펜/화살표 등을 사용해서 관계를 한눈에 알아볼 수 있는 장점이 있다.

 

레거시에 테스트 코드 작성하기

 

 

1. 범위를 좁혀서 테스트를 작성한다

  • 테스트 할 대상을 기존 코드와 분리해서 테스트를 작성한다.
  • 일부 코드/로직/기능만 테스트하고 싶을 때 사용한다.
  • 새로 추가한 코드만 테스트 하고 싶을 때 사용한다.
진행 과정
테스트 할 대상/기능/로직 확인 ➼ 테스트 대상 코드를 한 곳에 모은다 ➼ 테스트 대상 코드의 입력 파라미터와 결과 값을 확인한다 ➼ 필요하면 입력과 결과를 위한 타입을 추가한다 ➼ 해당 코드를 별도 메서드/클래스로 분리한다 ➼ 분리한 대상에 테스트 코드를 추가한다

 

예제😄

예제는 강의를 따라가면서 만들었던 테스트 코드를 가져왔습니다. 강의의 흐름을 모르면 예제 코드를 이해하기 어렵습니다. 흐름 파악용으로만 읽어주시면 감사하겠습니다 :)

 

1. 테스트 할 대상을 확인하고 코드를 한 곳에 모았습니다. 테스트 대상은 계산하는 로직에서 기간을 체크하는 구간입니다.

public void provideServicePeriod(Long ordNo, LocalDate loginDate) {
	Order order = getOrder(ordNO);
    
    LocalDate sdate = null;
    LocalDate edate = null;
    
    if (order.getGubun().equals("A")) {
    	sdate = order.getOrderDate();
        edate = YearMonth.from(order.getOrderDate().atEndOfMonth());
    } else {
    	sdate = loginDate;
        if (order.getUnit().equals("D")) {
        	edate = loginDate.plusDays(order.getQty());
        } else if (order.getUnit().equals("M")) {
        	edate = loginDate.plusMonths(order.getQty());
        }
    }
    updatePeriod(ordNO, sdate, edate);
}

 

2. 입력/결과 값 확인

입력결과
입력/결과

3. 코드를 분리한 후 테스트 코드 추가

public class PeriodCalculatorTest {
	@Test
    void gubunA() {
    	Order order = Order.builder()
        				.gubun("A")
                        .orderDate(LocalDate.of(2021,5,5))
                        .build();
            
        Period p = PeriodCalculator.calculate(order, LocalDate.of(2021,5,6));
        assertThat(p.getSdate()).isEqualTo(LocalDate.of(2021,5,6));
        assertThat(p.getEdate()).isEqualTo(LocalDate.of(2021,5,31));
    }
}

 

2. 대체 구현을 이용해서 테스트를 작성한다

  • 테스트 대상이 사용(의존)하는 객체/기능이 존재할 떄 사용한다.
  • 의존 대상의 구현을 대체할 대역을 만들어서 테스트를 작성한다.
  • 의존 대상 : 대역을 만들 수 있는 구조로 변경이 필요하다.
  • 테스트 대상 : 대역을 사용할 수 있는 구조로 변경이 필요하다.
진행 과정
테스트 대상이 의존(사용)하는 코드를 확인 ➼ 대역을 생성할 수 있는 구조로 변경 ➼ 테스트 대상이 대역을 사용할 수 있도록 구조 변경 ➼ 대역을 사용해서 테스트 코드 작성

 

3. 범위를 넓혀서 테스트를 작성한다

  • 의존성이 많아 특정 범위만 테스트 하기 어려울 때 사용한다.
  • 테스트를 만들기 위해 변경해야 하는 코드가 너무 많을 때 사용한다.
  • 일부 로직이 쿼리에 위치 했을 때 사용한다.
진행 과정
테스트 대상 확인 ➼ 테스트를 실행할 수 있는 환경 구성(DB 연결 등) ➼ 기능을 실행하는 테스트 작성 ➼ 테스트를 반복하면서 테스트 코드 완성

 

리팩토링(Refactoring)

리팩토링은 말 그대로 코드를 수정하는 행위입니다. 한 가지 예시로, 코드 이해에는 2시간이 걸렸는데 수정은 5분 만에 완료되는 상황을 겪어 보신 적 있으실 겁니다. 변경 비용을 낮추려면 이해/변경이 쉬운 구조로 점진적으로 리팩토링 해야 합니다.

 

테스트가 있다면 과감하게 리팩토링이 가능하지만, 테스트가 없어도 필요하면 리팩토링을 진행해야 합니다. 현재의 위험을 회피하는 행위는 미래에 더 큰 위험을 야기시킬 가능성이 높습니다. 그럼 리팩토링 하는 방법에 대해 알아볼까요?

 

리팩토링 방법🔨

  1. 주석으로 되어 있는 코드들은 삭제해야 합니다. 추후에 다시 코드를 보았을 때, 주석 처리로 인해 이해하기 더 어려울 수도 있습니다.
  2. 숫자나 문자에 의미 있는 이름을 부여하고 가독성 좋게 변수나 함수 이름 등을 재정의 해야 합니다.
  3. 변수는 사용 직전 위치로 이동 시키는 것이 좋습니다. 변수 선언 위치와 사용 위치가 멀리 떨어져 있으면 코드 이해에 부담이 증가합니다.
  4. 한 변수를 여러 의미로 사용하면 복잡도가 증가하기 때문에 올바른 방법이 아닙니다. 변수를 추적하는 행위 또한 복잡도가 증가하므로 변수가 필요하지 않은 부분에는 사용하지 않는 것이 좋습니다.
  5. if문을 줄여야 합니다. 중첩된 if문을 제거하여 코드 복잡도를 감소시켜야 합니다.
  6. 메서드를 분리합니다. 일부 비슷하게 동작하는 두 기능을 한 메서드에서 구현했는지 확인하고 만약 두 기능을 한 메서드에서 구현했다면 점진적으로 메서드를 분리해야 합니다.
  7. 파라미터 값을 정리합니다. 사용하지 않는 파라미터 값은 코드 분석을 어렵게 합니다.

 


👨‍👩‍👦‍👦 오픈채팅방 운영

취업을 준비하는 예비 개발자분들을 위한 질문&답변할 수 있는 공간을 만들었습니다. 취업과 이직을 하기 위해서 어떤 걸 중점적으로 준비해야 하는지부터 포트폴리오&이력서 작성법 등 다양한 질문들을 받고 답변을 드립니다. 참여하셔서 다양한 정보 얻고 가시면 좋을 것 같네요😁

 

참여코드 : 456456

https://open.kakao.com/o/gVHZP8dg

 

비전공 개발자 취업 준비방(질문&답변)

#비전공 #개발자 #취업 #멘토링 #부트캠프 #국비지원 #백엔드 #프론트엔드 #중소기업 #중견기업 #자바 #Java #sql

open.kakao.com

 


👨‍💻 전자책 출간

아울러 제가  🌟비전공자에서 2년만에 보안 전문 중견기업으로 이직 한 방법들을 정리한 전자책을 출간 하게 되었습니다. 어떤 걸 공부해야 하는지, 이직을 위해서 무엇을 준비해야 하는지, 제가 받았던 기술 면접 리스트 등 다양한 목차로 구성되어 있습니다. 또한, 구매 시 1:1 채팅을 이용하여 포트폴리오 첨삭을 도와드리고 있습니다. 🐕전자책으로 얻은 모든 수익은 유기견 센터 '팅*벨 입양센터'에 후원될 예정입니다. 관심 있으신 분들은 아래 링크를 참고해주세요😁

https://kmong.com/gig/480954

 

비전공개발자 2년만에 중견기업 들어간 방법 | 14000원부터 시작 가능한 총 평점 0점의 전자책, 취

0개 총 작업 개수 완료한 총 평점 0점인 Binco의 전자책, 취업·이직 전자책 서비스를 0개의 리뷰와 함께 확인해 보세요. 전자책, 취업·이직 전자책 제공 등 14000원부터 시작 가능한 서비스

kmong.com


 

마치며

지금까지 레거시리팩토링에 대해 알아보았습니다. 레거시가 없는 회사는 없다고 생각합니다. 그만큼 기술의 발전은 나날이 빨라지고 있으며, 그에 따라 필요 없어지는 코드들도 증가하는 추세인 것 같습니다. 리팩토링 한다는 자체가 개발자 입장에서 쉬운 과정은 아니지만, 습관을 들여 지속적으로 자기가 맡은 프로젝트를 발전시켜나가는 것만큼 뿌듯한 일은 없을 것 같습니다. 

 

관련 포스팅

* [ 코드 리뷰 주목적 ]

* [ TDD(Test Diven Development) 테스트 주도 개발이란? ]

반응형

'Lecture' 카테고리의 다른 글

코드 리뷰 주목적  (0) 2022.05.23