[2025백엔드] 스프링인액션 독서 #5 - 3장. 데이터로 작업하기 #3

2025. 8. 4. 02:18·CS/백엔드

나만못가펜타포트

이렇게 사진도 잘찍는 법을 알고싶다.. 보정공부도 해야하고 노출공부도 해야하고.. 이상하게 개발공부보다 더 어려운 것 같다. 이러면서 2학기 때 디디입을 한다고?

 

암튼 지금 DB의 늪에 빠져있는데, 우선 늪을 벗어나봅시다!

저번까지는 JDBC를 사용했고, 오늘부터는 JPA를 사용할 것이다.

 

다만 지금 GDG 프로젝트에서만 JPA를 적용할 것이고, 당분간 내 개인프로젝트에는 JDBC를 사용할 계획이다. 우선 SQL문에 익숙해지는게 목적이기 때문에...


JPA를 깔았다는 전제하에..

@Entity
@Data
@Builder
@NoArgsConstructor(access = AccessLevel.PRIVATE, force = true)
@AllArgsConstructor

public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

이런식으로 선언된다.

NoArgsConstructor 어노테이션이 붙었는데, JPA에서는 객체가 인자가 없는 생성자를 가져야한다. 그런데 커스텀 생성자를 사용자가 작성한다면 인자가 없는 생성자는 커스텀 생성자로 추가해주지 않는 이상 생기지 않는다. 따라서 자동으로 인자를 받지 않는 생성자를 자동으로 만들기 위해 붙은 어노테이션이다.

 

JPA에서 인자가 없는 생성자가 꼭 필요한 이유는 객체를 리플렉션 방식으로 만든다는데.. 이건 다음에 알아보기로

Access는 외부에서 접근가능한지의 여부를 다루고, final이 들어가있으므로 force 속성을 true로 지정하여 final로 선언된 변수들을 0이나 null 등으로 지정한다. (final로 선언된 변수는 반드시 초기화를 해야한다.)

 

Data 어노테이션과 NoArgsConstructor 관련해서도 한 문단을 차지했는데, 솔직히 무슨 말인지 전혀 모르겠다. 문장 구조가 좀 이상한 것 같기도하고 '그런 생성자'가 뭐지? 글 쓸 때 대명사의 가독성이 낮아지고 문장이 길어지더라도 대명사의 사용을 좀 자제하는 게 좋아보인다.


JPA 어노테이션에 대해서 몇 가지 소개된 것을 보자면..

@GeneratedValue

ID값, PK를 자동으로 형성해준다.

strategy를 인자로 받는데, AUTO와 IDENTITY SEQUENCE, TABLE 등이 있다. 다음 블로그 참고 https://devcamus.tistory.com/16

 

JPA 기본키 생성 전략, @GeneratedValue 사용시 주의점

JPA로 테이블과 엔티티를 매핑할 때, 식별자로 사용할 필드 위에 @Id 어노테이션을 붙여 테이블의 Primary Key와 연결 시켜줘야한다. 이 때, 컬럼 명을 따로 지정하지 않으면, 관례에 따라 매핑되는

devcamus.tistory.com

https://rutgo-letsgo.tistory.com/entry/Id-GeneratedValue%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90

 

@Id / @GeneratedValue에 대해 알아보자

@Id / @GeneratedValue에 대해 알아보자 PK를 나타내기 위해 @Id 어노테이션을 사용하며, 생성 전략을 정의하기 위해 @GeneratedValue 를 사용한다. 해당 어노테이션에 대해서 알아보도록 하자. @Id package javax

rutgo-letsgo.tistory.com

https://velog.io/@gudnr1451/GeneratedValue-%EC%A0%95%EB%A6%AC

 

@GeneratedValue 전략

직접 기본키를 생성하는 방법 @Id 어노테이션 만을 사용하여 기본키를 직접 할당해주는 방법이 있다. 기본키를 자동으로 생성하는 방법 4가지 > 기본키를 자동으로 생성할 때에는 @Id와 @GenerratedVa

velog.io

 

- IDENTITY

이전에 내가 하던 방법. DB가 자동으로 AUTO_INCREMENT를 한다. 1부터 하나씩 올라가는 형태

 

- SEQUENCE

DB의 시퀀스 오브젝트를 활용하여 자동으로 기본키를 만든다.

다음의 전제조건이 필요하다.

CREATE SEQUENCE member_sequence START WITH 1 INCREMENT BY 1;

1부터 1씩 증가하는 시퀀스를 만들어라

 @Entity
    @SequenceGenerator(
    	name = "USER_PK_GENERATOR",
        sequenceName = "USER_PK_SEQ",
        initailValue = 1,
        allocationSize = 50
        )
    public class PkEx() {
		
        	@Id
        	@GeneratedValue(strategy = GenerationType.SEQUENCE,
            			generator="USER_PK_GENERATOR")
        	private Long id;
        
        	private String name;
            
        }

