Backend
19 posts
Backend
Spring
September 07, 2024
컴파일러, JIT, AOT, Graal, 그리고 Spring Native 이해하기

컴파일러, JIT, AOT, Graal, 그리고 Spring Native 이해하기 💡 이 포스트에서는 컴파일러, Just-In-Time(JIT), Ahead-Of-Time(AOT) 컴파일, GraalVM, 그리고 이들이 Spring Native와 어떻게 연관되는지에 대해 살펴본다. 이러한 개념들은 자바 및 다른 언어들이 다양한 런타임 환경에서 어떻게 작동하는지 이해하는 데 중요한 역할을 하며, Spring 애플리케이션이 이 기술들을 통해 성능을 최적화할 수 있는 방법을 제공한다. 1. 컴파일러란 무엇인가? 컴파일러는 프로그래밍 언어로 작성된 소스 코드를 기계어로 변환하는 도구이다. 두 가지 주요 컴파일 방식이 있다: 정적 컴파일 (예: javac): 프로그램이 실행되기 전에 소스 코드를 기계어 또는 중간 형태로 변환한다. 자바에서는 파일을 파일(바이트코드)로 변환하는 과정이다. 동적 컴파일 (예: JIT): 프로그램이 실행되는 동안 코드의 일부를 기계어로 변환한다. 2. Jus…

Backend
Spring
SpringSecurity
April 04, 2024
SecurityBuilder와 SecurityConfigurer

SecurityBuilder와 SecurityConfigurer 본 포스팅 시리즈에서 Spring Security는 Spring Boot 2.7.x 버전을 기준으로한 강의를 최신 스프링 공식 문서를 참고하여 수정하였습니다. Deprecated된 여러 메서드들을 최대한 최신에 맞게 바꾸었지만 완벽하지 않을 수 있습니다. 포인터를 잘 알아야 하는 이유 개념 및 구조 이해 는 빌더 클래스로서 웹 보안을 구성하는 빈 객체와 설정 클래스들을 생성하는 역할을 하며 , 가 있다. 는 Http요청과 관련된 보안처리를 담당하는 필터들을 생성하고 여러 초기화 설정에 관여한다. 는 를 포함하고 있으며 인증 및 인가 초기화 작업은 에 의해 진행된다. 시퀀스 다이어그램 에서 를 호출하면, 의 과 가 호출되어 초기화 작업이 진행된다. 의 가 반환하는 최종 클래스는 내부의 가 반환한 이다. 의 가 반환하는 최종 클래스는 내부의 가 반환한 이다. 는 내부에 을 가지고 있다. 내부의 여러가지 필터들을…

Backend
Spring
SpringSecurity
JWT
April 03, 2024
Spring Security 6.2.1 JWT 설정하기

Spring Security 6.2.1 JWT 설정하기 Security Config 클래스 기본 요소 작성 스프링 시큐리티의 인가 및 설정을 담당하는 클래스이다. Security Config 구현은 스프링 시큐리티의 세부 버전별로 많이 상이하다 (이번 시리즈는 스프링 시큐리티 6.2.1 버전) BCryptPasswordEncoder 등록 커스텀 로직 구현 Form 로그인 방식에서는 클라이언트단이 username과 password를 전송한 뒤 Security 필터를 통과하는데 필터에서 회원 검증을 진행을 시작한다. (회원 검증의 경우 가 호출한 를 통해 진행하며 DB에서 조회한 데이터를 를 통해 받음) 우리의 JWT 프로젝트는 에서 formLogin 방식을 disable 했기 때문에 기본적으로 활성화 되어 있는 해당 필터는 동작하지 않는다. 따라서 로그인을 진행하기 위해서 필터를 커스텀하여 등록해야 한다. 🚀 구현 목표 아이디, 비밀번호 검증을 위한 커스텀 필터() 작성 DB에 …

Backend
Spring
March 23, 2024
Servlet Filter 와 Spring Interceptor

