블로그
전체 7
2025. 06. 22.
1
워밍업 클럽 4기 BE 클린코드&테스트 4주 차 발자국
@Mock, @Spy, @InjectMocks 등 테스트 코드에서 자주 사용되는 어노테이션에 대해서 학습했습니다.Given-When-Then 스타일을 지원하는 BDDMockito와테스트 철학과 관련된 Mockist, Classcist에 대해서 알게 됐습니다.명확한 주제 명시, Test Fixture, @ParameterizedTest, @DynamicTest 등 더 나은 테스트 작성을 위한 방법을 공부했습니다. 이를 토대로 이번 주 미션에서 각 테스트 레이어의 역할과 테스트 방법에 대해 정리했고Mockito의 주요 어노테이션과 스프링 환경과 순수 자바 환경에서의 테스트의 차이 및공통 환경을 고려한 객체 생성 및 동작 배치에 대한 미션을 수행했습니다 그간 테스트에 대해서 학습한 내용들이 정리가 되는 한 주였다고 생각합니다.또한 테스트 주도 개발은 답답하고 하기 싫다는 생각이 앞섰는데 멀리 가기 위한 지름길이라고 깨달았습니다.'잘 되냐 안 되냐'도 중요하지만 작성한 코드의 구조와 의존성을 확인하고맞는 설계로 진행해 나아가고 있는지 확인할 수 있다고 느꼈기 때문입니다.단순히 기술을 배운 것이 아닌 좋은 코드를 만들기 위한 시야와 기준이 생긴 것 같습니다.테스트를 돌리는 것에 의미를 두는 게 아닌 테스트를 통해 코드의 문제를 읽는 눈을 갖고더 나은 코드를 작성하는 실력을 기르고 싶다는 마음이 더 커진, 의미 있는 4주를 보냈던 것 같습니다.

2025. 06. 19.
0
워밍업 클럽 4기 BE 클린코드&테스트 Day 18 미션
@Mock스프링 컨테이너를 사용하지 않는 테스트에서 사용가짜 객체를 생성하여 의존 객체를 대체하여 사용하는 어노테이션 when().thenReturn() / given().willReturn() 사용 @Mockbean스프링 컨테이너를 사용하는 테스트에서 사용스프링 빈으로 로딩 된 빈을 가짜 객체로 교체해 테스트에 사용when().thenReturn() / given().willReturn() 사용 @InjectMocks테스트 하려는 객체에 사용하며 @Mock, @Spy 로 생성한 가짜 의존성을 주입하는 용도@Spy스프링 컨테이너를 사용하지 않는 테스트에서 사용진짜 객체를 생성하지만 특성 메서드만 가짜고 설정하고 싶을 때 사용(Stubbing)doReturn().when() 사용 @Spybean스프링 컨테이너를 사용하는 테스트에서 사용스프링 빈으로 로딩 된 빈을 가짜 객체로 교체해 사용doReturn().when() 사용 @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 3-3. 사용자 2 생성에 필요한 내용 준비 3-4. 사용자 2 생성 3.7. 사용자 1의 댓글 생성에 필요한 내용 준비 3-8. 사용자 1의 댓글 생성 // when 3-9.사용자 2가 사용자 1의 댓글 수정 시도 // then // 검증 } 모든 테스트에서 반복 되는 작업들을 @BeforeEach에 담음테스트를 위한 상태나 조건 작업 단계를 given 에 배치테스트의 목적이 되는 작업을 when 에 배치

2025. 06. 17.
0
워밍업 클럽 4기 BE 클린코드&테스트 Day 16 미션
프레젠테이션 레이어역할 사용자의 요청을 받아 처리하고, 응답을 반환하는 계층입니다.Controller 클래스가 이 역할을 담당합니다.테스트 방법@WebMvcTest 어노테이션을 이용하여 테스트 대상 컨트롤러를 빈으로 등록하고 나머지 의존성은 @MockBean으로 대체합니다.MockMvc를 이용해 가상의 HTTP 요청과 응답을 실행합니다.ObjectMapper를 활용해 객체를 JSON으로 직렬화하거나 객체를 JSON으로 역직렬화 합니다.mockMvc.peform(), .content() .andExpect() 등의 메서드를 통해 상태 코드 및 응답 바디 등을 검증합니다.이 레이어에서는 컨트롤러가 요청을 잘 전달하고 응답을 잘 반환하는지 확인합니다. 비즈니스 레이어역할도메인 중심의 비즈니스 로직을 처리하며 Service 클래스가 이 역할을 담당합니다.테스트 방법@SpringBootTest 를 사용하여 테스트를 진행하고 필요한 의존성을 @Autowired로 주입합니다.AssertJ의 assertThat(), .hasSize(), .containsExactlyInAnyOrder() 등의 메서드를 사용합니다.@Transactional, @AfterEach 등을 통해 데이터 일관성을 유지하고 테스트 데이터를 정리합니다.이 레이어에서는 의도한 로직이 제대로 동작하는지 검증합니다. 퍼시스턴스 레이어역할데이터 CRUD 역할을 하며 Repository 클래스가 이 역할을 담당합니다.테스트 방법@DataJpaTest를 사용하여 JPA 관련 컴포넌트를 빈으로 등록합니다.엔티티를 저장하고 조회하며 쿼리 동작이 잘 되는지 확인합니다.assertThat()을 이용해 저장한 데이터, 쿼리 결과를 검증합니다이 레이어에서는 쿼리 결과, 엔티티 연관관계 매핑, CRUD 가 제대로 동작하는지 검증합니다.

