무지를 아는 것이 곧 앎의 시작

Java 19

분산락 언제 잡고 어떻게 잡는게 좋을까

프로젝트 진행하다 보면 동시성 이슈를 해결해야할 때가 있다. 최근 사이드 프로젝트에 북마크 기능을 구현할 때 어떻게 동시성 이슈를 잡았었고 어떤 고민을 해서 잡는 방법을 채택했는지 기록해볼까 한다. 도메인 간단 이해 일단 도메인 구조를 보면, Place(장소)라는게 있고, 이 장소에 북마크를 찍는개념으로 해서 Bookmark(북마크)가 있고 1(장소):N(북마크)로 되어있다. 그리고 Place 리스트를 조회할 때 bookmark 갯수가 같이 노출돼야하기 때문에 성능 최적화를 위해 bookmarkCount라는 컬럼을 Place가 반정규화해서 들도록 했다. /// imports... /// annotations... public class Place extends AbstractRootEntity { @Id..

CS 2023.10.09

내편 로깅 정책 정리

요청정보 로깅에 대한 변천사 아 인터셉터에서 Request Body 로그 찍고싶다.. 요청 정보는 서비스 로직 시작 전에 찍어야지..? 요청로깅 AOP로 해야겠다 로깅 성능에 대한 고민 로깅 성능에 대한 고민 작업 트레이스 로깅 로그 잘 남기면 디버깅이 수월해짐 위 과정들을 통해 로깅 정책을 픽스한다. 로그 레벨 프로덕션 서버: 루트레벨 info, 어플리케이션 패키지 info 개발 서버: 루트레벨 info, 어플리케이션 패키지 debug 로컬: 루트레벨 info, 어플리케이션 패키지 debug 로그 관리 프로덕션 서버: 롤링 파일 어펜더를 사용해서 1일마다 최대 10mb 단위로 잘라서 압축 관리, 최대 14일치 보관 개발 서버: 파일 어펜더를 사용해서 파일을 남김. 서버 재실행마다 초기화 로컬: 콘솔창에..

Spring 2022.10.24

로그 잘 남기면 디버깅이 수월해짐

개발용 서버에선 프로덕션 서버로 배포되기 전 QA작업이 이뤄지고, 프론트엔드와의 협업시 사용되기 때문에 로컬에서 발견하지 못한 버그를 발견하게 되는 케이스가 꽤 잦았다. 하지만, 부실한 로그를 남기고 있었다면, 개발 서버 자체에서 버그의 발생 경로를 추측하는 데에 어려움이 있었다. 그래서 프로젝트의 로깅 정책에 debug레벨로 개발서버와 로컬 환경에서 모든 작업에 대한 트레이싱 정보를 남기는 정책을 추가했다. 왜 개발용 서버에서만 트레이싱 로그를 남겨야 하는가 로컬 환경에서 버그를 발견했다면, 대부분의 개발자는 IDE의 디버깅 모드로 디버깅을 시도할 것이다. 하지만, 로컬 환경이 아니라 서버에 올라간 프로그램의 경우 IDE의 기능을 이용할 수 없기에 어플리케이션이 남겨놓은 로그에 디버깅을 의존하게 된다...

Spring 2022.10.23

요청로깅 AOP로 해야겠다

2022.08.17 - [개발 이야기/Spring] - 아 인터셉터에서 Request Body 로그 찍고싶다.. 아 인터셉터에서 Request Body 로그 찍고싶다.. 요즘 우테코 레벨3과정의 팀 프로젝트를 하고 있다. 팀원끼리 업무 나눠서 분업하고 있는데 로깅을 맡게 되었다. 로깅 전략을 세우다 보니 모든 Http 요청에 대한 정보를 찍을 필요성을 느꼈다. alexander96.tistory.com 2022.09.26 - [개발 이야기/Spring] - 요청 정보는 서비스 로직 시작 전에 찍어야지..? 요청 정보는 서비스 로직 시작 전에 찍어야지..? 저번 포스팅에 있던 내용과 이어질 듯..ㅎ 바로 이전 포스팅 2022.08.17 - [개발 이야기/Spring] - 아 인터셉터에서 Request Bo..

Spring 2022.10.23

요청 정보는 서비스 로직 시작 전에 찍어야지..?

저번 포스팅에 있던 내용과 이어질 듯..ㅎ 바로 이전 포스팅 2022.08.17 - [개발 이야기/Spring] - 아 인터셉터에서 Request Body 로그 찍고싶다.. 아 인터셉터에서 Request Body 로그 찍고싶다.. 요즘 우테코 레벨3과정의 팀 프로젝트를 하고 있다. 팀원끼리 업무 나눠서 분업하고 있는데 로깅을 맡게 되었다. 로깅 전략을 세우다 보니 모든 Http 요청에 대한 정보를 찍을 필요성을 느꼈다. alexander96.tistory.com 여기서 보면 스프링 인터셉터의 afterCompletion에서 로그를 찍고 있다. 왜 afterCompletion에서 찍게 됐냐면 바로 RequestBody가 스트림 형태로 들어오기 때문. 스트림은 한번 소비하면 다시 못쓰기 때문에 로깅에서 써버..