Servlet Filter 와 Spring Interceptor 웹과 관련된 공통 관심사는 AOP를 사용할 수도 있지만 서블릿 필터 또는 스프링 인터셉터를 사용하는 것이 좋다. 웹도 관련된 공통 관심사를 처리할 땐, HTTP의 헤더나 URL의 정보들이 필요한데, 서블릿 필터나 스프링 인터셉터는 를 제공한다. 서블릿 필터 서블릿 필터 흐름 여기서 말하는 서블릿은 스프링 디스패처 서블릿이다. 필터 제한 필터 체인 필터는 순서를 지정하여 자유롭게 구성할 수 있다. 사용예시 LogFilter WebConfig 스프링 인터셉터 스프링 인터셉터 흐름 여기서 말하는 서블릿은 스프링 디스패처 서블릿이다. 스프링 인터셉터 제한 스프링 인터셉터 체인 스프링 인터셉터도 체이닝 기능을 사용할 수 있다. 스프링 인터셉터 인터페이스 서블릿 필터의 경우 단순하게 하나만 제공되나, 인터셉터는 컨트롤러 호출 전(), 호출 후(), 요청 완료 이후()와 같이 단계적으로 잘 세분화 되어 있다. 서블릿 필터의 경우 …

Backend
Spring
March 16, 2024
Bean Validation

Bean Validation Spring Framework에서 제공하는 Validator를 사용하여 로직을 분리하는 방법도 있지만, 본 포스팅에서는 더 편리하고 자주 사용되는 방법인 Bean Validation에 대해 다룬다. Bean Validation 관련 라이브러리 추가가 필요하다. 예제 코드 환경 설정 errors.properties 생성 에 errors 추가하여 errors.properties 등록 User 클래스 , , 의 차이는 다음과 같다. : null값을 허용하지 않는다. : null값과 ""(초기화된 String)을 허용하지 않는다. : null값과 "", ” “를 모두 허용하지 않는다. 와 같이 디폴드 메세지를 지정 가능하다. 추가로 어노테이션도 있는데, 이는 Hibernate에서 제공한다. UserController 클래스 Spring에서 자동으로 빈을 등록해주는 를 Autowired해주기 위해 사용 인자로 받는 에 어노테이션을 추가하여 검증 수행 인…

Backend
Spring
March 13, 2024
Spring 로그(log) 사용 및 레벨 설정

로그 로그를 사용하면 다음 이점이 있다. 쓰레드 정보, 클래스 이름 같은 부가 정보를 함꼐 볼 수 있고, 출력 모양을 조정할 수 있다. 로그 레벨에 따라 개발 서버에서는 모든 로그를 출력하고, 운영서버에서는 출력하지 않는 등 로그를 상황에 맞게 조절할 수 있다. 시스템 아웃 콘솔에만 출력하는 것이 아니라, 파일이나 네트워크 등, 로그를 별도의 위치에 남길 수 있다. 특히 파일로 남길 떄는 일별, 특정 용량에 따라 로그를 분할하는 것도 가능하다. 성능도 일반 System.out보다 좋다. (내부 버퍼링, 멀티 쓰레드 등등) 그래서 실무에서는 꼭 로그를 사용해야 한다. spring boot 로깅 라이브러리는 slf4j를 사용한다. slf4j는 인터페이스이며, 그 구현체로 spring boot는 logback을 사용한다. 로그 기본 사용법 로그를 출력한다. @Slf4j 롬복(lombok) 어노테이션을 사용하면 Logger 정의 필요없이 바로 다음과 같이 사용 가능하다. 로그 레벨 설정 …

Server
C++
Backend
January 08, 2024
TLS(Thread Local Storage)

TLS(Thread Local Storage) 쓰레드마다 갖고 있는 로컬 저장소 != 스택 동물원의 호랑이를 생각해보자 공통 영역에서 큼지막한 덩어리를 가져온 다음 필요한걸 꺼내쓰면 처음 가져올 때만 경합이 발생하고 큰 덩어리에서 고를 때는 경합이 필요 없다. TLS 예제 로 받는 난수 id가 아닌 쓰레드마다 직접 id를 할당하고 싶다면? 실행 결과 각 쓰레드 마다 자신의 id를 TLS에 저장했음을 확인할 수 있다. 이를 응용해서 쓰레드별 Stack이나 Queue를 구현할 수도 있다. 이어지는 궁금증… TLS는 스택영역과는 별개의 개념이라고 했다. 그럼 각 쓰레드의 TLS 공간은 전역변수 데이터 영역에 저장되며 다른 쓰레드에 의해 침범될 수 있을까? 이에 관련한 문답을 링크 : Stack overflow 에서 찾았다. TLS 예제 이어지는 궁금증…

