블로그

홍석호

[인프런 워밍업 스터디 클럽 2기 백엔드(클린코드, 테스트코드)] 3주차 발자국

강의 수강 학습 내용 요약테스트의 중요성, 단위 테스트, TDD, JUnit, JPA 기반 테스트 학습 내용 회고테스트는 변화하는 소프트웨어의 안정성을 보장한다.테스트는 [문서]다.테스트는 잘못 작성하면 오히려 유지보수 비용만 늘어난다.TDD를 적용하면 테스트하기 쉬운 구조로 프로그램을 만들게 되며, 좋은 설계로 이어진다.TDD는 상황에 따라 적용해야 한다.해피케이스에만 집중하지 말고 예외 케이스에도 집중해야 한다.레이어 별로 알맞은 유닛 테스트/통합 테스트 방법을 적용해야 한다. 미션readable-test 강의해서 작성했던 코드에 테스트 코드를 작성하는 미션이었다.미션을 진행할 때는 I/O 테스트는 하지 않아도 된다고 생각했는데, 강의를 듣다보니까 Repository의 동작을 보장하기 위해 테스트를 작성하는 것이 맞는 것 같다.간단한 예제다보니 콘솔 입/출력을 받는데, 이 부분의 테스트는 백엔드에서 고민할 영역이 아니라는 된다는 생각은 변함 없다. 마무리하며Spring & JPA 기반 테스트에 관해 구체적으로 알 수 있어서 좋았다. 내가 정말 원하는 내용이었다.최근에 코틀린 공부를 시작했는데, Kotest + mockk를 가장 많이 사용하는 것 같아서 이것들도 궁금해졌다.

dmstjd0214

[인프런 워밍업 스터디 클럽 2기_BE] 3주차 회고록 정리

테스트 코드를 작성하지 않음으로써의 문제점변화가 생기는 매순간마다 발생할 수 있는 모든 Case를 고려해야한다.변화가 생기는 매순간 마다 모든 팀원이 고민을 해야한다.빠르게 변화하는 소프트웨어의 안정성을 보장할 수 없다.근데 테스트 코드가 더럽다면?프로덕션 코드의 안정성을 제공하기 힘들어짐테스트 코드 자체가 유지보수하기 어려운 짐이된다.잘못된 검증이 나올수 있다.가까이 보면 멀어보이지만 , 멀리서 보면 빠르다.단위 테스트 도입여기서 단위 테스트란?작은 코드 단위를 독립적으로 검증하는 테스트 ( 클래스 or 메서드 )검증 속도가 빠르고 안정적이다.JUNIT5테스트 단위를 위한 테스트 프레임 워크AssertJ테스트 코드 작성을 원할하게 돕는 테스트 라이브러리풍부한 API 메서드 체이닝 지원!TDD란?프로덕션 코드보다 테스트 코드를 먼저 작성하여 테스트가 구현 과정을 주도하도록 하는 방법론Red-Green-Refactor실패가 되는 테스트 작성테스트 통과 최소한의 코딩 - 일단 굴러만 하기만 하면된다.구현 코드 개선 테스트 통과 유지1,2,3번 사이클이 계속 돕니다.테스트→ 기능 → 테스트기능을 먼저하면테스트 자체의 누락 가능성특정 테스트 케이스만 검증할 가능성잘못된 구현을 다소 늦게 발견할 가능성테스트를 먼저 작성하려면? → 요구사항분석과 테스트 단위를 잘 쪼개야한다.테스트를 하기 위한 구조생각이 떠오를 수 있다.클라이언트 관점에서의 피드백을 주는 Test Driven[]은 뭘까..내 생각은 철저한 요구사항이라고 생각한다.강의에서는 문서! 라고 하는거봐서 유사하다고 생각했다.문서?프로덕션 기능을 설명하는 테스트 코드 문서다양한 테스트 케이스를 통해 프로덕션 코드를 이해하는 시각과 관점을 보완어느 한 사람이 과거에 경험했던 고민의 결과물을 팀 차원으로 승격 시켜, 모두의 자산으로 공유 가능팀으로 일하기 때문에 팀이 보기 편하게 봐야한다!잘보려면 어떻게 해야할까?저번 강의에 대해 추상화 레벨을 맞춰 가독성을 좋게하는게 포인트다!마찬가지로 문서를 보기 편하게 하기위해 테스트 코드에서는 DisplayName이 있다!Displayname은 구체적으로 섬세하게 작성해야한다.Persistence Layer타 ORM으로 변경될 수 있기 때문에 이를 보장하기 위해 테스트를 진행해야 한다.미래에 어떤 형태로 변할지 모르기 때문에, 이러한 가능성에 대비해 테스트를 확실히 해야 한다.Business Layer비즈니스 로직을 구현하는 역할Repository와 상호작용을 통해 비즈니스 로직을 전개트랜잭션을 보장해야 한다비즈니스 레이어 테스트는 레포지토리 테스트와 함께 작성하는 것이 목표이다.테스트를 위해 Request 객체를 생성자로 만들어 놓는 경우도 있다.Order 계산 부분에 대한 테스트가 필요할 것이라는 생각이 중요하다.서비스 로직에서는 등록 시간을 처리하기 어려울 수 있는데, 이 경우 파라미터로 시간을 받아 작업하는 것이 좋은 방법이다.메서드 단위 테스트는 메서드를 잘 나눠야 나중에 테스트하기 편하다.테스트를 동시에 실행할 때 하나는 성공하고 다른 하나는 실패하는 이유는 중복된 동작이 영향을 주기 때문이다.따라서 매 테스트마다 초기화를 진행해야 한다.Teardown 순서가 올바르지 않으면 문제가 생길 수 있다.@DataJpaTest와 @SpringBootTest의 차이는 트랜잭션의 차이로, 자동으로 롤백 처리가 된다.직접 트랜잭션을 설정하면 롤백이 되며, 나중에 강의에서 문제에 대해 설명해 준다.간단한 테스트도 언제든지 바뀔 수 있기 때문에 미래를 대비한 테스트가 필요하다.Deduct 체크를 진행할 때 왜 두 번 검증할까?서비스 검증과 도메인 검증이 별개의 역할이라고 판단하여 두 번 진행하는 것이다.요구사항을 정확히 파악하고 테스트 케이스를 분리하는 것이 좋다고 생각했다.예외 케이스에 대한 테스트도 반드시 진행해야 한다.과제테스트 코드를 작성하는 것은 너무 생소하고 강의를 들었을때랑 내가 직접 작성하면서 했을때랑 떠오르는게 다르다 생각했다. 그리고 조그만한 테스트도 해야하나? 라는 고민도 많았고 기존에 했던 Readable보다 더 오랜 생각을 했었던 것같다. 테스트 코드를 작성 후 이후 강의에 대한 내용을 들어보고 나서 역시 모든 케이스는 커버를 해야된다라는 생각이 들었다.회사에서는 직접적으로 테스트 코드를 도입하지 않았지만 강의를 듣고 공부를 진행하면서 테스트 코드의 세분화를 잘해야할꺼같다.관련 코드 : https://github.com/backgom1/readable-code/tree/main/src/test/java/cleancode/minesweeper/tobe

홍석호

[인프런 워밍업 스터디 클럽 2기 백엔드(클린코드, 테스트코드)] 2주차 발자국

강의 수강 학습 내용 요약리팩토링 기법, 리팩토링 시 지켜야할 객체지향 원칙, 추상과 구체의 트레이드 오프 학습 내용 회고추상이란 사물이나 표상의 성질을 추출하는 것이고, 그것은 필요없는 것을 '버리는 것'이다.과도한 추상은 오히려 복잡도만 증가시킬 수 있다. 현 단계에서 필요한 정도의 추상을 해야 한다.개발을 진행하면서 우리는 도메인 지식을 획득하게 된다. 도메인 지식을 획득하면 그때 좋은 구조로 변경할 수 있다.추상과 구체를 넘나들면서 더 잘 이해할 수 있게 된다. 미션코드를 리팩토링하는 미션이었다.리팩토링 후에 강의를 들으면서 나의 코드와 비교해보았다.그리고 중간점검 라이브에서 피드백도 받았다.if 문 분기에서 분기에 들어가기 전에 처리할 수 있는 코드를 놓치면서, switch case 문으로 과도하게 리팩토링하게 된 것 같다. 메소드를 추출하기 전에 if 문 로직을 잘 살펴보아야 좋은 리팩토링을 할 수 있음을 명심하자.일급 컬렉션의 개념은 알고 있었는데, 적용하지 못했다. 앞으로는 더 신경 써서 적용하려고 노력해야겠다.추상화 레벨에 관해서는 단순히 메소드를 추출하는 것이 중요한 것이 아니라, 적절한 이름을 붙이면서 높은 추상화 레벨을 획득할 수 있음이 중요한 것이다.읽는 사람이 직관적으로 해석할 수 있을 정도로 코드의 의도를 분명하게 드러내야 한다.상태를 가지지 않고, 앞으로도 가지지 않을 확률이 높다면 VO로 만드는 것이 좋다. 마무리하며어떠한 지식을 한 번 들어본 것과 실제로 적용할 수 있음이 다르다는 것을 새삼 느꼈다. 반복 숙달, 의식적인 노력을 통해 머리로만 알고 있는 것을 체화해야겠다.2개의 강의 중 한 개를 완료했다. 내가 생각했던 것보다 더 많은 것을 얻을 수 있었다. 다음 강의가 더 기대된다.

