Spring, JPA 에 관한 정리

YEON·2022년 7월 12일
1

면접 준비

목록 보기
5/5

📝 백엔드/Spring에 관해 공부한 것을 정리해보고자 합니다 (업데이트 상시 예정)


📌 Spring 에 관해 기본적으로 학습했던 개념들은 따로 정리한 포스팅을 참조하면 된다.


Spring

스프링 프레임워크는 자바 개발을 편리하게 해주는 오픈소스 프레임워크 입니다.

  • 경량 컨테이너로서 자바 객체를 직접 관리
    → 각각의 객체 생성, 소멸과 같은 라이프 사이클을 관리하며 스프링으로부터 필요한 객체를 얻어올 수 있다.

  • 제어의 역전(IoC)이라는 기술을 통해 어플리케이션의 느슨한 결합을 도모
    → 컨트롤의 제어권이 사용자가 아닌 프레임워크에 있어서 필요에 다라 스프링에서 사용자의 코드를 호출한다.

  • 의존성 주입(DI)을 지원
    → 각각의 계층이나 서비스들 간에 의존성이 존재할 경우 프레임워크가 서로 연결시켜준다.

  • 관점 지향 프로그래밍(AOP)을 지원
    → 트랜잭션이나 로깅, 보안과 같이 여러 모듈에서 공통적으로 사용하는 기능의 경우 해당 기능을 분리하여 관리할 수 있다.



MVC 패턴

MVC는 Model, View, Controller 의 약자이며, 각 레이어간 기능을 구분하는데 중점을 둔 디자인 패턴이다.

  • Model : 데이터 관리 및 비즈니스 로직을 담당 (DAO, DTO, Service 등)
  • View : 유저 인터페이스가 표현되는 구간(사용자에게 보여주는 화면) (화면 구성, json 응답)
  • Controller : 사용자의 요청을 처리하고, Model과 View는 서로 연결되어 있지 않기 때문에 Controller가 중간에서 Model과 View를 중개하는 역할을 합니다.

장점
각각의 목적에 따라 코드(기능)가 분리되어 있어, 유지보수 및 확장성, 재사용성이 뛰어납니다.
실행되는 비즈니스 로직을 서로 영향 없이 쉽게 고칠 수 있다.

단점
viewmodel 사이에 의존성이 높아서 애플리케이션이 커질수록 복잡해질 수록 테스트와 유지보수가 어렵다.
(* 이런 의존성 문제를 해결하기 위해 MVVM, MVP 구조가 도입되었다.)


MVC 요청 처리 (동작 과정)

  1. 클라이언트는 URL을 통해 요청을 전송한다.
  2. 디스패처 서블릿핸들러 매핑을 통해 해당 요청이 어느 Controller에게 온 요청인지 찾는다. (= 핸들러(컨트롤러) 조회)
  3. 디스패처 서블릿핸들러 어댑터에게 요청의 전달을 맡긴다.
  4. 핸들러 어댑터는 해당 Controller에 요청을 전달한다.
  5. Controller는 비즈니스 로직 처리 후 View의 이름을 반환한다.
  6. 디스패처 서블릿뷰 리졸버를 통해 반환할 View를 찾는다.
  7. 디스패처 서블릿은 Controller에서 View에 전달할 데이터를 추가한다.
  8. 데이터가 추가된 View를 반환한다.(최종 결과 출력)







JPA


JPA는 자바의 ORM 기술 표준으로 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스이다.
데이터를 객체지향 관점으로 바라보고 다룰 수 있게 해준다.

JPA 사용 이유

  • SQL 중심적인 개발에서 객체 중심적인 개발이 가능하다.
  • 간단한 SQL 반복 작성 등을 대신 처리해주므로 생산성이 증가한다.
  • 기존 필드 변경시 모든 SQL을 수정 할 필요가 없으므로 유지보수가 용이하다.
  • Object와 RDB간의 패러다임 불일치를 해결한다.

다만, 복잡하고 무거운 쿼리 문은 속도를 위해 별도의 튜닝이 필요하므로 모든 상황에서 유용하지는 않다.



영속성 컨텍스트

영속성 컨텍스트(Persistence Context) 는 엔티티를 영구 저장하고 관리하는 환경이다.
애플리케이션과 데이터베이스 사이에서 객체를 관리하는 가상의 환경이다.