Server
C++
Backend
January 08, 2024
CPUPipeline 과 Memory Model

CPU Pipeline 여기서는 Pipeline의 효율 최대화를 위한 코드 재배치에 대해 알아볼 것이며, Pipeline Hazard, RISC, CISC에 관한 내용은 생략합니다. 개요 CPU가 연산 속도를 향상시키고 노는 시간을 최대한 줄이기 위해 CPU 파이프라인을 도입한다는 사실은 익숙하다. CPU는 각 연산 모듈(ALU 등)간 연산 속도, Task당 분배해야하는 시간 등을 고려하여 속도를 최적화 시키기 위해 로직이 엉키지 않는 선에서 코드 재배치를 수행한다. 일반적인 상황(싱글 쓰레드 = 중량 프로세스)에서는 이러한 코드 재배치가 논리 구조를 건드리지 않는 선에서 동작하기 때문에 문제를 일으키지 않지만, 멀티 쓰레드 환경에서는 이야기가 조금 다르다. 쓰레드간 논리 구조가, CPU의 코드 재배치에 의해 엉키게 되면, 나와선 안되는 결과가 나올 수 있다. 따라서 우리는 이러한 코드 재배치를 신경쓰며 멀티 쓰레드 프로그래밍을 해야 한다. 예제 코드 인 상황이 로직상 발생하면 …

Server
C++
Backend
January 07, 2024
Future

Future 동기 vs 비동기 위 코드는 동기적이다. 만약 Calculate가 굉장히 오랜 시간동안 연산하고, 그것을 기다리는 동안 다른 작업을 하고 싶다면? 우리가 배운 내용을 토대로 아래와 같이 작성 가능하다. Thread 이용 thread를 생성 후 task를 위임하여 비동기적으로 작동한다.= 간단한 작업을 하는데도 불구하고, 굳이 쓰레드까지 만들어서 관리하기 귀찮다. -> & 를 통해 해결 가능하다. + async에는 두가지 policy가 있다. Options deferred lazy evaluation : 지연해서 실행하세요 -> 테스트 결과 을 호출할 때가 돼서야 쓰레드로 분기되는듯? async 별도의 쓰레드를 만들어서 실행하세요 deferred | async 둘 중 알아서 골라주세요 + 🏳️이 부분은 아직 모던 C++에 대해 배우지 않아 대충 이해만 하고 넘어갔다. 모던 C++ 학습 후 오른값 참조에 대해 복습해야할 것 + 의 타입은 함수타입과 맞춰줘야 …

Server
C++
Backend
January 07, 2024
Condition Variable

Condition Variable Condition Variable은 Event의 변종 앞선 Event 코드에서… 생산자가 데이터를 넣고 파란불을 켜고, 소비자는 파란불을 확인하고 데이터를 꺼내고 빨간불로 바꾸고… 를 반복하면 q.size()는 0만 출력되지 않을까? 실제로 실행해보면 데이터가 무한정 계속 늘어나는 것을 확인할 수 있다. 왜 데이터가 계속 늘어나는가? 생산자가 데이터를 삽입하고 초록불로 바꿈 소비자는 초록불을 확인하고 빨간불로 바꿈, 진입 !!여기서 생산자가 또 다시 데이터를 삽입하려고 함 소비자는 락을 걸고 큐 사이즈를 읽어야 하는데, 이미 생산자가 락을 건 상태 ㅠㅠ 결과적으로 다음에 운 좋게 락이 풀렸을떄 큐에서 pop하고 사이즈를 읽는데, 이때는 이미 큐에 여러개의 데이터가 삽입된 상태임. Consumer 따라서 이런경우 if 대신 while을 사용하여 큐를 전부 비워주는 등의 조치를 취해야 함. Condition Variable 💡 참고 : CV는 Use…

Server
C++
Backend
January 07, 2024
Event