홍석호

[인프런 워밍업 스터디 클럽 2기 백엔드(클린코드, 테스트코드)] 1주차 발자국

강의 수강 학습 내용 요약클린 코드의 중요성과 객체 지향 원칙에 대해 배우고 적용해보았다. 학습 내용 회고이미 다른 매체를 통해 알고 있는 내용이 많았다. 그렇지만 새로웠다. 머리 속에서 파편화되어있던 정보들을 조각 모음한 것 같다.함수 내에서 추상화 레벨을 맞춰야 한다는 것은 최근 읽었던 '쏙쏙 들어오는 함수형 코딩'에서 다이어그램으로 본 것 같은데, '추상화 레벨'이라는 용어가 아니라 '계층'이라는 단어로 사용되어 있었다. 용어를 어떻게 사용하는지에 따라 내가 인지하고 받아들일 수 있는 정도가 달라지는 것 같아 신기했다. 강사님도 자신만의 언어로 말할 수 있어야 한다는 것을 강조한 적 있다. 배운 내용을 그대로 받아들이기 보다는 내가 받아들이기 쉬운 형태로 한 번 변형해서 받아들이도록 노력해봐야겠다. 미션두 개 모두 간단한 미션이어서 미션을 해결하는 것보다는 왜 이런 미션을 냈는지를 고민하는 것에 집중했다. 첫번째 미션은 위 내용과 비슷하다. 나만의 언어로 학습하는 메타인지적 측면을 강조한 것 같았다. 두번째 미션은 리팩토링 미션이었고, 지금까지 배운 내용을 돌아보라는 의미인 것 같았다. 강의에서 배운 리팩토링 기법과 객체지향 원칙을 적용해서 해결해보았다. 마무리하며이번에 깨달은 것은, 나의 지식이 모자르지는 않다는 것이다. 이미 알고 있거나, 들어본 적 있던 내용들이 꽤 많았다. 이것은 장점이지만 또 단점이기도 하다. 내가 이미 알고 있지만 적용하지 못하고 있던 점들이 꽤 많았다는 뜻이다. 내가 제대로 받아들이지 못한 점들을 찾아내서 하나씩 제대로 적용해보면 크게 성장할 수 있을 것 같다. 그리고 이 강의가 그것에 도움을 많이 줄 것 같다.

인프런 워밍업 스터디 클럽 2기 -백앤드 클린코드,테스트코드 3주차 발자국

https://inflearn.com/course/lecture?courseSlug=practical-testing-%EC%8B%A4%EC%9A%A9%EC%A0%81%EC%9D%B8-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B0%80%EC%9D%B4%EB%93%9C&unitId=144805&subtitleLanguage=ko호덜덜 3주차..배우고 싶었던 테스트코드 강의를 들어보았다!   4LS-회고법을 사용해보장!Liked (좋았던 점) 드디어 배우고 싶었던 테스트 코드! tdd의 중요성과 이미 기능을 구현한 후 테스트코드를 작성할 경우 발생할수있는 문제점을 숙제였던 이미 리더블 코드에서 사용했던 코드에 테스트코드를 만들며 실전으로 느꼈다 :(Lacked (아쉬웠던 점)저번 리더블코드 지뢰찾기 코드 따라하다가 뭘 잘못따라했는지 제대로 작동안되서 오류가 있는거에 테스트코드를 짜려니 찜찜했다..Learned (배운 점)1- 단위 테스트-클래스나 메서드같은 작은 단위의 테스트Junit은 단위테스트를 위한 테스트 프레임워크Assertj는 Junit위에 얹는 테스트코드의 작성을 돕는 test library- 체이닝 메서드로 조금더 가독성을 높힌다! -암묵적인 요구사항이 있는지 생각해보기해피케이스와 예외케이스들을 작성해야한다.+ 경계값 테스트 -테스트하기 어려운 영역 분리관측할때마다 달라지는 테스트 케이스 - 시간이나 사용자가 입력하는거에 따라 달라질때.이럴경우 테스트코드 friendly 코드로 기능을 구현을 해놓으면 한결 편안해진당! 2-TDD -test driven development기능 구현후 테스트케이스를 작성할때 테스트케이스를 짤때 제약을 받을수있다.해피케이스만 짜고 예외케이스는 자유롭게 못짜볼수있다. 이미 구현된 기능을 건드려야하니 귀찮아서..처음부터 테스트코드를 짜면 익숙하지않아 번거롭겠지만 테스트케이스를 만들어놓으면 오히려 과감하게 리펙토링을 하고 테스트케이스를 돌려 작동되는지 바로 확인할수있어서 좋다.기능과 기능을 검증하는 테스트수단의 상호작용. 3-테스트 코드는 문서다개발자가 아닌 사람이 봐도 이 기능은 무엇을 위한것인지 어떻게 작동해야하는지 이해할수있는걸 권장한다.테스트코드는 나의 고민의 결과를 문서화한 팀의 자산이 된다. 그만큼 중요하다.@DisplayName("음료 한개 추가하면 주문 목록에 담긴다.") 문장으로 적어야 더 이해하기 쉽다.성공 실패 같이 테스트 중심의 설명보다주문 실패 X아이탬의 갯수가 0일떄는 주문을 생성할수없다. O 4-BDD 스타일로 작성하기Behavior Driven Development TDD에서 파생된 개발방법론함수단위테스트보단 시나리오 기반의 테스트케이스 자체에 집중한다.Given - 시나리오 진행에 필요한 모든 과정 준비When - 시나리오 행동 진행Then - 시나리오 진행에 대한 결과 명시, 검증어떤 환경에서 (given) 어떤 행동을 진행했을때(when) 어떤 상태 변화가 일어난다 (then) Longed for (앞으로 바라는 점)다음주 화요일까지 5시간 넘는 강의 있는데 어서 호다닥 들어봐야겠당... 이번 스터디 후에는 테스트코드 만들기 고수가 되곱! 

인프런온보딩테스트코드

nnahye

세번째 발자국 👣

테스트는 왜 필요할까?-테스트를 통해 얻고자 하는것빠른 피드백자동화안정감단위테스트작은 코드단위를 독립적으로 검증하는 테스트검증속도가 빠르고, 안정적이다테스트 케이스 세분화하기해피케이스예외케이스경계값 테스트 ( 범위(이상,이하,초과,미만)구간 날짜 등)테스트하기 어려운 영역을 분리하기테스트하기 어려운 영역-> 관측할 때마다 다른 값에 의존하는 코드현재날짜/시간, 랜덤 값, 전역 변수/함수, 사용자 입력 등 -> 외부세계에 영향을 주는 코드표준 출력, 메시지 발송 , 데이터베이스에 기록하기 등TDD : Test Driven Development프로덕션 코드보다 테스트 코드를 먼저 작성하여 테스트가 구현과정을 주도하도록 하는 방법론레드: 실패하는 테스트 작성 -> 그린: 최소한의 코딩 -> 리팩터: 구현코드 개선 테스트 통과유지클라이언트 관점에서의 피드백을 주는 Test Driven테스트는 []다프로덕선 기능을 설명하는 테스트 코드 문서DisplayName을 섬세하게-명사의 나열보다 문장으로-테스트 행위에 대한 결과까지 기술하기-도메인 용어를 사용하여 한층 추상화된 내용을 담기-테스트 현상을 중점으로 기술하지 말것BDD 스타일로 작성하기-TDD에서 파생된 개발 방법-함수 단위의 테스트 보다 시나리오에 기반한 테스트케이스자체에 집중-개발자가 아닌 사람이 봐도 이해할수 있을 정도의 추상화 수준을 권장Given / When / ThenGiven : 시나리오 진행에 필요한 모든 준비 과정When : 시나리오 행동 진행Then : 시나리오 진행에 대한 결과 명시, 검증 Layerd Architecture와 테스트Layerd Architecture -> 관심사의 분리Persistence LayerData에 대한 CRUD에만 집중한 레이어 Data Access의 역할비지니스 가공 로직이 포함 되어서는 안된다.Business Layer비즈니스 로직을 구현하는 역할Persistence Layer와의 상호작용(Data를 읽고 쓰는 행위)를 통해 비즈니스 로직을 전개시킨다.트랜잭션을 보장해야한다.테스트 코드 작성하기 미션 회고 이렇게 하는 것이 맞는지 계속 의문이 들었다. DisplayName을 짓는 것도 어렵고 쉽지 않았다. 예외 케이스를 생각하는게 쉽지않았다.

