개발에서 내가 어떤 잘못을 하고 있었을까?

Yumin·2025년 8월 5일
0

Unity

목록 보기
12/18

최근에 개발을 하면서 느낀 게 있는데
회사를 다니면서 여태까지 개발을 잘 못하고 있다는 것을 깨달았습니다.

전체적으로 어떤 것이 잘못되었고 어떠한 방향으로 설계를 했어야 하는지 이 글에서 써보려고 합니다.

먼저 설계에 관한 부분입니다.


설계


전체적으로 설계를 잘 못하고 있다는 사실을 깨달았습니다.
겉핥기로 개발을 이해하는 것에 대해서는 크나큰 잘못이 따라온다는 점입니다.

public class GameData {
    public Dictionary<Tutorials, bool> TutorialStates { get; private set; } = new();
    public int CoinAmount { get; private set; }
    public int CashAmount { get; set; }
    public ItemData[] ShelfIngredients { get; } = new ItemData[9];
    public RecipesData[] CurrentPlayerFoods { get; } = new RecipesData[3];
    public Dictionary<string, RecipesData> KnownRecipes { get; } = new();
    public Dictionary<string, ItemData> KnownIngredients { get; } = new();
    public Dictionary<ItemData, int> IngredientStock { get; } = new();

이는 GameData입니다.
먼저 GameData라는 이름부터가 애매모 한 위치에 있습니다.

제목부터가 설계상의 미스였습니다.
회사를 다니면서 배운 건 좀 더 구체적이고 명확한 네이밍이 중요하다는 것을 깨달았습니다.

문제는 그것뿐만이 아니라
한 데이터 안에 수많은 책임을 가지고 있고 이 데이터가 마스터 데이터인지 유저 데이터인지 이해할 수 없게 되어있다는 점입니다.

또한 public으로 설계되어 있어서 다른 스크립트에서 접근 수정하기가 너무 쉽게 되어있습니다.

물론 이 뿐만이였으면 좋았겠지만 이 GameData 클래스는 GameManager에 포함되어 있습니다...

내가 왜 그랬을까라는 생각을 회사 연수를 받으면서 생각했습니다.

전체적으로 매니저 안에 넣고 매니저는 싱글톤을 사용해 의존성도 높고

설계적으로 아예 잘못된 방향으로 나아가고 있었습니다.


책임의 분리


개발을 하면서 가장 크게 깨달은 점 중 하나는 "하나의 클래스가 너무 많은 일을 하고 있다"는 것입니다.

GameData의 경우만 봐도

  • 튜토리얼 진행 여부
  • 재화(코인, 캐시) 관리
  • 아이템 재고
  • 레시피 정보
  • 플레이어 상태

이 모든 책임이 한 클래스에 뒤섞여 있습니다.
이는 단일 책임 원칙(SRP, Single Responsibility Principle)을 완전히 위반한 설계입니다.

이렇게 여러 역할을 한 곳에 몰아넣으면,

  • 특정 기능을 수정할 때 전혀 관계없는 코드가 영향을 받음
  • 테스트 코드 작성이 어려움
  • 다른 개발자가 코드를 읽고 구조를 파악하기 힘듦
  • 확장성 저하 (기능 추가가 어려워짐)

결국 유지보수 비용이 기하급수적으로 늘어납니다.

어떻게 했어야 했나?
각 데이터는 그 성격에 맞게 책임을 명확히 분리했어야 했습니다.
예를 들어:

  • PlayerCurrency : 코인, 캐시 등의 재화 정보
  • PlayerInventory : 아이템, 재고 관리
  • PlayerProgress : 튜토리얼, 퀘스트, 진행 상황
  • RecipeBook : 레시피 목록 및 해금 상태

그리고 이런 데이터 클래스들은 Manager나 Singleton에 바로 넣는 대신,
독립적인 데이터 컨테이너로 두고, 필요한 객체만 참조하게 해야 합니다.
그렇게 하면 의존성이 줄어들고, 각 부분을 독립적으로 교체하거나 테스트할 수 있습니다.

경험에서 얻은 교훈
"데이터"와 "로직"을 억지로 한 곳에 몰아넣으면 구조가 망가진다

이름은 역할이 명확하게 드러나야 한다

싱글톤은 신중하게 써야 하며, 쓰더라도 데이터 전용 객체와는 분리해야 한다


네이밍의 중요성


네이밍은 단순히 보기 좋은 단어를 고르는 문제가 아니라,
그 클래스나 변수, 메서드가 무엇을 하는지, 어떤 역할을 하는지를 개발자에게 명확히 전달하는 일종의 계약입니다.

GameData라는 이름만 봤을 때,
이 안에 무슨 데이터가 들어있는지 정확히 알 수 없습니다.

  • 플레이어 정보인지?
  • 시스템 전체의 데이터인지?
  • 임시 캐싱 데이터인지?

이름만으로는 알 수 없으니, 코드를 열어보고 해석해야 하는 상황이 발생합니다.

이런 네이밍은 협업에서 큰 문제를 만듭니다.
다른 개발자가 GameData를 사용하려고 할 때,
그 의도를 파악하는 데 불필요한 시간과 노력이 소모되기 때문입니다.

잘못된 네이밍의 부작용

  • 코드 리뷰 시 “이게 무슨 역할을 하는 클래스죠?”라는 질문이 반복됨
  • 유지보수 시 해당 데이터의 성격을 오해해 버그 발생
  • 기능 확장 시 어떤 데이터와 묶어야 할지 감이 안 옴

개선된 네이밍 예시

  • PlayerData : 플레이어의 진행 상황과 상태를 담는 데이터
  • InventoryData : 인벤토리 관련 데이터
  • RecipeData : 레시피 관련 데이터
  • CurrencyData : 재화(코인, 캐시) 정보

PR에서의 소통과 설명


코드 리뷰를 받으면서 크게 느낀 점이 있습니다.
리뷰어가 내가 작성한 코드를 ‘그냥 보면’ 바로 이해할 거라고 생각하면 안 된다는 겁니다.

예전에는 PR을 올릴 때,

  • 변경된 코드를 통으로 업로드
  • 설명 없이 “기능 추가” 정도만 적기
    이런 식으로만 했습니다.

그 결과, 리뷰어는

  • 변경 의도 파악에 시간이 오래 걸림
  • 왜 이런 구조로 작성했는지 알 수 없음
  • 특정 부분의 설계 이유를 추측해야 함
    이런 상황에 부딪히게 됩니다.

코드 리뷰는 단순히 “문법 체크”나 “오타 잡기”가 아니라,
설계 의도와 구현 이유를 공유하는 과정이기도 합니다.
그렇기 때문에 PR 설명은 단순 변경 요약이 아니라,

  • 무엇을 변경했는지
  • 왜 이렇게 변경했는지
  • 다른 대안은 없었는지
    를 함께 기록해야 합니다.

개선 방향

  1. PR 제목 : 변경 내용이 한눈에 보이도록 구체적으로 작성
  2. PR 설명 : 변경 이유, 설계 의도, 고려했던 대안, 예상되는 영향 범위 기록
  3. 코드 단위 : 관련 없는 변경은 PR에서 분리 (리뷰 집중도 향상)

이렇게 하면 리뷰어가 의도를 빠르게 이해하고,
더 건설적인 피드백을 줄 수 있습니다.
결국 나와 팀 모두의 시간을 절약하고, 코드 품질도 자연스럽게 높아집니다.


결론
개발은 혼자 하는 작업이 아니라 협업입니다.
좋은 설계, 명확한 책임 분리, 그리고 PR에서의 충분한 설명은 협업의 기본이자 필수입니다.
앞으로는 “코드를 봐서 이해해 주겠지”라는 생각을 버리고,
“의도를 전달하는 문서”로서의 PR을 작성하는 습관을 들이도록 의식하고 있습니다...


profile
クリエイティブを楽しむ開発者

0개의 댓글