안녕하세요. IT 엘도라도 에 오신 것을 환영합니다.
글을 쓰는 것은 귀찮지만 다시 찾아보는 것은 더 귀찮습니다.
완전한 나만의 것으로 만들기 위해 지식을 차곡차곡 저장해 보아요.   포스팅 둘러보기 ▼

회사 프로젝트 작업 일지

[오픈갤러리] Django 서버 정리 작업 ③ - 불필요한 파일/코드 삭제 및 코드 순서 정리

피그브라더 2021. 5. 27. 14:29

목차
⦁ 프로젝트 폴더 내 불필요한 파일 및 코드 삭제
⦁ 모델 클래스 내 코드 순서 정리
⦁ 모델 내 불필요한 필드 삭제
⦁ URL 및 뷰 순서 정리

 

▎프로젝트 폴더 내 불필요한 파일 및 코드 삭제

오픈갤러리는 지금까지 빠른 개발에 집중을 해왔다. 즉, 당장 필요한 기능의 '추가'에만 초점이 맞춰지고 기존 기능의 '삭제'에는 큰 정성을 들이지 못했다는 것이다. 이로 인해 더 이상은 사용되지 않는 불필요한 파일이나 코드들이 그때그때 제대로 지워지지 못한 채 오랜 시간 축적되어 왔다. 그래서 이제는 그러한 파일과 코드들을 찾아 지워줄 때가 되었다고 생각하였다. 다른 무거운 정리 작업들을 진행하기에 앞서, 먼저 프로젝트를 가볍게 만드는 게 우월 전략이라고 판단한 것이다.

일반적으로, 특정 기능을 삭제할 때는 그 기능과 의존성을 갖는 다른 기능들도 함께 삭제해주는 것이 맞다. 예를 들어, 더 이상 사용하지 않게 된 특정 페이지를 삭제하게 된다면, 그 페이지에서'만' 사용하는 각종 정적 파일(CSS 파일, JavaScript 파일, 이미지 파일 등)들도 함께 삭제해줘야 한다. 이때 지워주지 못하면 나중에는 그러한 파일들을 찾아 지워주는 게 더 어려워지고, 이런 현상들이 반복되면 프로젝트는 걷잡을 수 없이 커지기 때문이다.

더군다나, 불필요한 파일이나 코드들이 곳곳에 존재하는 것은 프로젝트의 크기에만 영향을 미칠 뿐 아니라 추후 개발자들의 작업 효율에도 적지 않게 영향을 미친다. 근속이 긴 개발자가 아니라면 더 이상 사용되지 않는 불필요한 파일이나 코드들의 역할에 대해 잘 인지하고 있지 못할 가능성이 크고, 이로 인해 특정 문제가 발생하였을 때 그 문제의 원인을 그러한 불필요한 파일 혹은 코드들에서 찾다가 시간을 허비하게 될 수도 있기 때문이다. "혹시 이 파일이 문제인가?" 등의 의심은 시간 낭비를 초래할 뿐이다.

 

그리고 여기서 말하는 삭제 작업은 곧 정리 작업으로 이어졌다. 불필요한 것들을 삭제하는 작업뿐 아니라 필요한 것들을 올바르게 재배치하는 작업까지 진행하였기 때문이다. 이 작업에서 정리한 파일들 중 가장 핵심이 되는 것을 뽑아 보자면 다음과 같이 세 가지이다.

 

▏1. Django 설정 파일

Django 프로젝트의 뇌 역할을 담당하는 설정 파일의 내용도 잘 정리가 되어 있지 않았었다. 각 코드 블록이 어떠한 역할을 위해 존재하는 것인지에 대한 주석도 달려 있지 않았고, 심지어는 불필요하게 작성되어 있거나 잘못 작성되어 있던 설정들도 있었다. 그리고 애초에 각 코드 블록이 의미 단위로 구분되어 잘 배치되어 있던 것도 아니었기 때문에 새로운 설정을 작성할 때도 임의의 위치에 작성하게 되는 일이 반복되어 나중에는 필요한 설정을 찾기가 어려워지곤 하였다.

 

그래서 불필요한 설정들은 지우고, 잘못된 설정들은 고치며, 필요한 설정들은 의미 단위로 위치를 재배치하여 정리하였다. 예를 들어, 인증(Authentication)과 관련된 설정들은 한 곳에 모아두는 것이다. 또한 각 코드 블록마다 그것이 대략 어떠한 역할을 수행하는 것인지에 대한 주석도 깔끔하게 작성하였다.

 