[워밍업 클럽 2기 BE 클린코드&테스트 코드] 3주차 발자국

강의에 대한 리뷰드디어 기다리던 테스트코드 작성 강의를 수강했다.강의 내용테스트 코드 작성법부터, Junit5, TDD, BDD 등 다양하게 배웠다. 중요한 건 테스트하기 좋은 코드와 그렇지 않은 코드를 구분하는 것 이라 생각한다. 나는 이것을 잘하는 게 SOLID 원칙을 지키는 것과 유사하며, 확장성있는 설계, 유지보수하기 쉬운 설계에 가까워진다고 생각한다. 실제로 적용하기에는 많은 연습이 필요하겠지만, 마스터(?)하게 되면 좀 더 좋은 코드를 작성할 수 있다는 것만큼은 확신할 수 있다.그리고 예제를 중심으로 스프링에서 테스트 코드를 레이어별로 어떻게 쌓아가는 지 알아봤다. 예제는 JPA 기반이었으며, 리포지토리는 새로 추가된 리포지토리만 테스트해봤다. 내가 알기로도 리포지토리 테스트는 @DataJpaTest 가 가볍기 때문에 다들 사용하는 것으로 알고있는데, 우빈님은 선호하지 않는다고 하신다. 그 이유는 뒤에 강의에서 나오는데 통합테스트할 때, 모든 테스트를 실행하게 되면 Spring boot가 너무 여러번 뜨게된다. 이 행위는 시간을 잡아먹기 때문에 비용이다. @DataJpaTest를 사용하면 그 볼륨은 작지만, 다른 레이어를 사용하면서 @SpringBootTest 를 사용했다면, 이미 띄운 서버를 그냥 같이 써버리는 게 훨씬 경제적이라는 맥락이다. 나는 제대로 테스트 코드를 작성해본 적이 없어서 엄청난 공감을 하진 못한다. 써보면서 테스트 비용에 대해 알아가야겠다.미션Readable Code에서 했던 예제 중 하나를 선택해서 테스트코드를 작성하는 미션이었다.나는 스터디카페 이용권 예제를 선택했다. 다음은 테스트를 작성하면서 정리한 내용이다.테스트 하기 어려운 코드IO 작업을 하는 코드요구 사항이 변하기 쉬운 코드. ex) 사물함 사용가능한 좌석 이용권ex) 비즈니스 로직에서 사용되는 상수에 따라 결과가 달라지는 코드테스트 하기 쉬운 코드input과 output이 명확한 코드의존성을 외부에서 주입할 수 있는 코드단위가 작은 메서드, 객체이것도 테스트를 해야하나? 하는 코드생성자, 정적 팩터리 메서드단순 getter 메서드단순 위임 메서드 (위임의 가장 안쪽 클래스는 테스트O)기타 어려웠던 점DisplayName에 나타낼 테스트명을 작성하는 것이 어려웠음비즈니스 코드를 리팩터링하고 싶은 코드들이 있었음. 우선 미션 외적인 것이라 생각해 손대지 않음. 회고이번주 강의 내용은 거의 실습위주라 이론적으로 정리할 게 별로 없었다. 조금 달렸던 일주일인 것 같은데, 다른 것도 막 병행하느라 놓친부분이 있진 않을까 걱정된다. 할 건 너무 많은데 이래저래 머리가 복잡하고 마음이 급하다.커리어를 길게보고 좀 더 여유를 가지자.

rhrud0412

[인프런 워밍업 클럽 Figma 2기] 프로덕트 디자인 3주차 발자국

인프런 워밍업 클럽 2기 3주차'2주차때 못했던 부분을 수정하고, 다음 진도를 꾸준히 따라가기'를 목표로 함.'주어진 과제를 완벽하게 끝내보자!!'는 마음가짐으로 시작 3주차 학습 내용내비게이션 컴포넌트 만들기 : Link, Bredcrumbs, Tab, Bottom Nav, Pagination, Side Nav, Header, Carousel베리어블 모드 활용(다크모드, 브랜드 컬러 지정 모드, 다중언어 지원화면)컴포넌트 활용하여 이커머스 어드민 페이지 만들기 잘한점그때 그때 미루지 않고 강의를 들으면서 과제 제출을 했다는 것막히는 부분은 할 수 있을때까지 시도해봤다는 점. 아쉬운점반응형 과제를 해보면서 예상한 방식으로 크기 조정이 되지 않는 부분이 존재했고, 상위 컴포넌트 auto layout의 설정을 확인하는 과정을 반복하게 되었다. 이를 통해 auto layout의 fill, hug 부분에 대하여 정확히 숙지하지 못했다는 생각이 들었다...ㅜ  전체회고 및 다음주 목표한동안 컴포넌트를 배우고 만들다가, 만든 컴포넌트를 활용해서 반응형 페이지를 만들게 되어서 재미있었다. 그리고 베리어블 모드를 통해 상황에 따라 바꿀수 있다는 점이 신기하고 편해서잘 활용해 볼 수 있도록 해봐야겠다는 생각이 들었다. 또한, 다음주가 마지막인데 꾸준히 따라온 만큼 마무리를 확실하게 하고싶다. 

UX/UIfigma디자인시스템boldUX워밍업클럽프로덕트디자인

인프런 워밍업 클럽 3주차 발자국

3주차 강의 정리테스트의 필요성 -> 커버할 수 없는 영역 발생 방지, 감보다 코드에 의존잘못 작성된 테스트 코드 -> 새로운 짐올바른 테스트 코드수동 테스트 -> 콘솔 출력 및 개발자에 의한 판단자동 테스트 -> 안정성 및 유지보수성 증가단위 테스트 -> 클래스 및 메소드 단위, JUnit5, AssertJ해피 케이스와 예외 케이스 -> 경계값 테스트테스트하기 어려운 영역을 분리하여 production code와 test code를 교체할 수 있도록 테스트 설계TDD -> 프로덕션 코드보다 테스트 코드를 먼저 작성, Red-Green-RefactorTDD로 엣지 케이스 발견 가능성을 높이고 복잡도가 낮은 코드 구현 가능테스트 코드가 기능의 보조 수단이 아닌 동등한 관점에서 협력하는 관계가 될 수 있다.기능을 설명하는 문서 -> 기능 이해 도움 & 고민의 결과물@DisplayNameBDD -> given-when-then통합 테스트Library vs Framework -> 내 코드의 관점@SpringBootTest vs @DataJpaTestassertThat().extracting().contains()Persistence Layer -> Data Access의 역할Business Layer -> 비즈니스 로직 구현 역할@Transactional vs tearDown() 3주차 강의 회고좋았던 점테스트에 대한 필요성에 대해 더 잘 알게 되었다.TDD를 실제로 적용해볼 수 있었다.Spring & JPA에 테스트를 적용할 수 있었다. 아쉬웠던 점테스트 지점을 아는 것이 어려웠다 배운 점테스트 도구 사용법단위 테스트와 통합 테스트 적용 방법앞으로 바라는 점테스트 커버리지 도구와 CI에 테스트 적용하는 법 공부미션Day12고민했던 점IO 담당하는 부분 테스트를 어떻게 해야하는지파일 입력을 테스트 상에서 구현하는 방법? @MappedSuperclassJPA에서 엔티티의 공통 속성을 정의하기위해 사용.부모 클래스에 정의된 모든 속성은 자식 클래스의 테이블에 포함@EntityListenersCollectors.groupingBy()Builder와 private 생성자

suover

인프런 워밍업 클럽 스터디 2기 - 백엔드 프로젝트 3주차 발자국

