게시글
블로그
전체 92025. 06. 22.
1
[워밍업 클럽 4기 백엔드] 4주차 발자국
[ 배운 내용 정리 ] 📝[ Test Double ]Dummy: 실제로 동작 하지 않지만, 파라미터를 채우기 위해 필요한 객체Fake: 동작은 하지만 테스트를 위해 간소화된 코드Stub: 테스트 중에 호출할 경우 특정 반환 값을 설정 가능 하고 값을 검증 할때 사용Mock: Stub과 같이 테스트 중 호출할 경우 특정 값을 반환 가능 하고 행위를 검증 할때 사용Spy: 객체의 일부분은 실제로 동작 하고 일부분은 동작 하지 않게 설정 하는 방법 📝[ 테스트 독립 보장 ]각 테스트는 서로 영향을 끼치면 안된다.영향을 끼치게 될 경우 테스트가 의도한 대로 동작 하지 않을 수 있다.그러므로 각 테스트의 DB를 @BeforeEach, deleteAllInBatch를 통해 제거 하거나테스트 코드에 @Transactional을 통해 롤백 하여 격리 할 수 있다. 📝[ 테스트 환경 통합 하기 ]테스트의 환경이 조금 이라도 다를 경우 스프링 서버를 다시 띄워야 한다.그러므로 추상 클래스를 통해서 같은 환경을 제공 한다면 스프링 서버가 그만큼 적게 떠서 시간적으로 이득이 있다. [ 미션 회고 ]테스트를 할때 @Mock, @MockBean, @Spy, @SpyBean 어노테이션을 어떤 차이점이 있는지깊게 생각 하지 않고 @MockBean 사용 했었다.미션을 통해 Test Double의 종류와 어떻게 사용 해야 할지 고민할 수 있어서 좋았습니다.또한 @BeforeEach 어노테이션을 각 테스트에 적용 하면 코드의 중복을 줄일 수 있다는점을 알게 되었습니다.
백엔드
・
백엔드
2025. 06. 19.
0
[워밍업 클럽 4기 백엔드] 완주 확인용 수료증 제출
백엔드
・
백엔드
2025. 06. 19.
0
[워밍업 클럽 4기 - 백엔드] Day 18 미션
📝 [ 어노테이션 차이 정리 ] [ @Mock ]가짜 객체 생성 필요한 어노테이션 Test Double 중 Mock, Stub 사용 가능스프링 컨테이너와는 무관 [ @MockBean ]스프링 컨테이너에 등록한 빈을 Mock으로 교체컨테이너를 통해 주입 하므로 @InjectMocks 필요x [ @InjectMocks ]주입 대상 클래스의 생성자를 확인 하여 객체 생성생성자 파라미터, Setter를 통해 @Mock, @Spy 객체 주입 [ @Spy ]객체 전체를 Mock 처리 하지 않고 일부 메서드만 Stub하는 방법실제 메서드 실행 가능 [ @SpyBean ]스프링 컨테이너에 등록된 빈을 Spy로 교체2. [ 테스트 항목을 적절히 배치 하기 ] @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 // then 3-9. 사용자2가 사용자1의 댓글 수정 시도 } 💡 [ 고려 사항 ]3개의 테스트 모두 게시물이 필요 하므로 @BeforeEach 사용자, 게시물 생성을 두었습니다.단. 여기서 고민 되는점은 현재는 @BeforeEach가 다른 테스트에 영향을 주지 않지만 추후 생성된 테스트는 영향을받을수도 있지않을까? 고민 됩니다.
백엔드
・
백엔드
2025. 06. 17.
0
[워밍업 클럽 4기 백엔드] Day 16 미션
✅ [ Presentation Layer ]사용자로부터 값을 받아 검증 하는 레이어Business Layer에 로직을 요청 하고 값을 받아 외부로 반환 하는 레이어 📝 [ 테스트 방법 ] 사용자로부터 온 값이 적절 한지 테스트 합니다. @WebMvcTest 어노테이션을 사용 하여 웹과 관련된 빈만을 주입 받아 테스트를 할 수 있습니다.@MockBean 어노테이션을 사용 하여 실제 로직은 호출 하지 않아 격리된 테스트를 할 수 있습니다.Mockmvc를 통해 Http 요청을 보내고 요청이 적절 한지 테스트 합니다.단. 중요한 점은 한번에 많은 테스트를 하지 않고 하나의 테스트는 하나의 목적을 가져야 합니다. ✅ [ BusinessLayer ]핵심 로직을 실행 하는 레이어로직에 필요한 값이 있다면 Persistence 레이어에 요청을 보내 값을 받아 사용 합니다. 📝 [ 테스트 방법 ]핵심 로직의 결과를 검증 합니다.성공 케이스도 중요하지만 예상치 못한 실패 케이스가 더 중요한 레이어 라고 생각합니다." 로직이 어떻게 하면 실패 할까? ", " 경계값은 통과할까? " 등에 대한 고민이 필요 합니다.✅ [ Persistence Layer ]데이터베이스와 소통 하는 레이어📝 [ 테스트 방법 ]데이터베이스 쿼리를 중심으로 로직을 검사 하고 반환 값을 검증 합니다.실제 운영 데이터 베이스를 사용 하지 않고 H2 데이터 베이스와 같이 테스트용 DB를 사용 하는 것이 좋습니다.
백엔드
・
백엔드
2025. 06. 15.
1
[워밍업 클럽 4기 BE] 3주차 발자국
🌱 배운 내용이번 강의 내용은 실습이 많기 때문에 기억에 남았던 말들과 느낀점을 정리해 보겠습니다. ✅[ 비지니스 레이어 ] " 이렇게 작은 메서드도 테스트 해야 할까요? -> " 네. 해야 합니다. " 재고 감소와 같이 작은 도메인 메서드도 테스트를 해야 하는지에 대한 질문과 답변 입니다.도메인 로직은 변할 수 있기 때문에 테스트를 통해 관리 해야 한다고 말씀 하신 부분이 기억에 남습니다.프로젝트를 하며 도메인 검증을 하지 않아 문제가 생긴적이 있었는데 반성하는 기회가 되었습니다. " 재고 차감을 비지니스 레이어, 도메인 둘다 체크 하고 있는데 둘 다 해야 할까요?" -> " 네. 해야 합니다. " 재고 차감을 할 때 비지니스 레이어, 도메인 각각 체크 하여 예외를 터트리는 상황에서 하신 말씀과 답변 입니다.이 부분도 마찬가지로 프로젝트를 하며 " 이 메서드는 도메인 로직일까?... 비지니스 로직 일까?.."고민 하며 하나만 체크 하려고 했습니다.강의를 통해 이둘은 다른 것임으로 따로 체크 하는 것이 좋구나 라고 생각 했습니다. ✅ Day 11 미션 회고 강의를 보며 코드를 짤 때는 " 그렇게 어렵지 않네? " 라고 생각 했습니다.하지만 미션을 해보고 느낀점은 " 고민할게 많구나 " 였습니다." @DisPlayName은 어떻게 작성 해야 내 의도를 잘 나타낼 수 있을까? "" 어떤 테스트를 해야 할까? "" 내가 놓친 부분은 없을까? " 등을 생각 하며 테스트 한개를 작성할 때도 많은 고민이 필요 했습니다.미션을 함으로써 테스트 코드에 대해서 고민을 해보는 시간을 가질수 있어 좋았습니다.!
백엔드
・
백엔드
2025. 06. 08.
1
[워밍업 클럽 4기 백엔드] 2주차 발자국
✅ 내용 정리 및 느낀점[ 테스트 코드 작성 이유 ]테스트 코드는 문서다.테스트 코드를 통해 안정적인 서비스가 가능 하고 리팩토링 시간을 단축할 수 있다.강의를 수강 후 프로젝트를 했습니다.이전에 혼자 공부할 때는 Postman을 사용 하여 일일이 테스트를 했습니다." 귀찮긴 하지만 이 정도는 할만하다" 라는 생각이였습니다.하지만 협업을 하며 서로의 코드를 수정 하는 경우가 빈번 하였습니다. 그 결과 코드를 신용할 수 없었습니다.테스트 코드를 적용해 보니 최소한의 기능을 보장할 수 있기 때문에 일일이 테스트 하지 않아도 된다는 장점이 있습니다.비록 테스트 코드를 작성 하는 시간은 걸리지만코드의 신뢰성과 유지 보수를 위해 테스트 코드는 "필수" 라고 생각 합니다. [ BDD ( Behavior Driven Development ) ]사용자 행위를 기반으로 사용자 시나리오를 구성 하여 테스트 케이스를 개발* Given - 행위를 수행하기 전 필요한 환경 * When - 실제 사용자 행위를 서술 * Then - 행위에 따른 기대 결과를 서술 ✅ [ 미션 회고 ]강의를 수강한 후 " 나도 이제 읽기 좋은 코드를 작성할 수 있다!" 라고 생각 하였지만이번 미션을 수행 하며 자만 이였음을 느꼈습니다.변수 이름 잘 짓기, 메서드 적절히 추상화 하기 강의를 수강할 때는 쉬운 레벨 같지만 실제론 해보니변수 이름 하나를 정하는 것도 많은 고민이 필요 했고 메서드도 "추상화 레벨을 어느정도로 해야 읽기 좋을까? "등을 고민 하는데 쉽지 않았습니다. 중간 점검을 통해 다른 분들의 코드를 보니 다들 비슷한 고민을 하신게 느껴져서 공감이 되었고,우빈님 피드백을 통해 많이 배웠습니다.
백엔드
・
워밍업클럽
・
4기
2025. 06. 01.
1
[워밍업 클럽 4기 백엔드] 1주차 발자국
✅ 학습 내용 요약📌 Section 2. 추상실생활에선 추상을 적절히 활용 하여 효율적으로 대화 할 수 있습니다.개발자는 말도 중요 하지만 협력할 때 코드를 보는 일도 많기 때문에 코드에도 적절한 추상이 필요 합니다.변수 이름 짓기 / 메서드 추상화를 통해 추상화에 조금 가까워질 수 있었습니다.이전에는 기능 개발, 코딩테스트 코드를 작성할 때 단순히 동작하는 코드를 작성 했지만 강의를 듣고 난 후 다시코드를 보니 시야가 넓어짐을 느꼈습니다. 📌 Section 3. 논리, 사고의 흐름코드를 짤 때 큰 신경을 쓰지 못했지만 불편 했던 점들 이였습니다.Early Return / 부정어 대하는 자세 등을 보며 읽기 좋은 코드가 좋은 코드라고 느꼈습니다. 📌 Section 4. 객체 지향 페러다임SOLID는 들어 본적 있지만 어려워서 나중에 공부 해야 겠다고 미뤄둔 주제였습니다.강의를 들으며 각 원칙들의 의미를 이해할 수 있었지만 실제로 적용 하기에는 경험이 필요 하다고 느꼈습니다. 📌 Section 5. 객체 지향 적용하기JPA 값 타입이 왜 존재 하는지 몰랐습니다. Value Object를 배우며 왜 JPA에 값 타입이 있는지 알게 되었습니다.📝 미션 해결 회고- Day 2추상화라는 것이 실생활에서 늘 쓰이는 것이며 어려운 것이 아니라고 느끼게 해준 미션 이였습니다.실생활의 모든것은 추상화네요! ㅎㅎ - Day 4Before 코드는 익숙한 제 코드를 보는 기분 이였습니다. 읽기 좋은 코드의 기본인 이름, 메서드 잘 짓기,사고 깊이 줄이기를 적용 하며 다른 코드도 리팩토링 하고 싶다고 생각이 들어 프로젝트 리팩토링을 할려고 합니다!
백엔드
・
워밍업클럽4기
2025. 05. 30.
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 (order.hasNoOrderItems()) { log.info("주문 항목이 없습니다."); return false; } if (order.isCustomerInfoAbsent()) { log.info("사용자 정보가 없습니다."); return false; } if (order.isInvalidTotalPrice()) { log.info("올바르지 않은 총 가격입니다."); return false; } return true; }🌱 [ 리팩토링 포인트 ] [ Early Return ]정보의 기억량을 최소화 하기 위해 Early Return 사용 [ 객체 위임 ]객체는 스스로 판단 하고 행동 하는 주체객체와 협력 하기 위해서 getter 사용 하여 값을 추출 하는 것이 아닌 메세지 요청객체 내부에서 관련된 로직을 수행 하고 외부에는 노출 하지 않으므로 캡슐화 [ 부정 연산자 사용x ]부정 연산자( ! )는 사고 Depth 상승부정 연산자를 사용 하지 않고 행위에 부정 의미를 담기 📝 2. SOLID SRP : 단일 책임 원칙 ( Single Responsibility Principle )클래스는 단 하나의 책임만 가져야 한다.ex ) 입출력을 한 객체가 담당할 경우 SRP 위반 OCP : 개방 폐쇄 원칙 ( Open Closed Principle )확장에 열려 있으며, 수정에는 닫혀 있어야 한다. public class OrderController(){ private final OrderService orderservice = new OrderServiceImpl(); } OrderController -> OrderServiceImpl 의존 OrderServiceImpl 구현체 변경시 OrderController 코드를 변경 해야 하므로 OCP 위반 ( DI 필요 ) LSP : 리스코프 치환 원칙 ( Liskov Substitution Principle )자식 타입은 부모 타입으로 교체될 수 있어야 한다. ISP : 인터페이스 분리 원칙 ( Interface Segregation Principle )인터페이스를 사용에 맞게 분리목적에 맞는 인터페이스 만을 제공 DIP : 의존 역전 원칙 ( Dependency Inversion Principle )상위 모듈이 하위 모듈에 의존 하는 것이 순방향상위 모듈 하위 모듈 모두 추상화에 의존 하는 원칙
2025. 05. 28.
0
워밍업 클럽 4기 백엔드 DAY-2 미션
[ 추상 ] : "나갈 준비 다 했어"[ 구체 ] 샤워를 하고 머리를 말린다.옷을 고르고 입는다.챙겨야할 물품들을 챙긴다.놓친건 없는지 확인 한다.
백엔드
・
워밍업클럽4기