Event 난 소중하니 직원한테 부탁 (갑질메타) 예제 생산자() 쓰레드는 10초 마다 한번씩 생산하고, 소비자() 쓰레드는 바쁜 대기를 통해 계속해서 CPU 코어를 점유함. 한 번 데이터를 소비하기 위해 10초동안 코어를 점유하는 것은 너무나 비효율적임. 큐에 데이터가 들어올때 알려주는 무언가가 있으면 좋을 것 같다. => Create Event HANDLE CreateEventW(LPSECURITY lpEventAttributes, BOOL bManualReset, Bool bInitialState, LPCWSTR lpName) 는 커널에서 만들어주기 때문에 라고도 불린다. 커널에서 관리하는 오브젝트다. Usage Count : 해당 오브젝트를 사용중인 프로세스나 쓰레드의 수. 커널 오브젝트가 공통으로 가진다. Signal / Non-Signal : 파란불, 빨간불 << bool Auto / Manual : 예제에선 Auto HANDLE은 int와 같은 숫자를 의미한다. ex…

Server
C++
Backend
January 06, 2024
Sleep

Sleep sleep_for, yield Spin Lock 코드에서 이어서 을 통해 일정 시간 CPU 제어권을 넘겨줄 수 있음 는 과 같으며 딱 한번 제어권을 넘겨줌. 프로세스가 block 상태로 전이 sleep_for, yield

Server
C++
Backend
January 06, 2024
SpinLock

Spin Lock lock이 해제될때까지 바쁜 대기(busy waiting) 스핀락은 유저 레벨에서 무한 while 루프를 돌고 있기 때문에 쓰레드 교체를 하지 않고 계속 CPU 자원(코어를 계속 점유)을 소모하면서 버티는 것 -> 컨텍스트 스위칭이 발생하지 않음. Spin Lock 구현 ver 1. 실행 결과 ⭐️ TIP C++ 에서의 키워드 : 최적화를 하지 말아달라. 왜 0이 안나오는가 ?? 락이 걸려있는가를 확인한다. 걸려있지 않으면 락을 걸고 통제권을 획득한다. 위 경우에서 만약 두 쓰레드가 i. 번을 동시에 확인하여 락이 걸려있지 않음을 확인한다면? 통제권을 함께 얻는 경우가 발생함. -> i, ii 가 한 묶음으로 동작하지 않음! 즉, 원자성이 보장되지 않음. 해결방안 -> 가 한 묶음으로 동작해야 함. ver 2. ⭐️ TIP 에는 volatile이 포함되어 있다! 실행 결과 참조 링크 CAS 란? Spin Lock 구현 ver 1. ver 2.

Server
C++
Backend
January 05, 2024
MutexLock

Mutex atomic은 일반적인 상황에서 쓰이기 힘들다. 객체에 대한 원자성을 보장해야 하는 일이 훨씬 많기 때문 Mutex 문제 발생 코드 실행 결과 오류 발생 이유 : vector는 크기가 2^n에 도달했을때 기존 capacity의 두배가 되는 공간을 새로 할당받고 기존 공간을 없애는데, 원자성 보장이 되지 않기 때문에, 이미 없어진 공간을 다시 없애려 하기 때문. 으로 미리 20000크기의 공간을 할당받으면 오류는 사라지지만, 여전히 원자성은 보장이 되지 않아 결과가 20000이 나오지 않음. Mutex Lock 실행 결과 mutex lock을 통해 상호배제 달성 속도는 기존보다 많이 느려짐. mutex lock은 재귀적으로 걸 수 없음. m.lock(); m.lock();을 연속으로 하면 crash발생. 재귀적 lock을 허용하는 recursive mutex에 관해서는 추후 학습. RAII(Resource acquisition is initialization) 패턴 래퍼 …

Server
C++
Backend
January 05, 2024
Atomic

원자성 각 쓰레드가 임계영역에서 경쟁(경합)할때, 공유자원에 대한 일관성이 보장되지 않는다. a++의 경우 load a a + 1 store a 위 과정이 CPU instruction level에서 일어나는데, 이 중간과정에 다른 쓰레드의 instruction이 개입하면 결과의 일관성이 보장되지 않음. atomic 을 통해 통합 원자성 라이브러리를 추가할 수 있다. int 사용 실행 결과 atomic 사용 실행 결과 atomic의 경우, 일반 int와의 구분을 위해 , 등과 같이 사용하는 것이 좋다. 그냥 을 사용해도 똑같이 동작한다. 내부적으로 오버로딩이 되어있기 때문. atomic int 사용 atomic 사용