입문자를 위한 Spring Boot with Kotlin - 나만의 포트폴리오 사이트 만들기강의와 함께한 인프런 워밍업 클럽 스터디 2기 - 백엔드 프로젝트 (Kotlin, Spring Boot) 3주차 발자국 입니다. 강의 수강이번 주에는 실습 중심으로 Spring Boot와 JPA를 사용한 컨트롤러 개발과 API 설계를 진행했습니다.API 테스트 코드를 작성해보고, Thymeleaf를 활용한 프론트 개발 작업도 수행했습니다.주요 학습 내용Spring MVC와 JPA를 활용한 컨트롤러 개발PresentationApiController 및 PresentationViewController에서 다양한 API 엔드포인트를 구현했습니다.JPA를 통해 데이터베이스와 상호작용하며 데이터를 처리하는 방법을 학습했습니다.Thymeleaf 프론트엔드 개발템플릿을 활용하여 데이터를 프론트엔드에 전달하고 뷰를 생성했습니다.커스터마이징을 통해 유지 보수가 용이한 뷰를 구성했습니다.컨트롤러 테스트 코드 작성API 테스트 코드를 작성하여 정확하게 동작하는지 검증했습니다.실제 API가 예상대로 동작하는지 검증하는 방법을 배웠습니다. 회고이번 주는 Spring Boot와 JPA를 활용한 컨트롤러 개발과 API 설계, 그리고 테스트 코드 작성까지 다양한 실습을 통해 실질적인 개발 경험을 쌓는 데 집중한 한 주였습니다. 특히, 데이터를 조회하고 처리하는 API를 설계하면서 RESTful 구조에 대해 깊이 고민했고, 테스트 코드 작성이 얼마나 중요한지 다시 한번 깨닫게 되었습니다. 실습을 통해 새로운 개념들을 익히고, 실제 프로젝트에 적용해보며 기술적 성장을 이뤘습니다.칭찬할 점테스트 코드를 작성하여 API의 주요 기능들을 효율적으로 검증했습니다.Thymeleaf 템플릿 커스터마이징을 통해 프론트엔드를 구성하고, 유지 보수가 용이하도록 최적화했습니다.아쉬웠던 점 및 보완할 점Thymeleaf 문법에 대한 이해가 부족하여 복잡한 작업에서 어려움이 있었습니다.테스트 코드를 더 간결하고 효율적으로 작성하기 위해 리팩토링 기법을 학습할 계획입니다.미션이번 주 미션은 게시글 조회 REST API를 개발하고, 이를 검증하기 위한 테스트 코드를 작성했습니다.API는 전체 게시글 조회와 특정 게시글 조회 두 가지 기능을 제공합니다. 미션 과정전체 게시글 조회 API 설계GET /api/posts 엔드포인트에서 전체 게시글을 조회하고, JSON 형식으로 데이터를 반환합니다.특정 게시글 조회 API 설계GET /api/posts/{postId}로 특정 게시글 ID를 기반으로 게시글을 조회하여 반환하는 기능을 구현했습니다.테스트 코드 작성 및 검증각 엔드포인트에 대해 단위 테스트를 작성하여 모든 기능이 예상대로 동작하는지 검증했습니다.특히 게시글이 없는 경우와 같은 예외 상황을 처리하는 테스트도 포함시켜 로직의 완성도를 높였습니다.  회고이번 미션을 통해 RESTful한 API 설계의 중요성을 다시 한번 느꼈습니다. 엔드포인트를 직관적이고 간결하게 설계하기 위해 많은 고민을 했으며, 테스트 코드를 작성하며 API 동작을 검증하는 과정에서 테스트의 중요성을 다시 한번 실감할 수 있었습니다.아쉬운 점 및 보완할 점테스트 코드의 가독성과 효율성을 높이기 위해 추가적인 리팩토링이 필요합니다.JPA의 복잡한 연관 관계 처리에서 어려움을 겪었으며, 이러한 부분을 더 명확하게 이해하기 위해 추가적인 학습이 필요합니다.이번 주의 학습과 미션을 통해 부족했던 부분들을 확인할 수 있었고, 앞으로도 지속적인 학습과 실습을 통해 문제를 개선해 나갈 계획입니다. 특히, JPA 연관 관계와 테스트 코드의 리팩토링에 집중하여 더 나은 품질의 코드를 작성하고, 실무에 적용할 수 있도록 역량을 키워가겠습니다.

백엔드인프런워밍업클럽스터디백엔드프로젝트발자국회고SpringBoot

Seul Ki Lee

워밍업 클럽 2기 BE 클린코드&테스트 발자국 3주차

강의 : Practical Testing: 실용적인 테스트 가이드테스트의 필요성잘 만든 테스트로 인하여 신뢰성 있는 소프트웨어를 만들 수 있다잘 만든 테스트로 인하여 과감한 수정 및 리팩토링이 가능하다테스트 코드 자체가 문서가 된다자동화 테스트와 JUnit테스트를 만드는 것 자체도 비용이 들기에 사람이 수동으로 하기 보다는 자동화 테스트가 필요함테스트를 빠르고 여러번 실행 가능하도록 하도록 JUnit이 돕는다 테스트 어려운 영역을 분리테스트는 반복가능하며 항상 성공하는 테스트여야 한다시간, 랜덤 등의 성격의 경우 매개변수로 주입하여서 테스트 힘든 부분을 분리하여 테스트가 가능하다TDD실패하는 테스트를 만든다테스트를 성공 시킨다리팩토링아래의 3단계를 짧은 사이클로 가져가면서 점차적으로 개발이 가능하다DisplayName테스트는 요구사항을 잘 드러내는 문서의 역할도 겸하기 때문에 Display name을 잘 지어야 한다~ 테스트가 아닌 문장으로 끝내며 주어, 목적, 결과가 다 드러나도록 기재해야 한다BDDgiven, when, then 3단계에 나눠거의 : Practical Testing: 실용적인 테스트 가이드 테스트의 필요성잘 만든 테스트로 인하여 신뢰성 있는 소프트웨어를 만들 수 있다잘 만든 테스트로 인하여 과감한 수정 및 리팩토링이 가능하다테스트 코드 자체가 문서가 된다자동화 테스트와 JUnit테스트를 만드는 것 자체도 비용이 들기에 사람이 수동으로 하기 보다는 자동화 테스트가 필요함테스트를 빠르고 여러번 실행 가능하도록 하도록 JUnit이 돕는다테스트 어려운 영역을 분리테스트는 반복가능하며 항상 성공하는 테스트여야 한다시간, 랜덤 등의 성격의 경우 매개변수로 주입하여서 테스트 힘든 부분을 분리하여 테스트가 가능하다TDD실패하는 테스트를 만든다테스트를 성공 시킨다리팩토링아래의 3단계를 짧은 사이클로 가져가면서 점차적으로 개발이 가능하다 DisplayName테스트는 요구사항을 잘 드러내는 문서의 역할도 겸하기 때문에 Display name을 잘 지어야 한다~ 테스트가 아닌 문장으로 끝내며 주어, 목적, 결과가 다 드러나도록 기재해야 한다BDDgiven, when, then 3단계에 나눠서 테스트를 작성하도록 한다given테스트에 필요한 객체 및 데이터를 생성한다when테스트하고자 하는 내용을 실행한다thenassertj 단언문을 이용하여 테스트하고자 하는 내용을 확인한다 

백엔드클린코드테스트워밍업클럽2기

Rojojun

[워밍업 클럽 스터디 2기::백엔드] 3주차 발자국

1주일간의 학습 회고테스트코드의 강의를 완강하였다.이번 주 공부한 분량은 생각보다 많지는 않았다.중점적으로 관심있던 부분은 TestFixture와 RestDocs였다.TestFixture 강의 내에서 나온 TextFixture는 많은 내용이 없었지만, 실제로 프로젝트에서 이 강의를 보기전에 적용해 본 적이 있다.가장 도움이 되었던 내용은 토스의 기술 블로그였다. (하단 참조)https://toss.tech/article/how-to-manage-test-dependency-in-gradle예전에 프로젝트에서 적용하면서 느낀 장점과 단점에 대해 간단하게 기술해보면 다음과 같다.사실 적용법은 너무 많은 블로그에 나와 있기 때문에, 개인적인 장/단점을 공유하는게 옳다고 생각한다.장점Fixture관리가 편하다테스트 코드에서 Fixture를 파편화 시켜서 사용하지 않아도 된다.Gradle에서 지원한다단점Fixture도 관리 대상이 된다실제로 Entity나 DTO가 변경될 때 Fixture를 변경하지 않아서 빌드가 안되거나 하는 경우가 있었는데, 너무 번거롭다.모든 팀원들이 인지하지 않으면 꽤나 힘들다... (개인적인 생각이다)깊은 연관관계가 되어 있는 경우에는 결국 여러개의 Fixture와 Fixture 시나리오를 구성해야하기 때문에 꽤나 번거롭다.위와 같은 문제점을 해결하기 위해서, 고민을 덜기 위해 FixtureMonkey 라는 것도 고민을 해보았는데, 막상 생각보다 그렇게 와우 모먼트를 이끌만하지 않았기에 Fixture를 계속 사용하였다. RestDocs강사님이 이야기한것들 중에 정말 많은게 공감이 되었다.강사님은 RestDocs, Swagger 비교를 하셨지만 거기서 더 나아가서 PostMan과 같은 상용 API 문서화 툴까지 비교를 하자면, 회사 내 우리팀은 BFF 로서 백엔드 프론트가 나뉘어져 있다. 그렇기에 API 문서화가 중요한데 API 문서화 툴의 단점은 업데이트 주기가 사람한테 맞추어져있다는 점이다.그래서, Swagger를 도입하느냐 마느냐에 대한 이야기가 있었다. 개인적으로... Swagger를 반대하는 이유는 강의내용과 같다. Swagger가 프로덕션 코드에 침투하는게 너무 싫다!! 그러나... RestDocs를 사용하는 이야기는 하지 않았다... 왤까?이유는 다음과 같다. 아스키독스에 대한 학습이 싫다 -> 빠르게 도입을 해야할 때 발목을 잡을 수 있다TestCode에 대한 지식이 모든 팀원이 100%가 아니다 -> 사실 위 내용이 컸다....좋은 방안과 툴이여도 결국 회사의 상황과 역량에 따라 어쩔 수 없지만, 개인적인 프로젝트에서는 도입을 해볼 계획이다.해봐야 ㅋㅋ 이게 효율적인지 아닌지 알거 같다! 이번 주 학습에서 잘한 점사내에 개선점들이 있어서 개선에 도움을 주고자 간단한 프로젝트를 자체 개발하고 있었다...프로젝트를 하면서, 느리지만 개인적으로 한달정도를 예상하고 있어서 TDD를 통해서 그리고 읽기좋은 코드로 만들고 있다.향후 유지보수와 문서화를 위해서 내가 공부한 내용을 적용할 수 있게 했다. 아쉬웠던 점금요일에!! 깜짝 세션이 있었다... 참여를 못했다!!!같이 공부하는 팀원들과 함께 질문할것이 있었는데 ㅠㅠㅠ 하지를 못했다... 내 질문은 TDD의 영역이다...TDD의 영역이란 테스트 커버리지 퍼센트가 아닌 실용적인 이야기다...개인적으로 실용주의적인 개발자라 생각하여 나는 테스트코드가 100% 커버리지 혹은 90% 이상 커버리지를 좋다고 생각하지는 않는다.그래서 TDD의 영역에 대해 물어보려 했는데ㅠㅠ.... 회사 팀원들과의 협업TDD의 영역에 대해 같이 공부하고 있는 회사 동료들에게 물어봤다! 동료 중 한 명이 강사님에게 물어보라 했는데 ㅠㅠ 까먹었다... 또한 그 동료가! 물어본 것들 중 하나가... 인터페이스의 테스트 영역에 대해서 세명이서 토론하다가 이것도 물어보자! 해서 끝났다...좋은 동료와 좋은 스터디를 하고 이런 개념들을 발전해 나가서 너무 좋다!

