Tim Corey와 함께하는 C# WinForms 리팩토링
리팩터링은 단지 작동하는 코드와 유지 가능하고 유연하며 미래에 대비한 코드를 구별하는 주제 중 하나입니다. "C# App From Start to Finish" 시리즈의 24과에서 Tim Corey는 WinForms 애플리케이션 내에서 실제 실용적인 리팩터링 세션을 진행합니다. 이론보다, Tim은 기존 프로젝트를 리팩터링하며 변화가 필요한 이유와 안전하게 접근하는 방법을 설명합니다.
이 글에서는 Tim의 비디오 설명을 엄격히 따르며 C# WinForms 리팩터링을 자세히 다룰 것입니다.
이번 수업에서 리팩터링이 의미하는 바
0:02에 Tim은 24과를 소개하며, 리팩터링은 동일한 작업을 수행하지만 더 나은 방법으로 수행하도록 코드를 재작업하는 것이라고 설명합니다. 그는 애플리케이션이 이미 작동하지만, "잡동사니"와 표준에 미치지 못하는 부분이 있다고 지적합니다. Tim에 따르면, 프로젝트가 더 커지기 전에 정리할 적절한 시기입니다.
그는 리팩터링이 기능 추가가 아닌 구조, 가독성, 장기적인 유지보수를 개선하되, 동작은 동일하게 유지하는 것이라고 강조합니다.
인터페이스에서 필요 없는 반환 값 정리
0:31부터, Tim은 첫 번째 리팩터링에 대한 다이빙을 시작합니다: 인터페이스 메서드 시그니처 수정. 그는 프로젝트 초기에 메서드들이 불필요하게 모델을 반환하고 있음을 설명합니다. 객체가 이미 참조로 전달되기 때문에, 같은 모델을 다시 반환하는 것은 실제로 목적이 없습니다.
Tim은 이러한 메서드를 void로 변경하여 즉시 구현을 깨뜨립니다. 그는 왜 이런 일이 발생하는지 설명합니다: 인터페이스가 변경되면 모든 구현 클래스가 새로운 시그니처와 정확히 일치해야 합니다. 그는 SQL 커넥터와 텍스트 커넥터를 수정하여 업데이트된 인터페이스와 맞추는 과정을 설명합니다.
2:33에 Tim은 Visual Studio가 자동으로 인터페이스를 구현하도록 두면 어떻게 되는지 보여줍니다. 그는 왜 중복 메서드 이름이 발생하는지 설명하고, 반환 유형만으로는 메서드 시그니처를 구별하기에 충분하지 않다고 명확히 합니다.
리팩터링으로 인한 빌드 오류 수정
4:00에 Tim은 솔루션을 빌드하고 의도적으로 오류가 나타나는 것을 보여줍니다. 그는 이 오류가 예상되었고 도움이 된다고 설명합니다. 예를 들어, 이전에 반환된 모델을 예상하던 코드는 이제 메서드가 void를 반환하므로 실패합니다.
Tim은 불필요한 할당을 제거하고 솔루션을 다시 빌드하여 이를 수정합니다. 그는 리팩터링이 종종 단기적인 깨짐을 초래하지만, 각 오류가 직접 개선이 필요한 코드를 나타낸다고 강조합니다.
GlobalConfig로 파일 이름 상수 이동
5:25부터, Tim은 텍스트 커넥터에서 파일 이름을 처리하는 방법을 리팩터링합니다. 이전에는 파일 경로가 클래스 내부에 개인 문자열 상수로 저장되었습니다. Tim은 이제 GlobalConfig에 파일 이름이 존재하기 때문에 더 이상 필요하지 않다고 설명합니다.
그는 로컬 상수를 GlobalConfig.PeopleFile, GlobalConfig.PrizesFile 및 유사한 속성으로 교체합니다. Tim은 이 변경이 구성을 중앙에 두고 애플리케이션 전체에서 일관된 파일 경로를 사용하도록 보장한다고 설명합니다.
그는 또한 중요한 점을 언급합니다: 너무 많은 것을 한꺼번에 리팩터링하지 말라는 것입니다. 그는 추가 개선이 가능한 것을 눈치챘을 때, 나중에 다시 돌아오겠다고 명확히 말합니다.
텍스트 커넥터 프로세서 리팩터링
7:44에 Tim은 텍스트 커넥터 프로세서에서 여러 메서드에서 파일 이름 매개변수를 제거함으로써 리팩터링을 계속합니다. 이제 파일 이름이 GlobalConfig에 있기 때문에 이를 전달하는 것은 중복입니다.
Tim은 메서드 시그니처를 신중하게 업데이트하고, 매개변수를 GlobalConfig 참조로 대체하며 Visual Studio의 오류 목록에 의존하여 그를 안내합니다. 그는 리팩터링 동안 여러 오류를 보는 것이 정상이며, 이에 대해 당황할 필요가 없다고 설명합니다.
13:16에 그는 프로젝트 전반에 걸쳐 메서드 호출을 체계적으로 정리하면서 실시간 오류 추적이 얼마나 도움이 되는지 언급합니다.
너무 많은 일을 하는 UI 로직 식별하기
15:24에 Tim은 UI 이벤트 핸들러 내의 너무 많은 로직이라는 주요 설계를 강조합니다. 그는 버튼 클릭 이벤트를 스크롤하여 그것이 이벤트가 가져야 할 것보다 훨씬 많은 코드를 포함하고 있다고 설명합니다. Windows Forms에서는 버튼 클릭과 같은 사용자 작업이 이벤트 핸들러에 의해 처리됩니다.
Tim은 UI 코드는 사용자 상호 작용에만 집중해야 한다고 설명합니다. Windows Forms는 이벤트 중심 프로그래밍 모델을 사용하며, 사용자 작업이 애플리케이션 코드에 의해 처리되는 이벤트를 트리거합니다. 비즈니스 로직—예를 들어, 토너먼트 점수 추적 및 승자 진전—은 클래스 라이브러리에 있어야 합니다. 이러한 분리는 동일한 로직을 나중에 웹 앱이나 WPF 애플리케이션에서 재사용할 수 있게 해줍니다.
클래스 라이브러리에 토너먼트 로직 추출하기
17:55부터, Tim은 토너먼트 점수 추적 로직을 토너먼트 로직 클래스 내의 새로운 공개 메서드로 이동합니다. 그는 그것을 UpdateTournamentResults라고 명명하고 왜 단일 맞대결이 아닌 전체 토너먼트 모델을 수락하는지를 설명합니다.
그는 로직을 폼에서 복사하여 클래스 라이브러리에 붙여넣고, UI 요소에 독립적으로 작동하도록 조정합니다. 이 리팩터는 토너먼트 규칙이 한곳에 거주하고 어디서든 재사용 가능하도록 보장합니다.
맞대결 점수 추적 및 무료 통과 처리
21:37에 Tim은 맞대결이 점수화 되는 방식을 리팩터링합니다. 단일 맞대결로 작업하는 대신, 그는 모든 라운드와 모든 맞대결을 순회하여 점수가 필요한 맞대결 리스트를 작성합니다.
그는 완료된 경기 및 무료 통과 주간을 감지하는 논리를 설명합니다. Tim은 무료 통과가 이전에 가짜 점수를 할당하는 "속임수" 방식으로 처리되었다고 지적합니다. 리팩터링은 그가 무료 통과를 명시적이고 깔끔하게 처리할 수 있게 합니다.
점수 추적을 비공개 메서드로 추출하기
28:17에 Tim은 점수 추적 로직을 비공개 메서드로 추출합니다. 그는 더 작고 집중된 메서드가 코드를 더 이해하기 쉽고 유지보수하기 쉽게 만든다고 설명합니다.
그는 또한 메서드의 이름을 더 잘 반영하기 위해 "맞대결에서 승자를 표시"하는 것으로 점수 로직을 변경하는 등 메서드를 새로 이름 짓습니다.
구성 가능한 우승자 결정
29:58부터, Tim은 우승자 결정 논리를 리팩터링해서 높은 점수가 이기는 시나리오와 낮은 점수가 이기는 시나리오 모두를 처리할 수 있게 만듭니다. 그는 새로운 응용 설정을 도입하고 왜 구성이 규칙을 하드 코딩하는 것보다 나은지를 설명합니다.
Tim은 이 값을 토너먼트 모델에 저장하는 것을 포함한 다른 디자인에 대해 논의하지만, 이 변경은 이번 수업의 범위를 벗어나는 것이라고 설명합니다.
우승자 진출 및 결과 저장
45:40에, Tim은 다음 라운드로 우승자를 진출시키는 것으로 넘어갑니다. 그는 우승자가 부모 대진과 어떻게 연결되는지를 설명하고, 데이터를 정확한 시점에 저장하는 것이 왜 중요한지를 설명합니다.
이후 52:10 경, 그는 대진 업데이트를 위한 간결한 ForEach 접근 방식을 보여주며, 전통적 루프와 기능적으로 동등하지만 더 간결한 방법이라고 설명합니다.
리팩터링으로 인한 버그 수정
58:33에, Tim은 데이터베이스에서 잘못된 데이터를 발견하고, 그것이 토너먼트가 저장되기 전에 논리를 호출해서 생긴 문제임을 추적합니다. 그는 리팩터링이 새로운 버그를 만드는 것이 아니라 종종 숨겨진 버그를 드러낸다고 설명합니다.
업데이트 논리를 올바른 위치, 즉 지속성 후로 옮김으로써 Tim은 문제를 해결하고 애플리케이션을 다시 테스트합니다.
리팩터링에 대한 최종 생각
1:09:00에, Tim은 이 수업에서 리팩터링이 달성한 것을 요약하며 마무리합니다. 그는 리팩터링이 단지 더 깔끔한 코드가 아닙니다 - 엣지 케이스를 처리하고, 디자인 결함을 수정하고, 미래의 변화에 대비하는 것 역시 포함한다고 설명합니다.
그는 리팩터링이 지속적인 과정임을 강조하며, 다음 수업이 에러 핸들링에 초점을 맞출 것이라고 암시합니다.
마무리 노트
이번 수업은 실제 프로젝트에서의 리팩터링을 정확히 보여줍니다: 점진적이고, 때로는 지저분한 과정이지만, 궁극적으로 보람 있는 과정입니다. Tim Corey의 단계별 접근법을 따라하면서, WinForms 응용 프로그램을 기능을 깨지 않고 개선하기 위한 실용적인 청사진을 얻을 수 있습니다 - 다음에 무엇을 해야 할지 추측할 필요 없이 말이죠.

