1. JDBC가 어댑터 패턴을 어떻게 적용하고 있는지?
JDBC에서 데이터베이스 드라이버가 어댑터 패턴을 사용하여 구현되는데, 각 데이터베이스 벤더는 JDBC 표준 인터페이스를 구현한 드라이버를 제공하며 이 드라이버가 어댑터 역할을 한다. 이로 인해 자바 어플리케이션은 다양한 데이터베이스와 상호작용 할 수 있다.
- JDBC 표준 인터페이스 : Connection, Statement, ResultSet 등
- 데이터베이스 드라이버 : 드라이버는 어댑터 패턴을 사용하여 JDBC 인터페이스 호출을 해당 데이터베이스에 맞는 네이티브 호출로 변환
- 드라이버 관리 : DriverManager 클래스는 어플리케이션이 데이터베이스에 연결을 요청하면 DriverManager 는 url을 기반으로 적절한 드라이버를 찾고 연결을 설정
이로 인해 JDBC는 데이터베이스 독립성을 유지하면서도 다양한 벤더의 데이터베이스와 호환될 수 있는 유연성을 갖추게 된다.
2. 트랜잭션 vs 락
⛔ 트랜잭션
데이터베이스의 일관성과 무결성 유지
데이터베이스에서 수행되는 일련의 작업 단위
- 원자성 : 트랜잭션 내의 작업이 모두 성공하거나 모두 실패하도록 보장. 여러 작업 중 하나라도 실패하면 전체 트랜잭션이 취소되고 데이터베이스는 트랜잭션이 시작되기 전 상태로 복구된다.
- 일관성 : 트랜잭션이 성공적으로 완료된 후 데이터베이스의 상태는 모든 정의된 규칙(무결성 제약 조건)을 만족해야 한다.
- 격리성 : 동시에 여러 트랜잭션이 실행될 때 각 트랜잭션은 서로의 중간 상태를 확인할 수 없다. 두 트랜잭션이 같은 데이터를 수정하려고 할 때, 하나의 트랜잭션이 완료될 때까지 다른 트랜잭션은 그 데이터를 변경할 수 없다.
- 지속성 : 트랜잭션이 성공적으로 완료되면 그 결과가 영구적으로 데이터베이스에 반영되어야 한다. 시스템 장애가 발생해도 트랜잭션 결과는 손실되지 않는다.
@Transactional 어노테이션
- 적용 대상 : 메서드 또는 클래스 레벨에 적용
- 기본 동작 : 트랜잭션을 시작하고 메서드가 정상적으로 완료되면 커밋, 예외가 발생하면 롤백을 한다.
⛔ 락
동시에 여러 트랜잭션이 동일한 데이터에 접근하는 경우 데이터의 무결성과 일관성을 유지하기 위해 데이터베이스에서 사용되는 메커니즘
- 공유 락 : 데이터에 대한 읽기 작업을 허용하지만 해당 데이터를 수정할 수 없도록 한다.
- 배타 락 : 데이터에 대한 읽기 및 쓰기 작업을 모두 허용하지 않는다.
3. Spring AOP에서 프록시 패턴을 어떻게 사용하는지?
❓Spring AOP (Aspect-Oriented Programming)
애플리케이션의 주요 비즈니스 로직과 부가 기능을 분리하여 모듈화할 수 있는 프로그래밍 패러다임.
로깅, 트랜잭션 관리, 보안 등과 같은 공통 관심사를 핵심 비즈니스 로직과 분리하여 코드의 가독성, 유지보수성, 재사용성 향상.
- Aspect : 공통 관심사를 모듈화한 것(로깅, 트랜잭션 관리, 보안)
- Join Point : Aspect 가 적용될 수 있는 지점. 주로 메서드 호출 시점
- Pointcut : 특정 Join Point를 선택하는 표현식. Aspect 가 적용될 지점을 정의
- Advice : Aspect 가 Join Point에서 수행하는 동작. 메서드 호출 전후/예외 발생 시점 등에 실행
- Weaving : Aspect 를 대상 객체에 적용하는 과정. 주로 런타임 Weaving을 사용
✅ Spring AOP에서 프록시 패턴 사용
Spring AOP는 런타임에 프록시 객체를 생성하여 Aspect을 메인 비즈니스 로직에 적용한다.
- JDK 동적 프록시 : 인터페이스 기반 프록시 생성. 타겟 클래스가 구현한 인터페이스를 통해 프록시 생성
- CGLIB 프록시 : 인터페이스가 없는 클래스에도 프록시 생성 가능. 클래스 상속을 통해 프록시 생성
서비스 객체가 빈으로 등록이 되면 스프링이 AbstractAutoProxyCreator라는 BeanPostProcessor (어떤 Bean이 등록되면, 그 Bean을 가공할 수 있는 life-cycle interface)로 서비스 빈을 감싸는 프록시 객체(빈)를 만들어 그 프록시 객체를 서비스 대신에 등록해서 사용한다.
4. 프록시 서버란 무엇인지?
➡ 클라이언트와 실제 서버 간의 중개자 역할을 하는 서버
클라이언트의 요청을 받아 실제 서버에 전달하고, 실제 서버의 응답을 받아 클라이언트에 전달한다.
✅ 주요 기능
- 트래픽 제어 및 관리 : 특정 웹사이트에 대한 접근 제한, 특정 유형의 트래픽 필터링
- 캐싱 : 자주 요청되는 웹 페이지나 파일을 캐싱하여 서버 부하를 줄이고 응답 시간 단축
- 보안 및 익명성 제공 : 클라이언트의 IP 주소를 숨기고 실제 서버와의 직접적인 접촉을 막음으로써 보안과 익명성 제공
- 콘텐츠 필터링 : 특정 콘텐츠에 대한 접근 제한, 악성 웹사이트 차단
- 로드 밸런싱 : 여러 서버에 걸쳐 트래픽을 분산시켜 서버 부하를 균형있게 분배하여 서버 성능 최적화
📶 종류
- 포워드 프록시 : 클라이언트가 인터넷에 접속할 때 사용. 클라이언트의 요청을 받아 인터넷으로 전달하고 인터넷의 응답을 클라이언트에 전달한다. 주로 보안 및 익명성을 위해 사용된다.
- 리버스 프록시 : 인터넷에서 들어오는 요청을 받아 내부 서버로 전달하고 내부 서버의 응답을 받아 클라이언트에 전달. 주로 로드 밸런싱, 보안, 캐싱을 위해 사용된다.
- 웹 프록시 : 웹 트래픽을 중개. 클라이언트가 퉵 사이트에 접속할 때 익명성을 유지할 수 있다.
- 오픈 프록시 : 누구나 사용할 수 있는 공개 프록시 서버. 익명성을 제공하지만 보안상 문제가 있을 수 있다.
5. 자바에서 싱글톤을 구현하는 방식이 무엇이 있는지?(즉시 로딩, 지연 로딩, syncronized, double-checked locking, lazy holder, enum 키워드 흐름대로)
🔵 즉시로딩
클래스가 로드될 때 인스턴스를 생성
인스턴스가 사용되지 않더라도 항상 메모리에 올라와있다는 단점이 있다.
public class Singleton {
// 클래스 로드 시 인스턴스 생성
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
🔵 지연 로딩
인스턴스가 처음 필요할 때 생성
멀티스레드 환경에서는 인스턴스가 여러 개 생성될 수 있어 문제가 발생할 수 있다.
public class Singleton {
private static Singleton instance;
private Singleton() {}
// 인스턴스 필요 시 생성
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
🔵 synchronized
지연 로딩 방식에서 스레드 안정성을 보장할 수 있지만 메서드 전체에 동기화를 적용하면 블로킹으로 인해 성능이 저하될 수 있다.
public class Singleton {
private static Singleton instance;
private Singleton() {}
// synchronized 키워드를 사용
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
🔵 Double-Checked Locking
synchronized 키워드 사용의 성능 저하 문제를 해결하기 위한 방법
인스턴스가 이미 생성된 경우는 동기화 블록을 통과하지 않도록 한다.
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
// 인스턴스가 이미 생성된 경우는 동기화 블록 통과하지 않음
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
🔵 Lazy Holder
내부 정적 클래스와 클래스 로더의 매커니즘을 이용한 지연 초기화 방식
내부 정적 클래스는 클래스가 로드될 때 인스턴스가 생성되지 않고 외부 클래스가 처음으로 참조될 때 초기화되는 특징
JVM은 클래스 로딩과 초기화를 스레드 안전하게 처리하기 때문에 별도의 동기화가 필요하지 않음
public class Singleton {
private Singleton() {}
// 내부 정적 클래스 : 싱글톤 인스턴스를 가지고 있음
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
//외부에서 호출할 수 있는 메서드 : 싱글톤 인스턴스를 반환
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
🔵 Enum
enum 타입은 고정된 인스턴스를 가지기 때문에 싱글톤 패턴과 매우 잘 맞다.
JVM에서 싱글톤 인스턴스가 스래드 안전하게 초기화되도록 보장
//enum 클래스 사용
public enum Singleton {
INSTANCE;
public void someMethod() {
// 비즈니스 로직
}
}
6. 콜백이란?
➡ 프로그램 내에서 특정 이벤트가 발생했을 때 호출되는 함수나 메서드
다른 함수에 인수로 전달되며 특정 조건이 만족되거나 이벤트가 발생하면 호출된다.
다른 코드의 인수로서 넘겨주는 실행 가능한 코드로 콜백을 넘겨받는 코드는 필요 따라 즉시 실행할 수도 있고 나중에 실행할 수도 있다.
자바에서는 주로 인터페이스와 람다식을 사용하여 콜백 구현
- 비동기 작업 후에 특정 작업을 수행하기 위해 콜백 사용
- 한 함수가 다른 함수의 결과에 따라 동작을 달리하기 위해 사용
7. 템플릿 메서드 패턴 vs 템플릿 콜백 패턴
템플릿 콜백 패턴은 템플릿 메서드 패턴과 유사하지만 공통 로직이 아닌 하위 클래스에서 구체화된 코드를 호출하는 부분을 자바8 이전에서는 익명 클래스로 구현하고 자바8 이후에서는 람다식으로 구현한다.
'공부 > f-lab' 카테고리의 다른 글
f-lab 17주차 (0) | 2024.07.09 |
---|---|
f-lab 11주차 (0) | 2024.05.28 |
f-lab 10주차 (0) | 2024.05.23 |
f-lab 9주차 (0) | 2024.05.19 |
f-lab 8주차 (0) | 2024.05.07 |