백엔드테스트코드백엔드자바스프링

[워밍업 클럽 2기 - Clean Code & Test Code] 3주차 발자국

워밍업 클럽 2기: Clean Code & Test Code의 3주차 발자국 작성입니다.2주차 발자국 보러가기<br>✍ 학습 내용 복습Q. 자동화된 테스트가 필요한 이유는?값을 직접 출력해서 확인하는 수동 테스트는 사람이 개입해서 확인해야 한다. 검증을 사람이 하기 때문에, 값을 확인하는 과정에서 휴먼 에러가 발생할 확률이 높다.자동화된 테스트를 도입하면 검증을 기계에 맡길 수 있기 때문에 사람이 직접 검증하는 것 보다 신뢰할 수 있다.사람이 일일이 확인하는 것보다 빠르다. Q. 단위(Unit) 테스트란?단위 테스트(Unit Test)라는 것은 코드의 가장 작은 기능적 단위를 독립적으로 검증하는 테스트를 일컫는다.여기서 작은 기능적 단위(Unit)는 보통 내가 작성한 클래스 또는 메서드를 의미한다.Q. 테스트할 때 신경 써야하는 부분들은?예외 케이스를 고민한다경계값에 대한 테스트는 중요하다(예시: 범위, 구간, 날짜, 등의 경계값에 대한 테스트) Q. TDD(테스트 주도 개발)란?프로덕션 코드보다 테스트 코드를 먼저 작성해서 테스트가 코드의 구현 과정을 주도하도록 하는 개발 방법론Red, Green, Blue의 3단계 과정으로 이루어진다Red제일 먼저 실패하는 테스트 코드를 작성한다이때 테스트 코드는 컴파일 조차 안돼도 괜찮다Green테스트를 통과하도록 위해 실제(프로덕션) 코드를 작성한다이때 작성하는 코드는 테스트를 통과할 정도로만 최소한의 코드를 작성하도록 한다최대한 빠르게 작성하려고 노력한다Blue코드를 리팩토링한다설계나 구현을 개선한다이때 테스트의 통과 상태는 유지되어야 한다 Q. 좋은 Display Name(테스트 네이밍)은?행위에 대한 결과까지 담는다도메인 용어를 사용한다코드의 단위를 검증하는 것이 아닌 동작(기능)의 단위를 검증하려고 노력한다 🤔 회고중간에 1, 2주차에서 활용했던 StudyCafe 애플리케이션에 대한 단위 테스트를 작성해보는 미션을 수행 했지만, 잘 작성하지 못했던 것 같다.코드를 따라 쳐보면서 학습 해야겠다  🔍 참고Practical Testing: 실용적인 테스트 가이드

백엔드발자국3주차테스트코드워밍업클럽2기백엔드

ailen22

[인프런 워밍업 클럽 2기 - 백엔드 프로젝트(Kotlin, Spring)] 3주차 발자국

3주차 발자국 컨트롤러 개발어노테이션@SpringBootTest 실제 애플리케이션과 유사한 환경을 구성하여 테스트를 실행@AutoConfigureMockMVC MockMVC 객체가 자동으로 구성되어 컨트롤 러를 모의로 테스트 할 수 있음 Thymeleaf 문법xmlns:th 타임리프의 네임스페이스를 선언th:fragment 템플릿의 일부를 재사용 가능한 fragment로 정의th:replace 해당 요소를 다른 요소로 대체할 때 사용th:href 링크의 URL을 동적으로 설정th:each 반복할 데이터의 개수만큼 HTML 요소를 생성th:class HTML 요소의 클래스를 동적으로 설정th:text 텍스트 컨텐츠를 동적으로 설정th:if 조건이 참일 경우 해당 HTML 요소를 표시하고, 거짓일 경우 표시하지 않음 관리자(admin) 개발오류의 종류Throwable 오류의 최상위 클래스Error 애플리케이션에서 대응할 수 없는 오류Exception 애플리케이션에서 대응할 수 있는 오류Unchecked Exception RuntimeException을 상속하는 모든 예외 (@Transactional에서 롤백의 대상) Checked Exception Exception을 상속하며 RuntimeException이 아닌 모든 예외, try-catch를 이용해 반드시 대응 코드를 작성어노테이션@ExceptionHandler 컨트롤러에서 던진 예외를 잡아 처리해주는 역할,컨트롤러마다 예외를 처리하는 중복 코드를 작성할 필요없이, 같은 예외를 공통적으로 처리할 수 있게 해줌@ControllerAdvice 범위 내의 모든 컨트롤러 클래스에 @ExceptionHandler를 공통적으로 적용 [미션4] 조회 REST API 만들기 미션을 만드는데 미리미리 강의랑 진도를 맞춰놓지않아 시간이 오래걸려서 조회 컨트롤러만 만들고 제출해버렸다. 오늘, 내일 시간을 들여서 고쳐야 한다. 조금씩 이해는 가는데 완전히 이해가 가지 않아서 반복학습을 해야할 것 같다.      3주차에 접어들면서 화면 사이트가 눈에 보이니까 만드는 재미가 있던 것 같다. 강의를 보면서 따라가기 급했지만 점차 이해가 가는 내용이 많아져서 즐거웠다. 그리고 자꾸 마지막 s를 빼먹어서 오타오류가 자주 난다. 확인 또 확인!          

[워밍업 클럽 스터디 2기::백엔드] 3주차 발자국

