분류 전체보기
[Spring Security6] 주요 구성요소
[Spring Security6] 주요 구성요소
2023.08.04스프링 시큐리티는 SpringBootWebSecurityConfiguration 파일을 제공해 스프링 부트가 자동으로 제공하는 보안 설정을 구성한다. @Configuration(proxyBeanMethods = false) @ConditionalOnDefaultWebSecurity static class SecurityFilterChainConfiguration { @Bean @Order(SecurityProperties.BASIC_AUTH_ORDER) SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests((requests) -> requests.anyRequ..
[Java] 스트림과 병렬 실행
[Java] 스트림과 병렬 실행
2023.08.02데이터 컬렉션을 병렬로 처리하려면 데이터를 작은 단위로 분할하고 분할된 서브파티를 각각의 쓰레드로 할당해서 실행해야 한다. 이 과정에서 쓰레드의 Race Condition이 발생하지 않도록 동기화 해 줘야 하고, 각 쓰레드의 작업 결과를 합쳐 줘야 한다. 몇 개의 쓰레드를 사용하고 결과 변수는 어떻게 동기화 해야 하는지도 함께 고려해 줘야 한다. 스트림은 순차 스트림을 병렬 스트림으로 바꾸는 기능을 제공한다. 스트림을 사용해 병렬 작업을 구현해보자. 컬렉션에서 parallelStream을 호출하면 병렬 스트림이 생성된다. 병렬 스트림은 각각의 쓰레드에서 처리할 수 있도록 스트림 요소를 여러 덩어리로 분할한 스트림으로, 멀티코어 프로세서가 각 덩어리를 처리하도록 할당할 수 있다. public long pa..
[Java] 컬렉션과 스트림
[Java] 컬렉션과 스트림
2023.08.01스트림은 데이터의 흐름을 나타내고, 흐름에 다양한 연산을 수행한다. 선언형으로 컬렉션 데이터를 처리할 수 있고, 이 작업을 병렬로 처리할 수 있다. List expensiveCarNames = cars.stream() .filter(car -> car.getPrice() > 1000) .sorted(Comparator.comparing(Car::getPrice)) .map(Car::getName) .collect(Collectors.toList()); List expensiveCarNames2 = cars.parallelStream() .filter(car -> car.getPrice() > 1000) .sorted(Comparator.comparing(Car::getPrice)) .map(Car::ge..
[Spring Security6] 내부 흐름
[Spring Security6] 내부 흐름
2023.07.30브라우저는 HTTP 프로토콜을 기반으로 서버에게 요청을 보낸다. 자바로 작성한 애플리케이션은 HTTP 프로토콜을 기반으로 사용자의 요청을 처리하는데... 자바 코드는 HTTP 프로토콜을 이해할 수 없다. 따라서 브라우저와 자바로 작성한 애플리케이션을 이어주는 다리가 필요하다. 스프링은 이 다리로 서블릿을 사용한다. 서블릿은 HTTP 프로토콜을 이해하고 처리할 수 있는 자바 코드로 생각하면 된다. 사용자의 HTTP 요청이 스프링으로 구축된 서버에 도착하면 가장 먼저 웹 애플리케이션 서버인 Tomcat이 요청을 받는다. 이후 Tomcat은 서블릿에게 HTTP 요청을 전달하고 서블릿은 요청을 처리한다. 처리된 요청은 Tomcat에게 전달되고, Tomcat은 사용자에게 HTTP 응답을 제공한다. Tomcat은 ..
[Spring] AOP 주의사항
[Spring] AOP 주의사항
2023.07.29스프링은 프록시로 AOP를 적용한다. 스프링 컨테이너는 실제 객체 대신 프록시를 스프링 빈으로 등록해 실제 객체를 직접 호출하는 문제가 발생하지 않을 것 같지만... 실제 객체 내부에서 메서드 호출 시 프록시를 거치지 않고 대상 객체를 직접 호출하는 문제가 발생할 수 있다. @Slf4j @Component public class CallServiceV0 { public void external() { log.info("call external"); internal(); //내부 메서드 호출(this.internal()) } public void internal() { log.info("call internal"); } } @Slf4j @Aspect public class CallLogAspect { @B..
[Spring] 포인트컷 지시자
[Spring] 포인트컷 지시자
2023.07.28@Pointcut("execution(...)") 지금까지 포인트컷을 작성할 때는 AspectJ가 제공하는 execution 지시자를 사용해서 작성했다. execution 지시자를 가장 많이 사용하긴 하지만.. AspectJ는 다른 지시자도 제공한다. 포인트컷을 작성하는 방식을 살펴보자. execution execution(접근제어자? 반환타입 선언타입?메서드명(파라미터) 예외?) ?가 뒤에 붙어있으면 생략 가능함을 의미한다. 선언타입은 패키지명과 클래스명을 모두 포함하고 * 표현을 사용할 수 있다. pointcut.setExpression("execution(public String start.aop.member.MemberServiceImpl.hello(String))"); pointcut.setEx..
[Spring] AOP 적용
[Spring] AOP 적용
2023.07.27애플리케이션 로직은 핵심 기능과 부가 기능으로 나뉜다. 트랜잭션 관리, 보안, 로깅 등 부가기능은 애플리케이션 전반에 걸쳐 사용되는 횡단 관심사이고, 횡단 관심사를 효과적으로 처리하기 위해 AOP 기술이 도입됐다. AOP는 부가 기능을 핵심 기능에서 분리하고 한 곳에서 통합해서 관리한다. 부가 기능과 부가 기능을 어디에 적용할 지 선택하는 기능을 Aspect 라고 부르고, @Aspect 애너테이션으로 사용한다. AOP는 Aspect Oriented Programming 의 약자로 이름 그대로 애플리케이션을 바라보는 관점을 기능에서 횡단 관심사로 옮겨서 바라보는 패러다임이고, OOP의 부족한 부분을 보조하는 목적으로 도입됐다. AOP의 구현 중 AspectJ 프레임워크가 있다. 스프링도 AspectJ의 문..
[Spring] 빈 후처리기
[Spring] 빈 후처리기
2023.07.26AOP를 적용하기 위해 프록시 기술에 대해 알아봤는데... 프록시 기술을 적용해 기존 코드를 수정하지 않고 부가 기능을 적용할 수는 있었지만 추가로 수행해 줘야 하는 설정이 너무 많고 빈 등록도 @Configuration과 @Bean 애너테이션을 통해 수동으로 해 줘야 하는 문제점이 있었다. 요즘은 빈 등록을 ComponentScan 방식으로 수행하는데... ComponentScan을 사용하면 빈 등록 과정에 개발자가 개입할 공간이 없어 그대로 실제 클래스를 빈으로 등록할 수 밖에 없다. 이런 문제를 처리하기 위해 빈 후처리기가 도입됐다. (BeanPostProcessor) 빈 후처리기는 스프링이 빈으로 등록할 목적으로 생성한 객체를 등록하기 직전에 조작할 때 사용한다. 객체는 빈으로 등록되기 전 빈 후..
[Spring] 프록시 팩토리
[Spring] 프록시 팩토리
2023.07.24JDK 동적 프록시와 CGLIB를 동시에 사용하려면 InvocationHandler와 MethodInterceptor를 각각 중복해서 만들어서 관리해야 되나? 아니면 인터페이스가 있으면 JDK 동적 프록시를, 클래스만 있으면 CGLIB를 쓰는 방법은 없을까? 이런 요소들을 해결하기 위해 프록시 팩토리가 도입됐다. 팩토리 패턴은 디자인 패턴 중 하나로 객체 생성 로직을 서브 클래스에게 위임해 인스턴스의 생성을 호출하는 측과 실제 생성되는 인스턴스 측으로 분리하는 역할을 한다. 팩토리 클래스 : 인스턴스를 생성하는 메서드를 제공해 인스턴스를 반환한다. 동적 프록시 클래스 : 해당 클래스의 인스턴스는 팩토리로부터 생성된다. 프록시 팩토리를 도입해 중복을 줄일 수 있고 다른 동적 프록시 기술에 대한 확장성을 얻..
[Spring] 동적 프록시 기술
[Spring] 동적 프록시 기술
2023.07.23JDK 동적 프록시 기술이나 CGLIB 같은 프록시 생성 기술을 활용하면 프록시 객체를 동적으로 만들 수 있다. 이전처럼 프록시 객체를 계속해서 만들지 않고 하나만 만들고 동적 프록시로 적용해보자. 자바의 리플렉션 기술을 사용하면 클래스나 메서드의 메타데이터를 동적으로 획득하고 코드도 호출할 수 있다. @Slf4j static class Hello { public String callA() { log.info("callA"); return "A"; } public String callB() { log.info("callB"); return "B"; } } @Test void reflection1() throws Exception { Class classHello = Class.forName("hello...
[Spring] 프록시 패턴과 데코레이터 패턴
[Spring] 프록시 패턴과 데코레이터 패턴
2023.07.22메서드 실행 단위로 로그를 출력할 때 템플릿 메서드 패턴과 전략 패턴을 사용했지만, 기존 코드를 수정해야 한다는 문제점이 남아있다. 프록시를 사용하면 해당 문제를 해결할 수 있다. 네트워크에서의 프록시는 클라이언트와 서버 사이에서 중개자 역할을 수행한다. 클라이언트는 직접 서버와 통신하는 대신 프록시 서버를 통해서 실제 서버에 요청을 보내고, 프록시 서버는 해당 요청을 받아 실제 서버에 전달한다. 1. 캐싱 : 자주 요청되는 리소스를 캐시로 저장해 클라이언트에게 더 빠르게 응답한다. 2. 필터링 : 특정 서비스에 대한 접근을 차단하거나 제한한다. 3. 로드밸런싱 : 프록시 서버가 요청을 여러 서버에 분산시켜 서버 부하를 줄인다. 4. 보안 : 클라이언트의 실제 IP주소를 숨시고 프록시 IP주소를 사용해 ..
[Spring] 템플릿 메서드 패턴과 전략 패턴
[Spring] 템플릿 메서드 패턴과 전략 패턴
2023.07.19템플릿 메서드 패턴은 변하는 부분과 변하지 않는 부분을 분리하기 위해 사용되는 디자인 패턴이다. 하나의 메서드는 비즈니스 로직을 실행하는 부분과 비즈니스 로직의 실행 시간을 측정하는 부분으로 구성된다. 여기서 핵심 기능은 비즈니스 로직을 실행하는 부분이고, 실행 시간을 측정하는 부분은 부가적인 기능이다. 핵심 기능과 부가 기능을 분리해보자. public abstract class AbstractTemplate { public void execute() { long startTime = System.currentTimeMillis(); call(); long endTime = System.currentTimeMillis(); long resultTime = endTime - startTime; log.in..