오공완
스프링 부트3 시작하기
konjee
2024. 2. 5. 19:15
자바 백엔드 환경의 핵심은 스프링 부트!
JPA: 자바에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스
포스트맨: HTTP 요청을 보낼 수 있는 클라이언트 프로그램
[서버와 클라이언트]
- 클라이언트
- 서버로 요청하는 프로그램
- ex) 웹 브라우저에서 주소를 입력한 뒤 enter을 눌러 정보를 요청하는 행위 → ‘서버에 요청한다’
- 서버
- 클라이언트의 요청을 받아 처리하는 주체
[데이터베이스]
- 데이터베이스
- 데이터베이스 관리 시스템: MySQL, 오라클, 포스트그레SQL 등
- 클라이언트에서 SQL(데이터베이스 조작 언어)로 데이터베이스 관리 시스템에 데이처 요청하면 데이터베이스 관리 시스템은 데이터베이스에서 데이터를 꺼내 응답
- RDB: Relational Database
- 관계형 데이터베이스
- 데이터를 행과 열로 이루어진 테이블로 관리하며 기본키를 사용해 각 행을 식별
- 각 테이블 간에 관계를 지을 수 있음
- 오라클, 마이에스큐엘, SQL 서버, 포스트그레큐엘 등
- SQL: Structured Query Language
- 쿼리, 즉 데이터 검색을 하는 언어
- NoSQL
- SQL을 쓰지 않음 or Not Only SQL
- RDB의 성능을 올리기 쉽지 않은 문제들을 해결하기 위해 등장
- 다이나모디비, 카우치베이스, 몽고디비 등
[아이피와 포트]
- 아이피: 서버를 찾기 위한 번호
- 포트: 그 서버에서 운용되고 있는 서비스를 구분하기 위한 번호
[라이브러리와 프레임워크]
- 라이브러리
- 애플리케이션 개발에 필요한 기능인 클래스, 함수 등을 모아놓은 코드의 모음
- 개발을 하는 과정에서 필요한 기능을 구현하기 위해 사용
- 라이브러리는 독립적으로 라이브러리끼리 영향을 크게 주지 않음
- 프레임워크
- 소프트웨어 개발을 수월하게 하기 위한 소프트웨어 개발 환경
- 일(work)하기 위한 틀(frame)을 제공
- 애플리케이션을 개발할 때 전체적인 구조를 잡기 위해 사용하는 것
[스프링 부트]
- 스프링과 스프링 부트
- 스프링의 단점을 보완하여 출시됨
- 스프링 프레임워크를 더 쉽고 빠르게 이용할 수 있도록 만들어주는 도구
- 스프링 부트는 스프링에 속한 도구
- 스프링 부트의 주요 특징
- 톰캣, 제티, 언더토우 같은 웹 애플리케이션 서버(WAS)가 내장되어 있어서 따로 설치를 하지 않아도 독립적으로 실행할 수 있음
- 빌드 구성을 단순화하는 스프링 부트 스타터를 제공
- XML 설정을 하지 않고 자바 코드로 모두 작성할 수 있음
- JAR를 이용해서 자바 옵션만으로도 배포가 가능
- 애플리케이션의 모니터링 및 관리 도구인 스프링 액츄에이터(spring actuator)를 제공
- 스프링과 스프링 부트의 차이
- 구성의 차이: 스프링은 개발에 필요한 환경을 수동 구성, 스프링 부트는 자동으로 로드
- 내장WAS의 유무: 스프링 부트는 jar 파일만 만들면 별도로 WAS를 설정하지 않아도 애플리케이션 실행 가능
[스프링의 주요 콘셉트]
- 제어의 역전성과 의존성 주입
1-1. IoC (Inversion of Control): 제어의 역전
- 다른 객체를 직접 생성하거나 제어하는 것이 아니라 외부에서 관리하는 객체를 가져와 사용하는 것
- 스프링 컨테이너가 객체를 관리, 제공하는 역할을 함
1-2. DI (Dependency Injection): 의존성 주입
- 어떤 클래스가 다른 클래스에 의존한다는 뜻
- 클래스 A에서 B 객체를 쓰고 싶은 경우 객체를 직접 생성하는 것이 아니라 스프링 컨테이너에서 객체를 주입받아 사용
[빈과 스프링 컨테이너]
- 스프링 컨테이너
- 빈을 생성하고 관리
- @Autowired: 스프링 컨테이너에 있는 빈을 주입
- 빈
- 스프링 컨테이너가 생성하고 관리하는 객체
[관점 지향 프로그래밍]
- AOP, Aspect Oriented Programming
- 프로그래밍에 대한 관심을 핵심 관점, 부가 관점으로 나누어서 관심 기준으로 모듈화하는 것
[이식 가능한 서비스 추상화]
- PSA, Portable Service Abstraction
- 스프링에서 제공하는 다양한 기술들을 추상화해 개발자가 쉽게 사용하는 인터페이스
!! 스프링 프레임워크는 IoC/DC를 통해 객체간의 의존 관계를 설정, AOP를 통해 핵심 관점과 부가 로직을 분리해 개발, PSA를 통해 추상화된 다양한 서비스들을 일관된 방식으로 사용하도록 함
- IoC: 객체의 생성과 관리를 개발자가 하는 것이 아니라 프레임워크가 대신하는 것
- DI: 외부에서 객체를 주입받아 사용하는 것
- AOP: 프로그래밍을 할 떄 핵심 관점과 부가 관점을 나누어서 개발하는 것
- PSA: 어느 기술을 사용하던 일관된 방식으로 처리하도록 하는 것
[스프링 부트 3 프로젝트 만들기]
Gradle 프로젝트를 스프링 부트 3 프로젝트로 바꾸는 방법: build.gradle 수정
- localhost는 아이피로는 127.0.0.1: 컴퓨터에서 사용하는 루프백 호스트명, 현재 사용중인 컴퓨터 의미
- 8080: 스프링 부트의 포트 번호
- test: 코드에 @GetMapping이라는 애너테이션으로 메서드와 매핑할 때 스프링 부트에서 설정한 경로
[스프링 부트 스타터]
- 의존성이 모여 있는 그룹
- 명명규칙: spring-boot-starter-{작업유형}
[자동 구성]
- 스프링 부트에서는 애플리케이션이 최소한의 설정만으로도 실행되게 여러 부분을 자동으로 구성
[스프링 부트 3 코드 이해하기]
- @SpringBootApplication
@SpringBootApplication
public class SpringBootDeveloperApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootDeveloperApplication.class, args);
}
}
- 스프링 부트 사용에 필요한 기본 설정
- @SpringBootConfiguration: 스프링 부트 관련 설정을 나타냄
- @ComponentScan: 사용자가 등록한 빈을 읽고 등록, @Component라는 애너테이션을 가진 클래스들을 찾아 빈으로 등록
- @EnableAutoConfiguration: 스프링 부트에서 자동 구성을 활성화, 서버가 실행될 때 스프링 부트의 메타 파일을 읽고 정의된 설정들을 자동으로 구성
- 테스트 컨트롤러 살펴보기
@RestController
public class TestController {
@GetMapping("/test")
public String test() {
return "Hello, world!";
}
}
- @RestController: 라우터 역할, HTTP 요청과 메서드를 연결, 클라이언트의 요청에 맞는 메서드를 실행
- TestController를 라우터로 지정해 /test라는 GET 요청이 왔을 때 test() 메서드를 실행하도록 구성
- @Compponent 애너테이션이 있는 클래스는 빈으로 등록되며, @Controller, @RestController, @Configuration, @Repository, @Service 모두 @Component 애터네이션을 가지고 있음
[스프링 부트 3 구조 살펴보기]
- 계층
- 프리젠테이션 계층: HTTP 요청을 받고 이 요청을 비즈니스 계층으로 전송하는 역할, 컨트롤러
- 비즈니스 계층: 모든 비즈니스 로직을 처리, 서비스
- 퍼시스턴스 계층: 모든 데이터베이스 관련 로직을 처리,리포지토리
[테스트 코드]
- given-when-then 패턴
- given: 테스트 실행 준비단계
- when: 테스트 진행 단계
- then: 테스트 결과 검증 단계
- JUnit
- 자바 언어를 위한 단위 테스트 프레임워크
- 테스트 방식을 구분할 수 있는 애너테이션을 제공
- @Test 애너테이션으로 메서드를 호출할 때마다 새 인스턴스를 생성, 독립 테스트 가능
- 예상 결과를 검증하는 어설션 메서드 제공
- 사용 방법이 단순, 테스트 코드 작성 시간이 적음
- 자동 실행, 자체 결과를 확인하고 즉각적인 피드백을 제공
import org.aspectj.lang.annotation.After;
import org.junit.jupiter.api.*;
public class JUnitCycleTest {
@BeforeAll // 전체 테스트를 시작하기 전에 1회 실행하므로 메서드는 static으로 선언
static void beforeAll() {
System.out.println("@BeforeAll");
}
@BeforeEach // 테스트 케이스를 시작하기 전마다 실행
public void beforeEach() {
System.out.println("@BeforeEach");
}
@Test
public void test1() {
System.out.println("test1");
}
@Test
public void test2() {
System.out.println("test2");
}
@Test
public void test3() {
System.out.println("test3");
}
@AfterAll // 전체 테스트를 마치고 종료하기 전에 1회 실행하므로 메서드는 static으로 선언
static void afterAll() {
System.out.println("@AfterAll");
}
@AfterEach // 테스트 케이스를 종료하기 전마다 실행
public void afterEach() {
System.out.println("@AfterEach");
}
}
[데이터베이스]
- 데이터베이스 관리자
- DBMS, database management system
- 관계형 DBMS = RDBMS(relational): 테이블 형태로 이루어진 데이터 저장소
- 데이터베이스 용어
- 테이블: 데이터를 구성하기 위한 가장 기본적인 단위
- 행 row: 가로로 배열된 데이터의 집합, 고유한 식별자인 기본키를 가짐, 레코드 record라고 부르기도 함
- 열 column: 행에 저장되는 유형에 데이터
- 기본키 primary key: 행을 구분할 수 있는 식별자, 테이블에서 유일해야 하며 중복값을 가질 수 없음, 수정되어서는 안 되며 유효한 값이어야 함(NULL이 될 수 없음)
- 쿼리 query: 데이터를 조회하거나 삭제, 생성, 수정 같은 처리를 하기 위해 사용하는 멸여문
[ORM, object-relational mapping]
- ORM
- 자바의 객체와 데이터베이스를 연결하는 프로그래밍 기법
- 장점: SQL을 직접 작성하지 않아도 됨
- 단점: 프로젝트 복잡성이 커질수록 사용 난이도 올라감, 복잡하고 무거운 쿼리는 해결 불가능한 경우도 있음
- JPA (java persistence API)
- 자바에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스
- 인터페이스이므로 실제 사용을 위해서는 ORM 프레임워크를 추가로 선택해야함
- 하이버네이트: JPA 인터페이스를 구현한 구현체, 자바용 ORM 프레임워크, 내부적으로는 JDBC API 사용
[엔티티]
- 엔티티
- 데이터베이스의 테이블과 매핑되는 객체
- 본질적으로는 자바 객체이나 테이블과 직접 연결된단든 특징이 있어 구분지어 부름
- 데이터베이스에 영향을 미치는 쿼리를 실행하는 객체
- 엔티티 매니저
- 엔티티를 관리해 데이터베이스와 애플리케이션 사이에서 객체를 생성, 수정, 삭제하는 등의 역할
- 엔티티 팩토리: 엔티티 매니저를 만드는 곳, @PersistenceContext 또는 @Autowired 사용
- 영속성 컨텍스트
- JPA의 중요한 특징 중 하나로, 엔티티를 관리하는 가상의 공간
- 1차 캐시, 쓰기 지연, 변경 감지, 지연 로딩
- 엔티티의 상태
- 분리 detached: 영속성 컨텍스트가 관리하고 있지 않는 상태
- 관리 managed: 영속성 컨텍스트가 관리하는 상태
- 비영속 transient: 영속성 컨텍스트와 전혀 관계가 없는 상태
- 삭제 removed: 삭제된 상태
[스프링 데이터와 스프링 데이터 JPA]
- 스프링 데이터 JPA
- 리포지터리 역할을 하는 인터페이스를 만들어 데이터베이스의 테이블 조회, 수정, 생성, 삭제 같은 작업을 간단히 할 수 있음
public interface MemberRepository extends JpaRepository<Member, Long>{
} // 기존 CRUD 메서드를 사용하기 위한 JpaRepository 상속 예
- 리포지토리: 엔티티에 있는 데이터들을 조회하거나 저장, 변경, 삭제를 할 때 사용하는 인터페이스
- JpaRepository 클래스를 상속받을 때, 엔티티 Member와 엔티티 기본키 타입 Long을 인수로 넣어