영속성 컨텍스트가 엔티티를 관리하는 것의 장점

  • 1차 캐시 : 엔티티가 저장 되는 곳으로, 조회시 DB를 먼저 조회하기 전에 캐시에서 우선 조회한다
  • 동일성 보장 : 1차 캐시에서는 같은 엔티티를 반환하여 아이디를 기반으로 동등성을 보장한다
  • 쓰기 지연 : 엔티티 저장하면 바로 DB 저장되는게 아니라 플러시 순간 DB에 보내는 점
  • 변경 감지 : 매번 SQL 수정 쿼리를 쌓지 않아도 된다. 플러시 시점에 스냅샷과 엔티티를 비교하여 수정한다.
  • 지연 로딩 : 필요한 시점에 연관된 객체의 데이터를 불러오는 것 이다.

엔티티 생명주기

영속성 컨텍스트 생명주기는 트랙잭션과 동일하다. 트랜잭션을 종료하면 같이 종료된다.

  • 영속성 (managed) : 영속성 상태에 저장된 상태
  • 준영속 (detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태
  • 비영속 (new) : 영속성 컨텍스트와 전혀 관계가 없는 상태
  • 삭제 (removed) : 삭제된 상태



ORM

ORM(Object-Relational Mapping)은 객체와 관계형 데이터베이스의 테이블을 매핑(연결)한다는 것을 의미한다.

ORM을 이용하면 SQL 쿼리가 아닌 코드를 통해 데이터를 조작할 수 있다.
ex) SELECT * FROM Memver 대신 member.findAll() 의 메소드 호출로 데이터 조회

ORM을 사용하면, 객체지향적인 코드로 인해 더 직관적이고 로직에 집중할 수 있도록 해주고, 객체의 재사용 및 유지보수의 편리성이 증가한다.



N+1 문제

조회 시 1개 쿼리를 생각하고 설계 했으나, 나오지 않아도 되는 조회의 쿼리가 N개 더 발생하는 문제이다.

즉, A객체와 연관된 B객체가 1개가 아닌 N개일 때
A객체를 즉시 로딩 하여 조회하게 되면 (필요하지 않은) B객체를 조회하는 쿼리가 N개 더 발생하는 문제이다.

때문에 가급적 지연 로딩을 권장한다.


* 자세한 정리는 JPA 포스팅 참조







🖍 면접 질문

1. Spring 을 왜 사용하나요?

스프링은 Java 기반의 프레임워크입니다. Java는 객체지향 언어인데,
이때 Spring이 지원해주는 IoC,DI 등을 통해 객체지향이 지닌 다형성이라는 특징을 편리하게 이용할 수 있어
애플리케이션을 변경용이하고 확장가능성있게 개발 할 수 있기 때문에 사용합니다.(사용하게 되었습니다)

2. Spring Framework에 대해 설명해주세요 ↩️

스프링 프레임워크는 Java 기반의 오픈소스 프레임워크 입니다.
스프링은 POJO 방식의 프레임 워크로, 경량 컨테이너로서 자바 객체를 직접 관리하고, IoC,DI, AOP 를 지원하며 확장성이 높다는 특징이 있습니다.

3. Spring Boot와 Spring Framework의 차이점을 설명해주세요. +Spring boot를 사용한 이유?

스프링 부트는 스프링을 편리하게 사용할 수 있도록 지원해주는 기능입니다.
스프링 부트는 내장된 톰캣을 제공해 웹 서버를 설치하지 않아도 서버를 바로 실행할 수 있습니다.
스프링을 지원해주는 역할이기 때문에 스프링 프레임워크과 별도로 사용할 수는 없습니다.

4. Spring MVC에 대해 설명해주세요.

MVC는 Model, View, Controller의 약자이며, 각 레이어간 기능을 구분하는데 중점을 둔 디자인 패턴입니다.

Model은 데이터 관리 및 비즈니스 로직을 담당 (DAO, DTO, Service 등)
View는 유저 인터페이스가 표현되는 구간(사용자에게 보여주는 화면) (화면 구성, json 응답)
Controller는 사용자의 요청을 처리하고, Model과 View는 서로 연결되어 있지 않기 때문에 Controller가 중간에서 Model과 View를 중개하는 역할을 합니다.

5. Spring MVC 에서 요청이 들어왔을 때부터 응답이 나갈 때까지의 흐름을 설명해주세요.

