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

전체 글 41

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

개발용 서버에선 프로덕션 서버로 배포되기 전 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

내편 리프레시 토큰 도입기

우아한테크코스 4기 과정에서 팀 프로젝트로 내편이라는 서비스를 개발하고 있다. 모임을 만들고 그 모임의 구성원들끼리 롤링페이퍼를 작성할 수 있는 서비스다. 해당 서비스에선 로그인 구현을 1시간 유효기간의 Access Token을 클라이언트에 발급해서 구현했는데, 직접 사용해보고 우테코 내의 다른 크루들의 피드백을 받았을 때 로그인이 너무 자주 풀려서 불편하다는 피드백을 받았다. 그래서 리프레시 토큰 도입을 고민했고 이를 적용한 내용을 기록해볼까 한다. 리프레시 토큰 도입을 고민하게 된 이유 현재 accessToken 유효시간은 1시간인데, 이 시간이 지나면 사용자는 로그인이 풀리게 된다. 너무 자주 로그인이 풀리고, 매번 로그인을 다시 하기 번거롭기 때문에 개선해야 한다. 그럼 accessToken 유효..

Web 2022.10.13

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

저번 포스팅에 있던 내용과 이어질 듯..ㅎ 바로 이전 포스팅 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

DB의 락 기능을 이용해서 동시성 이슈 해결하기 (feat. 우테코 체스미션)

학습 동기 우테코 체스 미션을 하던 도중 한 게임에 대해 동시에 여러 이동 요청이 들어올 시에 발생할 문제점에 대해 피드백 받고 동시성 이슈에 대한 해결법을 찾다 학습. 문제점 상세 설명 체스 DB 구조 체스 미션의 기물 이동 명령은 이동할 기물의 위치와 목적지의 위치를 입력받고 해당 게임의 모든 체스기물을 불러와서 체스 보드를 만든 후에 이동할 수 있는지 도메인 검증을 거친 후 Piece테이블에 game_id와 위치로 조건절 걸고 update 쿼리를 사용하는 방식으로 구현되었다. 만약 동시에 같은 게임에 대해서 이동 명령이 들어온다면 트랜잭션의 독립성 속성에 의해 update 문을 사용하는 두 기물 데이터는 락이 이미 걸려서 뒤에 들어온 트랜잭션이 접근할 수 없지만, 동시에 들어온 두 트랜잭션 작업이 ..

DB 2022.05.24

옵셔널(Optional) 클래스

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

Java 2022.05.02

스프링 컨트롤러 Request Mapping

스프링 프레임웍의 컨트롤러에서는 http 요청이 들어오면 특정 메서드를 실행하고 반환하는 방식으로 작동합니다. 이 포스팅에서는 컨트롤러에서 요청을 처리할 메서드에 매핑하는 기준들에 대해 작성해볼까 합니다! Http Method (요청 방식) http 요청 메세지에는 method라는 것이 존재합니다. 대표적으로 GET, POST, PUT, PATCH, DELETE 5가지가 존재하며, 특별한 역할을 하는 기타 메서드들도 존재합니다. 스프링 컨트롤러에선 이 http 메서드로 요청 매핑을 나눌 수 있습니다. @PostMapping("/http-method/users") public ResponseEntity createUser(@RequestBody User user) { Long id = 1L; return ..

Spring 2022.04.30

상태 패턴 정리

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

Java 2022.04.12