블로그
전체 8#카테고리
- 백엔드
#태그
- 백엔드
2025. 06. 19.
1
[워밍업 클럽 4기 백엔드] 4주차 발자국
4주차 회고 학습 내용섹션 7. mock을 마주하는 자세mockito 어노테이션 별로 사용하는 방법과 용도를 알수 있게 되었다classist와 mockist 개념을 알게 되었고 어떤것을 중점을 나아갈지 생각해 보았다 섹션 8. 더 나은 테스트를 작성하기 위한 구체적 조언 @beforeEach에 넣는것을 아무 생각 없이 썼는데 테스트 환경에 영향을 주지 않는것으로 고려해서 써야한다는것을 알게 되었다여러가지 테스트 환경을 구성하는 방법에 대해 알게 되었다 섹션 9, 10 appendix , outrospring rest docs 를 예전에 써보았는데 다시한번 복습하는 시간 이었다앞으로 테스트를 어떤식으로 써야 할지 생각을 해보는 챕터였다 4주차 과제 실제 테스트를 해보면서 테스트 코드 작성하는 감을 잡을 수 있었다mockito 어노테이션을 정리하면서 해당 어노테이션을 알게 되었다각 레이어 별로 테스트를 어떻게 짜야할지 정리해 볼수 있었다 수료 후 느낀점 개발을 하면서 어떤식으로 코드리뷰를 해야하고 코드를 리펙토링을 해야할지 알게 되는 기회가 되어 좋았다 어떤 주제로 코드를 작성하고 테스트를 작성하는 방법에 대해 자세히 알수 있게 되었다 위에서 배운 내용을 실무적으로 적용을 해야할지 한번 생각을 해봐야겠다
백엔드
2025. 06. 18.
0
[워밍업 클럽 4기 백엔드] Day 18 미션
1. @Mock, @MockBean, @Spy, @SpyBean, @InjectMocks 의 차이를 한번 정리해 봅시다. mockito 관련 어노테이션@Mock역할 : 가짜 (mock) 객체를 생성해줌주용도 : 의존 객체의 동작을 테스트 대상과 분리하고자 할때 사용 @MockBean역할 : spring applicationContext에 있는 기존 빈을 mockito의 mock 객체로 교체함 용도 : 통합 테스트시 sping bean의 동작을 mock으로 대체할때 사용 @Spy역할 : 실제 객체를 감싸서 생성한 spy 객체를 만듬용도 : 객체의 대부분 로직은 그대로 사용하면서 특정 메서드만 mock 하고 싶을때 사용 @SpyBean역할 : spring bean 을 spy 객체를 감싸서 일부는 실제 메서드 실행용도 : spring 통합 테스트에서 실제 빈의 대부분은 사용하되 특정메서드만 mocking 하고 싶을때 사용 @InjectMocks역할 : @mock 또는 @spy 로 선언 된 객체들을 해당 객체에 자동 주입하여 테스트 대상 객체를 생성용도 : 테스트 대상 객체를 명시하고 그 내부 의존성을 자동으로 mock/spy 객체로 주입할때 사용 2. 아래 3개의 테스트가 있습니다. 내용을 살펴보고, 각 항목을 @BeforeEach, given절, when절에 배치한다면 어떻게 배치하고 싶으신가요?(@BeforeEach에 올라간 내용은 공통 항목으로 합칠 수 있습니다. ex. 1-1과 2-1을 하나로 합쳐서 @BeforeEach에 배치) @BeforeEach void setUp() { 사용자 생성에 필요한 내용 준비 (1-1, 2-1, 3-1) 사용자 생성 (1-2, 2-2, 3-2) 게시물 생성에 필요한 내용 준비 (1-3, 2-3, 3-5) 게시물 생성 (1-4, 2-4, 3-6) } @DisplayName(""사용자가 댓글을 작성할 수 있다."") @Test void writeComment() { // given 댓글 생성에 필요한 내용 준비 (1-5) // when 댓글 생성 (1-6) // then 검증 } @DisplayName(""사용자가 댓글을 수정할 수 있다."") @Test void updateComment() { // given 댓글 생성에 필요한 내용 준비 (2-5) 댓글 생성 (2-6) // when 댓글 수정 (2-7) // then 검증 } @DisplayName(""자신이 작성한 댓글이 아니면 수정할 수 없다."") @Test void cannotUpdateCommentWhenUserIsNotWriter() { // given 사용자2 생성에 필요한 내용 준비 (3-3) 사용자2 생성 (3-4) 사용자1의 댓글 생성에 필요한 내용 준비 (3-7) 사용자1의 댓글 생성 (3-8) // when 사용자2가 사용자1의 댓글 수정 시도 (3-9) // then 검증 }@BeforeEach 추출한 조건각 테스트시 필요없는것만 배치 , 수정해도 모든 테스트에 영향을 주지 않는것 모든 테스트에서 공통적인 수행되는 부분 추출
백엔드
2025. 06. 16.
0
[워밍업 클럽 4기 백엔드] Day 16 미션
Layered Architecture 구조의 레이어별 테스트 작성법을 알아보았습니다. 레이어별로 1) 어떤 특징이 있고, 2) 어떻게 테스트를 하면 좋을지, 자기만의 언어로 다시 한번 정리해 볼까요? 1. persistence layer 테스트 (Repository layer) 특징data access 역할 데이터베이스와 직접적으로 통신하는 레이어비즈니스 로직은 포함되어서는 안된다 오직 데이터에 대한 CRUD에만 집중한 레이어 테스트 방법단위테스트 : 잘하지 않음 통합테스트 : @DataJpaTest 등으로 테스트 쿼리 동작 및 복합 조건 검색등을 테스트 2. business layer 테스트 (Business logic layer) 특징비즈니스 로직을 구현하는 역할 트랜잭션을 관리해야 한다이 레이어는 순수한 자바 로직이 많고 변경에 유연해야 한다 테스트 방법단위 테스트 : Repository 등을 mock 처리하고 service 만 테스트 통합테스트 : 실제 DB 를 연결하거나 인메모리 DB를 연결 트랜잭션 흐름 및 로직 분기처리 등을 확인 3. presentation layer 테스트 (Web layer) 특징외부 세계의 요청을 가장 먼저 받는 계층 외부 요청을 받아 적절한 서비스 계층에 위임하고 결과를 가공해서 반환함 테스트 방법단위 테스트 : Mocking 된 service 를 주입해서 controller 만 테스트 (@WebMvcTest)통합 테스트 : 실제 서버 없이 전체 흐름을 테스트 (@SpringBootTest)입력 유효성 검사 및 응답 포맷 검증등을 확인
백엔드
2025. 06. 15.
1
[워밍업 클럽 4기 백엔드] 3주차 발자국
학습 내용persistence layer 테스트persistence layerdata access 의 역할비즈니스 가공 로직이 포함되어서는 안된다. 데이터에 대한 CRUD에만 집중한 레이어 미래에 어떠한 변경이 될수도 있고 내가 작성한 코드를 확인하기 위해 테스트를 해야한다 Repository test통합 테스트이지만 해당 레이어만 띄워서 하기 때문에 단위 테스트 느낌이 난다 스프링 통합테스트를 위한 어노테이션@springBootTest, @DataJpaTest차이dataJpaTest : jpa 관련 빈 주입해서 서버를 띄워 빠르다assertThat(product).hasSize(2) - 사이즈 확인 .extrating("productNumber", "name" , "sellingStatus") - 검증하고 싶은 셀만 확인 가능 .containsExactlyInAnyOrder( -- 순서 상관없이 해당 것이 포함하는지 확인 tuple("001", "아메리카노", selling), tuple("002", "카페라떼", HOLD) ) business layer 테스트비즈니스 로직을 구현하는 역할Persistence Layer와의 상호작용을 통해 비즈니스 로직을 전개시킨다트랜잭션을 보장해야 한다service 테스트asserThat(orderResponse.getId).isNotNull(); -- null 이 아니다 @springBootTest, @DataJpaTest차이DataJpaTest 는 트랜잭션 어노테이션 있어 사용하면 자동으로 롤백이 된다 presentation layer 테스트 presentation layer외부 세계의 요청을 가장 먼저 받는 계층파라미터에 대한 최소한의 검증을 수행한다 persenation layer 테스트시 해당 부분은 단위테스트 하는 느낌으로 하고 나머지 layer는 mocking 처리를 하여 테스트를 한다 @transactional(readOnly = true)CRUD에서 CUD 동작 X, only read 만 가능jpa : cud 스냅샷 저장, 변경 감지 x (성능 향상)서비스 테스트를 할때 전체 클래스에 @transactional(readOnly = true) 를 걸고 각 command 작업을 하는 메서드에는 @transactional 따로 걸자 느낀점실제 단위 테스트 하면서 어떤 것을 테스트를 해야할지 모르겠다는 느낌을 받았지만 강의를 들으면서 이러한 주제로 나눠서 테스트 해야겠다고 생각을 해볼수 있는 기회가 된거 같다
백엔드
2025. 06. 08.
1
[워밍업 클럽 4기 백엔드] 2주차 발자국
1. 2주차 회고1) 리펙토링 연습관련 내용을 학습하여 직접 리펙토링을 해보았는데 쉽지 않았다 . 분류를 하는데도 이게 맞는지 확신이 들지 않았다. 좀더 학습을 해보고 다른사람들꺼랑 비교를 해봐야 겠다 2) 테스트 코드 학습테스트 코드를 왜 쓰는지랑 어떻게 하면 테스트 코드를 깔끔하게 쓸수 있는지 배울수 있어서 좋았다. 2. 아쉬운점- 다른일 때문에 코드 리펙토링 할 시간이 많이 부족했다. 강사님이 하신것을 참고해서 좀더 잘해보도록 해야겠다
백엔드
2025. 06. 01.
1
[워밍업 클럽 4기 백엔드] 1주차 발자국
1. 1주차 회고1) 추상 - 추상과 구체 과제를 통해서 추상 개념에 대해 다시 생각해볼수 있었다- 매직 넘버를 보고 추상적인 넘버같은 경우 따로 변수로 바꿔서 해야 한다는것을 알게 됐고 추상화 레벨 과정을 통해서 해당 추상화 레벨에 대해 생각해 볼수 있었다2) 논리, 사고의 흐름 - 내 코드를 봤을때 뇌 메모리를 얼마나 쓰게 될지 확인을 해보았고 얼리 리턴을 통해서 리펙토링을 해보았다- 부정어를 대하는 자세에서 부정에 대해서 한번 생각해 보았다 - 직접 과제를 통해 이 섹션에서 배운 내용을 확인해보니 리펙토링하는데 있어서 감을 익힐수 있었다 3) 객체지향 - 각 SOLID 개념에 대해 한번 확인해 볼수 있었고 해당 개념이 필요한 코드단에서는 적용을 해볼수있도록 노력을 해봐야 겠다 2. 아쉬운점 - 강의 내용이 길어서 1주차에 전부 듣으려고 하려니 시간이 많이 부족했다. 주말에 보충을 해봐야겠다
2025. 05. 29.
0
워밍업 클럽 4기 - 백엔드 Day 4 미션
1. 코드 리펙토링 이전코드 public boolean validateOrder (Order order) { if (order.getItems().size() == 0){ log.info("주문 항목이 없습니다"); return false; } else { if (order.getTotalPrice() > 0) { if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } else { return true; } } else if (!(order.getTotalPrice() > 0)) { log.info("올바르지 않은 총 가격입니다"); return false; } } return true; }수정 코드 public boolean validateOrder(Order order) { if (isEmptyOrder(order)) { log.info("주문 항목이 없습니다"); return false; } if (!hasValidTotalPrice(order)) { log.info("올바르지 않은 총 가격입니다"); return false; } if (!hasCustomerInfo(order)) { log.info("사용자 정보가 없습니다."); return false; } return true; } Early return- 각 조건 실패시 조기 반환을 통해서 깊은 중첩을 제거 공백라인을 대하는 자세 - 각 조건별 블록별로 공백줄을 넣어서 논리 단위 분리 부정어를 대하는 자세- !isEmptyOrder 대신에 isEmptyOrder로 대신하여 구현하여 가독성이 더 좋게 변경 2. SOLID 원칙 1. SRP - 하나의 클래스는 단 한가지의 변경 이유만을 가져야한다 - 단 하나의 기능만을 담당하게되어 응집도를 높이고 변화에 유연하게 대처할 수 있다 2. OCP- 확장에는 열려있고 수정에는 닫혀있어야 한다 - 기존 코드는 건드리지 않고 기능을 확장할수 있게 해준다 3. LSP- 상속구조에서 부모클래스의 인스턴스를 자식 클래스이 인스턴스로 치환할수 있어야 한다 - 상속 구조에서 자식 클래스가 부모의 행위를 깨뜨리지 않도록 설계 4. ISP- 클라이언트는 자신이 사용하지 않는 인터페이스에 의존하면 안된다 - 인터페이스를 작게 나눠 불필요한 구현을 피하고 불필요한 의존성을 제거한다 5. DIP- 상위 수준의 모듈은 하위 수준의 모듈에 의존해서는 안된다 - 구체적인 구현이 아닌 추상에 의존하게 하여 결합도를 낮추고 유연성과 테스트 용이성을 향상 시킨다
백엔드
2025. 05. 27.
0
워밍업 클럽 4기 - 백엔드 Day 2 미션
추상: 노래를 듣는다구체:스피커나 이어폰에서 공기중으로 소리 진동이 퍼진다이 진동이 귀의 고막을 흔든다고막의 진동이 귓속 뼈를 거쳐 달팽이관으로 전달된다달팽이관 안 유모세포가 진동을 전기 신호로 바꾼다이 신호가 청신경을 통해 뇌로 전달되어 '노래'로 인식한다
백엔드