@SequenceGenerator 어노테이션이 필수로 들어가야한다.

name은 generator에 들어갈 이름이다. 즉, 어떤 이름의 시퀀스를 참고해야할지 지정하는 과정에 필요한 이름

sequenceName은 실제 DB 내의 시퀀스 이름

allocationSize는 한 번에 몇 개의 ID값을 생성할지 정한다. 기본값은 50

 

- AUTO

어떤 전략을 취할지 DB에 위임한다.

mySQL은 IDENTITY, H2는 SEQUENCE 방식을 채택하는 등... DB의 종류마다 방식이 다르다.

TABLE도 있는데 낮은성능과 복잡성 때문에 잘 쓰이지는 않는단다.


@ManyToMany

다대다관계를 나타낼 때의 어노테이션. 이건 DB구조를 좀 배우고 들어가기로


@Table

테이블 이름을 지정한다. 원래는 JPA가 클래스 이름으로 테이블을 만들어서 DB에 생성할텐데, 만약 클래스명이 SQL 예약어일 경우에는 그 클래스의 이름을 테이블로 등록할 수 없으므로 테이블 이름을 직접 등록한다. 인자는 name = "테이블 이름"으로 받는다.


JPA의 막강한 기능 - save / findAll / findById

JDBC에서는 내가 직접 구현했지만, JPA 레포지토리에서 CrudRepository 인터페이스를 확장하면 save / findAll / findById 메서드가 자동으로 지원된다. 이것 뿐 아니라 CRUD 연산을 위한 메서드들이 선언되어 있다. 인자로는 <저장할 개체, 매개변수 타입> 으로 지정할 수 있다. 

 

(나는 인터페이스를 만들지는 않았지만) 여러 인터페이스에서 CrudRepository 인터페이스를 확장했다면, 그 모든 인터페이스마다 CrudRepository의 메서드를 선언해야할 수 있으나, 실제로는 그렇지 않다. JPA의 장점으로, 애플리케이션이 시작될 때 JPA가 인터페이스 구현체를 자동으로 생성해준다.

 

그냥 인터페이스만 컨트롤러나 서비스 등에 주입하기만 하면 된다. 그리고 JPA로 완전 이주(?)한다면 JDBC로 정의된 레포지토리는 삭제해야한다.


null을 막자 - Optional

백엔드 개발을 처음 배울 때 null이 나오지 않도록 하는게 중요하다고 했는데.. 확실히 어른들의 말 틀린 것 하나 없습니다.

Optional<객체명>을 활용하여 null이 나오지 않도록 할 수 있다. Optional은 일종의 래퍼 클래스로, null이 반환되어도 에러가 발생하지 않는다.

 

Optional에 관련해서는 다음 포스트 참고.. -> https://mangkyu.tistory.com/70

 

[Java] Optional이란? Optional 개념 및 사용법 - (1/2)

이번에는 Java8부터 지원하는 Optional 클래스에 대해 알아보도록 하겠습니다. 1. Optional이란? Optional 개념 및 사용법 [ NPE(NullPointerException) 이란? ] 개발을 할 때 가장 많이 발생하는 예외 중 하나가 바

mangkyu.tistory.com


내 입맛에 맛게 - JPA 레포지토리 커스터마이징

JDBC에서 findById를 구현한 다음, 이메일로도 DB에서 값을 읽어오고 싶다면 findByEmail 메서드를 만들어서 수정하고, 디버깅하고를 해야했다. 하지만 JPA에서는? 레포지토리를 만들 필요가 없다! 인터페이스만 요래요래 만지면 된다.

 

List<Member> findByEmail(String email);

인터페이스에 다음과 같이 선언하면 된다. 그럼 메서드 이름을 분석하여 어떤 값을 원하는지 안다.

테이블 명을 어떻게 아냐면, CrudRepository를 확장할 때 매개변수로 <개체명, 타입명>을 줄 때, 개체명으로 사용된 값이 레퍼런스 타입으로 들어가기 때문이다. 

 

이 JPA가 생각보다 똑똑해서

read, find, get 등이 개체를 읽는 것이고, 수를 찾기 위해서는 count를 메서드 이름에 넣으면 어떤 역할을 하는지 이해한다.

 

예시코드를 그대로 가져와봤다.

스프링인액션 3장 113쪽

 

 

List<Order> readOrderByDeliveryZipAndPlacedAtBetween(String deliveryZip, Date startDate, Date endDate);

이렇게 인터페이스에 선언되었다면,

read - 읽어라

Order - 개체

By - 일치 여부 확인에 사용될 속성 시작 선언 (이 뒤로부터 어떤 속성값을 찾을지 선언함)

DeliveryZip - .deliveryZip 또는 .delivery.zip 속성값에서의 일치값을 찾는다.

And - 그리고

PlacedAt - .placeAt / .placed.at 속성값에서 일치값을 찾는다.

