Discover us

About us

Projects

Blog

Events

Members

Development Blog

GDGoC CAU 개발자와 디자이너의 작업 과정과
결과물을 공유하는 공간입니다.

어떻게 프로젝트를 시작하게 되었고,
진행하면서 느낀 개발자와 디자이너의
생생한 스토리를 직접 확인해보세요!

Development

Springboot와 JPA 개요

  • #Back-End
  • Seungwoon Chae
  • 2023. 11. 6.

Springboot와 JPA 개요

계층 돌아보기

notion image
  • Domain Model: 도메인 데이터와 비즈니스 로직을 포함
    • 도메인: 객체의 속성들이 가질 수 있는 값들의 집합
    • 비즈니스 로직이란?
      • 프로그램에서 규칙에 따라 데이터를 생성·표시·저장·변경하는 부분
  • Repository: DB와 상호 작용하여 Domain model 객체를 메모리에 띄운다.
  • Dto: Client - Controller - Service 사이의 약속된 데이터 교환 형식
  • Service: 외부에서 요청하는 비즈니스 로직을 처리하고 도메인 모델 객체 간의 상호 작용을 통제
  • Controller: HTTP 요청을 받아와 Service 계층에 전달하고 응답을 처리

백엔드는 뭘 하는가?

notion image
  • 클라이언트(유저)의 요청이 Web Server를 통해 인터넷 상에 전송되어, 목적지인 백엔드에 도착
  • 어떤 요청인데요? (예시: 인스타그램)
    • 회원가입?
      • 보낸 회원가입 폼이 유효한가?
    • 로그인?
      • 유저의 로그인 요청이 정상적인가?
    • 게시글 업로드(저장)?
      • 누가 어떤 게시물을 언제 업로드하는가?
    • 게시글 수정?
      • 어떤 게시글을 수정하지?
      • 수정을 요청하는 사람이 작성자가 맞는가?
    • 게시글 삭제?
      • 어떤 게시글을 삭제하지?
      • 삭제를 요청하는 사람이 작성자가 맞는가?
    • 댓글?
    • 좋아요?
  • 다시 클라이언트는 요청을 처리한 백엔드의 응답을 받아 관련된 사안을 처리
  • 백엔드는 클라이언트의 요청을 받아 유효성 검사 등을 거친 뒤 요청을 처리하고 적절한 형식의 응답을 전송

퀴즈: 색깔에 관련된 계층 및 객체 맞히기

  • 클라이언트의 요청을 받아
    • Controller, RequestDto
  • 유효성 검사 등을 거친 뒤
    • Service, RequestDto, Repository
  • 요청을 처리하고
    • Service, Repository, Domain
  • 적절한 형식의
    • ResponseDto, Domain
  • 응답을 전송
    • ResponseDto, Controller

ORM이란?

  • Object-Relational Mapping (객체-관계 매핑)
  • Java 객체와 RDB 테이블을 서로 매핑해주는 일종의 중재자
  • 다른 진영에도 ORM은 존재(JavaScript 등)

JDBC란?

  • Java Database Connectivity
  • Java 기반 애플리케이션의 데이터를 DB에 저장 및 수정하거나, 저장된 데이터를 Java에서 사용할 수 있도록 하는 자바 API
  • Java 애플리케이션에서 데이터베이스에 접근하기 위해 JDBC API를 사용하여 데이터베이스에 연동
  • 애플리케이션 쪽에서 DB에 존재하는 데이터에 쿼리를 가할 수 있음

JPA란?

  • Java Persistence API
  • Java 진영의 ORM 기술 표준
  • 인터페이스이며, 따라서 실제 구현체가 아니다.
  • JPA 인터페이스를 구현한 대표적인 오픈소스가 Hibernate
notion image
  • 개발자가 애플리케이션에서 JPA API를 호출하면, 해당하는 구현체(Hibernate 등) 내부에서 JDBC API를 호출하여 DB에 소통한다.
  • 예) 찾고 싶은 User 객체의 id(Long)를 서버에서 전송하여 특정 User의 정보를 조회하는 경우
    • 객체(Entity)의 정보를 바탕으로 JPA API를 호출
    • 내부에서 JDBC API가 호출되어 쿼리를 DB에 날림
    • DB가 쿼리 결과 데이터를 JDBC API에 응답으로 전달
    • 받은 결과 데이터를 JPA가 객체에 매핑하여 User 객체를 Java 애플리케이션에 띄운다.
    • userRepository.findById(Long userId);

