1. Call by reference란 무엇이고 보통 어떻게 쓰이나요?
- Call by Reference는 함수 호출 시 변수의 참조값(주소)을 전달하는 방식입니다. 이렇게 하면 함수 내부에서 원본 변수의 값을 직접 변경할 수 있습니다. 즉, 함수 내부에서 변경한 내용이 원본 변수에 반영됩니다.
- Call by Value는 함수 호출 시 변수의 값을 복사해서 전달하는 방식입니다. 이 경우 함수 내부에서 변수 값을 변경해도 원본 변수의 값은 변경되지 않습니다.
- 꼬리 질문
- 자바의 호출 방식은?
2. override와 overload 설명
- 오버라이딩(Override)은 상위 클래스의 메서드를 하위 클래스에서 재정의하는 것입니다.오버로딩(Overload)은 같은 이름의 메서드를 매개변수 타입이나 개수를 달리하여 정의하는 것입니다.오버라이딩은 상속 관계에서 발생하지만, 오버로딩은 같은 클래스 내에서 발생합니다.
- 꼬리 질문
- 오버라이딩한 메서드를 오버로딩할 수 있나요? Yes!
3. jpa는 언제 필요하고 언제 필요하지 않은지 설명해주세요
- 자바 객체와 rdb의 원활한 관계를 위하여, 성능향상, 복잡한쿼리는 부적합
- JPA가 필요하지 않은 경우
- 간단한 프로젝트: 작은 규모의 프로젝트에서는 JPA를 사용하지 않고 JDBC와 SQL을 직접 다루는 것이 좋습니다.
- 쿼리가 복잡하지 않은 경우: 간단한 쿼리로 데이터베이스와 상호작용할 때는 JPA를 사용하는 대신 직접 SQL을 작성하는 것이 더 효과적일 수 있습니다.
- 성능이 매우 중요한 경우: JPA는 객체와 데이터베이스 간의 변환을 처리하는데 일정한 오버헤드가 발생할 수 있습니다. 매우 높은 성능을 요구하는 애플리케이션의 경우 직접 SQL을 작성하는 것이 더 효율적일 수 있습니다.
- JPA는 객체 중심적인 애플리케이션 개발을 가능하게 하므로 아래와 같을 때 필요합니다.
- 복잡한 데이터베이스 관계: 데이터베이스 테이블 간에 복잡한 연관 관계가 있을 때, 복잡한 조인 쿼리를 작성할 필요가 없어집니다.
- 패러다임 불일치 해결: 객체는 상속 구조를 만들 수 있으며, 다형성 구현이 가능하지만, 관계형 데이터베이스의 테이블은 상속이라는 개념이 존재하지 않습니다. 객체는 참조를 통해 관계를 표현하며 방향을 가지고 있으나, 관계형 데이터베이스는 외래 키를 통해 관계를 표현하며, 방향이 존재하지 않습니다. JPA는 객체 간의 상속과 다형성을 데이터베이스에서 표현할 수 있게 해줘, 객체 중심적으로 데이터베이스를 다룰 수 있게 해줍니다.
- 엔티티 클래스 생성할 때 빈 생성자가 필요함, 그 이유는?
4. jpa의 더티체킹이란 무엇인가요?
- 더티 체킹은 JPA가 엔티티의 변경 사항을 자동으로 감지하고 트랜잭션 커밋 시 변경 내용을 데이터베이스에 반영하는 기능입니다.이를 통해 개발자가 직접 데이터베이스 업데이트 쿼리를 작성할 필요가 없어져 생산성이 향상됩니다.
- 꼬리질문
- 트랜잭션이 없는 경우에는 더티체킹일 불가능한가요? Yes!
5. JVM이란 무엇이고 왜필요할까요?
- JVM(Java Virtual Machine)은 자바 프로그램을 실행하는 가상 머신입니다. JVM은 자바 바이트코드를 해석하고 실행하여 플랫폼 독립성을 제공합니다 .JVM의 주요 역할은 다음과 같습니다:
- 플랫폼 독립성: JVM은 Java 프로그램이 어떤 하드웨어와 운영 체제에서도 실행될 수 있게 해줍니다. 즉, Java로 작성된 프로그램은 JVM이 설치된 모든 시스템에서 동작하게 됩니다. 이러한 특성을 통해 '한 번 작성하면 어디에서나 실행할 수 있다(Write Once, Run Anywhere)'는 Java의 핵심 철학을 가능하게 합니다.
- 메모리 관리: JVM은 자동 메모리 관리를 제공합니다. JVM 내부의 가비지 컬렉터가 자동으로 더 이상 사용되지 않는 메모리를 회수하여 메모리 누수를 방지합니다.
- 보안: JVM은 샌드박스 보안 메커니즘을 통해 시스템 자원에 대한 바이트 코드의 접근을 제한합니다. 따라서, 악의적인 행동을 하는 코드의 실행을 방지합니다.
- 최적화: JVM은 Just-In-Time 컴파일러를 통해 바이트 코드를 기계어로 변환하고 최적화합니다. 이를 통해 프로그램의 성능을 향상시킵니다.
- 멀티스레드 지원: JVM은 스레딩 기능을 지원하며, 스레드 간의 동기화를 관리합니다.
- 꼬리 질문
- jvm의 구조는?
6. 자바 컴파일 과정
- 소스 코드 작성: Java 언어로 프로그램을 작성하고 .java 확장자로 파일을 저장합니다.
- 컴파일: javac 컴파일러를 사용하여 소스 코드(.java 파일)를 바이트 코드(.class 파일)로 컴파일합니다. 이 바이트 코드는 플랫폼에 독립적인 중간 코드입니다.
- 실행: java 명령어를 사용하여 JVM(Java Virtual Machine) 위에서 바이트 코드를 실행합니다. JVM은 바이트 코드를 해당 플랫폼의 기계어로 변환하여 실행하는 역할을 합니다.이렇게 Java는 '컴파일 한 번, 실행은 어디서든'이라는 이점을 가집니다. 즉, 한 번 컴파일된 Java 바이트 코드는 어떤 플랫폼에서든 JVM이 설치되어 있다면 실행할 수 있습니다. 이는 Java의 가장 큰 장점 중 하나로, 이를 통해 Java는 다양한 환경에서 활용되고 있습니다.
7. JVM의 스택과 힙 메모리 영역에 대해 아는 만큼 설명해주실 수 있을까요?
- 1. 스택(Stack) 영역
- 메서드 호출 시 생성되는 지역 변수와 매개 변수가 저장되는 영역입니다.
- 메서드가 호출되면 해당 메서드의 스택 프레임이 생성되고, 메서드 실행이 끝나면 해당 프레임이 제거됩니다.
- 스택 영역은 LIFO(Last-In-First-Out) 구조로 관리되며, 메서드 호출과 반환이 효율적으로 이루어집니다.
- 스택 영역의 크기는 일반적으로 고정되어 있으며, 스택 오버플로우 오류가 발생할 수 있습니다.
- 동적으로 생성되는 객체와 배열이 저장되는 영역입니다.
- 힙 영역은 가비지 컬렉터(Garbage Collector)에 의해 관리됩니다.
- 가비지 컬렉터는 더 이상 사용되지 않는 객체를 자동으로 제거하여 메모리 공간을 확보합니다.
- 힙 영역은 스택 영역과 달리 동적으로 크기가 변경될 수 있습니다.
- 힙 영역의 크기가 부족하면 OutOfMemoryError가 발생할 수 있습니다.
- 클래스 수준의 데이터(static 변수, 상수, 메서드 코드 등)가 저장되는 영역입니다.
- 프로그램 시작 시 로드되며, 프로그램 종료 시까지 유지됩니다.
- 메서드 영역은 JVM의 또 다른 중요한 메모리 영역입니다.
8. 클래스와 인스턴스의 차이에 대해 설명해주실 수 있을까요?
- 1. 클래스(Class)
- 클래스는 객체를 생성하기 위한 설계도 또는 틀입니다.
- 클래스에는 객체의 속성(변수)과 기능(메서드)이 정의되어 있습니다.
- 클래스는 추상적인 개념으로, 실제로 존재하는 것이 아닙니다.
- 인스턴스는 클래스를 바탕으로 생성된 구체적인 객체입니다.
- 인스턴스는 클래스에 정의된 속성과 기능을 가지고 있습니다.
- 인스턴스는 실제로 메모리에 할당되어 존재하는 객체입니다.
- 클래스는 객체를 생성하기 위한 설계도이며, 인스턴스는 클래스를 바탕으로 생성된 구체적인 객체입니다.
- 클래스는 추상적인 개념이지만, 인스턴스는 실제로 메모리에 할당되어 존재합니다.
- 클래스에는 객체의 속성과 기능이 정의되어 있지만, 인스턴스는 클래스에 정의된 내용을 실제로 가지고 있습니다.
- 객체는 실세계의 엔티티(Entity)를 대표하는 것으로, 속성과 기능을 가지고 있습니다.
- 객체는 클래스를 바탕으로 생성된 인스턴스입니다.
- 객체는 실제로 존재하는 구체적인 실체입니다.
9. Garbage Collector의 역할, 원리, 알고리즘에 대해 아는 만큼 설명해주실 수 있을까요?
- 1. 가비지 컬렉터의 역할
- 가비지 컬렉터는 JVM(Java Virtual Machine)의 Heap 영역에서 더 이상 사용되지 않는 객체(Garbage)를 자동으로 찾아내어 메모리에서 제거하는 역할을 합니다.
- 개발자가 직접 메모리 관리를 하지 않아도 되게 해주는 것이 가비지 컬렉터의 주요 역할입니다.
- 이를 통해 메모리 누수(Memory Leak) 문제를 해결할 수 있습니다.
- 가비지 컬렉터는 Heap 영역을 주기적으로 스캔하여 더 이상 사용되지 않는 객체를 찾아냅니다.
- 이를 위해 가비지 컬렉터는 객체의 참조 관계를 추적하여 도달 가능한 객체(Reachable Object)와 도달 불가능한 객체(Unreachable Object)를 구분합니다.
- 도달 불가능한 객체가 바로 가비지(Garbage)이며, 이 객체들은 메모리에서 제거됩니다.
-
- Mark-Sweep 알고리즘:
가비지 객체를 식별하고 제거하는 가장 기본적인 알고리즘입니다.
먼저 Heap 영역의 모든 객체를 마킹(Mark)하고, 마킹되지 않은 객체를 가비지로 간주하여 제거(Sweep)합니다.
단순하지만 메모리 단편화 문제가 발생할 수 있습니다. - Mark-Compact 알고리즘:
Mark-Sweep 알고리즘의 단편화 문제를 해결하기 위해 고안된 알고리즘입니다.
마킹 후 가비지 객체를 제거하고, 살아남은 객체들을 Heap 영역의 한쪽으로 압축(Compact)합니다.
메모리 단편화 문제를 해결할 수 있지만, 압축 과정에서 성능 저하가 발생할 수 있습니다. - Copying 알고리즘:
Heap 영역을 두 개의 반으로 나누고, 한 쪽에 있는 살아남은 객체들을 다른 쪽으로 복사하는 방식입니다.
복사 과정에서 자동으로 메모리 단편화 문제가 해결되며, 빠른 속도로 가비지 컬렉션을 수행할 수 있습니다.
단, 메모리 사용량이 2배 증가하는 단점이 있습니다. - Generational 알고리즘:
객체의 수명에 따라 Heap 영역을 Young 영역과 Old 영역으로 나누어 관리하는 알고리즘입니다.
Young 영역에서는 Copying 알고리즘을, Old 영역에서는 Mark-Sweep 또는 Mark-Compact 알고리즘을 사용합니다.
대부분의 객체는 Young 영역에서 빨리 소멸되므로, 효율적인 가비지 컬렉션이 가능합니다. - Concurrent 알고리즘:
가비지 컬렉션 작업을 애플리케이션 실행 스레드와 병렬로 수행하는 알고리즘입니다.
애플리케이션 실행을 중단하지 않고 가비지 컬렉션을 수행할 수 있어, 응답 시간 지연 문제를 해결할 수 있습니다.
복잡한 구현으로 인해 다른 알고리즘에 비해 오버헤드가 크다는 단점이 있습니다.
- Mark-Sweep 알고리즘:
- 객체가 Heap 메모리에 할당되면 우선 Eden 영역에 배치됩니다.
- Minor GC 발생 시, Eden 영역의 살아남은 객체는 Survivor 영역으로 이동합니다.
- 다음 Minor GC 때 Survivor 영역의 살아남은 객체는 나이(Age)가 증가하며, 일정 나이에 도달하면 Old 영역으로 이동합니다.
- Old 영역이 가득 차면 Major GC가 발생하여 Old 영역의 가비지를 제거합니다.
- 꼬리 질문
- 메모리 단편화에 대해 설명해주세요
10. Java Map의 내부 구현은 어떻게 이루어져 있을지 추측해보실 수 있을까요?
- HashMap: 기본적인 맵 구현체로, 키와 값을 쌍으로 저장합니다. 키의 해시코드를 사용하여 빠르게 검색할 수 있습니다. 순서가 보장되지 않으며, null 키와 null 값이 허용됩니다.
- LinkedHashMap: HashMap을 기반으로 하며, 추가된 순서 또는 접근된 순서에 따라 요소를 정렬합니다. 순서가 유지되며 성능은 HashMap에 비해 약간 느린 편입니다.
- TreeMap: 레드-블랙 트리를 기반으로 하는 정렬된 맵 구현체입니다. 키에 대해 자동 정렬되며, 키에 대한 비교를 제공하는 Comparator를 사용하여 정렬 방식을 지정할 수 있습니다. 순서가 유지되며 성능은 HashMap에 비해 느린 편입니다.
- ConcurrentHashMap: 멀티스레드 환경에 최적화된 HashMap의 변형입니다. 동시성에 대한 지원을 제공하며 높은 성능을 유지합니다. 단, 순서가 보장되지 않습니다.
- Hashtable: 자바 초기부터 사용된 맵 구현체로, 키와 값을 쌍으로 저장합니다. HashMap과 유사하지만 동기화되어 있어 멀티스레드 환경에서 안전하게 사용할 수 있습니다. 그러나 성능이 떨어지며 현대적인 Java에서는 ConcurrentHashMap을 사용하는 것이 권장됩니다.
- 꼬리 질문
- 해시충돌이 발생하는 이유?
- 해시 함수의 한계, 해시 테이블의 크기 제한, 해시 함수의 품질 저하, 데이터 분포의 편중 등
11. DI와 IoC에 대해 아는 만큼 설명해주실 수 있을까요?
IoC(제어의 역전)는 프로그래밍의 설계 원칙 중 하나로, 컴포넌트 간의 제어 흐름에 관한 책임을 프레임워크나 컨테이너에게 넘기는 것을 의미합니다. Ioc의 목적을 달성하기 위해 DI를 사용하게 되는데 DI(의존성 주입)은 클래스 관계를 등록된 빈을 통해 외부에서 자동으로 주입해주는 것을 말한다.
12. MVC 모델이란 무엇인지 설명해주실 수 있을까요?
- 모델(Model):
애플리케이션의 데이터와 비즈니스 로직을 담당합니다.
데이터 액세스, 데이터 변환, 데이터 유효성 검사 등의 기능을 수행합니다. - 뷰(View):
사용자 인터페이스를 담당합니다.
모델에서 제공된 데이터를 표시하고 사용자 입력을 처리합니다. - 컨트롤러(Controller):
사용자 입력을 받아 모델을 업데이트하고 뷰를 업데이트합니다.
모델과 뷰 사이의 중재자 역할을 합니다.
13. Annotation이란 무엇이고 구체적으로 어떤 것이 있는지 예시를 들어 설명해주실 수 있을까요?
- Annotation은 Java 프로그래밍 언어에서 사용되는 메타데이터(데이터에 대한 데이터)입니다.
Annotation은 소스 코드에 추가되어 컴파일러나 JVM에 추가 정보를 제공합니다. - Annotation의 예시
- @Override: 메서드가 상위 클래스의 메서드를 오버라이드하고 있음을 나타냅니다.
- @Autowired: Spring 프레임워크에서 의존성 주입을 위해 사용됩니다.
- @RequestMapping: Spring MVC에서 URL과 메서드를 매핑하는 데 사용됩니다.
14. Spring Security의 구조와 JWT 발급 과정에 대해 설명해주실 수 있을까요?
Spring Security는 웹 애플리케이션의 보안을 담당하는 프레임워크로, 크게 인증(Authentication)과 권한 부여(Authorization) 두 가지 기능을 제공합니다.
- 인증 과정
- 사용자가 로그인 정보와 함께 인증 요청을 한다.(Http Request)
- AuthenticationFilter가 요청을 가로채고, 가로챈 정보를 통해 UsernamePasswordAuthenticationToken의 인증용 객체를 생성한다.
- AuthenticationManager의 구현체인 ProviderManager에게 생성한 UsernamePasswordToken 객체를 전달한다.
- AuthenticationManager는 등록된 AuthenticationProvider(들)을 조회하여 인증을 요구한다.
- 실제 DB에서 사용자 인증정보를 가져오는 UserDetailsService에 사용자 정보를 넘겨준다.
- 넘겨받은 사용자 정보를 통해 DB에서 찾은 사용자 정보인 UserDetails 객체를 만든다.
- AuthenticationProvider(들)은 UserDetails를 넘겨받고 사용자 정보를 비교한다.
- 인증이 완료되면 권한 등의 사용자 정보를 담은 Authentication 객체를 반환한다.
- 다시 최초의 AuthenticationFilter에 Authentication 객체가 반환된다.
- Authenticaton 객체를 SecurityContext에 저장한다.
최종적으로 SecurityContextHolder는 세션 영역에 있는 SecurityContext에 Authentication 객체를 저장한다.
출처: https://dev-coco.tistory.com/174 [슬기로운 개발생활:티스토리]
- JWT 발급 과정
- 사용자 인증 요청: 사용자가 ID와 비밀번호를 입력하여 로그인 요청을 합니다.
- 사용자 정보 검증
서버는 사용자가 입력한 ID와 비밀번호를 시큐리티 등을 통해 검증합니다.
사용자 정보가 유효하면 JWT 토큰을 생성합니다. - JWT 토큰 생성
JWT 토큰은 Header, Payload, Signature로 구성됩니다.
Header에는 토큰 타입과 알고리즘 정보가 포함됩니다.
Payload에는 사용자 정보(ID, 이름 등)가 포함됩니다.
Signature는 Header와 Payload를 암호화한 값입니다. - JWT 토큰 반환: 생성된 JWT 토큰을 클라이언트에게 반환합니다.
- JWT 토큰 저장 및 사용
클라이언트는 받은 JWT 토큰을 저장하고, 이후 요청 시 헤더에 포함하여 전송합니다.
서버는 JWT 토큰의 Signature를 검증하여 사용자 인증을 수행합니다.
이와 같은 과정을 통해 JWT 기반 인증이 이루어집니다. JWT는 기존 쿠키/세션 기반 인증 방식의 단점을 보완하여, 보안성과 확장성이 높은 인증 방식을 제공합니다.
[JWT 장단점]
- 장점:
- 보안성: JWT 토큰은 암호화되어 있어 안전합니다.
- 확장성: 토큰 기반 인증이므로 서버 상태 관리가 용이합니다.
- 상태 관리: 세션 정보를 서버에 저장할 필요가 없어 확장성이 높습니다.
- 단점:
- 토큰 유출 위험: 토큰이 유출되면 보안 문제가 발생할 수 있습니다.
- 토큰 크기 제한: JWT 토큰의 크기가 제한적이므로 많은 데이터를 포함할 수 없습니다.
15. N+1 문제의 발생 이유와 해결 방법에 대해 설명해주실 수 있을까요? 해결 방법은 3가지 이상 말씀해주시면 좋습니다.
N + 1문제란 1번의 쿼리를 날렸을 때 의도하지 않은 N번의 쿼리가 추가적으로 실행되는 것을 의미합니다.
첫 쿼리에서 하위 엔티티까지 한 번에 조회하기 않고, 하위 엔티티를 실제로 사용할 때 추가로 조회하기 때문에 발생하는 것입니다.
- 해결 방법
- Fetch Join(패치 조인)
미리 두 테이블을 join해서 한 번에 모든 데이터를 가져오게 되므로 n+1문제가 발생하지 않는다. 1:N 관계가 두개 이상인 경우에는 사용할 수 없고 패치 조인 대상에게 별칭 부여가 불가능합니다. - @EntityGraph
엔티티 조회할 때 연관된 엔티티를 함께 조회하는 기능임니다.
사용 방법은 같이 조회할 연관 엔티티 이름들을 attributePaths 옵션에 작성해주면 됩니다.
(1번은 기본적으로 inner join, 2번은 기본적으로 outer join 을 사용한다.) - Batch Size
Batch Size 옵션을 적용하여 한 번의 쿼리로 관련 엔티티들을 가져올 수 있습니다.
- Fetch Join vs Batch Size
- Fetch Join: 한 번의 쿼리로 모든 연관 엔티티를 가져오는 방식입니다. 데이터 중복이 발생할 수 있어 대량의 데이터를 다룰 때 성능 문제가 발생할 수 있습니다.
- Batch Size: 한 번의 쿼리로 여러 개의 연관 엔티티를 가져오는 방식입니다. Batch Size 값에 따라 가져오는 엔티티 수를 조절할 수 있어 메모리 사용량을 효율적으로 관리할 수 있습니다.
[Fetch Join, @EntityGraph 사용시 주의할 점]
Fetch Join, @EntityGraph 사용시 주의할 점
카테시안 곱이 발생해서 중복이 발생할 수 있다. (두 테이블 사이에 유효 join 조건을 적지 않았을 때 해당 테이블에 대한 모든 데이터를 전부 결함해 테이블에 존재하는 행 개수를 곱한 만큼의 결과가 반환되는 것)
중복 문제 해결 방법
1. JPQL에 DISTINCT 추가해서 중복 제거
2. OneToMany 필드 타입을 Set으로 선언해서 중복 제거
출처: https://dev-coco.tistory.com/165 [슬기로운 개발생활:티스토리]
[각 해결 방법의 장단점]
Fetch Join
- 장점
- N+1 문제를 해결할 수 있습니다.
- 한 번의 쿼리로 관련 엔티티들을 가져올 수 있습니다.
- 단점:
- 패치 조인 대상에 별칭을 줄 수 없습니다.
- 둘 이상의 컬렉션은 페치 조인할 수 없습니다.
- 컬렉션을 페치 조인하면 페이징이 불가능합니다.
@EntityGraph
- 장점:
- 엔티티 조회 시 연관된 엔티티를 함께 조회할 수 있습니다.
- 별칭 사용이 가능합니다.
- 페이징이 가능합니다.
- 단점:
- 컬렉션 관계의 엔티티를 모두 가져오므로 성능 이슈가 발생할 수 있습니다.
- 엔티티 그래프 설정이 복잡할 수 있습니다.
Batch Size
- 장점:
- 한 번의 쿼리로 관련 엔티티들을 가져올 수 있습니다.
- 페이징이 가능합니다.
- 단점:
- Batch Size 값을 너무 크게 설정하면 메모리 사용량이 증가할 수 있습니다.
- 엔티티 간 연관관계가 복잡한 경우 Batch Size 설정이 어려울 수 있습니다.
16. 즉시로딩과 지연로딩은 각각 언제 사용하면 좋은지 설명해주실 수 있을까요?
즉시로딩은 연관된 엔티티나 객체를 처음 엔티티를 로딩할 때 함께 로딩하는 방식입니다. 즉, 부모 엔티티를 조회할 때 관련된 자식 엔티티들도 함께 데이터베이스로부터 조회하여 로드합니다. 연관된 객체나 엔티티들이 대부분의 경우에 함께 사용될 때
지연로딩은 연관된 엔티티나 객체를 실제로 사용하는 시점에 로딩하는 방식입니다. 즉, 부모 엔티티만 먼저 로드하고, 실제로 자식 엔티티에 접근하는 순간에 해당 자식 엔티티들을 로드합니다. 연관된 데이터 중 일부만 자주 사용되거나, 사용 패턴이 다양할 때
17. Spring bean container 생성부터 스프링 종료까지의 사이클에 대해 알려주실 수 있을까요? @PostConstruct, @PreDestroy 어노테이션의 역할도 함께 알려주시면 좋습니다.
- 스프링 컨테이너(ApplicationContext) 초기화
- 스프링 컨테이너는 `ApplicationContext` 인터페이스를 구현한 객체를 통해 초기화됩니다. 이 과정에서 설정 파일(`XML`, `Java Config` 등)을 로드합니다.
- 빈(Bean) 정의 로드 및 빈 인스턴스 생성
- 스프링 컨테이너는 설정 정보를 바탕으로 빈 정의를 로드하고, 이를 기반으로 빈 인스턴스를 생성합니다.
- 의존성 주입(Dependency Injection)
- 생성된 빈 인스턴스의 필요한 의존성을 주입합니다.
- 초기화 콜백
- 모든 속성이 설정되고, 빈이 생성되고, 의존성 주입이 완료되면 초기화 콜백이 호출됩니다. 이때 `@PostConstruct` 어노테이션이 붙은 메소드가 실행됩니다. `@PostConstruct`는 빈의 생명주기에서 초기화 단계 직후에 호출되어야 할 로직을 정의하는 데 사용됩니다.
- 빈 사용
- 스프링 컨테이너가 관리하는 빈들은 이제 애플리케이션에서 사용할 준비가 완료됩니다.
- 소멸 콜백
- 스프링 컨테이너가 종료될 때, 즉 애플리케이션을 종료할 때 `@PreDestroy` 어노테이션이 붙은 메소드가 실행됩니다. `@PreDestroy`는 빈의 생명주기에서 소멸하기 직전에 호출되어야 할 정리 로직을 정의하는 데 사용됩니다.
- 스프링 컨테이너 종료
- 애플리케이션 종료 시 스프링 컨테이너도 함께 종료됩니다.
`@PostConstruct`와 `@PreDestroy` 어노테이션은 빈의 생명주기에 중요한 포인트에서 사용자가 정의한 작업을 실행할 수 있게 해주는 역할을 합니다. `@PostConstruct`는 주로 리소스 생성, 초기화 작업에 사용되며, `@PreDestroy`는 리소스 해제, 정리 작업에 사용됩니다. 이러한 어노테이션들을 사용함으로써 개발자는 빈의 생명주기를 보다 세밀하게 제어할 수 있게 됩니다.
18. AOP, Interceptor, Filter 의 차이점, Request가 들어올때 거치는 순서, 각 역할들의 장점을 설명해주실 수 있을까요?
AOP(Aspect-Oriented Programming), Interceptor, 그리고 Filter 는 모두 Java 및 Spring Framework 에서 요청 처리 과정에 특정 기능을 추가하는 데 사용되는 기술입니다. 각각의 차이점과 요청이 들어올 때 거치는 순서, 그리고 각각의 장점을 설명하겠습니다.
- 순서
1. Filter: Servlet Filter 는 가장 먼저 요청을 처리합니다. 이는 서블릿 컨테이너 단계에서 작동하기 때문입니다.
2. Interceptor: 요청이 Spring 의 DispatcherServlet 에 도달한 후, Controller 로 가기 전에 Interceptor 가 작동합니다.
3. AOP: Interceptor 이후, 메소드 실행 단계에서 AOP 가 적용됩니다. 특정 메소드 호출 전후로 추가적인 작업을 수행할 수 있습니다.
- 차이점 및 역할
- Filter
- 역할: Filter는 주로 인코딩 변환, 로그 및 인증과 같은 요청과 응답을 전처리 및 후처리하는 데 사용됩니다.
- 장점: Servlet API 의 일부이기 때문에 Spring 이 아닌 다른 Java 웹 애플리케이션에도 적용할 수 있습니다. 요청과 응답에 대한 가장 낮은 수준의 접근 권한을 제공합니다. - Interceptor
- 역할: Interceptor 는 Spring MVC 의 컨텍스트 내에서 작동하며, 주로 컨트롤러를 호출하기 전후와 뷰를 렌더링하기 전에 추가 작업을 수행하는 데 사용됩니다.
- 장점: Spring 의 컨텍스트에 통합되어 있어서 Spring 의 다양한 기능(예: DI, 데이터 변환)과 함께 사용할 수 있습니다. 또한 요청 처리 과정에서 세밀한 제어를 가능하게 합니다. - AOP
- 역할: AOP 는 횡단 관심사(cross-cutting concerns)를 분리하여 재사용성을 높이고 코드의 중복을 줄이는 데 사용됩니다. 로깅, 트랜잭션 관리, 보안 등의 공통 기능을 메소드 호출 전후로 삽입할 수 있습니다.
- 장점: AOP 를 사용하면 비즈니스 로직에서 공통 기능의 구현을 분리할 수 있어 코드의 가독성과 유지보수성이 향상됩니다. 또한, 다양한 포인트컷(Pointcut)과 어드바이스(Advice)를 정의하여 세밀한 제어가 가능합니다.
- Filter
- 결론
Filter, Interceptor, AOP 는 각각 다른 단계와 방식으로 요청 처리 과정에 관여합니다. Filter 는 가장 낮은 수준에서 요청과 응답을 처리하는 반면, Interceptor 는 Spring MVC 의 컨텍스트 내에서, AOP 는 메소드 호출의 전후로 작동하여 공통 기능을 추가합니다. 각각의 기술은 특정 상황과 요구 사항에 따라 선택하여 사용할 수 있으며, 함께 사용하여 애플리케이션의 요구 사항을 효과적으로 충족시킬 수 있습니다.
댓글