더불어, 현재 설정들은 베이스 설정 파일에 기반한 상태로 환경별(실서버 전용, 테스트 서버 전용, 로컬 전용)로 구분된 파일들에 각각 작성되어 있는데, 각 파일의 설정들도 해당 환경에 맞게 적절히 정리하였다. 예를 들어, 로컬 전용 설정 파일에는 정말 로컬에서만 사용하는 설정들이 들어가 있도록 하고, 세 환경에서 전부 사용하는 설정이라면 반드시 베이스 설정 파일에 들어가 있도록 하는 것이다. 이러한 정리 과정을 통해 설정 파일의 각 코드 블록이 어떠한 역할을 위해 왜 이곳에 존재하는지 명확하게 만들었다.

 

▏2. requirements 파일

설치되어야 하는 Python 패키지들의 목록을 명시한 requirements 파일도 정리하였다. 더 이상 사용되지 않는 패키지들도 그대로 남아 있었기 때문에 현재 사용되는 패키지들만 남기고 전부 삭제하였다. 그리고 각 패키지가 어떠한 역할을 수행하는지에 대해서도 깔끔하게 주석을 작성하였다.

 

▏3. Django 테스트 코드

오픈갤러리도 과거에 Django 테스트 코드를 작성했던 시기가 있었다. 그러나 필자가 입사한 시점 이후에는 한 번도 테스트 코드를 작성한 적 없었고, 근속이 긴 개발자분께 물어보니 필자가 들어오기 훨씬 전부터도 테스트 코드는 작성되지 않고 있었던 것 같다. 아무래도 빠른 기능의 개발에 집중해야 하는 분위기를 타게 되면서 테스트 코드의 작성도 우선순위에서 뒤로 밀린 것이 아니었을까 추측해본다.

 

그런데 문제는 오히려 그러한 과거의 테스트 코드들이 현재 새로운 기능을 개발할 때마다 장벽이 되었다는 것이다. CI/CD에서 자동으로 실행되는 테스트 코드들이 종종 실패하게 되면서 개발 작업을 힘들게 만들었기 때문이다. 이는 과거의 테스트 코드들이 정밀하게 작성되어 있지 않았을 뿐 아니라(그때도 실험적으로 시작했던 것이었기 때문에) 새로운 기능을 개발할 때마다 해당 테스트 코드의 내용이 함께 갱신되지 않았기 때문이다. 그래서 테스트 코드는 추후 여유가 생긴 후 다시 제대로 작성하는 것으로 합의하고, 기존의 테스트 코드는 전부 삭제하는 것으로 결론을 내렸다. 사실 제대로 작성된 테스트 코드가 그렇게 많이 있던 것도 아니라서 삭제하는 것에 큰 부담은 없었다.

 

참고로, 이 작업에서는 주로 프로젝트에서 전역으로 사용하는 설정 파일과 같은 것들의 정리에 초점을 맞추었다. 즉, 각 앱 폴더 내에 존재하는 뷰, 템플릿, 모델 등과 관련된 상세 코드들은 지금 당장 정리하기에 규모가 너무 크기 때문에 추후 진행하게 될 작업들을 통해 하나씩 차근차근 정리해 나갈 계획을 세웠다.

 


▎모델 클래스 내 코드 순서 정리

오픈갤러리 프로젝트에는 100개가 넘는 모델들이 정의되어 있는데, 각 모델의 코드가 어떠한 컨벤션도 없이 작성되어 있었기 때문에 컨벤션을 확립하고자 진행한 작업이다. 굵직하게는 각 모델 클래스 내 코드들의 순서를 정해진 규칙대로 수정하는 작업이었고, 세부적으로는 각 필드에 명시되어 있는 인자들의 순서를 정리하는 것까지 포함하였다.

 

기본적으로 모델 클래스 내 코드들의 순서는 다음과 같이 정하였다. Django 공식 문서에 나와 있는 것을 참고하긴 했지만, 이렇다 할 명확한 기준이 알려져 있지는 않은 것 같아서 내부적으로 합의를 통해 규칙을 정하였다.

1. 상수 (EX. choices 인자로 설정할 값) : 대문자로 작성
2. 이미지 필드의 upload_to 인자로 설정할 메소드
3. 필드
4. 프로퍼티 : get_ 형태의 이름 사용 불가능
5. 메소드 : get_ 형태의 이름 사용 가능
6. save() 메소드
7. delete() 메소드
8. __str__() 메소드 : 필수 (모델 자체의 verbose_name 역할)
9. Meta 클래스

 