JPA 왜 쓰나요?

  1. 직접적인 SQL 쿼리 작성을 피하고 “객체” 중심으로 복잡한 문제를 풀어나갈 수 있다.
  • 어떤 앱이든 기초적이면서도 핵심적인 기능을 공통적으로 갖고 있기 때문
  • 특정 테이블의 정보 조회 → select * from ?? where ….
    • 반복되는 단조로운 쿼리 작성→ 개발자 자체의 휴먼 에러 발생 가능
    • 그냥 repository.findBy로 한줄로 찾는게 정신건강에 이롭다.
  • 다만 쿼리를 아예 작성할 필요가 없는 것은 아니다.
 
  1. RDB와 객체 간의 괴리감을 ORM의 중재로 극복
  • Java의 객체 상속 개념과 RDB 테이블의 SuperType/SubType은 상당한 괴리가 존재
  • JPA의 테이블 간 관계 매핑 기능을 활용하여, 개발자는 객체간의 관계에만 초점을 맞출 수 있음
  • 개발자가 Java 클래스 상에 추가하는 객체 사이의 크고 작은 관계들을 JPA가 유효성 검사 후 테이블에 이행
 
  1. JPA 자체에서 제공하는 수많은 편의 기능들
  • 어노테이션을 기반으로 한 깔끔하고 직관적인 관계 설정
    • mySQL에서 show columns from tables;
  • 지연로딩(LAZY) 및 Cascade, orphanRemoval 등 디테일한 객체 및 테이블 상태 관리
 
  1. 그 외
      • SQL Injection 등의 외부 공격을 ORM 레벨에서 기초적으로 방어 가능
      • 그냥 모두가 하니까?

Springboot에서 mySQL 데이터베이스 연동

  • MacOS 기준
    • mySQL 설치 (brew install mysql)
    • mysql -u root -p 명령어 실행
    • 비밀번호 입력 란 등장, 최초로 설치한 경우 비밀번호가 없기에 바로 Enter
      • 만약 이미 mySQL이 있고 인증 계정과 비밀번호를 등록해놓은 경우 입력해야 함
    • create database “이름”; 으로 데이터베이스 생성

application.properties

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect // Hibernate 설정 spring.jpa.show-sql=true // 서버에서 발생하는 쿼리를 로그에 드러낸다. spring.jpa.properties.hibernate.format_sql=true // 나타날 쿼리를 일정한 형식으로 출력 spring.datasource.url=jdbc:mysql://localhost:3306/[만든 DB명]?useSSL=false&serverTimezone=UTC spring.datasource.username=[이름] -> 최초 실행해서 계정이 없는 경우 root spring.datasource.password=[비번] -> 최초 실행해서 계정이 없는 경우 생략 spring.jpa.hibernate.ddl-auto=create // JPA로 DB 접근 시 테이블을 다 깨뜨리고 처음부터 다시 생성
 
편집 테스트 한 번 해볼게요.. 이거 보이시나요? 보이시면 당근을 흔들어주세요.

build.gradle

implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-jdbc' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok'
 
  • User 객체를 domain 패키지에 추가하고 빌드하여 DB에 생성 (구체적인 내용은 추후 다룰 예정)
@Entity public class User { @Id @Column(name = "user_id") private Long id; private String name; // 닉네임 private int height; // 키 private int weight; // 몸무게 private int gender; // 성별 (0, 1) private int age; public User(String name, int height, int weight, int gender, int age) { this.name = name; this.height = height; this.weight = weight; this.gender = gender; this.age = age; } }
 

계층 돌아보기

notion image
  • Domain Model: 도메인 데이터와 비즈니스 로직을 포함
    • 도메인: 객체의 속성들이 가질 수 있는 값들의 집합
    • 비즈니스 로직이란?
      • 프로그램에서 규칙에 따라 데이터를 생성·표시·저장·변경하는 부분
  • Repository: DB와 상호 작용하여 Domain model 객체를 메모리에 띄운다.
  • Dto: Client - Controller - Service 사이의 약속된 데이터 교환 형식
  • Service: 외부에서 요청하는 비즈니스 로직을 처리하고 도메인 모델 객체 간의 상호 작용을 통제
  • Controller: HTTP 요청을 받아와 Service 계층에 전달하고 응답을 처리

백엔드는 뭘 하는가?

notion image
  • 클라이언트(유저)의 요청이 Web Server를 통해 인터넷 상에 전송되어, 목적지인 백엔드에 도착
  • 어떤 요청인데요? (예시: 인스타그램)
    • 회원가입?
      • 보낸 회원가입 폼이 유효한가?
    • 로그인?
      • 유저의 로그인 요청이 정상적인가?
    • 게시글 업로드(저장)?
      • 누가 어떤 게시물을 언제 업로드하는가?
    • 게시글 수정?
      • 어떤 게시글을 수정하지?
      • 수정을 요청하는 사람이 작성자가 맞는가?
    • 게시글 삭제?
      • 어떤 게시글을 삭제하지?
      • 삭제를 요청하는 사람이 작성자가 맞는가?
    • 댓글?
    • 좋아요?
  • 다시 클라이언트는 요청을 처리한 백엔드의 응답을 받아 관련된 사안을 처리
  • 백엔드는 클라이언트의 요청을 받아 유효성 검사 등을 거친 뒤 요청을 처리하고 적절한 형식의 응답을 전송

퀴즈: 색깔에 관련된 계층 및 객체 맞히기

  • 클라이언트의 요청을 받아
    • controller, requestdto
  • 유효성 검사 등을 거친 뒤
    • service, dto, repository
  • 요청을 처리하고
    • Service,
  • 적절한 형식의
    • responsedto
  • 응답을 전송
    • dto,

ORM이란?

