| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
- Markdown
- stepzen
- react
- Nextjs
- dokerfile
- vercel
- Delphi
- spring
- tessrect
- beautifullsoup
- TypeScript
- wsl2
- flyio
- docker
- Expo
- java
- vmmem
- 일의격
- shadcn-ui
- edgestore
- reactnative
- superbase
- Book
- WSLHostPatcher
- FastAPI
- svelte
- kidznote
- oraclecloude
- AWS
- springboot
- Today
- Total
Blog
[book] Spring Boot Up & Running 6장 본문
6.진짜로 데이터를 깊이 파고들기
Spring Boot 애플리케이션에서 데이터를 다루는 일은 단순히 저장하고 불러오는 것을 넘어, 시스템 전체의 구조와 품질에 큰 영향을 미친다.
이 장에서는 Spring Data를 활용해 다양한 저장소(Redis, JPA, MongoDB)에 데이터를 저장하고 읽어오는 여러 접근 방식을 실제 예제와 함께 설명한다.
데이터 접근의 복잡성과 Spring Data의 등장
현대 애플리케이션은 다양한 데이터 저장소를 사용하지만, 각각의 API, 설정, 쿼리 언어가 다르기 때문에 복잡도가 커진다.
이를 해결하기 위해 등장한 Spring Data는 저장소마다 다른 접근 방식을 하나의 일관된 프로그래밍 모델로 추상화해준다.
Spring Data는 크게 두 가지 접근 방식을 제공한다.
- 템플릿 기반: 낮은 수준의 API를 통해 유연하게 제어 가능
- 리포지토리 기반: 고수준의 선언적 API로 간결한 데이터 접근 가능
템플릿 기반은 RedisTemplate, MongoTemplate처럼 저장소별 API를 직접 사용하는 방식이다.
데이터 연산 과정을 세밀하게 제어할 수 있어 유연하지만, 코드가 장황하고 반복적인 작업이 많다.
주로 캐시 처리나 복잡한 직렬화 설정이 필요한 경우에 적합하다.
리포지토리 기반은 CrudRepository, JpaRepository 등을 상속받아 사용하는 방식으로,
Spring Data가 구현을 자동으로 생성해준다.
코드가 간결하고 생산성이 높으며, 단순한 CRUD나 조건 검색에는 매우 효과적이다.
하지만 복잡한 쿼리나 저장소별 특수 기능을 사용할 때는 제약이 있을 수 있다.
도메인(엔터티) 클래스 정의
데이터 저장을 위해 우선 도메인 객체를 정의해야 한다.
이 장에서는 항공기 정보를 담는 Aircraft 클래스를 사용한다.
@Data
@NoArgsConstructor
@AllArgsConstructor
@RedisHash
@JsonIgnoreProperties(ignoreUnknown = true)
public class Aircraft {
@Id
private Long id;
private String reg;
private String route;
private int altitude;
...
}
필요에 따라 @Entity, @Document 등의 애노테이션으로 저장소와 매핑된다.
템플릿 기반 데이터 접근 - Redis
구조
WebClient를 통해 외부 API에서 항공기 데이터를 수신RedisTemplate을 사용해 Redis에 저장
설정 예시
@Bean
public RedisOperations<String, Aircraft> redisOperations(RedisConnectionFactory factory) {
RedisTemplate<String, Aircraft> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.setDefaultSerializer(new Jackson2JsonRedisSerializer<>(Aircraft.class));
template.setKeySerializer(new StringRedisSerializer());
return template;
}
데이터 저장 예시
redisOperations.opsForValue().set(ac.getReg(), ac);
리포지토리 기반 데이터 접근으로 전환
템플릿 방식보다 간결하고 추상화된 방식으로 데이터를 처리할 수 있다.
public interface AircraftRepository extends CrudRepository<Aircraft, Long> {
Optional<Aircraft> findByReg(String reg);
List<Aircraft> findByRouteContaining(String route);
}
repository.save(ac);
repository.findByReg("N754UW");
JPA 기반 서비스 구현 (MySQL)
관계형 데이터베이스와 연동할 때는 Spring Data JPA를 사용한다.
의존성
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
도메인 및 리포지토리
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Aircraft {
@Id @GeneratedValue
private Long id;
private String reg;
private String route;
...
}
public interface AircraftRepository extends JpaRepository<Aircraft, Long> {
List<Aircraft> findByRouteContaining(String keyword);
}
데이터 초기화 전략
SQL 스크립트 방식
schema-mysql.sql,data-mysql.sql파일 작성application.properties설정
spring.datasource.initialization-mode=always
spring.jpa.hibernate.ddl-auto=none
코드 기반 방식
@Component
public class DataLoader {
@PostConstruct
public void init() {
repository.save(new Aircraft(null, "N123AB", "ATL-DCA", ...));
}
}
Kotlin + MongoDB 기반 문서 데이터 처리
데이터 클래스
@Document
data class Aircraft(
@Id val id: String,
val reg: String,
val route: String,
...
)
리포지토리
interface AircraftRepository : ReactiveMongoRepository<Aircraft, String> {
fun findByRouteContains(route: String): Flux<Aircraft>
}
MongoDB는 스키마가 자유롭고, Kotlin과 결합하면 간결하고 유연한 문서 기반 저장이 가능하다.
결론
Spring Data는 다양한 저장소를 일관된 방식으로 다룰 수 있게 도와준다.
템플릿은 더 많은 제어를 제공하고, 리포지토리는 더 높은 생산성을 제공한다.
이 장의 다양한 예제들을 통해 어떤 방식이 어떤 상황에 적합한지 감을 잡을 수 있다.