전체 글

저의 지식이 세상에 가치를 더하길 바라는 백엔드 지망생입니다.
토비님의 유튜브 영상을 보던 중 내부 클래스를 스프링 컨테이너에 등록 가능한지 확인해보는 컨텐츠가 있었다. 제목을 읽고 확실히 답을 해볼 수 없었기에 영상을 기반으로 정리를 해보고자 한다. 내부 클래스 vs 정적 중첩 클래스 분석에 앞서, 기존에 헷갈렸던 개념에 대해 한번 정리를 하고자 한다. @Configuration public class NestedClass { @Component public static class StaticNestedClass{ } public static void main(String[] args) { // 외부 클래스와 상관 없이 생성 가능! StaticNestedClass staticNestedClass = new StaticNestedClass(); } } 위의 코드에서..
· Git & Github
오랜만에 글을 작성하는 것 같습니다. 오늘은 Pull Request 과정에서 번거로움을 느꼈던 작업들을 자동화하는 방법에 대해 살펴볼까 합니다. 우리는 PR을 진행할때 누구에게 리뷰를 받을지, PR의 담당자는 누구인지 그리고 어떤 라벨에 해당하는지를 설정한다. 이 과정에서 별도의 설정이 없다면 수동으로 인원을 할당하고 라벨을 직접 선택해야한다. 아직 서비스 규모가 작고 PR 주기가 길다면 그리 귀찮지 않을 수 있다. 하지만 PR의 단위를 작게 가져가는 방향으로 협업 방식이 개선되고, 하루에도 몇 십번씩 PR, Merge, 배포를 진행하는 팀이 된다면 이 반복적인 일은 꽤나 귀찮게 다가올 것이다. 비효율을 개선하고 싶었고, PR을 올리기만 하면 자동으로 할당해주는 방법을 찾아봤다. 그러던 중 Github ..
공유 자원에 대한 동시 접근을 제어하기 위해 우리는 락 메커니즘을 사용할 수 있고, 그중에서도 분산 서버 환경에서 동시성을 제어하기 위해 분산락을 사용할 수 있다. 분산락을 적용하는 것만으로도 대부분의 동시성 문제를 해결할 수 있다. 하지만 대규모 분산 환경에서는 외부 시스템과의 연결 문제, 네트워크 지연 문제 등 우리가 예측할 수 없는 예외 상황이 얼마든지 발생할 수 있다. 지금부터 예외가 발생할 수 있는 시나리오를 재현해보고, Redis 기반의 분산락과 JPA의 낙관적 락을 함께 적용해서 문제를 해결하는 과정을 알아보자. 또한 락을 사용하게 되면 비즈니스 로직에 락을 획득하고 해제하기 위한 코드가 침범하게 된다. 이를 방지하기 위해 락 관련 코드를 AOP로 추출하는 과정까지 진행해보도록 하자. 발생 ..
인턴을 진행하면서 실제 실무에서 사용하는 코드를 접할 수 있는 기회를 가지게 됐다. 객체 지향의 장점을 살리기 위한 다양한 디자인 패턴들이 코드에 자연스럽게 녹아있는걸 알 수 있었다. 최근 클린 아키텍처에 대한 관심이 커져서 패키지 구조나 계층 간 매핑 전략 등에 신경을 많이 쓰고 있었지만, 이번을 계기로 객체 지향의 특징을 잘 지키는 코드를 작성하는 방법에 대한 고민을 많이 하게 되었다. 그러던 중, 망나니 개발자님의 블로그 글 중에 팩토리 패턴에 대한 글을 발견했고, 앞으로 팀 프로젝트나 실무에서 많이 사용할만한 패턴인 것 같아서 블로그에 정리를 하려고 한다. // 구체 클래스들이 구현하게 될 LoginService 인터페이스이다. public interface LoginService { // if-..
· DevOps
현재 진행하고 있는 프로젝트에서 Github Actions을 통해 CI를 구축했다. Travis CI처럼 유료 전환이 되는 것도 아니고, 젠킨스처럼 별도의 젠킨스 서버를 구축하지 않아도 된다는 점이 Github Actions의 큰 장점이라고 생각한다. 무엇보다 사용하기가 매우 간편하다. 오늘은 Github Actions에서 Gradle을 캐싱해서 사용하는 방법에 대해 공유하고자 한다. 왜 Gradle을 캐싱해서 사용해야 하는가 Gradle은 빌드할때 의존성 패키지들을 모두 다운받는다. 이때 Gradle은 빌드 시간과 네트워크 통신을 줄이기 위해 의존성 패키지를 캐싱해서 재사용하는 방법을 사용한다. 하지만 Github Actions의 workflow는 매 실행하다 새로운 환경을 구축하고, 매번 새롭게 의존..
· Spring/JPA
현재 진행하고 있는 프로젝트의 메인 페이지를 페이징 기능을 사용해서 구현했다. 모바일 환경에 최적화해서 개발했기 때문에 Offset과 Limit을 사용한 게시판 형식의 기본 페이징이 아닌, 무한 스크롤 방식을 사용하기로 결정 했다. 아래에 보이는 망고플레이트의 페이징 기능을 구현했다고 보면 된다. 제목에서 설명한대로 무한 스크롤을 구현하기 위해서 No Offset 방식과 Slice를 사용했는데, 두 가지 방식이 무엇이고, 왜 사용해야 하는지 알아보자. No Offset 방식은 무엇이고 왜 사용하는가 기존의 페이징은 offset과 limit을 사용해서 페이징할 범위를 정한다. 이 방식은 초반에는 효율이 나쁘지 않지만 뒤로 갈수록 효율이 급격히 떨어진다는 단점이 있다. 왜 이런 현상이 발생하는지 알아보자. ..
· Database
Naver D2의 트랜잭션 관련 아티클을 정리해보려 한다. 프레임워크 레벨에서만 적용하던 트랜잭션의 내부 동작 방식을 자세히 공부할 수 있는 좋은 기회였다. 트랜잭션 종료의 3가지 상태 - 문제 없이 정상적으로 커밋 - 롤백(철회) - 시스템 문제로 인한 DBMS 서버의 재시작 트랜잭션 관리를 위한 DBMS의 전략 위의 사진처럼 DBMS는 크게 질의 처리기와 저장 시스템으로 구성되어있다. MySQL을 예로 든다면 MySQL 엔진과 스토리지 엔진을 말한다. DBMS는 대부분의 데이터를 디스크에 저장하지만 데이터의 일부는 메인 메모리에 유지한다. 이 메인 메모리 영역을 페이지 버퍼라고 하고, MySQL에서는 InnoDB 버퍼 풀을 지칭한다. 페이지 버퍼를 관리하는 모듈을 버퍼 관리자라고 하는데, 이 모듈의 ..
현재 진행하고 있는 프로젝트에서 로그인 로직을 Spring security와 JWT로 구현했다. 구현 중에 인증 예외와 JWT 관련 예외 처리를 분리하기 위해 많은 노력을 했는데 이 과정을 공유하고자 한다. 우선 로그인하지 않은 사용자가 허용되지 않은 API에 접근할때 발생하는 인증 예외의 메커니즘에 대해 살펴보자. 기본 인증 예외 처리 방법 SpringConfig 클래스에는 위의 사진과 같이 권한 설정이 되어있다. /api 로 시작하는 API로는 비 로그인 사용자가 접근할 수 없다. API를 호출하면 위와 같은 응답이 반환되도록 설정했다. 응답은 AuthenticationEntryPoint에서 커스터마이징했다. AuthenticationEntryPoint의 코드를 살펴보자. public class Re..
Jemlog
깊게 자라기