그리고 각 필드의 인자들과 관련된 컨벤션은 다음과 같이 정하였다. 

  • choices 인자로 설정할 값들은 대문자로 선언하여 클래스 내 최상단에 작성하는 것을 원칙으로 한다.
  • 기본적으로 필드들은 추가 개행 없이 붙여 쓰는 것을 원칙으로 하되, 가독성을 위해 의미 단위로 블록을 나눌 수는 있다. 이때는 각 블록마다 간단한 주석을 작성해주면 좋다.
  • Log 기능을 위해 verbose_name 인자는 필수로 설정해 주며, 가장 첫 번째 인자여야 한다. 이때는 인자 이름(verbose_name)을 생략해준다. 단, ForeignKey, ManyToManyField, OneToOneField 필드의 경우에는 두 번째 인자로 설정해 줘야 하며, 인자 이름(verbose_name)을 반드시 명시해 줘야 한다.
  • null 인자 또는 default 인자가 필요한 경우, 이들은 맨 뒤에 위치해야 한다. 단, null=True인 경우 default 인자가 필요 없고 null=False인 경우 null 인자를 생략해도 되므로 두 인자는 공존하면 안 된다.
  • ForeignKey, ManyToManyField, OneToOneField 필드의 인자 순서
    • to : 인자 이름을 명시하지 않고 항상 문자열로 설정해 주는 것으로 통일
    • verbose_name : Log 기능을 위해 항상 설정해주는 것으로 통일
    • related_name, related_query_name : 항상 명시적으로 설정해 주는 것으로 통일
    • on_delete : ManyToManyField 필드의 경우에는 필요 없음
    • through : ManyToManyField 필드에서만 의미가 있음
    • null : null=False인 경우에는 생략 가능
    • default : null=True인 경우에는 생략 가능

 

그리고 위 컨벤션을 바탕으로 각 종류의 필드에 명시되는 인자들의 순서는 다음과 같이 정하였다.

  • ForeignKey(to, verbose_name, related_name, related_query_name, on_delete, null)
  • OneToOneField(to, verbose_name, related_name, related_query_name, on_delete, null)
  • ManyToManyField(to, verbose_name, related_name, related_query_name, through)
  • GenericRelation(to, verbose_name, related_query_name)
  • PositiveSmallIntegerField(verbose_name, choices, null, default)
    SmallIntegerField(verbose_name, choices, null, default)
  • CharField(verbose_name, max_length, choices, unique, null, default)
    EmailField(verbose_name, max_length, choices, unique, null, default)
    TextField(verbose_name, blank=True)
  • BooleanField(verbose_name, default)
  • DateField(verbose_name, null, default)
    TimeField(verbose_name, null, default)
    DateTimeField(verbose_name, null, default)
  • ImageField(verbose_name, upload_to, null)
    FileField(verbose_name, upload_to, null)
  • ArrayField(verbose_name, base_field, default)
  • JSONField(verbose_name, default)

 


모델 내 불필요한 필드 삭제

조금 더 구체적으로는, 더 이상 참조가 되지 않는 필드이거나 과거 데이터를 저장하고 있는 용도로 남겨둔 필드들 중 더 이상 데이터를 저장하고 있을 필요가 없다고 판단되는 필드를 삭제한 작업이다. 더불어, 오픈갤러리 프로젝트는 Django admin을 사용하지 않기 때문에 각 앱의 admin.py 파일도 삭제해주었다.

 


URL 및 뷰 순서 정리

오픈갤러리 서비스에는 기본적인 웹사이트 외에도 관리자용 웹사이트와 작가용 웹사이트가 따로 존재하는데, 이 세 종류의 웹사이트에서 사용하는 URL의 개수가 대충 세어 봐도 500개는 족히 넘었다. 그런데 심지어 그중에는 더 이상 사용되지 않는 URL도 있었고, URL의 순서에 대한 규칙도 명확하지 않았으며, URL의 순서가 뷰의 순서와 일치하지도 않았다. 이러한 점들은 유지보수나 개발 과정에 있어서도 여러모로 비효율을 야기하였다.

 

해당 문제를 해결하기 위해 가장 먼저 진행한 작업은 먼저 URL의 순서 정리였다. 이때 URL의 순서는 웹사이트의 메뉴 순서와 최대한 일치시키는 규칙을 적용시키기로 하였다. 물론 그 과정에서 메뉴 이름 등을 이용하여 주석을 달아주는 것은 기본이었다. 또한 사용되지 않는 URL이나 API로 사용하는 URL의 경우에는 별도의 블록으로 빼서 구분해두고 여기에도 마찬가지로 주석을 적절히 달아주었다. 단, 사용되지 않는 URL의 경우 아카이빙의 목적이 분명하게 있는 것이 아니라면 바로 삭제하였다. 물론 그 삭제 과정에서 여러 의존성도 꼼꼼히 체크하여 함께 삭제를 해주었다.

 

다음으로, 정리한 URL의 순서에 맞게 뷰의 순서도 정리해주었다. URL의 순서와 뷰의 순서가 일치하지 않아서 개발 시에 혼란을 겪은 적이 꽤나 있었기 때문이다. 물론 삭제된 URL에 해당하는 뷰는 당연히 함께 삭제해주었다.