이번주 학습 내용테스트를 작성을 위해 생각하는 요령과 테스트를 왜 필요한지 등 테스트에 관해서 학습했다.테스트 작성을 위해 고민 해나가는 과정새로운 요구사항이 들어왔을 때, 요구사항이 잘 정의 되었는지, 암묵적으로 이야기 되지 않은 내용이 있거나, 아직 고려하지 못한 예외상황에 대한 처리가 필요할지 확인을 해야한다.테스트 케이스들을 세분화 해서, 해피 케이스 말고도, 예외 케이스인 경우도, 개발자가 예상한 상황이 되는지 체크할 수 있다.예외 케이스의 경우, 경계값 (범위나 구간, 날짜 등)으로 체크를 하는 것이 좋다.TDD 방식코드 구현이전, 테스트를 작성 후, 구현을 통해 테스트가 구현과정을 주도로 하는 방법TDD 방식은 다음과 같은 과정을 거친다RED 실패하는 테스트 작성GREEN 테스트 통과를 위한 최소 작업REFACTOR 구현 코드 개선 하며, 테스트 통과를 유지하도록 한다.장점테스트를 먼저 작성한 뒤, 구현을 하게 된다면, 테스트하기 어려운 영역(관측할 떄마다 다른 값에 의존을 하거나, 외부 세계에 영향을 주는 코드)들에 대해서 외부 파라미터 등으로 넘겨주도록 해, 해당 부분도 테스트 가능한 코드를 작성할 수 있다.내가 작성하는 코드에 대해서, 자주, 빠르게 피드백 받을 수 있게된다. (테스트 케이스 확인만으로 가능)구현 후 테스트를 작성하게 되면, 구현부에 의존한 테스트에 대해서만 생각하게 될 수 있어, 놓치기 쉬운 엣지 케이스들에 대해서도 고려할 수 있게 된다.테스트를 통해 보장해야할 기능목록이 생성 되 있어, 과감한 리팩토링도 가능하게 된다.BDD 방식개발자가 아닌 사람이 봐도 이해할 수 있을만한 추상화 수준을 테스트에 적용하는 것함수 단위의 테스트 보다 시나리오에 기반한 테스트케이스 자체에 집중하여 테스트 한다.Given / When / ThenGiven : 시나리오 진행에 필요한 모든 준비 과정When : 시나리오 행동 진행Then : 시나리오 진행에 따른 결과 명시, 검증BDD방식으로 테스트를 작성 한다면, 테스트 코드로 프로덕션의 기능을 명시하는 문서의 역할을 할 수 있다.해당 방식으로 작성된 테스트를 보고, 코드를 이해하는 다양한 시각과 관점을 키워갈 수 있고, 팀단위로 관리된 테스트 들은 다른 사람들이 어떤 관점으로 테스트를 작성했는지를 통해 팀의 자산으로 관리될 수 있다.좋았던점 (Liked)테스트 코드를 좀더 알아가고 싶어서 깃에 스프링 부트 소스등 잘 만들어진 테스트 코드가 무엇이 있는지 찾아보는 시간을 가졌다.아쉬웠던 점 (Lacked)이번주에 회사 회식과, 타 일정이 많아 미션에 쏟은 시간도 짧았고, 이번주에는 강의도 많이 밀렸다..내가 저번주에 2주만에 완강을 하면서 끝난듯이 너무 쉬는 시간이 많았던것 같다.다시 마음을 다잡고 완강할 수 있도록 해야겠다.배운 점 (Learned)이전에, 테스트 코드를 TDD 방식으로 작성해보고자 했었던 적이 있었는데, 그때는 TDD의 장점에 대해서 전혀 파악하지 못하고, 어떻게 사고해야 하는지, 테스트가 진짜 의미는 있는걸까 하는 의문점이 지금은 조금씩 해결되 가고 있는 느낌이다. 강의를 잘 쫓아가며, 테스트에 대해 더 빠져보아야 겠다.앞으로 바라는 점(Longed for)일단 이번주에 진행하지 못한 부분이 커서.. 진도에 맞추어 진행할 수 있도록 열심히 쫓아가야겠다!

백엔드

[인프런 워밍업 스터디 클럽 2기 백엔드(클린코드, 테스트코드)] 3주차 발자국

TDD에 대해가까이보면 느려보이지만 멀리보면 가장 빠른 개발 방법 테스트를 하는 이유빠른 피드백을 위해 레이어별로 코드 작성하고… 빌드하고… 포스트맨 돌리고… 하는 시간을 절약할 수 있습니다. 자동화된 피드백 사람이 직접 수동으로 확인하는게 아니라 테스트 환경에서 피드백을 받을수 있습니다.심리적 안정감 내가 작성한 코드에 대한 안정감, 자신감귀찮게 느껴지지만 직접 작성해보니 생각보다 많은 시간을 아낄수 있게 도와준다는 인상을 받았습니다. 단위테스트(Unit test)작은 코드 단위를 독립적으로 검증하는 테스트클래스, 메소드등 가장 작은 단위를 테스트 하는 것외부에 의존하지 않음 TDD(Test Driven Development)사이클의 실패하는 테스트, 최소한의 코딩이 이해되지 않았었는데극단적인 예시지만 바로 이해를 시켜주셨습니다. 테스트를 먼저 작성하는 이유기능 먼저 작성하면기능 먼저 구현시 테스트 자체가 누락될 가능성이 높음 → 귀찮으니까해피케이스만 검증할 가능성이 높음 → 사고가 갇히게 됨 예외 상황을 예측하기 어려움잘못된 구현을 늦게 알아차림 → 유지보수가 힘들어 진다.결국 테스트가 불가능한 코드가 탄생하게 될수도테스트를 먼저 작성하면복잡도가 낮은, 테스트가 가능한 코드로 구현이 시작됨예외 케이스에 대해 생각하므로 문제를 조기에 발견 가능함과감하게 리팩토링, 구현이 가능하다. TDD에 대한 오해테스트의 진짜 목적은 검증이 아닌 상호 작용을 통한 프로덕션 코드의 발전입니다테스트 코드는 프로덕션 코드에 대한 여러 케이스를 보여주기 때문에하나의 명세가 될 수 있고 무엇이 필요한지 어떤걸 주의해야할 지 코드로 설명이 가능합니다.덕분에 프로덕션, 도메인에 대해 여러 시각과 관점을 가질수 있게 되고이런 장점은 결과적으로 팀의 자산이 되어 팀원 모두에게 도움을 줄 수 있습니다. 하지만 테스트 코드가 병목이 될수도 있다.그래서 우리가 고민 해야할 것드러나지 않은, 숨겨진 혹은 암묵적인 요구사항이 없는지 기획 의도는 대부분 해피케이스를 말합니다 때문에 예외 케이스를 스스로 고민해봐야 합니다 특히 엣지 케이스 경계값 테스. 트가 필요하지 않우리가 무얼 검증하고 있는것인지 생각해봐야함. 테스트 코드는 반드시 프로덕션 코드와 같지 않아도 됨 하지만 내가 만드는 기능이 무엇인지 어떤 검증이 필요한지를 명확하게 해야함값에 의존하는 코드인지 외부 세계에 영향을 주는 코드인지 판단하기 = 테스트하기 어려운 기능 값에 의존적이라면 테스트 내부에 있던 값을 파라미터, 상수로 값을 메서드 밖으로 꺼내는걸 고려해야하고 외부 세계에 영향. 을 준다면 신중하게, 예외처리 등을 섬세하게 처리해주어야 합니다. 회고테스트 코드를 안개속에 있는것처럼 느끼고 있었는데너무 쉽고 명확하게 설명을 해주셔서 좋았습니다.저에게 큰 도움이 된 주차였습니다. 

김민성

[워밍업 클럽 스터디 2기 - BE] (클린코드, 테스트코드) 3주차 발자국

