Spring과 SpringBoot의 차이
SpringBoot는 Spring Framework 프로젝트를 간편하게 셋업할 수 있는 서브 프로젝트이다.
독립 컨테이너에서 동작할 수 있기 때문에 추가 WAS 설치 없이 내장된 톰캣으로 실행한다.
Spring Framework 특징
자바 엔터프라이즈 개발을 편하게 해주는 오픈소스 경량급 어플리케이셔 프레임워크이다.
어플리케이션을 개발하는데 필요한 기능들을 제공해주기 때문에 개발자들은 개발에 집중할 수 있다.
- 경량 컨테이너로 자바 객체를 생성하고 조립하는 등 관리한다.
- POJO(순수한 자바 객체) 기반의 구성
- 의존성 주입(DI)을 통한 객체 간의 관계 구성
- AOP: 관점 지향 프로그래밍
- 편리한 MVC 구조
- WAS에 종속적이지 않은 개발 환경, 내장 서버(톰캣)이 내장되어 있다.
- Java 객체와 라이브러리를 관리해준다.
IoC / DI란
IOC: 제어의 역전
- 인스턴스의 제어권이 개발자가 아니라 컨테이너(프레임워크)가 대신 관리해주는 것을 말한다.
DI: 의존성 주입
- Spring에서 지원하는 IOC의 형태로 클래스 사이의 의존 관계를 빈(Bean) 설정 정보를 바탕으로 컨테이너가 자동으로 연결해주어 객체들 간의 의존성을 줄인다.
- DI 방법: 생성자 삽입, 수정자 주입, 필드 주입
생성자 주입 사용하는 이유
- 필드 주입은 코드가 간결하다. 필드 주입은 외부에서 수정이 불가능하기 때문에 테스트 코드를 작성할 때 객체를 수정할 수 없게 된다. 또한 필드 주입은 Spring 같은 DI를 지원하는 프레임워크가 있어야만 사용이 가능해진다.
- 수정자 주입의 경우 public으로 구현하기 때문에 관계를 주입받는 객체의 변경 가능성을 열어두게 된다. 때문에 수정자 주입 방식은 주입받는 객체가 변경될 필요성이 있을 때만 사용되어야 한다.
- 생성자 주입은 생성자로 객체를 생성하는 시점에 필요한 빈을 주입하게되어 순환참조를 해결할 수 있다. 또한 필드를 final로 선언도 가능(불변성 보장)하다. DI 컨테이너를 사용하지 않고도 테스트를 진행할 수 있다.
Spring Bean이란
Spring IoC 컨테이너가 관리하는 자바 객체를 Bean이라 부른다. 즉 스프링 컨테이너가 생성한 객체들을 빈이라고 한다.
스프링에서 Bean 생성시 별다른 설정이 없으면 싱글톤이 적용된다. 스프링은 컨테이너를 통해 싱글톤 객체를 생성하고 관리하는데, 요청이 들어올때 마다 매번 객체를 생성하지 않고, 이미 만들어진 객체를 공유하기 때문에 효율적인 사용이 가능하다.
(프로토타입 빈은 싱글톤과 달리 빈을 요청할 때마다 매번 새로운 객체를 생성하여 반환해준다. scope 설정을 프로토타입 scope로 설정하면 된다. @Scope("prototype"))
Spring Bean Scope란
Bean Scope는 Bean이 존재할 수 있는 범위를 뜻한다.
싱글톤, 프로토타입, request, session, application 등이 있다.
싱글톤은 기본 스코프로 스프링 컨테이너의 시작과 종료까지 유지되는 범위의 스코프입니다.
프로토타입은 빈의 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는 매우 짧은 범위의 스코프입니다.
@Component / @Bean 차이
둘다 IoC 컨테이너에 Bean을 등록하기 위해 사용합니다.
- @Component는 class를 기반으로 실행시점에 인스턴스 객체를 생성합니다. @Controller, @Service, @Repository 등 모두 @Component를 포함하고 있으며 실행시점에 자동으로 의존성을 주입합니다.
- @Bean은 method 기반으로 메서드에서 반환하는 객체를 인스턴스 객체로 생성합니다.
AOP란
관점 지향 프로그래밍이란 뜻으로 공통으로 사용되는 기능들을 외부 독립된 클래스로 분리하는 것을 의미한다. 공통 로직과 핵심 비즈니스 로직을 분리하여 응집도를 높여 개발할 수 있다.
Filter와 Interceptor 차이
- 실행 시점 차이
- Filter
- DispatcherServlet으로 요청이 되기 전/후에 실행된다. 웹 Context에서 동작합니다.
- Filter에서는 웹 어플리케이션 전역으로 처리되는 작업들을 처리할 수 있습니다. 대표적인 예로는 보안 공통 작업이나 이미지 압축, 문자열 인코딩과 같이 웹 어플리케이션 전반적으로 사용되는 기능을 구현하기에 적합합니다.
- Interceptor
- Dispatcher Servlet에서 Controller로 요청이 가기 전/후에 실행되며 Spring Context에서 동작을 합니다.
- Interceptor는 클라이언트의 요청과 관련된 작업을 처리하는 작업들을 처리할 수 있습니다. 대표적인 예로는 API 호출에 대한 로깅 남기기나 Controller로 넘겨주는 정보 가공 등이 있습니다.
- Filter
- 즉 둘 다 Controller에서 작업하기 전 처리된다는 공통점이 있지만 호출되는 시점이 다르다.
CORS 에러 방안
- Filter를 사용하여 Cors 설정
- WebMvcConfigurer를 구현한 Configuration 클래스를 만들어 addCorsMappings()를 재정의
- Spring Security에서 CorsConfigurationSource를 Bean으로 등록하여 config에 추가
- Controller 클래스에 @Crossorigin 어노테이션
Spring Boot 특징
스프링을 이용하기 위해서는 환경 설정할 것이 많은데 스프링 부트를 이용하여 프로젝트를 간단하게 설정할 수 있게 되었다. 즉 Spring 개발을 더 쉽게 만들어주는 역할이다. 개발자는 비즈니스 로직에 더욱 집중할 수 있게 되었다.
Spring MVC란?
MVC란 Model - View - Controller 구조인 소프트웨어 디자인 패턴이다. 사용자 인터페이스와 비즈니스 로직을 분리하여 각자 개발에 집중할 수 있게 되었다.
- Model
- 데이터 처리를 담당하는 영역이다. Service와 DAO 영역으로 나누어진다.
- Model에서는 View와 Controller 어떠한 정보도 가지고 있어서는 안 된다.
- View
- 사용자 인터페이스를 담당하며 사용자에게 보이는 부분이다.
- Model이 가지고 있는 정보를 저장해서는 안되고, Model, Controller 구성 요소를 알아서 안 된다.
- Controller
- 사용자의 요청을 처리하고 Model과 View를 중개하는 역할을 한다.
- View로 부터 받은 요청을 가공하여 Model에 전달한다.
- Model로부터 받은 결과를 View로 넘겨주는 역할을 하며, 에러 발생도 처리한다.
- Model과 View의 정보를 알고 있어야 한다.
- 사용자의 요청을 처리하고 Model과 View를 중개하는 역할을 한다.
Spring MVC 처리 과정
- DispatcherServlet
Request를 받으면 Controller에게 전달하고 처리한 값을 받아서 View에게 전달하는 등 흐름을 제어한다. - HandlerMapping
Request URL을 받으면 어떤 Controller에게 처리하게 할 것인지 찾아주는 역할을 한다. - HandlerAdapter
HamdlerMapping에서 결정된 핸들러 정보를Controller에 알맞는 처리요청 - Controller
Request를 처리한 후 결과를 다시 DispatcherServlet에게 돌려준다. - ModelAndView
Controller에게 받은 결과와 결과를 보여줄 View에 관한 정보를 담고 있는 객체 - ViewResolver
View 관련 정보를 갖고 실제 View를 찾아주는 역할을 한다.
Spring에서 CORS 해결 방법
- Servlet Filter를 사용하여 커스텀한 CORS 설정을 한다.
- WebMvcConfigurer를 구현한 Configuration 클래스를 만들어서 addCorsMappings()를 재정의 한다.
- Spring Security에서 CorsConfigurationSource를 Bean으로 등록하고 config에 추가한다.
@RequestParam / @RequestBody / @ModelAttribute
- @RequestParam
HTTP 요청 파라미터를 받기 위해 사용된다. 속성 required 기본값이 true이기 때문에, 파라미터가 들어오지 않으면 400에러가 발생된다. - @RequestBody
JSON 형태인 HTTP body 내용을 MessageConverter를 통해 객체로 변환시켜주는 역할을 한다. - @ModelAttribute
HTTP 요청 파라미터와 HTTP body 내용을 getter/setter,생성자를 통해 주입하기 위해 사용한다.
VO / DTO / DAO
VO (Value Object)
값을 갖고있는 객체이다. 비즈니스 값을 가져올 때 사용하며, 보통 값을 수정할 수 없는 것으로 한다. DTO와 혼용해서 쓰기도 한다.
DTO (Data Transfer Object)
VO와 같이 값을 갖고 있는 객체이다. VO와의 차이점은 DB로 치자면 하나의 인스턴스로, 데이터 핸들링에 사용되는 객체이다. DTO를 통해 데이터를 전달할 수 있다.
- VO와 DTO의 차이
VO는 DTO와 같은 개념이지만 Read Only 속성을 갖는다. VO는 특정한 비즈니스 값을 담는 객체이고
DTO는 Layer간의 통신 용도로 오고가는 객체를 말한다.
DAO (Data Access Object)
실제 DB에 접속하는 객체이다. Service와 DB사이에서 가져온 데이터를 엔티티로 변환시켜 가져온다. 대부분의 CRUD API를 제공한다.
JPA
Java ORM 기술에 대한 API 표준 명세를 의미한다.
ORM이란 객체와 관계형 데이터베이스의 데이터를 매핑해주는 것을 말한다.
Entity
Entity 클래스는 실제 데이터베이스의 테이블과 1:1로 매핑되는 클래스로 DB의 테이블 내에 존재하는 컬럼만을 속성으로 가져와야 합니다.
Entity를 작성할 때 Setter를 무분별하게 사용하면 객체(Entity)의 값을 변경할 수 있기 때문에 객체의 일관성을 보장할 수 없게됩니다.
DTO를 사용하는 이유
- 순환참조를 예방할 수 있다.
- Entity 내부 구현을 캡슐화 할 수 있다.
- DB와 View 사이의 역할을 분리할 수 있다.
영속성 컨텍스트
영속성 컨텍스트는 엔티티를 저장하는 환경이다.
엔티티 매니저를 생성하면 자동으로 영속성 컨텍스트가 생성되고 엔티티를 관리 혹은 보관할 수 있다.
- 1차 캐시
영속성 컨텍스트 내부에는 캐시를 갖고 있다. 영속 상태의 엔티티는 모두 1차 캐시에 저장된다.
캐시는 @Id를 키로 가지고 있는 Map이 존재한다. 엔티티를 조회할 때 바로 DB에 접근하는 것이 아닌 캐시에 있는 데이터를 먼저 조회한 후 없는 경우 DB에 접근하여 조회하고 이를 캐시에 저장한다.
DB에 바로 접근하는 것이 아닌 캐시에 먼저 접근하기 때문에 데이터의 결과를 빠르게 가져올 수 있다. - 동일성 보장
모든 엔티티 데이터들은 1차 캐시에 저장되기 때문에 식별자가 동일한 엔티티의 경우 동일성(같은 객체를 참조한다는 것)이 보장된다. - 트랜잭션 지연
영속성 컨텍스트에서 DML(CRUD) 발생하면 바로 DB에 적용하지 않고, 트랜잭션이 커밋될 때 영속성 컨텍스트의 쓰기 지연 SQL 저장소에 모아둔 쿼리들을 한 번에 적용한다. 이는 DB에 접근하는 횟수가 줄어들기 때문에 성능면에서 이점이 있다. - 변경 감지
영속성 컨텍스트의 캐시에는 스냅샷을 통해 엔티티의 변경을 감지한다.
JPA Propagation
propagation
- @Transactional의 propagation 속성을 통해 트랜잭션의 전파옵션을 지정할 수 있습니다.
- REQUIRED (DEFAULT) : 현재 트랜잭션에서 실행되고 없을 경우 신규 트랜잭션 생성합니다.
- REQUIRED_NEW : 현재 트랜잭션이 종료될 때까지 대기한 후 실행됩니다. 없을 경우 신규 트랜잭션 생성합니다.
- SUPPORTS : 현재 트랜잭션에서 실행되고 없을 경우 트랜잭션 없이 수행됩니다.
- NOT_SUPPORT : 현재 트랜잭션이 종료될 때까지 대기한 후 실행됩니다. 없을 경우 트랜잭션 없이 수행됩니다.
- MANDATORY : 현재 트랜잭션에서 실행되고 없을 경우 Exception 발생합니다. 즉 이전 트랜잭션이 있어야 합니다.
- NEVER : 트랜잭션이 존재하는 경우 Exception 발생하고, 없는 경우 트랜잭션 없이 수행됩니다.
- NESTED : 현재 트랜잭션에 Save Point를 걸고 트랜잭션을 수행합니다. 없을 경우 신규 트랜잭션 생성합니다.
즉시 로딩(EAGER) vs 지연 로딩(LAZY)
- 즉시 로딩
- 엔티티를 조회할 때, 연관된 엔티티도 함께 바로 조회된다.
- 이를 사용할 경우 어떤 SQL이 나갈지 추적하기 어렵다.
- 지연 로딩
- 연관된 엔티티가 실제 사용될 때 조회된다.
N+1 문제
- 연관관계에서 발생하는 이슈로 하나의 쿼리를 날렸을 때 조회된 결과 수 N 만큼 연관된 쿼리를 추가로 실행되는 문제이다.
- 발생하는 이유는 연관관계를 가진 엔티티를 조회할 때 해당 테이블을 조회하고 연관된 테이블을 따로 조회하기 때문입니다. 간단한 해결 방법으로는 Fetch Join이 있습니다. 다른 방법으로는 @EntityGraph를 사용하는 방법 등이 있습니다.
Spring Security
- 스프링 기반의 어플리케이션 인증과 권한을 담당하는 프레임워크
- 세션-쿠키 방식으로 인증한다.
JWT
JWT는 확장성에서 큰 강점을 가진다.
만약 세션을 사용한다면 서버를 확장할 때마다 각 서버에 세션 정보를 저장해주어야 한다. 이렇게 된다면 특정 서버에서 로그인 인증을 받을 때 다른 서버에서는 로그인을 했는지 알 수 없다는 단점이 생기게 됩니다.
OAuth2
- 타사의 사이트에 대한 접근 권한을 얻고 그 권한을 이용하여 개발할 수 있도록 도와주는 프레임워크다.
- 구글, 카카오, 네이버 등과 같은 사이트에서 로그인을 하면 직접 구현한 사이트에서도 로그인 인증을 받을 수 있도록 하는 구조다.
- Oauth는 세션대신 토큰을 사용하여 인증을 진행한다.
- OAuth2를 사용한다면 UsernamePasswordAuthenticationFilter 대신 OAuth2LoginAuthenticationFilter가 호출되게 해야 한다.
'CS > 면접 준비' 카테고리의 다른 글
백엔드 면접 질문 (0) | 2023.02.05 |
---|---|
웹과 네트워크 면접 질문 (0) | 2022.12.23 |
운영체제 면접 질문 (0) | 2022.12.22 |
Database 면접 질문 (0) | 2022.12.22 |
객체지향 프로그래밍 & Java 면접 질문 (0) | 2022.12.22 |