✅ @Data vs record: DTO 작성 방식 비교
Lombok의 @Data
@Data
public class MemberDto {
private Long id;
private String email;
private String nickname;
private LocalDate birthday;
}
- @Getter, @Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor 등을 한 번에 생성해주는 Lombok 애노테이션입니다.
- 가변(mutable) 객체를 만들 수 있음.
Java 14+의 record
record는 Java 14 이상에서 사용할 수 있는 간단한 DTO 정의 방식입니다. 모든 필드는 final로 선언되며, 불변성을 자동으로 보장합니다.
public record MemberDto(
Long id,
String email,
String nickname,
LocalDate birthday
) {}
- final 필드와 자동 생성 생성자, toString, equals, hashCode 제공
- 불변(immutable) 객체
항목 | @Data | record |
불변성 | ❌ (가변 객체) | ✅ (불변 객체) |
생성자 | 수동 또는 @RequiredArgsConstructor 필요 | 자동 생성 |
lombok 의존성 | 필요 | 불필요 (Java 표준 기능) |
유연성 | OOP에서 확장성 높음 | 상속 불가, 제한적 사용 |
DTO에 적합성 | API 응답용 DTO, 가변성 필요한 경우 | 조회 전용 DTO, 불변 데이터 구조 |
✅ @RestController vs @Controller
@RestController
- @Controller + @ResponseBody 조합과 동일
- API 응답을 JSON으로 반환할 때 사용
@Controller
- View 템플릿(.jsp, .html 등) 렌더링을 위한 컨트롤러
👉 언제 사용하나요?
- REST API 서버에서는 @RestController
- Spring MVC 기반 페이지 렌더링 앱에서는 @Controller
✅ @RequiredArgsConstructor
이 애노테이션은 final로 선언된 필드에 대해 생성자를 자동 생성해주는 Lombok 기능입니다.
@RequiredArgsConstructor
@RestController
public class HelloWorldController {
final private NamedParameterJdbcTemplate jdbcTemplate;
}
장점
- 불변 필드 + 생성자 주입으로 의존성 주입의 안정성 증가
- 깔끔한 코드 유지
🤔 @RequiredArgsConstructor: 왜 생성자 자동 생성이 유리할까?
✅ 왜 좋을까?
- 불변 필드 보장: final은 한 번만 주입 → 객체 무결성 향상
- 테스트 쉬움: 명시적 생성자가 있으니 Mockito 등에서 주입이 쉬움
- 안정성: 필드 주입(@Autowired)보다 생성자 주입이 순환참조 방지에 좋음
✅ RowMapper와 NamedParameterJdbcTemplate
RowMapper는 ResultSet을 객체로 변환하는 인터페이스입니다.
static final RowMapper<MemberNicknameHistory> rowMapper = (ResultSet rs, int rowNum) -> MemberNicknameHistory
.builder()
.id(rs.getLong("id"))
.memberId(rs.getLong("memberId"))
.nickname(rs.getString("nickname"))
.createdAt(rs.getObject("createdAt", LocalDateTime.class))
.build();
NamedParameterJdbcTemplate은 명명된 파라미터로 쿼리를 수행할 수 있도록 도와주는 템플릿 클래스입니다.
var sql = "SELECT * FROM MemberNicknameHistory WHERE memberId = :memberId";
var params = new MapSqlParameterSource().addValue("memberId", memberId);
return namedParameterJdbcTemplate.query(sql, params, rowMapper);
장점
- 가독성 높고 유지보수 쉬운 쿼리
- 동적 파라미터 구성에 적합
✅ stream().map(this::toDto)와 Optional
Stream 활용 예시
List<MemberDto> result = members.stream()
.map(this::toDto)
.toList();
- map()은 변환 메서드 (예: 엔티티 → DTO) 에 자주 사용됨
🚀 Stream의 장점: 왜 써야 할까?
Java Stream은 컬렉션을 함수형으로 처리할 수 있게 해주는 도구입니다.
기능 | 설명 |
간결성 | for 루프 없이 짧게 표현 가능 |
가독성 | 데이터 흐름(→변환→필터→수집)이 자연스럽게 표현됨 |
체이닝 | 여러 연산(map, filter, sort...)을 연결해 가독성 높임 |
병렬 처리 | .parallelStream()으로 쉽게 병렬화 가능 |
불변성 | 원본 데이터를 수정하지 않음 (Functional style) |
Optional
Optional<Member> maybeMember = repository.findById(id);
maybeMember.ifPresent(member -> ...);
- NPE 방지
- null 처리를 더 명시적으로
✅ Object Mother vs EasyRandom
EasyRandom (실제 사용 예)
EasyRandomParameters param = new EasyRandomParameters();
Member member = new EasyRandom(param).nextObject(Member.class);
테스트에서 객체 생성 자동화를 위한 라이브러리입니다. 다양한 속성을 랜덤하게 채워주어 테스트 생산성을 높여줍니다.
Object Mother 패턴
반복되는 테스트 객체 생성을 메서드로 추상화한 패턴입니다.
public class MemberFixtureFactory {
public static Member create() {
return new EasyRandom().nextObject(Member.class);
}
}
차이점
항목 | EasyRandom | Object |
생성 방식 | 자동화된 랜덤 데이터 | 명시적으로 정의된 고정값 |
장점 | 빠르고 다양한 케이스 생성 | 통제된 테스트 데이터 생성 |
사용 위치 | 빠른 테스트용 | 검증된 구조 테스트용 |
'패스트캠퍼스 데브캠프 : 남궁성의 백엔드 개발 3기' 카테고리의 다른 글
대용량 처리를 위한 MySQL 이해 | MySQL (0) | 2025.04.28 |
---|---|
대용량 처리를 위한 MySQL 이해 | 실습 환경 구축, 대용량 시스템에 대한 이해 (0) | 2025.04.28 |
FastAPI 기반 챗봇 프로젝트에서 로그인 인증 및 RDB 파트 구현기 (0) | 2025.04.28 |
토이 프로젝트 3 | Fast API를 활용한 OpenAI 챗봇 개발 (RDB 파트) (0) | 2025.04.21 |
Spring DI (의존성 주입, Dependency Injection) (0) | 2025.04.01 |