인프런 워밍업 클럽 스터디 2기 - 백엔드 클린코드, 테스트 코드(Java, Spring Boot)Practical Testing: 실용적인 테스트 가이드해당 강의를 학습하며 정리하는 내용입니다. 2주차 발자국에 이어서 이번주도 배운 내용을 정리하고 회고를 작성한다. 이번주는 Practical Testing: 실용적인 테스트 가이드를 수강을 시작했다. 평소에도 테스트 코드를 작성해야 좋다 라는건 알고 있었지만 각종 핑계로 작성을 잘 안했었는데, 이번 강의를 통해 테스트 코드를 잘 작성하는 습관을 기르고자 한다. 왜 테스트 코드를 사용할까? 점점 기능을 추가할 때마다 새로운 사람들이 새로운 수동 테스트를 진행하고, 이전 기능이 잘 동작하는지 이전 테스트도 또 진행 해야한다.그럼 시간이 지날수록커버할 수 없는 영역 발생경험과 감에 의존늦은 피드백 유지보수 어려움결국 소프트웨어 신뢰 ↓라는 결과가 나타난다. 그래서 테스트 코드로 얻고자 하는 것은빠른 피드백자동화안정감이다.  테스트 코드는 귀찮다 → 귀찮지만 해야한다. 단위 테스트작은 코드 단위를 독립적으로 검증하는 테스트작은 → 클래스 or 메서드다른 코드에 의존적이지 않는검증 속도가 빠르고, 안정적인테스트 코드 세분화해피케이스만 생각하지 말자. 예외 케이스도 검증해야 한다.경계 값 : 범위(이상, 이하, 초과, 미만), 구간, 날짜 등 테스트 하기 어려운 영역을 분리현재 시간 : 이건 테스트 할 때마다 바뀌는 값.. 관측할 때마다 다른 값에 의존하는 코드현재 날짜/시간, 랜덤 값, 전역 변수/함수, 사용자 입력 등외부 세계에 영향을 주는 코드표준 출력, 메시지 발송, 데이터 베이스에 기록 등 Order order = cafeKiosk.createOrder(LocalDateTime.of(2024, 10, 13, 10, 0));이렇게 테스트하기 어려운 값들을 외부에서 받아오도록 분리하면 테스트가 가능해진다.[CafeKiosk 요구조건 추가 - 특정 시간에만 주문 가능 - 테스트하기 어려운 영역을 분리하기](https://github.com/iamminseongKim/PracticalTesting/commit/4cbb22efb698f77796bdc52c84237d2bf61d4c2c) TDD프로덕션 코드보다 테스트 코드를 먼저 작성하여 테스트가 구현 과정을 주도하도록 하는 방법론Red - Green - Refactor 단계 개발Red : 실패하는 테스트 작성Green : 테스트 통과를 위한 최소한의 코딩Refactor : 구현 코드 개선, 테스트 통과 유지 테스트는 [문서]다.프로덕션 기능을 설명하는 테스트 코드 문서다양한 테스트 케이스를 통해 프로덕션 코드를 이해하는 시각과 관점을 보완어느 한 사람이 과거에 경험했던 고민의 결과물을 팀 차원으로 승격시켜서, 모두의 자산으로 공유할 수 있다.BDD : Behavior Driven DevelopmentGiven / When / Then Spring & JPA 기반 테스트Layered Architecture관심사의 분리를 위해 레이어를 분리A모듈과 B모듈이 만나서 AB, BA, C? 뭐가 나올지 모른다. 통합 테스트가 필요 Persistence Layer 테스트쿼리를 테스트. 스프링 서버를 띄워서 테스트해야 하지만 계층을 분리해서 테스트 하기 때문에 일종의 단위 테스트 성격을 가지고 있다.@DataJpaTest : @SpringBootTest 에서 JPA 관련 기능만 올려서 빠르게 테스트 할 수 있도록 도와줌. 하지만 @Transactional이 들어가 있기 때문에, 테스트 시 이 점을 고려하고, 이해하고 사용해야함.리스트 테스트 할 때 팁 : size를 먼저 체크하고, extracting&contain 으로 안에 내용물을 검증 Business Layer비즈니스 로직을 구현하는 역할Persistence Layer와의 상호작용(Data를 읽고 쓰는 행위)를 통해 비즈니스 로직을 전개시킨다.트랜잭션을 보장해야 한다. [CafeKiosk - Business Layer 테스트 (1)](https://github.com/iamminseongKim/PracticalTesting/commit/70a421e2eec5bb2eedafea368f08148ac486c3cb)[CafeKiosk - Business Layer 테스트 (2)](https://github.com/iamminseongKim/PracticalTesting/commit/779e2c0ac4a92a317dc96a5cd52dea6934518b1a)[CafeKiosk - Business Layer 테스트 (3)](https://github.com/iamminseongKim/PracticalTesting/commit/ab172150610a70445e19f2a7b8ab587db63e43f5)미션readable code때 사용한 지뢰찾기/키오스크 둘 중 하나에 대한 test코드를 작성해보는 미션이였다. 미션을 하면서 내가 작성한 테스트 코드가 이게 진짜 잘 되는지 아직 감이 살짝 안 오긴 한다. 이건 경험의 문제 같고 아직 느끼지 못하는 것 같지만, 꾸준히 작성해보려 한다.그리고 미션을 하면서 다른 분들의 코드를 보는데 jacoco라는 테스트 커버리지 도구가 있어서 이것도 사용해 보았다.jacoco를 사용하니깐 테스트가 어디가 진행 됐고, 어딘 안됐고 이걸 시각적으로 볼 수 있는데, 이걸 보니깐 또 다른 게임을 하는 것 같아서 매우 재밌었다. 그리고 이번 미션이 스프링이 아니라 순수 자바로 된 코드를 테스트 하는 것이기 때문에 단위 테스트를 모두 작성해서 커버리지를 90퍼센트 이상 찍게 되었다.회고이번주는 드디어 내가 이 워밍업 클럽을 신청한 이유인 테스트 코드에 대해 배울 수 있게 되어서 좋았다.현재 내 실무에서는 테스트를 잘 작성하지 않는 환경이라 테스트에 대한 갈망도 있었고, 호기심도 있었다.  이번주는 테스트 코드가 이런거구나~ 정도를 학습하고 이해했다. 다음주는 이제 실질적으로 자주 사용하는 스프링 환경에서 테스트 코드를 작성하는 방법 같은걸 배우니 더 집중해서 학습해야 할 듯 하다.           

백엔드워밍업클럽테스트코드클린코드백엔드

양치잘하기

코틀린 백엔드 프로젝트 2기 - 3주차

섹션 4 6강 ~ 섹션 5 9강까지의 내용 학습 타임리프 문법 정리xmlns:th="" 타임리프의 네임스페이스 선언, 타임리프 문법 사용을 위한 선언 문법 th:fragment="" 템플릿 일부 재사용을 위한 문법th:replace="" 해당 요소를 다른 요소로 대체할 때 사용, fragment로 대체할 영역에 사용th:href="" 링크의 URL을 동적으로 설정th:each="" 반복문, 반복할 데이터의 개수만큼 HTML 요소를 생성 th:class="" HTML 요소의 클래스를 동적으로 설정합니다th:text=""텍스트 컨텐츠를 동적으로 설정 컨트롤러 개발@RestController @controller와 @ResponseBody가 합쳐진 어노테이션, 리턴을 HTTP 바디에 문자열로 넣을 수 있으며 JSON형식으로도 지정이 가능@RequestMapping("/경로")클래스 단위에 달아주고 경로를 설정해주면 컨트롤러 클래스의 ENTRY 포인트 지정@GetMapping("/test")메서드 단위에 달아주면 컨트롤러에 진입한 메서드의 ENTRY 포인트 지정 http 메서드 get을 받음, post, put, patch, delete도 존재 @RestController @RequestMapping("/api") class PresentationApiController( private val presentationService: PresentationService ) { @GetMapping("/test") fun test(): String { return "OK" } }/api의 경로 에서 /test로 진입하면 fun test() 메소드가 실행됨현재 코드에선 "ok"가 리턴됨 즉, HTTP 바디에 OK하는 문자열이 담김 @Controller 해당 어노테이션이 붙은 클래스는 리턴값의 이름과 같은 html파일에 연동됨 해당 html파일에는 model을 이용해서 값을 넘겨줄 수 있으며 해당 html파일이 view가 되어 model에 담긴 값을 꺼내어 사용하고 타임리프 뷰 템플릿을 사용하여 동적으로 만들어 주는 것이 가능함@Controller class PresentationViewController( private val presentationService: PresentationService ) { @GetMapping("/resume") fun resume(model: Model): String { val resume = presentationService.getResume() model.addAttribute("resume", resume) model.addAttribute("skillTypes", SkillType.values()) return "presentation/resume" } }get 메서드로 /resume로 요청을 하면 fun resume() 메소드가 실행됨모델에 resume, SkillType.values() 값을 담고 리턴을 하면 리턴에 해당하는 html파일에서 모델에 담긴값을 이용해서 뷰를 꾸며줌 컨트롤러 테스트 코드@SpringBootTest Spring Boot 애플리케이션을 테스트하는 데 사용 실제 애플리케이션과 유사한 환경을 구성하여 테스트를 실행할 수 있습니다@AutoConfigureMockMVCSpring MVC를 모의 테스트 할 때 사용, MockMVC객체가 자동으로 구성되어 컨트롤러를 모의로 테스트 하는것이 가능함@SpringBootTest @AutoConfigureMockMvc @DisplayName("[API 컨트롤러 테스트]") class PresentationApiControllerTest( @Autowired private val mockMvc: MockMvc ) { @Test @DisplayName("Introductions 조회") fun testGetIntroductions() { // given val uri = "/api/v1/introductions" // when val mvcResult = performGet(uri) val contentAsString = mvcResult.response.getContentAsString(StandardCharsets.UTF_8) val jsonArray = JSONArray(contentAsString) // then assertThat(jsonArray.length()).isPositive() } private fun performGet(uri: String): MvcResult { return mockMvc .perform(MockMvcRequestBuilders.get(uri)) .andDo(MockMvcResultHandlers.print()) .andReturn() } }@Autowired private val mockMvc: MockMvcmockmvc를 주입받아서 모의 객체 생성을 함"/api/v1/introductions"의 uri로 요청을 하면 해당 경로의 메서드가 실행되어 응답을 받고 그 응답을검증함.  인터셉터 개발인터셉터의 호출 순서는HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 -> 컨트롤러이며 컨틀롤러 도달전의 호출된다HandlerInterceptor 를 구현하였고 프로젝트에선 afterCompletion만 오버라이딩 하여 모든 요청에 대한 정보를 데이터 베이스에 저장하도록 구현하였다 인터셉터는 경로를 설정하여 어떤 경로게 대하여 인터셉터를 실행할지 결정이 가능하다WebMvcConfigurer 를 구현한 클래스의 addInterceptors() 메소드를 통해 인터셉터를 등록하고 경로 설정이 가능하다override fun addInterceptors(registry: InterceptorRegistry) { registry.addInterceptor(presentationInterceptor) .addPathPatterns("/**") .excludePathPatterns("/assets/**", "/css/**", "/js/**", "/admin/**", "/h2**", "/favicon.ico", "/error") }  어드민 패키지AdminApiControllerAdvice@RestControllerAdvice 를 사용하면 전역적으로 모든 컨트롤러에 대한 예외를 처리하는 것이 가능해진다.@ExceptionHandler와 같이 사용해야 하며 특정 예외 클래스에 대한 핸들러 메서드를 작성할 수 있습니다.오류의 종류개발자가 직접 처리가 가능한 오류는 Exception의 하위 오류들이다. 애플리케이션에서 대응할 수 있는 오류로서 UnckechedException, ckechedException이 존재하고 UnckechedException은 실행중에 발생하는 오류이다.  

자료구조

*이 내용은 인프런 그림으로 쉽게 배우는 자료구조와 알고리즘 (기본편)을 수강하며 정리한 내용입니다. 덱데이터의 삽입과 제거를 head와 tail 두군데서 자유롭게 할 수 있어.덱의 추상자료형printAll - 모든 데이터 출력addFirst - head에 데이터 삽입removeFirst - head에서 데이터 제거addLast - tail에 데이터 삽입removeLast - tail에서 데이터 제거isEmpty - 리스트 비었는지 체크구현DoublyLinkedList.mjs를 import 해줘.class Deque{ constructor(){ this.list = new DoublyLinkedList(); } printAll(){ this.list.printAll(); } addFirst(data){ this.list.insertAt(0, data); } removeFirst(){ return this.list.deleteAt(0); } addLast(data){ this.list.insertAt(this.list.count, data); } removeLast(){ return this.list.deleteLast(); } isEmpty(){ return (this.list.count == 0); } }해시테이블해시(Hash), 맵(Map), 해시맵(HashMap), 딕셔너리(Dictionary)라고도 불려.해시 테이블은 이름에서도 알 수 있듯이 해시와 테이블이 합쳐진 자료구조야.해시 함수Key만 알면 Value에 O(1)의 성능으로 읽기가 가능하다!하지만 동일한 Key에 많은 Value를 집어넣는다면 많은 연결리스트를 뒤져야해.그러므로 데이터를 골고루 분배하는 것이 중요해!!장점 : 빠른 데이터 읽기, 삽입, 삭제단점 : 메모리를 많이 차지함, 좋은 해시 함수의 구현이 필수적!추상자료형set - 데이터 삽입get - 데이터 읽기remove - 데이터 제거 구현구현하기 전 hash 함수를 어떻게 만들거냐면~위와같은 형식으로 10으로 나눈 나머지의 인덱스에 값을 삽입할거야!HashDataclass HashData{ constructor(key, value){ this.key = key; this.value = value; } }HashTableclass HashTable{ constructor(){ this.arr = []; for(let i = 0; i < 10; i++){ // 0~9까지 연결리스트 초기화 this.arr[i] = new DoublyLinkedList(); } } hashFunction(number){ return number % 10; } set(key, value){ this.arr[this.hashFunction(key)].insertAt(0, new HashData(key, value)); } get(key){ let currentNode = this.arr[this.hashFunction(key)].head; while(currentNode != null){ if(currentNode.data.key == key){ return currentNode.data.value; } currentNode = currentNode.next; } return null; } remove(key){ let list = this.arr[this.hashFunction(key)]; let currentNode = list.head; let deletedIndex = 0; while(currentNode != null){ if(currentNode.data.key == key){ return list.deleteAt(deletedIndex); } currentNode = currentNode.next; deletedIndex++; } return null; } }Set데이터의 중복을 허용하지 않는 자료구조야. 셋은 해시 테이블을 이용해.해시 테이블의 value 값은 사용하지 않고 key만 사용해서 구현해!!추상자료형add(data) - 데이터 삽입isContain(data) - 데이터 체크remove(data) - 데이터 제거clear() - 셋 비우기isEmpty() - 셋이 비었는지 체크printAll() - 모든 데이터 출력구현class HashSet{ constructor(){ this.hashTable = new HashTable(); } add(data){ if(this.hashTable.get(data) == null){ this.hashTable.set(data, -1); // value는 쓰이지 않기때문에 그냥 -1값 넣어줌 } } isContain(data){ return this.hashTable.get(data) != null; } remove(data){ this.hashTable.remove(data); } clear(){ for(let i = 0; i < this.hashTable.arr.length; i++){ this.hashTable.arr[i].clear(); } } isEmpty(){ let empty = true; for(let i = 0; i < this.hashTable.arr.length; i++){ if(this.hashTable.arr[i].count > 0){ empty = false; break; } } return empty; } printAll(){ for(let i = 0; i < this.hashTable.arr.length; i++){ let currentNode = this.hashTable.arr[i].head; while(currentNode != null){ console.log(currentNode.data.key); currentNode = currentNode.next; } } } } 참조 : 그림으로 쉽게 배우는 자료구조와 알고리즘 (기본편) 3주차 회고칭찬하고 싶은 점 : 기한을 지켰다 😅아쉬웠던 점 : 권장 커리큘럼을 지키지 못했다. 

알고리즘 · 자료구조워밍업클럽CS

워밍업 클럽 2기 백엔드 클린코드&테스트 3주차 발자국

 주간 요약테스트의 중요성: 자동화된 테스트의 필요성, 테스트 주도 개발(TDD)의 개념단위 테스트 작성: JUnit5 활용, 테스트 케이스 세분화, 테스트하기 어려운 영역 분리테스트 스타일: BDD 스타일 테스트 작성, DisplayName 활용Spring & JPA 기반 테스트: 레이어드 아키텍처에서의 테스트, Persistence Layer와 Business Layer 테스트학습 회고칭찬할 점테스트 작성의 중요성을 이해하고 실제로 적용해보았습니다.JUnit5를 활용한 테스트 작성 능력이 향상되었습니다.아쉬운 점TDD 방식을 완전히 적용하는 데 어려움을 겪었습니다.Spring & JPA 기반 테스트에서 개념 이해가 부족했습니다.보완하고 싶은 점TDD 방식을 더 연습하여 자연스럽게 적용할 수 있도록 하겠습니다.Spring과 JPA에 대한 기본 지식을 보충하여 테스트 작성에 활용할 계획입니다.다음 주 학습 목표실제 프로젝트에 TDD 방식을 적용해보기Spring & JPA 기반의 복잡한 비즈니스 로직에 대한 테스트 작성 연습하기 주간 미션접근기존 프로젝트에 단위 테스트를 추가하고, 일부 기능을 TDD 방식으로 개발해보았습니다.BDD 스타일의 테스트 작성을 시도하여 가독성 있는 테스트 코드를 만들었습니다.과정JUnit5를 활용한 기본 단위 테스트 작성주요 비즈니스 로직에 대한 테스트 케이스를 작성했습니다.TDD 방식으로 새로운 기능 추가실패하는 테스트를 먼저 작성하고, 이를 통과하는 코드를 구현했습니다.BDD 스타일 테스트 적용given-when-then 구조를 사용하여 테스트의 가독성을 높였습니다.결과프로젝트의 전반적인 테스트 커버리지가 향상되었습니다.TDD 방식을 통해 더 견고하고 유지보수가 쉬운 코드를 작성할 수 있었습니다.BDD 스타일의 테스트로 인해 테스트 코드의 의도를 더 명확히 표현할 수 있게 되었습니다.

wisehero

[인프런 워밍업 스터디 클럽 2기] 클린코드, 테스트코드 백엔드 3주차 발자국

토요일에 백엔드 3주차 진도를 모두 진행했습니다.클린코드에 이어 테스트 코드 역시 애플리케이션 개발 과정에서 매우 중요한 과정 중 하나로 저도 생각하고 있습니다.사실 이미 이전에 전부 수강을 다 했던 강의라서 다시 이 강의에서 배운 것들 중에 적용하지 못한 것은 없는지를 중점적으로보았습니다. 이번 주차에는 레이어드 아키텍처의 큰 축인 Presentation, Service, Repository 계층 테스트 코드를 작성했습니다.강의를 다시 보면서 우빈님께서 테스트 코드의 @DisplayName을 짓는 법이나 BDD에 기반해서 테스트 과정을 잘 나누고 구분하시는 것 같다는 느낌을 다시 받았습니다. 회사에 다시 돌아갔을 때 다시 한번 고칠 부분을 찾아볼 수 있는 계기가 될 것 같습니다.  강의를 수강하면서 저를 고민에 빠지게한 것은 우빈님께서는 중간에 비즈니스 로직과 테스트 코드간에 계속해서 스위칭을 하시면서 레드-그린-리팩토링 과정을 잘 거치고 계신데, 제가 아직 TDD에 익숙하지 못한 것이 이러한 전환을 하면서 생기는 복잡함을 이겨내지 못하고 있는 것 같은데 연습이 조금 더 필요한 것 같습니다. 

백엔드워밍업클럽클린코드테스트코드

채널톡 아이콘