Skip to content

백엔드 코드 컨벤션

이상진 edited this page Jul 10, 2024 · 1 revision

네이버 캠퍼스 핵데이 코딩 컨벤션을 따르며, 해당 링크에 있는 Intellij Formatter를 사용하여 정렬한다.

코드 스타일 컨벤션

패키지 구조

member
 controller
 dto
     request
     response
 domain
 service
 repository
  • 도메인 기준으로 패키지를 분리한다.
  • 도메인 사이의 의존이 생기는지 확인하고 문제가 생긴다면 다시 피드백한다.

줄바꿈

@PostMapping("/posts/{categoryId}")
public RepsonseEntity<PostSaveResposne> savePost(
	@PathVariable Long categoryId,
	@RequestBody PostSaveRequeset postSaveRequest, 
	@Auth final Member member
) {
	...
}
  • 메서드 시그니처의 길이가 120자 이상을 넘는 경우 파라미터를 기준으로 줄바꿈한다.
  • 파라미터가 3개가 넘는 경우 줄바꿈한다.
void save() {
	Post savedPost = postRepository.save(
			new Post("title", "content", new Author("anna", 24))
	);
}
  • 한 줄의 코드가 120자 이상을 넘는 경우 줄바꿈 허용 위치에서 줄바꿈한다.

변수/상수 개행

public class Member {
	
	private static final int MAX = 10;
	
	@Id
	@GeneratedValue(GeneratedType.IDENTITY)
	private final Long id;
	
	@Column(nullable = false)
	private final String name;
}
  • 클래스 시작 후 개행한다.
  • 변수 및 상수나 메서드 간에 개행한다.

개발 컨벤션

테스트

테스트 메서드 & 어노테이션

@DisplayName("모임 생성에 성공한다.")
@Test
void saveGathering() {
}
  • 테스트 어노테이션은 @DisplayName@Test 순으로 사용한다.
  • @DisplayName는 완전한 문장으로 작성한다.
  • 테스트 메서드는 영어로 작성하며 기본적으로 테스트하려는 메서드 명을 작성한다. 테스트 메서드에 test는 사용하지 않는다.

@Nested

@DisplayName("주문 조회 테스트")
@Nested
class OrderReadTest { // 자원 + 요청 형태 + Test

	@DisplayName("주문을 성공적으로 조회한다.")
	@Test
	void success() {
	
	}
	
	@DisplayName("상품이 존재하지 않아서 주문 조회에 실패한다.")
	@Test
	void fail_When_ItemDoesNotExists() {
	
	}
}
  • 하나의 메서드에 대한 테스트가 여러 조건으로 나누어지는 경우 @Nested를 이용하여 기능을 분리하고 내부에서 위와 같이 케이스를 나눈다.
  • @Nested 사용에 의한 Inner class의 클래스 명과 @DisplayName은 검증하려는 자원 + 요청 형태 + 테스트/Test 형식으로 작성한다.
  • 실패 테스트의 경우 실패의 원인을 메서드명과 @DisplayName에 명시한다.

빈 주입

class MemberServiceTest {

	@Autowired
	private MemberRepository memberRepository;
	
	... 
}
  • 테스트 클래스의 빈 주입은 필드 주입을 사용한다.
  • private를 사용해 선언한다.

@Transactional

  • 테스트에서는 @Transactional을 사용하지 않는다.

DTO

public record MemberSaveRequest(
		int age, 
		String name,
		String address
) {
}
  • DTO는 record를 사용한다.
  • 클래스 이름은 자원 - 행위 - 요청/응답 으로 명명한다.
    • 예시: ProjectFindRequest, ProjectFindResponse
  • 파라미터는 기본적으로 개행해서 작성한다.

컨트롤러 응답

@RestController
public class .. {
	
	public ResponseEntity<..> ..() {
		..
	}
}
  • 응답 시 @RestController와 ResponseEntity를 사용한다.

예외 처리

public enum ProjectErrorCode {
	..
}

public class ProjectException {

	private final ProjectErrorCode ..
	private final String message;
	..
}
  • Custom Exception은 도메인마다 한 개씩 정의한다. 해당 도메인에서 발생하는 비즈니스 예외는 해당 Custom Exception을 사용한다.
  • 각 예외 코드는 별도의 enum으로 관리한다.

@Transactional

@Transactional 
@Service
public class MemberService {

	public void save() {
		...
	}
	
	@Transactional(readonly = true)
	public void find() {
		...
	}
}
  • 서비스 레이어의 경우 기본적으로 @Transactional 을 클래스 레벨에 추가한다.
  • 조회만을 목적으로 트랜잭션을 필요로 하는 경우 메서드에 @Transactional(readonly = true)를 작성한다.

Swagger

@Operation(summary = "참여자 목록 조회", description = "모임에 참여 신청한 사용자의 닉네임을 전체 조회한다.")
@ApiResponses({
	@ApiResponse(responseCode = "200", description = "참여자 목록 조회 성공"), 
	@ApiResponse(responseCode = "400", description = "올바르지 않은 요청"),	
	@ApiResponse(responseCode = "401", description = "올바르지 않은 인증 코드")
}) 
  • @Operation 부분에는 기능에 대한 요약과 설명을 작성한다. 요약과 설명의 내용이 일치하는 경우 설명은 따로 적지 않는다.
  • @ApiResponse가 하나만 있는 경우에도 @ApiResponses 하위에 넣는다.