  • Object-Relational Mapping (객체-관계 매핑)
  • Java 객체와 RDB 테이블을 서로 매핑해주는 일종의 중재자
  • 다른 진영에도 ORM은 존재(JavaScript 등)

JDBC란?

  • Java Database Connectivity
  • Java 기반 애플리케이션의 데이터를 DB에 저장 및 수정하거나, 저장된 데이터를 Java에서 사용할 수 있도록 하는 자바 API
  • Java 애플리케이션에서 데이터베이스에 접근하기 위해 JDBC API를 사용하여 데이터베이스에 연동
  • 애플리케이션 쪽에서 DB에 존재하는 데이터에 쿼리를 가할 수 있음

JPA란?

  • Java Persistence API
  • Java 진영의 ORM 기술 표준
  • 인터페이스이며, 따라서 실제 구현체가 아니다.
  • JPA 인터페이스를 구현한 대표적인 오픈소스가 Hibernate
notion image
  • 개발자가 애플리케이션에서 JPA API를 호출하면, 해당하는 구현체(Hibernate 등) 내부에서 JDBC API를 호출하여 DB에 소통한다.
  • 예) 찾고 싶은 User 객체의 id(Long)를 서버에서 전송하여 특정 User의 정보를 조회하는 경우
    • 객체(Entity)의 정보를 바탕으로 JPA API를 호출
    • 내부에서 JDBC API가 호출되어 쿼리를 DB에 날림
    • DB가 쿼리 결과 데이터를 JDBC API에 응답으로 전달
    • 받은 결과 데이터를 JPA가 객체에 매핑하여 User 객체를 Java 애플리케이션에 띄운다.
    • userRepository.findById(Long userId);

JPA 왜 쓰나요?

  1. 직접적인 SQL 쿼리 작성을 피하고 “객체” 중심으로 복잡한 문제를 풀어나갈 수 있다.
  • 어떤 앱이든 기초적이면서도 핵심적인 기능을 공통적으로 갖고 있기 때문
  • 특정 테이블의 정보 조회 → select * from ?? where ….
    • 반복되는 단조로운 쿼리 작성→ 개발자 자체의 휴먼 에러 발생 회치
    • 그냥 repository.findBy로 한줄로 찾는게 정신건강에 이롭다.
  • 다만 쿼리를 아예 작성할 필요가 없는 것은 아니다.
 
  1. RDB와 객체 간의 괴리감을 ORM의 중재로 극복
  • Java의 객체 상속 개념과 RDB 테이블의 SuperType/SubType은 상당한 괴리가 존재
  • JPA의 테이블 간 관계 매핑 기능을 활용하여, 개발자는 객체간의 관계에만 초점을 맞출 수 있음
  • 개발자가 Java 클래스 상에 추가하는 객체 사이의 크고 작은 관계들을 JPA가 유효성 검사 후 테이블에 이행
 
  1. JPA 자체에서 제공하는 수많은 편의 기능들
  • 어노테이션을 기반으로 한 깔끔하고 직관적인 관계 설정
    • mySQL에서 show columns from tables;
  • 지연로딩(LAZY) 및 Cascade, orphanRemoval 등 디테일한 객체 및 테이블 상태 관리
 
  1. 그 외
      • SQL Injection 등의 외부 공격을 ORM 레벨에서 기초적으로 방어 가능
      • 그냥 모두가 하니까?

Springboot에서 mySQL 데이터베이스 연동

  • MacOS 기준
    • mySQL 설치 (brew install mysql)
    • mysql -u root -p 명령어 실행
    • 비밀번호 입력 란 등장, 최초로 설치한 경우 비밀번호가 없기에 바로 Enter
      • 만약 이미 mySQL이 있고 인증 계정과 비밀번호를 등록해놓은 경우 입력해야 함
    • create database “이름”; 으로 데이터베이스 생성

application.properties

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect // Hibernate 설정 spring.jpa.show-sql=true // 서버에서 발생하는 쿼리를 로그에 드러낸다. spring.jpa.properties.hibernate.format_sql=true // 나타날 쿼리를 일정한 형식으로 출력 spring.datasource.url=jdbc:mysql://localhost:3306/[만든 DB명]?useSSL=false&serverTimezone=UTC spring.datasource.username=[이름] -> 최초 실행해서 계정이 없는 경우 root spring.datasource.password=[비번] -> 최초 실행해서 계정이 없는 경우 생략 spring.jpa.hibernate.ddl-auto=create // JPA로 DB 접근 시 테이블을 다 깨뜨리고 처음부터 다시 생성

build.gradle

implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-jdbc' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok'
 
  • User 객체를 domain 패키지에 추가하고 빌드하여 DB에 생성 (구체적인 내용은 추후 다룰 예정)
@Entity public class User { @Id @Column(name = "user_id") private Long id; private String name; // 닉네임 private int height; // 키 private int weight; // 몸무게 private int gender; // 성별 (0, 1) private int age; public User(String name, int height, int weight, int gender, int age) { this.name = name; this.height = height; this.weight = weight; this.gender = gender; this.age = age; } }