[Spring 심화 개인 과제] Lv.5 코드 개선

말하는 감자·2025년 4월 18일

내일배움캠프

목록 보기
45/73

Lv5. ‘내’가 정의한 문제와 해결 과정

  1. [문제 인식 및 정의]

  2. [해결 방안]
    2-1. [해결 방안제시]
    2-2. [해결 완료]
    2-3. [전후 데이터 비교]

  3. [회고]

일단 지금 보는 프로젝트는 todo에 관련된 게시글을 쓰고, 게시글 안에 댓글을 달 수 있는 기능이 주축이다.
로그인과 회원가입이 있고 회원들간의 역할이 나누어져있다.




1. 404 Error 추가

1. [문제 인식 및 정의]

  • todoID를 찾지 못할 경우 InvalidRequestException 발생
    • InvalidRequestException요청 자체가 잘못된 경우 사용해야 함.
      • 예시 : Id값이 음수/ 숫자가 아닌 값 등..
    • 요청값의 형태가 올바른데 row값을 찾지 못하는 것은 404 Not Found 케이스임.


2. [해결 방안]

  • todoID 값을 검증하는 Validation 추가
  • findById에서 일어나는 예외로 404 Not Found 추가

  • 추가적으로 Auth에서 사용자를 찾지 못하는 경우는 404보다는 400이 맞다고 생각해서 고치지 않음.




2. 예외 처리 구조 변경

1. [문제 인식 및 정의]

  • 해당 프로젝트에서는 예외 처리를 RuntimeException을 상속받는 개별 오류클래스를 각각 처리하는 방식으로 사용중
  • ->GlobalExceptionHandler 에서 반복되는 코드가 상당히 있음
    • 이후에 프론트와 연계가 필요하거나 프로젝트가 확장되어 협업을 하게되거나, 문서화가 중시되면 GlobalExceptionHandler에서 하나하나 처리하는 방식이 불편할 것이다.
      -> 현재 예외 처리 구조에서는 공통 부모 예외 클래스 방식으로 변경이 가장 쉬워 보인다.

2. [해결 방안]

  • GlobalExceptionHandler 에서 반복되는 코드를 줄이고, 오류가 늘어나더라도 추가되는 코드가 줄어들도록 생각했음.

  • RuntimeExceptionmessage만 받길래 커스텀 에러클래스에서 HttpStatus도 보관하도록 설정

만약 오류종류가 늘어나게된다면

여기에 오류 종류에 맞는 클래스 하나 생성

고민사항 & 해결법

enum사용이 낫나..?

  • enum을 사용하는 경우
    • enum은 상수로 사용되는 만큼 형태 변경이 어렵다.
    • 작은 프로젝트 + 예외의 형태가 잘 변하지 않음 일수록 enum을 쓴다고함

그대로 두기로했다!




3. 패키지 구조 변경

1. [문제 인식 및 정의]

  • 예외처리하다가 느낀 점인데 config의 구성들과 domain>common과의 관계가 모호하다고 느꼈음
  • 인증/인가에 대한 예외처리가 InValidRequestException으로 처리되고 있는것을 발견
    • auth-> exception의 내용이 다른 exception과 같이 관리되어야 한다고 생각.
    • GlobalExceptionHandler가 다른 exception과 분리되어있어서 찾기 불편하다는 생각을 했음.
  • Lv.4 과제로 Logging역할을 하는 클래스가 두개 생겨서 이것도 따로 분류하면 좋겠다고 생각함.

2. [해결 방안]

expert
├── domain
│   ├── user
│   ├── comment
│   └── ... (도메인별 패키지)
├── global
│   ├── config                ← 설정
│   ├── exception             ← 공통 예외
│   ├── logging               ← LoggingAspect, LoggingInterceptor
│   ├── auth
│   │   ├── jwt               ← JwtFilter, JwtUtil
│   │   ├── annotation         ← @Auth
│   │   ├── resolver         ← AuthUserArgumentResolver
│   │   └── dto               ← 인증 관련 DTO
│   └── common
│       └── entity            ← BaseEntity, 공통 상속 클래스

이런식으로 생각했음.

  • global 패키지를 생성 domain 안의 commonglobal안에 모두 넣고 다시 기능에 따라서 분류




4. 반환형