2025. 06. 15.
1
워밍업 클럽 4기 BE 클린코드&테스트 3주 차 발자국
금주에는 레이어드 아키텍처를 배우고 각 레이어 별로 테스트를 진행했습니다. Persistence Layer 는 Data Access의 역할을 맡아 CRUD가 실행되는 레이어입니다.Persistence Layer의 테스트를 위해 Spring Data JPA 를 구현한 Repository 및 서비스를 사용했고기본 엔티티를 설계 및 개발하며 ProductRepositoryTest 를 진행했습니다.Business Layer 는 비즈니스 로직을 담당하는 레이어로OrderServiceTest를 통해 Product를 저장하고 orderService를 통해 OrderDto인 OrderResponse를 만들며.extracting(), .containsExactlyInAnyOrder() 등 메서드를 사용해 검증을 진행했습니다.Presentation Layer는 외부 세계의 요청을 가장 먼저 받는 계층으로파라미터에 대한 최소한의 검증을 수행합니다.동시성 이슈가 발생할 수 있는 부분과 그에 대한 해결 방안을 간략하게 알아보았고성능 최적화와 조회용 메서드와 CUD 메서드를 분리하기 위해클래스 상단에 @Transactional(readOnly = true) 를 위치하고CUD 가 필요한 메서드 마다 @Transactional 애노테이션을 오버라이딩 시켜주었습니다. 레이어드 아키텍쳐 이외에 테스트를 위한 공통 설정에 대해서도 배웠습니다. application.yml 파일을 이용해 프로파일별(local, test)로 설정을 분리하는 방법을 배웠습니다.Test에 사용되는 애노테이션에는@SpringBootTest @DataJpaTest가 있습니다.@DataJpaTest는 리포지토리와 JPA의 설정을 가지고 CRUD 테스트를,@SpringBootTest는 서비스를 포함한 전체 테스트 진행 시 사용합니다.테스트 클래스에서 사용되는 @Transactional 자동 롤백 기능과 부작용에 대해서 공부하고@AfterEach 로 테스트 후 각 리포지토리를 롤백해주었습니다. 금주의 미션은 given, when, then 패턴, BDD 스타일을 이용하여테스트 시나리오를 작성하고, 레드/그린/리팩토링 순서로 테스트를 진행 및 구현하는 미션이였습니다.작성했던 메서드를 기반으로 테스트를 작성했기에 레드 그린 순서로 진행하지는 못 했지만어떤 시나리오를 작성하면 좋을지 생각해보고 작성에도 도움을 주었다고 생각합니다.다만 아쉬운 점은 미션을 수행하는 것에만 치중하여 스스로 테스트 리팩토링을 소홀하게 진행한 것이 아쉬웠습니다. 일과 학습을 병행하니 이 정도면 충분하지 않나 생각으로 보내 아쉬움이 많이 남는 한 주였던 것 같습니다.물론 많은 도움이 되는 강의와 미션이지만 스스로 더 많은 경험치를 쌓기 위해매일 진행하는 학습 이후 반드시 배운 내용을 정리하며 마무리하는 연습을 하려고 합니다.

