들어가기에 앞서 1. 폴더 구조2. 테스트 전략3. 예외 처리 전략4. DTO ↔ Entity 변환 전략5. EndPoint 규칙6. 로깅 전략 7. Git Branch 전략 8. Validation 전략
OOP, CleanCode를 지향하자
테스트도 프로덕트 코드처럼 생각하자.
들어가기에 앞서
객체 지향 생활 체조 원칙Clean Code1. 폴더 구조
Presentation - Application - Domain - Infrastructure
- commmon - exception - domain - config - member - presentation - memberController - Application - dto - CreateMemberRequest - MemberResponse - memberService - entity - Member - MemberRepository - infrastructure - s3 , querydsl
2. 테스트 전략
- 단위 테스트는 필수
- 테스트 템플릿
- given when then 주석붙이기
- Fixture 관리
- 비즈니스 로직 테스트는 통합 테스트를 이용해보자
@SpringBootTest
jacoco , sonarcloud
사용- 도입하고 커버리지를 조금씩 올리자
- `@DisplayName("저장 성공")
- save_success()
save_success save_duplicateName_fail (유저 저장 성공) (이름 중복으로 인한 실패)
3. 예외 처리 전략
- Enum errocode
- (A001 , HttpStatus.NotFound , “존재하지 않은 유저입니다” )
- 보내는 메시지의 경우 예외 안에 있는 메시지를 보내도록
public class BusinessException extends RuntimeException { private ErrorCode errorCode; public BusinessException(String message, ErrorCode errorCode) { super(message); this.errorCode = errorCode; } public BusinessException(ErrorCode errorCode) { super(errorCode.getMessage()); this.errorCode = errorCode; } public ErrorCode getErrorCode() { return errorCode; } } @JsonFormat(shape = JsonFormat.Shape.OBJECT) public enum ErrorCode { // Common INVALID_INPUT_VALUE(HttpStatus., "C001", " Invalid Input Value"), METHOD_NOT_ALLOWED(405, "C002", " Invalid Input Value"), INTERNAL_SERVER_ERROR(500, "C004", "Server Error"), INVALID_TYPE_VALUE(400, "C005", " Invalid Type Value"), HANDLE_ACCESS_DENIED(403, "C006", "Access is Denied"), // Member EMAIL_DUPLICATION(400, "M001", "Email is Duplication"), LOGIN_INPUT_INVALID(400, "M002", "Login input is invalid"), // Coupon COUPON_ALREADY_USE(400, "CO001", "Coupon was already used"), COUPON_EXPIRE(400, "CO002", "Coupon was already expired") private final String code; private final String message; private int status; ErrorCode(final int status, final String code, final String message) { this.status = status; this.message = message; this.code = code; } public String getMessage() { return this.message; } public String getCode() { return code; } public int getStatus() { return status; } }
- 최상위 예외 : BusinessException
- 도메인 예외 : UserException
- 상세 예외 : UserDuplicateException , UserInvalidException
- custom Exception 사용
- 유저를 예로
public class UserException extends BusinessException{ public UserException(String message, ErrorCode errorCode) { super(message, errorCode); } }
public class UserCustomException extends UserException { private static final ErrorCode errorCode = ErrorCode.USER_NOT_FOUND; public UserCustomException(String message) { super(message, errorCode); } }
4. DTO ↔ Entity 변환 전략
- 라이브러리 사용하지 않고 DTO 자체 변환 메소드 구현해 사용
- Controller에서 받은 request, response DTO를 그대로 사용
- 변환 위치
- DTO에서 반환하도록
- from, toEntity
- 후에 리팩토링 하는 식으로 진행

5. EndPoint 규칙
- Rest API Best Practice로 따라가자
- 단수 지양
- 복수 지향
- 동사 지양
- 명사 지향
/api/
를 prefix로 붙여주자
6. 로깅 전략
- 커스텀 예외는 어떤 레벨로 찍을까?
error
→ Exception (예상하지 못한 에러는 error)warn
→ 커스텀 예외 (예상할 수 있는 에러는 warn)- 원래는
info
인듯하나 편의성을 위해warn
으로 설정
- SQL 로깅까지
- 비동기 로깅 → logback , log4j
cloudwatch 로그 연동
및 슬랙에 error시 알람 올 수 있도록
7. Git Branch 전략
8. Validation 전략
- 도메인에서 하기에 복잡한 validation은 Validator 유틸성 클래스를 만들어서 진행
- null 체크