들어가며프로젝트를 진행하다 보면 로깅의 중요성을 몸소 느끼게 됩니다. 오디 프로젝트 초기만 해도 모니터링 시스템이 구축되지 않아, QA를 진행하는 데 어려움이 있었습니다. 적절한 로깅은 빠른 문제 해결에 큰 도움이 됩니다. 프로젝트에서 모니터링 시스템을 구축한 경험을 바탕으로, 로깅과 모니터링 구축 방법을 공유하고자 합니다. 스프링 부트 기반 애플리케이션의 로깅 시스템을 처음 다뤄보는 분들께 도움이 되길 바랍니다.로그와 로깅우선 정의부터 하겠습니다. 로그(log)란 시스템이나 애플리케이션에서 발생하는 사건이나 상태를 기록한 데이터를 의미합니다. 로깅(logging)은 로그를 수집하는 행위입니다. 개발에서 로깅은 중요합니다. 특히, 에러 상황을 빠르게 인지하고 디버깅하는데 용이합니다. 이 밖에도 성능 분석..
sql 파일로 더미 데이터를 생성하던 중 이런 리뷰를 받았습니다.production, test 모두 실제 데이터를 쿼리로 넣는 것은 좋은 방법은 아닐 것 같습니다!이렇게 쿼리로 작성하면 어떤 문제가 있을까요? 쿼리로 데이터를 넣었던 이유는 쉽고 빠르기 때문이었습니다.그러나, 왜 좋은 방법이 아닐까요? '비즈니스 로직을 타지 않는다'는 점입니다. 직접 쿼리로 데이터를 넣으면 테이블에 걸려 있는 제약 조건 외에는 검증이 되지 않아, 데이터의 신뢰성이 떨어질 수 있습니다.데이터 무결성과 정합성도 보장할 수 없습니다. varchar로 정의된 날짜 칼럼에 "abc" 같은 문자열이 들어갈 수도 있을 것이고, 외래키 제약이 걸려 있지 않다면 존재하지 않는 id를 참조하게 될 수도 있을 것입니다. 비즈니스 로직을 잘 ..
스프링 부트로 웹 애플리케이션을 만들다 보니, controller 또한 테스트의 영역이 되었습니다.아래 코드는 예약을 생성하는 api입니다. controller 로직을 어떻게 테스트할 수 있을까요? 웹 애플리케이션에 대해 알지 못했다면아래 코드처럼, 직접 createReservationByLoginMember 메서드를 호출하여 단위테스트로 구현했을 것 같습니다. 그러나, 이런 방식으로 controller를 테스트하진 않겠죠.왜일까요? 웹 애플리케이션에서 controller의 동작의 핵심은 HTTP 요청을 받아, 관련 모듈에게 협력을 요청하고 응답을 생성하여 다시 반환해 주는 것입니다. 즉, 웹 애플리케이션의 요청과 응답 사이의 상호 작용을 담당합니다. 이 부분까지 테스트를 하려면 어떻게 하면 좋을까요? ..
레벨 2가 되어 스프링 프레임워크로 미션을 진행하게 되었습니다.DB 사용하는 테스트를 작성해야 했는데요, 이런 리뷰를 받게 되었습니다.@DirtiesContext를 사용하셨군요.프로젝트가 커지면 어떤 문제가 있을 수 있나요? 테스트 격리를 위해 @DirtiestContext를 사용하는 것이 어떤 문제가 있을까요?문제점을 알아보고, 더 좋은 방안은 없는지 알아보겠습니다. @DirtiestContext우선, @DirtiestContext이 어떤 역할을 하는지 알아보겠습니다.Test annotation which indicates that the ApplicationContext associated with a test isdirty and should therefore be closed and removed..
레벨 2의 시작드디어 스프링 프레임워크로 웹 애플리케이션을 만드는 레벨 2가 시작됐다. 레벨 1까지만 해도 자바 콘솔 애플리케이션을 만들었다. 이번 레벨에서도 읽기 좋은 코드, 유지보수하기 좋은 코드를 작성하기 위한 공부를 이어나간다. 레벨 1을 지나며 절실히 느꼈던 것은 목표를 지속해서 상기시켜야 한다는 점이다. 짧은 시간에 많은 학습 키워드가 지나가고 2달가량의 시간이 흘렀다. 자칫 정신을 잃고 있으면 내가 무엇을 하고 있지?, 왜 하고 있지? 하는 생각이 든다. 레벨 2에서는 목표를 잘 잡고 계속 상기시키기 위한 노력을 이어나갈 것이다. 뭘 얻고 싶니?미션을 시작하기 전까지 목표는 스프링 마스터였다. 스프링의 동작 원리를 잘 이해하고, 스프링으로 읽기 좋은 코드를 작성하는 역량을 기르는 것이었다. ..
빈으로 등록해서 사용하셨군요. @component 와는 어떤 차이가 있나요 방탈출 예약 관리 미션을 하면서 이런 질문을 받았습니다. 왜 repository에는 @Repository 애너테이션을 붙이는 걸까요? @Component를 붙이면 안 될까요? 어떤 차이가 있는 지 알아보겠습니다. @Repository @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Repository { /** * Alias for {@link Component#value}. */ @AliasFor(annotation = Component.class) String value() default ""..
상태를 유지하며 일련의 시나리오를 테스트하고 싶으시다면 Junit의 DynamicTest를 활용해 보시면 좋을 것 같습니다. 지금처럼 상태를 공유하는 단위테스트는 지양하시는 것이 좋습니다. 체스 미션을 하면서 받았던 피드백입니다. 상태를 공유한다는 의미는 무엇일까? 시나리오 테스트는 무엇이고, DynamicTest는 어떻게 할 수 있을까? 코드를 수정해가며 알아보겠습니다! Bad 우선 문제의(?) 테스트 코드의 일부입니다. 게임의 상태 `GameStatus`를 전역변수로 공유하여 사용하고 있습니다. GameStatus gameStatus; // 상태를 공유하는 부분 Board board = new InitialBoardFactory().generate(); @BeforeEach void setUp() {..
Board를 어떻게 만드는지에 대한 제어를 하고 싶으시다면 제어하고 싶은 영역의 의존성을 역전시켜 보면 좋을 것 같습니다. 체스 미션을 수행하던 중 이런 리뷰를 받았었습니다. 왜 의존성 역전을 제안 하셨을까? 또 어떤 장점이 있을까? 기존 코드는 이러했습니다. public class Board { private static final List INITIAL_BOARD = List.of( "RNBQKBNR", "PPPPPPPP", "........", "........", "........", "........", "pppppppp", "rnbqkbnr" ); private final Map board; private int turnCount; private Board(Map board, int turnC..
블랙잭 미션을 수행하면서 이런 피드백을 받았었습니다. 돈과 관련된 건 BigDecimal을 사용해 보면 좋을 것 같습니다! 왜 int나 double로 연산하면 안 되는 걸까요? 직접 두 눈으로 확인해 보겠습니다. double vs BigDecimal 간단한 테스트를 먼저 해보겠습니다. 잔돈을 구하는 간단한 로직입니다. !!! 테스트는 실패합니다. 눈앞에서 소중한 `0.00000000000000002`가 사라졌습니다. BigDecimal으로 해보면 어떨까요? 소중한 `0.00000000000000002`를 되찾았어요! double이 정확한 소수점을 표현하지 못한 이유는 부동소수점이기 때문입니다. 즉, 정확한 값이 아닌 근사치 값으로 표현되고 있어 계산에 오차가 생겼던 것입니다. BigDecimal BigD..
1주 차 자동차 미션을 진행하면서 주 생성자/부 생성자 패턴에 대한 피드백을 받았었습니다. 생성자에도 패턴이 있다는 사실 알고 계셨나요?🤔 수정 전) 생성자 각각 초기화하는 상황 두 개의 오버로딩된 생성자가 보이네요. `name`만 인자로 받는 생성자와 `name`과 `movedDistance`를 함께 받는 생성자가 있습니다. public class Car { private final String name; private final int movedDistance; public Car(String name) { this.name = name; movedDistance = 0; } public Car(String name, int movedDistance) { this.name = name; this.mo..