Spring 2022.09.26

아 인터셉터에서 Request Body 로그 찍고싶다..

요즘 우테코 레벨3과정의 팀 프로젝트를 하고 있다. 팀원끼리 업무 나눠서 분업하고 있는데 로깅을 맡게 되었다. 로깅 전략을 세우다 보니 모든 Http 요청에 대한 정보를 찍을 필요성을 느꼈다. 모든 요청에 대한 공통 처리이니 '아 스프링의 인터셉터에서 로그 찍음 되겠네!' 싶었다. 찍고싶은 요청 정보는 HTTP Method, Request URI, AccessToken 존재 여부, Request Body 정도였다. Interceptor는 preHandle이라는 메서드에서 파라미터로 HttpServletRequest 가 들어오고 여기서 요청 정보를 뽑을 계획이었다. 그래서 짠 코드 @Slf4j @Component @RequiredArgsConstructor public class LoggingInterce..

Spring 2022.08.17

[JPA] 즉시 로딩과 지연 로딩, 지연 로딩을 써야하는 이유

JPA에서는 연관 관계로 설정된 엔티티를 조회할 때 즉시 로딩과 지연 로딩 두 가지 방식이 있다. 당장 지연 로딩으로 검색을 해보면 두 방식중 지연 로딩이 즉시 로딩보다 권장되는 분위기다. 이번 포스팅에선 즉시 로딩과 지연 로딩의 차이점과 왜 두 방식중 지연 로딩이 추천되는 지 알아보려 한다.🧐 학습테스트 준비 Team 엔티티 @Entity public class Team { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String teamName; @OneToMany(mappedBy = "team") private List members = new ArrayList(); protected Team() {..

JPA 2022.07.26

옵셔널(Optional) 클래스

아이템55. 옵셔널(Optional) 자바 8 이전 메서드가 특정 조건에서 값을 반환할 수 없을 때 취할 수 있는 선택지 예외를 던진다. null을 반환한다. 위 두 방법의 문제점. 예외는 예외적인 상황에만 사용해야 하며, 예외를 생성할 때 스택 추적 전체를 캡처하므로 비용도 만만치 않다. null을 반환하도록 메서드를 구현하면, NPE를 고려해서 클라이언트에서 항상 null체크를 해야함. NPE(NullPointerException)이 무서운 이유 근본적인 원인 즉, null을 반환한 부분에서 예외가 발생하는 것이 아니라, 원인과 상관 없는 부분에서 그 값을 사용하려할 때 예외가 발생하기 때문에 발생 시점을 추적하기 번거롭다. 지비8 이후 null처리의 구원자 Optional Optional은 null..

Java 2022.05.02

상태 패턴 정리

상태 패턴은 현재 상태에서 어떤 행위를 했을 때 그 행위를 실행하고 다음 상태를 반환하는 것을 말합니다. 무슨 뜻이냐면, 어떤 상태라는 것을 인터페이스로 추상화 하고 그 인터페이스에 행위 메서드들을 정의합니다. 그리고 특정 상태를 나타내는 구체 클래스들을 구현하고, 그 상태에서 하는 행위마다 다음 상태를 반환하도록 메서드를 구현합니다. 설명은 이게 전부고 바로 코드로 알아보죠.🧐 초등학교 시절 게임방에서 100원 넣고 했던 격투 게임이 떠올라서 그걸 토대로 상태를 한번 디자인 해봤는데요.👊 게임 캐릭터를 기준으로 상태를 한번 정의해봤어요! 일단 구조를 파악할 수 있게 클래스 다이어그램을 봅시다! CharacterState에서는 게임 캐릭터가 할 수 있는 모든 행위를 정의! public interface ..

Java 2022.04.12

타입 안전 이종 컨테이너

아이템33 타입 안전 이종 컨테이너 타입 안전 이종 컨테이너란?🧐 컨테이너 Set, Map, List 등 여러 요소를 담는 컬렉션들과 ThreadLocal, AtomicReference등 단일원소를 담는 클래스들. 타입 안전 이종 컨테이너 여러 타입을 안전하게 담을 수 있는 컨테이너 List는 오직 Integer 타입만 담을 수 있음. 그럼 여러 타입을 담게 하려면 어떻게 해야할까? Object에 저장하기 public class ObjectContainer { public static void main(String[] args) { List container = new ArrayList(); container.add("1"); container.add(1); container.add(1L); contai..

Java 2022.04.05