Between - 지정된 값의 범위에 해당 값이 포함되어야한다.

 

이렇게...?

마지막으로 전달된 인자의 사이값이라는 것을 알리기 위해 Between이 사용되었다.

Equals, Between 등 이런 특징을 지닌 인자로 여러 개가 있는데,

 

- IsAfter, After, IsGreaterThan, GreaterThan

- IsGreaterThanEqual 등...

꽤 양이 많아서 스프링인액션 3장 113~114쪽을 참고하면서 읽으면 되겠다.

 

 

추가로 대소문자를 무시하기 위해서 AllIgnoringCase를 메서드 이름에 추가할 수 있다.


이것보다 훨씬 복잡해진다면 그냥 내가 원하는 메서드 이름을 지은 후 수행할 @Query 어노테이션을 사용하면 된다.

 

@Query("Member member where member.email = 'MRCH328@g.hongik.ac.kr'")
List<Order> findEmailWhoIsMRCH();

이런식으로


암튼 이렇게 며칠동안 빠졌던 DB의 늪에서 빠져나왔다...는 아니고 다시 내용정리가 필요하긴 하다. 4장으로 넘어갈 수는 있지만, 언제 한 번 3장을 다시 읽어보면 좋을듯하다.

 

암튼 JDBC와 JPA를 배웠고, 이제 한 번 활용해봐야하는데 활용은 다음에 합시다

홍대 맛집 아카이빙 프로젝트에서 직접 적용시켜보기로~ JPA가 JDBC에 비해 훨씬 쉬우니까 금방금방 적용시킬 수 있을 것이다.

 

개인프로젝트라고 하긴 좀 애매하지만... GDG 프로젝트 트랙이 끝나고 첫 번째로 진행할 예정인 CRUD16 프로젝트에서 JPA와 JDBC를 모두 적용시켜보기로 해보자

DB설계에 대해서도 배우고..

 

DB는 어렵지만, DB를 통해 내 프로그램이 더 발전한다.

'CS > 백엔드' 카테고리의 다른 글

[2025백엔드] 스프링인액션 독서 #7 - 4장. 스프링 시큐리티 2  (2) 2025.08.05
[2025백엔드] 스프링인액션 독서 #6 - 4장. 스프링 시큐리티 1  (4) 2025.08.04
[2025백엔드] 스프링인액션 독서 #4 - 3장.데이터로 작업하기 2  (2) 2025.08.01
[2025백엔드] 스프링인액션 독서 #3 - 3장.데이터로 작업하기 1  (3) 2025.07.29
[2025 백엔드] 스프링 인 액션 독서 #2 - 2장. 웹 애플리케이션 개발하기  (7) 2025.07.24
'CS/백엔드' 카테고리의 다른 글
  • [2025백엔드] 스프링인액션 독서 #7 - 4장. 스프링 시큐리티 2
  • [2025백엔드] 스프링인액션 독서 #6 - 4장. 스프링 시큐리티 1
  • [2025백엔드] 스프링인액션 독서 #4 - 3장.데이터로 작업하기 2
  • [2025백엔드] 스프링인액션 독서 #3 - 3장.데이터로 작업하기 1
Radiata
Radiata
개발을 합니다.
  • Radiata
    DDD
    Radiata
  • 전체
    오늘
    어제
    • 분류 전체보기 (211)
      • 신년사 (3)
        • 2025년 (2)
        • 2026년 (1)
      • CS (59)
        • JVM (12)
        • 백엔드 (20)
        • 언어구현 (1)
        • 객체지향 (1)
        • 논리회로 (5)
        • 컴퓨터구조 (9)
        • 데이터베이스 (1)
        • 컴퓨터 네트워크 (10)
      • 언어공부 (64)
        • Java | Kotlin (48)
        • JavaScript | TypeScript (9)
        • C | C++ (6)
      • 개인 프로젝트 (11)
        • [2025] Happy2SendingMails (3)
        • [2026] 골든리포트! (8)
        • [2026] 순수자바로 개발하기 (0)
        • 기타 이것저것 (0)
      • 팀 프로젝트 (29)
        • [2025][GDG]홍대 맛집 아카이빙 프로젝트 (29)
      • 알고리즘 (13)
        • 백준풀이기록 (11)
      • 놀이터 (0)
      • 에러 수정일지 (2)
      • 고찰 (24)
        • CEOS 23기 회고록 (2)
  • 블로그 메뉴

    • CS
    • 언어공부
    • 개인 프로젝트
    • 팀 프로젝트
    • 알고리즘
    • 고찰
    • 신년사
    • 컬러잇 개발블로그
  • 링크

    • 컬러잇 개발블로그
  • 공지사항

  • 인기 글

  • 태그

    144
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
Radiata
[2025백엔드] 스프링인액션 독서 #5 - 3장. 데이터로 작업하기 #3
상단으로

티스토리툴바