클라이언트는 URL을 통해 요청을 전송하면,
디스패처 서블릿이 핸들러 매핑을 통해 맞는 Controller 를 찾고, 핸들러 어댑터를 통해 요청을 전달합니다.
Controller 에서 요청 처리 후 view 이름 리턴한다.
그럼 디스패처 서블릿이 뷰 리졸버를 통해 View를 찾고, 다시 요청 결과가 반영된 View를 반환합니다.

6. 제어의 역전(IoC)에 대해 설명해주세요.+사용이점

스프링에서 IoC는 모든 객체에 대한 (생성, 라이프사이클 등) 제어권을 개발자가 주도하는 것이 아니라 스프링 컨테이너에게 넘긴 것을 말합니다.
객체관리 주체를 스프링 컨테이너가 맡게되므로, 응집도를 높이고 결합도를 낮춰(역할과 책임이 분리되어) 변경에 유연한 코드를 작성할 수 있습니다. 때문에 개발자는 로직에 집중할 수 있는 장점이 있습니다.

6-1. IoC Container 직접 만든다면 어떻게 구현하실 생각인가요? ↩️

7. 의존관계 주입(DI)에 대해 설명해주세요.

스프링에서 DI는 객체들 간의 의존성을 줄이기 위해 사용되는 스프링 IoC 컨테이너의 구체적인 구현 방식입니다.
필요한 객체를 직접 생성하는 것이 아닌 외부로부터 주입받아 사용합니다.
객체들 간의 의존성이 줄어들어 코드의 재사용성을 높일 수 있습니다.

7-1. 스프링의 의존성 주입 방법들에 대해서 설명해주세요 ↩️

의존성 주입은 생성자 주입, 필드 주입, 세터 주입의 3 가지 방법이 있습니다.
이 중 Spring에서 가장 권장하는 의존성 주입 방법은 생성자를 통한 주입 방법입니다.
그 이유는 1. 순환 참조를 방지 2. 불변성을 가짐 3. 테스트에 용이하기 때문입니다.

8. IoC 와 DI 의 차이점은 무엇인가요?

IoC가 객체에 대한 제어권을 외부로 넘긴다는 개념이라면, DI는 IoC를 달성하기 위한 방법이라고 볼 수 있습니다.
제어의 역전이 일어나는 것을 전제로 객체들간의 관계를 관리할때 사용됩니다.

피자 주문을 예로 들어보았을 때, 피자 스스로 재료들을 선택할 수 없는 것이 제어의 역전이라면,
피자 스스로 재료들을 선택하지 못하여, 외부에서 재료들을 선택하여 넣어준다는 행위에 초점을 맞추는 것이 의존관계 주입입니다.

9. 스프링 빈의 라이프사이클은 어떻게 관리되는지 설명해주세요

스프링 빈은 별다른 설정을 주지 않으면 기본적으로 싱글톤 빈이 됩니다.
싱글톤 스프링 빈의 라이프 사이클은
스프링 컨테이너 생성 → 스프링 빈 생성 → 의존관계 주입 → 초기화 콜백 → 사용 → 소멸 전 콜백 → 스프링 종료
로 이루어지며, 싱글톤 빈은 스프링 컨테이너에서 한 번만 생성되고 컨테이너가 사라질 때 제거됩니다.

  • 스프링은 크게 3가지 방법으로 빈 생명주기 콜백을 관리합니다.

10. 스프링에서 빈(Bean)을 등록하는 방법에 대해 알고있나요?

Bean을 등록하는 방법은 기본적으로 2가지가 있습니다.

  1. @Component 어노테이션을 붙이는 방법
  2. 설정 클래스를 따로 만들어 @Configuration 어노테이션을 붙이고,
    해당 클래스 안에서 빈으로 등록할 메소드를 만들어 @Bean 어노테이션을 붙여주는 방법

@Bean의 경우 개발자가 컨트롤이 불가능한 외부 라이브러리들을 Bean으로 등록하고 싶은 경우에 사용됩니다.

11. AOP는 무엇이고, 언제 사용할 수 있을까요?

AOP는 관점지향 프로그래밍으로 핵심 비즈니스 로직과 부가 기능를 분리하여 각각 모듈화 하는 방식입니다.
OOP를 적용하여도 여전히 핵심 비즈니스 로직안에 로그 등 공통적으로 반복되는 중복 코드가 발생하는 단점이 발생합니다.
이때 AOP가 OOP를 보완하여 위의 문제점을 해결함으로써 핵심 비즈니스 로직에 더욱 집중하고, 반복적인 코드들을 한 곳에서 유지하고 관리할 수 있습니다.

12. Spring의 AOP 특징은 어떻게 되나요?