Server
C++
Backend
January 05, 2024
C++ 쓰레드

C++ 쓰레드 Windows IOCP기반 Stateful Server 구현에 관한 학습 내용을 정리한 것입니다. Linux OS 및 epoll 기반의 서버 구현과는 다소 차이점이 있을 수 있습니다. 쓰레드 기본 하나의 프로세스는 여러개의 쓰레드로 분리할 수 있다. 쓰레드는 같은 프로세스 내의 힙과 데이터 영역을 공유하고, 개별적인 스택영역을 갖는다. TCB를 통해 관리된다. CPU 코어 개수 = 쓰레드의 개수 일 때 가장 이상적(ideal)임. api Type.h를 통해 타입의 이름이 변경된 부분이 있습니다. 예) int32, int64, … : 쓰레드의 id 확인, 유효하지 않은 쓰레드는 0 : 사용 가능한 CPU 코어 개수 확인 : 쓰레드를 stb::thread 객체에서 분리. 더 이상 join할 필요 없음 linux의 데몬 프로세스와 유사함. : 해당 쓰레드가 join 가능한 상태인지 확인. : 쓰레드 종료를 기다림 인자가 있는 쓰레드 실행결과 쓰레드…

Backend
Spring
November 21, 2023
Meta Annotation이란?

Meta Annotation 김영한님 스프링 강의 복습 중, 위 어노테이션을 사용법이 궁금해서 찾아봤다. 위 어노테이션은 에서 끌어다 썼는데, 무슨의미일까? meta-annotaiton 은 다른 에서도 사용되는 의 경우를 말하며 custom-annotation 을 생성할 때 사용된다. @Target 은 Java compiler 가 annotation 이 어디에 적용될지 결정하기 위해 사용한다. 예를 들어 위에서 사용한 의 ElementType.TYPE 은 “해당 Annotation 은 타입 선언 시 사용한다는 의미”이다. 종류는 다음과 같다. ElementType.PACKAGE : 패키지 선언 ElementType.TYPE : 타입 선언 ElementType.ANNOTATION_TYPE : 어노테이션 타입 선언 ElementType.CONSTRUCTOR : 생성자 선언 ElementType.FIELD : 멤버 변수 선언 ElementType.LOCAL_VARIABLE : 지역…

Backend
Spring
October 02, 2023
Spring Bean 조회하기

Spring Bean 조회하기 Spring을 쓰다보면, Bean이 잘 들어갔는지, 싱글톤이 유지되는지 등 다양한 이유로 Bean을 조회할 일이 많다. 매번 검색으로 찾아봤는데, 일반 빈 조회와 어플리케이션 빈 조회 로직이 헷갈려서 자꾸 까먹는다. 그래서 여기에 Bean 조회 방법을 정리해둔다. JUnit Test로 작성되었다. Spring Bean 조회하기

Backend
Spring
React
July 11, 2023
Spring React간 CORS 이슈 트러블슈팅(WebMvcConfigurer)

Spring React간 CORS 이슈 트러블슈팅 백엔드 Spring, 프론트엔드 React로 풀스택 개발 중, CORS에러를 마주하여 이에 대한 트러블슈팅 기록을 남겨둔다. 기존에는 React를 빌드한 결과물을 Spring의 경로에 넣고 Spring서버를 실행하면 별 다른 이슈가 발생하지 않았는데, 이번에 React와 Spring을 서로 다른 포트에서 개방할 경우, CORS에러가 발생한다. CORS란? Cross-Origin-Resource-Sharing의 약자로 서로 다른 출처에서 리소스를 공유하는 것을 뜻한다. React클라이언트의 경우, GET방식으로 API를 요청할때 다음과 같은 URL을 사용한다.(포트 3000) 이 URL에서 Origin을 나타내는 부분은 Protocol, Host, Port 부분이다. 즉, 과 은 서로 다른 Origin으로 구분된다. 만약 localhost로 테스트한다고 하면, , 은 서로 다른 origin이다. 스프링부트 서버에 http://lo…