1. [문제 인식 및 정의]

  • 선택적 파라미터 많고, DTO/응답 생성시에는 가독성(명시성), 유지보수성을 위해서 build() 를 사용하는 것으로 알고있다.

  • 객체만들어서 responseDto 만들기 위해서 하나하나 다시 꺼내서 순서별로 지정해야 한다는 것이 가독성이 좋아보이지 않는다.

2. [해결 방안]

  • Dto가 가진 필드가 4개 이상이면 builder로 변경 (post 서비스의ResponseDto만 변경했음)




5. Repository.findBy@@ 검증

1. [문제 인식 및 정의]

  • 현재 UserRepository , PostRepository 들은 다른 서비스에서도 Repository 참조가 일어나고 있음
  • 모든 메소드에서 공통적으로 findBy@@ 를 많이 사용하는데, 아이디값에 유효한 row가 있으면 그 객체반환, 없으면 똑같은 메시지로 에러를 발생시킴

2. [해결 방안]

  • Repository를 참조하는김에 default함수로 findBy@@orElseThrow 를 만드는게 낫겠다는 판단을 함.


위 처럼, 반환해야하는 에러 메시지가 다를 경우는 그냥 놔둠




6. 비밀번호 교체함수

1. [문제 인식 및 정의]

  • userService에 있는 비밀번호 교체함수다.
  • user 엔ㅌ티 안에 이미 changePassword라는 함수가 있고 userService에서는 바꿀 비밀번호의 값을 검증하고있음
  • 동일한 이름의 메서드가 서로 다른 수준(서비스 vs 도메인)에서 "부분적으로" 역할을 나눠가지고 있는 점이 모호하다고 느꼈음.

2. [해결 방안]

  • 비밀번호라는 특수한 값은 단순한 값 변경이아니라 값에 대해나 검증까지 포함해서 작동해야한다고 생각함.
  • user 엔티티가 비밀번호 검증하는 함수와 변경하는 함수를 가지고 있도록 변경


user 엔티티 내부에 비밀번호를 변경하느 ㄴ함수와
입력한 비밀번호가 저장된 비밀번호가 같은지 검증하는 함수를 생성했음.

그리고 비밀번호를 교체하는 함수도 저 두 함수를 이용하는 방식으로 변경함

  • 추가로 로그인할 때 비밀번호 검사하는 함수도 isPasswordCorrect 으로 검증함.




7. saveManager

1. [문제 인식 및 정의]

  • 분기점이 너무많다. 코드 흐름이 한눈에 안들어온다
  • AuthUser 에서 사용하는 정보는 id값 밖에없는데 굳이 User으로 바꿀 필요가 있나
  • "담당자를 등록하려고 하는 유저나 일정을 만든 유저가 유효하지 않습니다."에러 코드 메시지 내용이 모호하다.

2. [해결과정]


검증하는 로직은 따로 다 내부함수로 빼줌.

  • User.fromAuthUser(authUser); 이라는 static 함수를 사용하지 않고 바로 id값만 가져옴
  • `"일정 작성자 본인만 담당자를 등록할 수 있습니다. 로그인 정보와 작성자를 확인하세요." 로 메시지 변경




[회고]

엄 음 엄

  • 다른 사람이 작성한 코드라서 이해하는데 시간이 오래걸리기도 했고, 작성하신 분이 나보다 코드 잘짠다는 느낌을 받아서 건들이기 좀 주저했던 것이 있다..
  • 정리하고 보니, 내가 문제라고 느끼는 부분들은 보통 메서드 내에 공통적으로 있는 로직을 잘 못보는 것같다 ㅋㅋㅋ..
  • 그 외에도 팀원들이랑 스크럼에 얘기를 하다가 책임 분리에 대해서 이번에 고민을 좀 하게됐는데, 아직까지 얼마나 분리해야할지 감이안온다.
    • 이번에는 비밀번호 교체함수 같이 다른 서비스에서도 사용하는 로직이 있고(비밀번호 맞는지 검사), 분리 해볼법 한 내용이 있는 것만 빼냈다.
  • 로그인 한 상태일때 User객체를 Repository를 거치지 않고 static 메서드인 fromAuthUser으로 바로 바꾸는 것은 보고 배웠다 (나중에 써먹어야지)
profile
대충 데굴데굴 굴러가는 개발?자

0개의 댓글