Spring에서 AOP는 프록시 패턴 기반입니다. 프록시 객체를 사용하는 이유는 기존 코드의 변경 없이 접근 제어 또는 부가 기능 추가를 위해서입니다.
또한 스프링 빈에만 AOP를 적용할 수 있고,
중복코드, 객체 간 관계 복잡도 증가 등의 문제점에 대한 솔루션을 제공하는 것을 목적으로 하여 모든 AOP 기능을 제공하지는 않습니다.

13. Spring 동작방식에 대해 알고있나요?

//아직 말이 제대로 정리가 안되는 것 같아서 다시 학습하겠습니다ㅜ.ㅜ


ORM에 대해 설명해주세요

ORM은 객체와 관계형 데이터베이스의 테이블을 매핑하는 것을 의미합니다.
ORM을 사용하면 SQL 쿼리가 아닌 객체지향적인 코드로 인해 더 직관적이고 로직에 집중할 수 있도록 해주고,
객체의 재사용 및 유지보수의 편리성이 증가한다.

JPA를 사용하는 이유에 대해서 설명해주세요

JPA는 자바 ORM 기술 표준으로 SQL 중심적인 개발에서 객체 중심적인 개발이 가능합니다.
기존 필드 변경시 모든 SQL을 수정 할 필요가 없으므로 유지보수가 용이하고, 간단한 CRUD의 경우 대신 처리해주므로 생산성이 증가됩니다.

영속성 컨텍스트에 대해서 설명해주세요

영속성 컨텍스트는 엔티티를 영구 저장하는 환경입니다.
트랜잭션 범위 안에 존재하여 트랜잭션을 시작과 종료에 맞춰 영속성 컨텍스트를 생성하고 종료합니다.
(영속성 컨텍스트는 트랜잭션마다 준비되기 때문에 엔티티는 같은 트랜잭션에서만 공유되고 다른 트랜잭션에서 처리 중인 엔티티는 보이지 않음)

이때 데이터베이스의 캐시와 같은 역할을 하여, 작업이 수행되더라도 즉시 데이터베이스에 반영되지는 않고,
트랜잭션을 커밋하면 JPA는 영속성 컨텍스트를 플러시해서 변경 내용을 데이터베이스에 반영합니다.

영속성 컨텍스트가 엔티티를 관리하게 되면 장점은 무엇일까요

영속성 컨텍스트는 1차캐시, 동일성 보장, 쓰기 지연, 변경 감지의 이점이 있습니다.

영속성 컨텍스트는 1차 캐시에 엔티티를 조회하여 DB를 거치지 않고 1차 캐시에서 우선적으로 조회를 합니다.
1차 캐시는 엔티티 요청 시 같은 엔티티를 반환하여 동일성을 보장합니다.
또한 객체를 생성하거나 수정하게 되더라도, 바로 DB를 거치지 않고 있다가 플러시 순간에 해당 작업들을 관리하여 이루어지는 쓰기지연과 변경감지의 이점이 있습다.

엔티티 생명주기에 대해 설명해주세요

영속성 컨텍스트 생명주기는 트랙잭션과 동일합니다.
엔티티는 영속성, 준영속, 비영속, 삭제의 생명 주기를 갖고 있습니다.

영속성은 영속성 상태에 저장된 상태이며, 준영속은 영속성 컨텍스트에 저장되어있다가 분리된 상태이고 비영속은 영속성 컨텍스트와 관계가 없는 상태이며 삭제는 삭제된 상태입니다.

JPA의 N+1 문제에 대해서 설명해주세요

N+1이란 1번의 쿼리를 날렸을 때 의도하지 않은 N번의 쿼리가 추가적으로 실행되는 것을 의미합니다.
해결 방법에는 여러 방법이 있지만 가장 많이 사용되는 방법은 Fetch Join을 사용해 해결하는 방법입니다.

N+1 문제가 발생하는 이유는 연관관계를 가진 엔티티를 조회할 때  한 쪽 테이블만 조회하고 연결된 다른 테이블은 따로 조회하기 때문인데, Fetch Join을 사용하면 미리 두 테이블을 Join하여 한 번에 모든 데이터를 가져오기 때문에 N+1문제를 애초에 막을 수 있습니다.







[참조]
https://dev-coco.tistory.com/163?category=1056309
https://recordsoflife.tistory.com/302

https://mkil.tistory.com/532

profile
- 👩🏻‍💻

0개의 댓글