이 블로그는 스프링입문 - 코드로 배우는 스프링 부트를 기반으로 쓰여졌습니다.
스프링 빈과 의존관계
스프링 빈(Bean)
스프링 컨테이너가 관리하는 자바 객체를 뜻하며, 하나 이상의 빈(Bean)을 관리한다.
의존성을 만들기 위하여 사용한다고 한다.
객체가 의존관계를 등록할 때 스프링 컨테이너에서 해당하는 빈을 찾고, 그 빈과 의존성을 만든다.
스프링 빈의 등록방법은 2가지 정도가 있다.
- 컴포넌트 스캔과 자동 의존관계 설정
- 자바 코드로 직접 스프링 빈 등록하기
++ 빈(Bean)은 스프링 컨테이너에 의해 관리되는 재사용 가능한 소프트웨어 컴포넌트이다.
스캔 범위는 application 시작 내에 패키지에 있는 것을 기본으로 스캔 하며 추가등록이 가능하다.
package hello.hello_spring;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HelloSpringApplication {
public static void main(String[] args) {
SpringApplication.run(HelloSpringApplication.class, args);
}
}
!! 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본으로 싱글 톤으로 등록한다.
직접 스프링 빈 등록하기
자동으로 할 수도 있지만 직접하는 방법도 알아 두어야 한다.
SpringConfig
package hello.hello_spring.service;
import hello.hello_spring.repository.MemberRepository;
import hello.hello_spring.repository.MemoryMemberRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringConfig {
@Bean
public MemberService memberService() {
return new MemberService((MemoryMemberRepository) memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
}
의존성 주입
DI는 객체 간의 관계를 외부에서 설정하는 디자인 패턴으로, 클래스 간의 강한 결합을 피하고 런타임 시 유연한 객체 관계를 가능하게 한다. 예를 들어, Store가 Pencil에 의존할 때, DI를 통해 Pencil 대신 다른 상품을 주입할 수 있다.
장점
- 결합도 감소: 클래스 간의 강한 결합을 제거하여, 코드 변경 시 유연성을 확보할 수 있다.
- 관심사 분리: 객체 간의 관계를 클래스가 아닌 인터페이스를 통해 설정함으로써, 객체의 구체 클래스에 대한 의존성을 줄인다.
- 테스트 용이성: DI를 통해 모의 객체(mock objects)를 주입할 수 있어 테스트가 용이해진다.
회원 관리 예제
홈 화면 추가
기존에 실행하면 static 파일에서 index.html을 읽어 왔지만 controller가 존재하고 매핑 되어 있으므로 우선 순위에 따라
controller 안에 있는 home.html을 반환한다.
화면이 뭔가 심심하니 GPT에게 꾸며달라고 하자.
심플하게 잘 된거같다.
문제 발생
addAttribute가 알 수 없는 이유로 동작하지 않는다.
import 문을 확인하라는 글을 확인해 보아도 Model은 이미 존재한다.
import ch.qos.logback.core.model.Model;
위 모델의 import를 아래로 바꾸었더니 해결되었다.
이유를 찾아보자.
import org.springframework.ui.Model;
같은 모델을 다루나 각각 로그와 뷰로 사용처가 다르다.
무언가 이유없이 되지 않는 것 같다면 잘못된 패키지를 가져오진 않았는지 확인해야겠다.
스프링 DB 접근 기술
H2 데이터베이스 설치
[ https://www.h2database.com ]
윈도우는 권한을 설정해줄 필요는 없지만 파일이 어디 가버린건지는 찾아야한다.
그냥 cmd 아무데서나 열고 치면 빨간글씨가 날 반겨준다.
Program Files(x86) > H2 > bin 순서로 들어가서 터미널을 열어야 수행할 수 있다.
H2의 설정화면
테이블 생성
create table member
(
id bigint generated by default as identity,
name varchar(255),
primary key (id)
);
값 넣기
insert into member(name) values('감자')
순수 JDBC vs JDBC 템플릿
JDBC는 자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API이다. - jdbc, jdbcTemplate 차이
아래 그림과 같은 구조로 자바에서 api를 호출하면 드라이버가 받아 db에 접근한다.
JDBC 템플릿?
강의 자료에서는 템플릿이 JDBC API의 반복 코드를 대부분 제거해준다고 한다. 그럼 어느정도 줄어드는지 살펴보자.
순수
@Override
public Optional<Member> findById(Long id) {
String sql = "select * from member where id = ?";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setLong(1, id);
rs = pstmt.executeQuery();
if (rs.next()) {
Member member = new Member();
member.setId(rs.getLong("id"));
member.setName(rs.getString("name"));
return Optional.of(member);
} else {
return Optional.empty();
}
} catch (Exception e) {
throw new IllegalStateException(e);
} finally {
close(conn, pstmt, rs);
}
}
template
@Override
public Optional<Member> findById(Long id) {
List<Member> result = jdbcTemplate.query("select * from members where id = ?", memberRowMapper(), id); // ID 매개변수 추가
return result.stream().findAny();
}
생각보다도 더 많이 줄어드는 모습이다.
template은 실무에서도 쓰인다고 하니 좀 더 깊이 공부할 필요가 있겠다.
GPT 에게 물어본 각각의 장단점
순수 JDBC
장점:
- 세밀한 제어:
- SQL 쿼리를 직접 작성하므로 성능 최적화 및 세밀한 조정이 가능합니다. 데이터베이스의 기능을 최대한 활용할 수 있습니다.
- 자유로운 SQL 사용:
- 복잡한 쿼리나 특정 데이터베이스의 기능을 사용할 때, 더 유연하게 접근할 수 있습니다. SQL 문장을 원하는 대로 작성할 수 있습니다.
- Dependency Free:
- JDBC API는 Java 표준이므로, 추가적인 라이브러리나 프레임워크에 대한 의존성이 없습니다.
단점:
- Boilerplate Code:
- 많은 반복적인 코드가 필요합니다. 데이터베이스 연결, 쿼리 실행, 결과 처리, 자원 해제를 위한 코드가 모두 수동으로 작성되어야 합니다.
- 자원 관리:
- Connection, PreparedStatement, ResultSet 등을 수동으로 닫아야 하므로 자원 누수의 위험이 있습니다. 예외가 발생하면 자원 해제가 제대로 이루어지지 않을 수 있습니다.
- 예외 처리:
- 예외 처리를 직접 구현해야 하며, 다양한 예외 유형을 다루어야 하므로 복잡성이 증가합니다.
템플릿 (예: Spring JdbcTemplate)
장점:
- 코드 간결성:
- JDBC를 사용할 때 필요한 반복적인 코드가 줄어들고, 더 간결하고 읽기 쉬운 코드가 작성됩니다. 템플릿 메서드 패턴을 사용하여 일반적인 패턴을 재사용할 수 있습니다.
- 자동 자원 관리:
- 자원(커넥션, 스테이트먼트, 결과 집합 등)을 자동으로 관리하므로, 자원 누수의 위험이 줄어듭니다. 개발자는 자원 해제에 대해 걱정할 필요가 없습니다.
- 유연한 예외 처리:
- Spring의 예외 변환 기능을 통해 JDBC 예외를 런타임 예외로 변환하여 일관된 예외 처리를 제공합니다. 이를 통해 오류 처리가 간편해집니다.
- 객체 매핑:
- RowMapper 인터페이스를 사용하여 SQL 결과를 객체로 쉽게 매핑할 수 있습니다. 데이터베이스와 객체 간의 변환을 쉽게 처리할 수 있습니다.
단점:
- 추상화에 따른 제어 감소:
- SQL 쿼리의 세밀한 조정이 필요할 때, 템플릿을 사용하는 것은 제한적일 수 있습니다. 복잡한 쿼리나 성능 최적화 시 제어가 어려울 수 있습니다.
- 프레임워크 의존성:
- Spring이나 다른 템플릿 라이브러리에 대한 의존성이 생기므로, 해당 프레임워크에 맞춰 학습해야 할 필요가 있습니다.
- 추가 학습 필요:
- 템플릿을 사용하는 방법에 대한 학습이 필요합니다. 특히 Spring의 다양한 기능과 설정을 이해해야 합니다.
결론
- 순수 JDBC는 세밀한 제어가 필요하거나 데이터베이스의 특정 기능을 활용해야 하는 경우에 적합합니다. 그러나 반복적인 코드 작성과 자원 관리의 복잡성을 감수해야 합니다.
- **템플릿 (Spring JdbcTemplate 등)**은 코드의 가독성과 유지 보수성을 향상시키며, 자원 관리를 자동화하여 개발자의 부담을 줄입니다. 복잡한 쿼리 작업이 필요할 경우 제약이 있을 수 있지만, 일반적인 CRUD 작업에서는 매우 유용합니다.
테스트
이전에도 테스트를 진행했지만 테스트는 일관성있는 상태를 유지하는 것이 좋다.
아래는 데이터베이스 트랜잭션을 관리하는데 도움이 되는 어노테이션이다.
@Transactional
JPA
기존의 반복코드는 물론이고, 기본적인 SQL도 직접 만들어 실행해준다.
대표적인 특징은 데이터 베이스의 매핑인데 이를 ORM ( Object-Relational Mapping ) 이라고 한다.
데이터베이스에 왜 매핑이 필요한가? 라는 의문이 들 수 있는데 JAVA에서는 상속을 지원하나 db 는 보통 지원하지 않는다.
이 사이의 간극을 채워주기 위해서 사용한다고 생각하면 좋을 것 같다.
++DB가 id를 생성해 주는 것 identity
스프링 데이터 JPA
!! 스프링 데이터 JPA는 JPA의 숙련도가 충분히 오르고 난 후에 학습할 것을 권장
오 이건 혁명이다. 인터페이스만 만들고 레포(db) 넣어주니까 알아서 매서드를 구현해 준다.
세상에 이것만 쓰면 개발자 망하는거 아닌가 싶었는데..
기본적인 것만 제공해서 각 서비스에 맞는 것은 JPA로 개발해야한다고 한다.
SpringDataJpaMemberRepository
package hello.hello_spring.repository;
import hello.hello_spring.domain.Member;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface SpringDataJpaMemberRepository extends JpaRepository<Member, Long>, MemberRepository {
@Override
Optional<Member> findByName(String name);
}
AOP
모든 매소드의 시간을 측정하고 싶을 때...!!
try...finally 매소드 마다 다 넣어줘야함
하지만 시간 측정은 핵심 기능이 아니다.. 아니면서도 공통 관심사항이다.
즉 필요하긴 한데 그리 중요하진 않고 귀찮게 다 넣어줘야 했던 일이다.
AOP: Aspect Oriented Programming
공통 관심 사항(cross-cutting concern) vs 핵심 관심 사항(core concern) 분리
후기
시험이 끝나니 너무 추워져서 감기가 찾아왔다...
모두 감기 조심하세요..
머리에 뭐가 안들어 가는 느낌이긴 한데 그래도 사용해본 경험과 느낌이 생겨
목표인 모바일 프로그래밍 백엔드 만들어보기는 시도해볼만 한 것 같다.
'WINK-(Web & App) > Spring Boot 스터디' 카테고리의 다른 글
[2024-2 Spring Boot 스터디] 김문기 #2주 (0) | 2024.11.07 |
---|---|
[2024 Spring Boot 스터디] 김아리 #2 주차 (0) | 2024.11.06 |
(미완성)[2024-2 SpringBoot 스터디] 정호용 #1주차 섹션 5~9 (2) | 2024.11.05 |
[2024-2 Spring Boot 스터디] 백채린 #1주차 (0) | 2024.10.10 |
[2024-2 SpringBoot 스터디] 정호용 #1주차 섹션 1~4 (2) | 2024.10.10 |