2025. 06. 01.
1
워밍업 클럽 4기 BE 클린코드&테스트 1주 차 발자국
'읽기 쉬운 코드'가 중요한 이유는코드를 작성한 나 뿐만 아니라 다른 사람의 시간과 에너지를 절약해줍니다. 읽기 쉬운 코드를 위해 핵심 로직을 추상화 시켜 표현하고 그 것을 구현한 구체는 감추어 코드를 나눕니다. 핵심 로직을 추상화 시킨다는 것은 데이터를 직접 비교하며 코드를 읽는 것이 아닌메서드 시그니처를 읽는 순간 우리가 그 기능이 무엇을 하는지 이해하는 것을 의미합니다. 구현 중 상수, Early Return 과 중첩 반복문 회피, 사용 변수의 위치 및 공백 라인 등코드를 읽는 사람이 쉽게 이해하기 위한 여러 요소가 사용됩니다. 하나의 클래스가 점차 많은 기능을 맡게 된다면 읽기와 작성 모두 어려워집니다.관심사에 따른 객체로 추출하여 사용하는 곳에서 구현에 신경쓰지 않고 도메인 로직을 다룰 수 있게 합니다. 객체는 한 개의 관심사로 책임을 정의해야 하며 파라미터를 직접 넣고 사용하는 것 보다응집도를 위해 캡슐화 및 추상화된 메서드 사용 및 객체 내부 필드를 이용해 내용을 구체화하고 SOLID 원칙을 준수하기 위한 상속과 조합, Value Object, 일급 컬렉션과 다형성 등 여러 구현 수단이 존재합니다. 1주차를 진행하면서 마음 속에 가장 와 닿았던 말은 "객체에게 객체를 존중하는 마음으로 물어봐라" 였습니다.객체를 존중하는 마음을 가지려 하다보니 수업의 방향성을 한 번에 찾은 듯 했고수업 이해에 많은 도움이 되었고 1주차 내내 워밍업 클럽에 신청하길 잘 했다는 생각을 했습니다. 처음 만나는 스트림 API 와 구현 도구를 이해하는데 어려움이 있었습니다.스트림 API 의 경우 AI 도구를 이용해 배열을 스트림화 하는 등 여러 문제를 풀어보며 급하게 공부를 했지만급히 공부한 만큼 여전히 어색함이 있고 객체 지향 적용 수업은 꼭 틈틈히 복습을 해야겠다는 생각이 들었습니다.수업이 끝나는 대로 나름 정리를 바로 했지만 두서 없이 정리 되어 다음 주에는 Readable 하게 정리해야겠습니다. 추상과 구체 미션은 일상에서 쉽게 경험하는 일을 선택해 진행했습니다.일상의 경험을 추상으로 표현하고 포괄적으로 표현된 내용을 구체적으로 표현하며 구현의 예시를 적었습니다.단계 별로 메서드가 하나씩 진행하듯 이후 실제 코드에서 진행되는 수업을 생각하며 구현을 표현하려고 했습니다. 리팩토링 및 SOLID 미션은 읽는 사람이 읽고 바로 이해할 수 있는 정도를 고려하며 작성했습니다.중복된 메서드는 통합했고 Optional 을 사용해 수업에서 배운 NPE 방지를 어떻게 하는지 알 수 있었습니다.자신만의 언어로 SOLID에 대해서 설명하는 과정은 설명을 위해 제 스스로 이해를 먼저 했어야 했고 구현하는 과정은 힘들 수 있겠지만 개념을 이해하는 것에 많은 도움이 되었습니다.

2025. 05. 30.
0
워밍업 클럽 4기 BE 클린코드&테스트 Day 4 미션
1. package cleancode.minesweeper.asis; import java.util.List; import java.util.Optional; public class Order { private List items; private int price; //private Customer customer; private Optional customer = Optional.empty(); public boolean validateOrder(Order order) { if(order.isOrderItemsListEmpty()) { return printErrorMessage("주문 항목이 없습니다."); } if(order.isTotalPriceBelowZero()) { return printErrorMessage("올바르지 않은 총 가격입니다."); } if(order.hasNotCustomerInfo()) { return printErrorMessage("사용자 정보가 없습니다."); } return true; } private boolean hasNotCustomerInfo() { //return customer == null; return customer.isEmpty(); } private boolean isTotalPriceBelowZero() { return price 2. SOLID는 연인 관계와 비슷하다SRP : 연인에게 모든 집안일을 맡겨서는 안된다 각자 맡은 일을 하나씩 하자OCP : 연인의 이런 저런 요구사항이 생겨도 교제 초기 내 마음을 수정하지 말고 받아들이는 확장적인 자세를 갖자LSP : 다른 연인을 만나도 연애하는 기본 방식은 같다ISP : 연인에게 불필요한 부탁은 하지말고 꼭 필요한 부탁을 하자DIP : 내가 좋아하는 건 연인의 외모나 마음이 될 수도 있지만 내가 좋아하는 건 연인 그 자체다

2025. 05. 27.
0
워밍업 클럽 4기 BE 클린코드&테스트 Day 2 미
2. "추상과 구체" 강의를 듣고, 생각나는 추상과 구체의 예시가 있다면 한번 3~5문장 정도로 적어봅시다.집에 가서 저녁을 준비한다.퇴근 후에 지하철에 몸을 싣고 집 근처 역으로 간다.귀갓길에 마트에 들러 대파와 계란을 산다.집에 들어와 손과 발을 깨끗하게 씻는다.라면 한 봉지를 꺼내고 냄비에 넣고 끓인다.아까 사온 대파와 계란을 넣는다.




