블로그

ppusda

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

⭐ 1주 동안 배운 내용을 정리하고 회고하는 시간을 가져보자. 16~18 일차 - Admin ViewView3주차에 이어서 Admin View를 만들어보게 되었다.이번에도 마찬가지로 중복되는 부분을 fragment와 layout으로 분리하는 작업을 진행했다.그리고 사용자가 직접 업데이트 하는 부분이 있기에, 추가적으로 script-util 파일을 통해 API에 요청을 보내도록 했다. 19 일차 - GCP, Docker암호화배포 이전에 설정 값을 암호화 하기 위해 jasypt를 사용하게 되었다.Jasypt?애플리케이션을 배포할 때 공개되면 안되는 값들이 평문으로 올라가는 것을 막기 위해 암호화할 수 있는 라이브러리이다.아래는 암호화한 DB 비밀번호가 들어있는 설정파일의 일부분이다. datasource: url: jdbc:mysql://mysql:3306/portfolio username: root password: ENC(ZeronFrlX1yD4JW496HshMgc9t1kUrQi) driver-class-name: com.mysql.cj.jdbc.Driver ENC(암호화 내용)으로 내용이 암호화 되었음을 표시해야한다. 배포Docker를 이용해서 빌드 한 이미지를 Docker hub에 올리고 이를 서버에서 내려받아 사용했다.이후 GCP를 이용하여 서버를 생성하고, Docker를 이용해 MySQL과 프로젝트를 빌드 시켰다.마지막으로 도메인을 연결하고, 이를 제출하며 마지막 7번째 미션도 해결 할 수 있었다.결과물은 아래와 같다.Dongguk's Portfolio 20일차 - 서브 미션, 코드 리뷰3주차 때와 일정이 거의 겹쳐 3주차 발자국에 포함시키지 못했던 미션 5는 4주차에서 소개하겠다.각 API마다 3개의 테스트 코드를 작성해야 했기에 열심히 작성해서 테스트를 진행해보았다. 이번에도 관련 내용은 README에 정리했다.https://github.com/ppusda/MML 이후 마지막에는 최종 점검과 코드 리뷰 시간이 진행되었다.https://github.com/ppusda/MML/pull/1많이 배워갈 수 있었던 좋은 시간이 되었던 것 같아서 조언 받은 내용을 정리해보고자 한다. Rest API와 VersioningRest APIAPI를 작성할 때 Restful 하도록 고려를 하는 편이라고 생각했지만, 주의하지 못했던 부분이 있었다.자원을 복수형으로 명시/user ⇒ /usersVersioning사실 지금까지 코드를 작성해보면서 “API에 버저닝이 굳이 필요할까?” 라고 생각해서 배제 했었다.하지만 이번 코드리뷰를 받아보면서 버저닝의 중요성을 알게되었다.API의 기능이나 데이터 구조가 변경될 때, 기존 클라이언트가 정상적으로 작동하도록 하기 위해 버전 관리를 통해 이전 버전을 유지하도록 사용할 수 있다.⇒ 사용자가 원하는 버전을 사용하도록 할 수 있고, 업데이트 시기를 사용자가 정하도록 할 수 있다.이로 인해 호환성과 안정성을 챙기고 사용자 경험을 개선시킬 수 있다는 것을 알게되었다. find 와 get의 차이이 부분에 대해서는 진지하게 고민해 본 적은 없었던 것 같다.간단하게 find는 “DB에서 찾기”, get은 “찾아온 데이터를 가져오기”라고만 생각하고 코드를 작성했었다. 하지만 코치님께서 소개해주신 내용을 통해 좀 더 시선을 달리하게 되었다.How and why to decide between naming methods with "get" and "find" prefixes get~은 실패하지 않으며 짧은 시간으로 요소를 가져올 때 사용되는 단어.find~는 실패할 수 있으며 긴 시간이 소요되어 요소를 찾아낼 때 사용되는 단어. 위 내용을 참고해서 앞으로 메서드 네이밍을 사용할 때 주의해야 할 것 같다. Test code 방향성요즘에 가장 관심이 많이가고 그만큼 잘 모르겠는 내용이 테스트 코드이다.이번에 테스트 코드를 강의를 기반으로 혼자 프로젝트에 작성해다보니까 방향성에 대해 의문이 많이 들었다. “이런 테스트 코드를 어떻게 짜면 좋은건지 모르겠다” 라고 질문 드렸는데, 그 부분에 대해서 커버리지를 최대한으로 채워보면서 감을 익히면 좋을 것 같다고 말씀해주셨다. 추가로 관련해서 좋은 레퍼런스를 추천해주셨다.토스ㅣSLASH 21 - 테스트 커버리지 100% 내용을 들어보고 서브 미션 프로젝트를 고도화 할 때 좀 더 좋은 테스트 코드를 작성하도록 노력해볼까 한다. 총 회고4주차로 스터디가 마무리 되었다.이번 4주차에는 일정이 너무 많고 도저히 시간이 안나기도 했지만, 강의를 보면서 따라 친 부분들이 잘못 입력되어서 동작하지 않는 곳들을 찾아내는데 고생을 좀 하게 되었다.이상하게 로컬 환경에서는 잘되었는데, 배포만 하면 고장이 나서 원인을 찾기가 힘들었지만, 너무 간단한 오타들이어서 허무했다. 강의도 끝나고 더 이상 미션도 없어서 강제성은 사라졌지만 계속해서 나름대로 고도화를 진행해보려고 한다.최종 점검에서 아직 나의 부족한 모습들을 많이 보게 되었지만, 여러모로 자극도 많이 받아서 힘들어도 계속해서 학습을 이어나가려고 한다. 코치님도 너무 친절하셨고 꾸준하기가 쉽지 않아서 많이 몰아들었지만, 어찌저찌 마무리를 하게 되었다.이상의 내용은 개인 블로그에 완전 총 회고로 다시 한 번 작성하겠다. 모두 화이팅! (o゚v゚)ノ

백엔드워밍업클럽백엔드2기Kotlin

또니

[인프런 워밍업 클럽 2기 CS] 특별 미션

회사에서 야근 이슈로 참여하지 못했던 중간 점검을 만회할 수 있는 기회를 주시다니 감사합니다🥰 특별 미션)  실수로 워밍업 클럽 출석을 빼먹었는데 우연히 데이터를 수정할 수 있는 권한이 주어졌습니다. 러너분의 이름(name)과 출석수(count)가 저장된 배열에서 여러분(나)의 데이터를 퀵정렬을 이용해 오름차순 정렬하고 가장 첫 번째 데이터인 여러분의 출석수를 변경하도록 코드를 작성해주세요. (퀵정렬 구현 부분도 변경)function quickSort (arr, left, right) { if (left < right) { let index = divide(arr, left, right); quickSort(arr, left, index - 1); quickSort(arr, index + 1, right); } } function divide(arr, left, right) { let rightCnt= arr[right].count; let leftIndex = left - 1; for (let i = left; i < right; i++) { if (arr[i].count <= rightCnt) { leftIndex++; [arr[leftIndex], arr[i]] = [arr[i], arr[leftIndex]]; } } [arr[leftIndex + 1], arr[right]] = [arr[right], arr[leftIndex + 1]]; return leftIndex + 1; } let user1 = { name: "홍길동", count: 5 }; let user2 = { name: "임꺽정", count: 4 }; let user3 = { name: "이순신", count: 3 }; let user4 = { name: "나", count: 1 }; let user5 = { name: "짱구", count: 5 }; let arr = [user1, user2, user3, user4, user5] console.log("===== 정렬 전 ====="); console.log(arr); quickSort(arr, 0, arr.length - 1); arr[0].count = 5 console.log("===== 정렬 후 ====="); console.log(arr); [예상 결과] ===== 정렬 전 ===== [ { name: '홍길동', count: 5 }, { name: '임꺽정', count: 4 }, { name: '이순신', count: 3 }, { name: '나', count: 1 }, { name: '짱구', count: 5 } ] ===== 정렬 후 ===== [ { name: '나', count: 5 }, { name: '이순신', count: 3 }, { name: '임꺽정', count: 4 }, { name: '홍길동', count: 5 }, { name: '짱구', count: 5 } ] 

알고리즘 · 자료구조CS지식인프런워밍업클럽2기

박민지

(인프런 워밍업 클럽-스터디 2기) 프로덕트 디자인 마지막 발자국

드디어 마지막 주차!! 강의를 들은 뒤 발자국을 제출하려고 토요일까지 기다렸다. 마지막 주차는 그동안 만든 배리어블과 컴포넌트를 이용해서 진짜 화면을 만드는 주차였다.포트폴리오 작업을 할때는 대부분 배리어블이나 디자인 시스템 구성을 하지 않아 하나씩 조합해서 시간이 더 오래걸렸는데 확실히 미리 써야할 컴포넌트를 전부 구성해 만드니 훨씬 작업속도가 빨라졌다.그리고 구성하면서 예시와 문구가 달라지는 부분이 있었는데 화면에 비해 폰트가 커서 몇몇 용어는 짧게 줄여서 사용해야 했다.아직 모바일 화면에 들어가는 폰트 크기에 대한 감을 더 익혀야 겠다는 생각이 들었다. 아니면 모바일 용 배리어블을 만들던가..특히 데이터를 넣을 때 이전에는 하나씩 전부 복붙하거나 직접 썼는데 플러그인을 이용해서 구글시트에 정리해 둔 데이터를 그대로 불러오는 방식을 적용하니 훨씬 쉬웠다. 그리고 플러그인은 해봤자 더미 데이터 만드는 정도로만 있겠지 싶었는데 드라마나 영화 데이터를 그대로 불러올 수 있는 플러그인이 있다는 걸 알고 무작정 복붙하기 전에 플러그인을 찾아보아야 겠다는 생각도 들었다.그리고 오늘!! 기다렸던 프로토타입 강의는 이전에 개발자를 잠깐 꿈꿔보며 이전에 들었던 파이썬 강의가 떠올랐다 그 때 해봤자 난수 만들기, 숫자 증감 정도만 배웠었고 도저히 적성에 맞지 않아 아 개발은 나의 길이 아니구나 하고 끝났었는데 피그마 프로토타입을 하면서 적용하게 될 수 있을 줄은 몰랐다. 프로토타이핑 자체에는 익숙하지 않아서 과제는 제 시간에 끝내지 못했지만...프로토타입은 간단하게 스크롤정도만 활용했었는데 다른 분들이 좋은 화면들을 질문해 준 덕에 생각하지 못했던 프로토타입을 직접 만들어볼 수 있었고 어떤 매커니즘으로 만들어지고 활용할 수 있는지 알게 된 유익한 시간이었다. 그리고 확실히 직관적으로 보여주면 같이 협엽하는 개발자들이 훨씬 디자인을 잘 이해할 수 있으리란 생각이 들었다. 그러면 내가 원하는 디자인도 번거로움 없이 더 빨리 얻을 수 있겠지! 한달여간 어려운 부분도 있었지만 새로운 개념과 기능을 익히며 너무 즐거웠다. 과제 따라가는게 힘들긴 했지만..개인적인 점수를 주자면 100점중 87점 정도는 되지 않을까? 게으름 때문에 미룬 순간들이 있었다는 걸 내 자신이 제일 알기 때문에 90점을 넘게 줄 수는 없었다. ㅎ...강의 내용도 정말 좋았고 유익했다. 같이 달린 워밍업 클러버 여러분, 그리고 볼드UX 강사님 모두 수고하셨고 남은 한해 건강하게 잘 보내셨음 좋겠습니다.뜻하는 바 이루시길!! 

UX/UI워밍업클럽피그마디자인시스템프로토타입

elly

[인프런 워밍업클럽 CS 2기] 특별 미션

특별 미션)  실수로 워밍업 클럽 출석을 빼먹었는데 우연히 데이터를 수정할 수 있는 권한이 주어졌습니다. 러너분의 이름(name)과 출석수(count)가 저장된 배열에서 여러분(나)의 데이터를 퀵정렬을 이용해 오름차순 정렬하고 가장 첫 번째 데이터인 여러분의 출석수를 변경하도록 코드를 작성해주세요. (퀵정렬 구현 부분도 변경) // 퀵 정렬 구현 function quickSort(arr, left, right) { if (left < right) { let pivot = divide(arr, left, right); quickSort(arr, left, pivot - 1); quickSort(arr, pivot + 1, right); } } function divide(arr, left, right) { let pivot = arr[left].count; let leftStartIndex = left + 1; let rightStartIndex = right; while (leftStartIndex <= rightStartIndex) { while (leftStartIndex <= right && arr[leftStartIndex].count <= pivot) { leftStartIndex++; } while (rightStartIndex > left && arr[rightStartIndex].count > pivot) { rightStartIndex--; } if (leftStartIndex < rightStartIndex) { swap(arr, leftStartIndex, rightStartIndex); } } swap(arr, left, rightStartIndex); return rightStartIndex; } function swap(arr, index1, index2) { let temp = arr[index1]; arr[index1] = arr[index2]; arr[index2] = temp; } // 미션 데이터 let user1 = { name: "홍길동", count: 5 }; let user2 = { name: "임꺽정", count: 4 } let user3 = { name: "이순신", count: 3 } let user4 = { name: "나", count: 1 } let user5 = { name: "짱구", count: 5 } let arr = [user1, user2, user3, user4, user5] // 미션 구현 및 데이터 출력 (퀵정렬 후 나의 출석 수 변경) console.log("===== 정렬 전 ====="); console.log(arr); quickSort(arr, 0, arr.length - 1); arr[0].count = 5 console.log("===== 정렬 후 ====="); console.log(arr);// 출력 결과

알고리즘 · 자료구조알고리즘자료구조운영체제

표수진

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

드디어 오늘 저녁에 있을 온라인 특강을 제외하고 어찌보면 길고 어찌보면 짧은 워밍업 클럽 프로그램이 마무리되었다! 확실히 온라인 강의만 결제해서 혼자 공부할 때보다는 스터디 프로그램이 함께 진행되다보니 열심히 듣고자 하는 의지도 더 활활 타올랐던 것 같고, 매일 기한에 맞춰서 미션을 진행해야 되기 때문에 미루지 않고(사실 못하고..) 들었던 것 같다 ㅎㅎ퇴사를 하고나서 세웠던 계획 중에 하나인 피그마 공부와 디자인 시스템 공부를 한번에 해결할 수 있어서 뿌듯하면서도 알찬 시간이였고, 이제부터는 지금까지 배운 내용을 계속해서 반복하고 작업해보면서 내 것으로 만드는 시간을 가져봐야 할 것 같다. 이렇게 좋은 강의를 만들어주신 볼드님께도 다시 한번 감사하다는 말씀을 드리고 싶다! [4주차 강의 요약]4주차에도 지난주에 이어서 지금까지 열심히 만들어놨던 파운데이션과 컴포넌트를 이리저리 조합해서 새로운 페이지로 만들어보는 시간을 가졌다. 강의 초반에 볼드님께서 이 부분을 수강생분들이 제일 좋아하셨다는 말을 하셨었는데 실제로 나도 이 부분 강의가 제일 재미있고 흥미로웠다. 잘 다져놓은 기반으로 튼튼한 건물을 짓는 기분이랄까.. B2C E-Learning 페이지 제작모바일 OTT 서비스 페이지 제작 확실히 배리어블 모드를 잘 만들어놓으니까 디바이스별 반응형 디자인, 다크모드 전환을 이렇게 쉽게 할 수 있는 것에 다시 한번 박수를 보낸다..👍 그리고 실제 데이터를 'Google Sheet Sync' 플러그인으로 바로 적용할 수 있는 것도 앞으로 디자인할 때 편하게 사용할 수 있는 기능인 것 같다.   [이번주 회고]스스로 칭찬하고 싶은 점프로그램이 끝날 때까지 강의랑 미션을 기한에 맞춰서 다 완수했다!기존에 XD로 작업했던 작업물을 다시 피그마로 제작해보면서 배웠던 내용을 적용하고 있다퇴사를 하고 '나는 어떤 디자이너가 되고 싶은가'라는 의문과 함께 내가 부족한 부분 중 어떤 점을 먼저 채워야 할지 고민만 하다가 시간이 흘렀는데 프로그램을 열심히 참여하면서 다시 한번 디자인에 대한 열정을 가질 수 있었고 더 많이 공부하고 싶다는 생각이 들었다. 아쉬웠던 점, 보완하고 싶은 점조금 더 피그마, 디자인 시스템에 익숙해져서 작업 시간을 줄이고 싶고 앞으로 실무에서 활용할 수 있는 효과적인 디자인 방법을 고안해보고 싶다.내 디자인을 보다 효과적으로 전달하기 위해 프로토타이핑 관련 공부도 더 해보고싶다.

UX/UIUX/UI프로덕트디자인디자인시스템피그마figma토큰디자인볼드UX

winnercold

워밍업 클럽 스터디 - 2기 2주차 발자국

해당 글은 [인프런 워밍업 클럽 2기 클린 코드 & 테스트 코드]에 참가하여 박우빈님의 <Readable Code: 읽기 좋은 코드를 작성하는 사고법> 강의를 듣고 작성한 글입니다. 강의를 통해 배운것객체 지향 적용하기코드 다듬기 1. 객체 지향 적용결합도가 높은 상속보다는 조합과 인터페이스를 활용하자상속을 통한 코드의 중복 제거가 주는 이점 보다, 중복이 생기더라도 유연한 구조로 설계해보기Enum의 특성을 활용하자Enum은 상태와 행위를 한 곳에서 관리할 수 있는 추상화된 객체로 특정 도메인 개념에 대해 종류와 기능을 명시적으로 표현해 줄 수 있다.다형성 활용변하는 것과 변하지 않는 것을 분리하여 추상화 하자숨겨져 있는 도메인 개념을 도출하자도메인 지식은 만드는 것이 아니라 발견하는 것이다.2. 코드 다듬기주석을 작성해보자무분별한 주석은 독이 된다. 코드를 통해 최대한 의도를 드러내고, 그렇게 해도 드러내지 못한 정보들을 주석에 작성해보자.변수와 메서드의 나열 순서 만으로도 의도와 정보를 전달할 수 있다.패키지를 나누자패키지는 문맥으로써의 정보를 제공할 수 있다ide의 도움을 받아 보자 ex) sonarlint회고객체 지향 섹션을 들으면서 강의는 이해가 되었지만 이것을 내것으로 체화 시키는 것이 정말 어려웠다. 아직도 이것을 일급 컬렉션으로 빼서 관리하는 것이 좋을지, 또는 인터페이스로 분리할지, 또 다형성을 어떻게 활용하면 좋을지 이해를 제대로 하지 못한 것 같다. 반복적으로 들으면서 내것으로 만들어야겠다고 생각했다.

백엔드

winnercold

워밍업 클럽 스터디 - 2기 1주차 발자국

해당 글은 [인프런 워밍업 클럽 2기 클린 코드 & 테스트 코드]에 참가하여 박우빈님의 <Readable Code: 읽기 좋은 코드를 작성하는 사고법> 강의를 듣고 작성한 글입니다. 강의를 통해 배운것추상과 구체논리 사고의 흐름SOLID 1. 추상과 구체리팩토링의 첫 단계는 추상화를 잘해야 한다고 배웠다. 그렇다면 추상화를 잘해야 하려면 어떻게 해야할까?추상화의 첫 단계는 이름을 잘 짓는 것으로 부터 기인한다.이름을 짓는다는 것은 추상적 사고를 기반으로 한다.추상적 사고란 : 표현하고자 하는 구체에서 정말 중요한 핵심 개념만을 추출하여 잘 드러내게 표현하는 것변수의 이름을 잘 짓는 것 뿐 아니라 메서드 그리고 객체에도 잘 지어 그 의미를 전달해야 한다.추상화 레벨을 동등하게 만들어 코드를 읽는 사람으로 하여금 의문점이 없게 만들어야 한다.2. 논리 사고의 흐름early return 으로 (if-else 지양) 코드의 가독성을 높일 수 있다.중첩 분기문, 반복문을 줄임으로써 사고의 깊이를 줄여야 한다.사용할 변수는 가깝게 선언함으로써 코드의 가독성을 높인다.복잡한 로직은 의미 단위로 나누어 공백라인을 줌으로 가독성을 높인다.부정어구 사용을 지양함으로 코드의 가독성을 높인다.3. SOLID리팩토링 할 때는 SOLID원칙에 근거하여 작성하도록 한다.한 객체에 너무 많은 책임이 있진 않는지, 요구사항이 늘어나서 코드를 고쳐야 할 때 너무 많은 변경비용이 들진 않는지 생각하며 코드를 작성해야 한다.회고리팩토링의 첫 발걸음은 추상이라는 것을 이번 강의를 통해 깨닫게 되었다. 항상 리팩토링이 필요한 코드를 보면 어디서부터 고쳐야할지 막막했는데, 우빈님 강의를 통해 우선 이름을 잘 지어보고, 메서드로 분리하며, 추상화 레벨을 맞추는 것부터 해야겠다고 생각이 들었다.

백엔드

winnercold

워밍업 클럽 스터디 - 2기 3주차 발자국

해당 글은 [인프런 워밍업 클럽 2기 클린 코드 & 테스트 코드]에 참가하여 박우빈님의 <Practical Testing: 실용적인 테스트 가이드> 강의를 듣고 작성한 글입니다. 강의를 통해 배운것테스트 왜 작성해야 할까?TDD테스트는 문서다 1. 테스트 왜 작성해야 할까? 테스트는 정말 귀찮지만 해야한다.내가 작성한 코드가 의도대로 잘 작동 하는지 확인 할 수 있다.테스트 코드를 작성하지 않으면 소프트웨어의 안정성을 보장할 수 없다. 올바른 테스트 코드를 작성한다면 빠르게 버그를 발견 할 수 있고, 수동 테스트 비용을 절약할 수 있다. 2. TDD (테스트 주도 개발)TDD는 테스트를 먼저 작성 하고 그 테스트가 Red-Green-Refactor 주기로 통과 하는 것이다.먼저 실패하는 테스트를 작성한다테스트를 통과하기 위한 최소한의 코드를 작성한다코드를 개선하면서 테스트가 통과 되도록 유지한다. 이렇게 테스트를 작성함으로써 엣지 케이스를 놓치지 않고, 유지보수가 쉬운 코드로 작성할 수 있게 한다.3. 테스트는 문서다다양한 테스트 케이스를 통해 프로덕션 코드를 이해하는 시각과 관점을 보완할 수 있게 한다.한 사람이 고민했던 결과물이 팀 차원으로 승격시켜 모두의 자산으로 공유할 수 있다.  회고테스트코드 작성은 정말 필수적이라고 할 수 있을만큼 중요한데, 어디서 부터 어떻게 시작해야 될지 몰랐던 것 같아 쉽게 도전해보지 못했는데 이번 강의를 통해 한 클래스에서 하나의 테스트라도 작성을 해야겠다고 생각이 들었다.

백엔드백엔드

nnahye

네번째 발자국 👣

Presentation Layer 테스트외부세계의 요청을 가장 먼저 받는 계층파라미터에 대한 최소한의 검증을 수행한다.@Mock, @Spy, @InjectMocks@Mock : Mock(가짜) 객체로 만든다@InjectMocks : Mock 객체를 주입해준다@Spy : 기능들중 일부만 Mock으로 만든다.더 나은 테스트를 작성하기 위한 구체적 조언한문단에 한 주제완벽하게 제어하기 : 현재시간 랜덤 값 등 외부시스템과 연동하는 경우 상위계층으로테스트 환경의 독립성을 보장하자 : given 환경에서 다른 api 사용 지양, 생성자로만 구성하는 것이 좋다테스트간 독립성을 보장하자 : 공유자원 사용하지 않아야 한다.한눈에 들어오는 Test Fixture 구성하기Test Fixture 클렌징 : deleteAll() 와 deleteAllInBatch() 구분해서 사용@ParameterizedTest : 값이나 데이터를 바꿔가면서 테스트 하고싶을 때@DynamicTest : 시나리오 기반으로, 환경을 공유하면서 테스트 할수있다.테스트 수행도 비용이다. 환경통합하기학습테스트: 테스트를 하면서 학습하기Spring REST Docs: 테스트 코드를 통한 API 문서 자동화 도구 미션 ✔ 게시판 게시물에 달리는 댓글을 담당하는 Service Test ✔ 댓글을 달기 위해서는 게시물과 사용자가 필요하다. ✔ 게시물을 올리기 위해서는 사용자가 필요하다. 👇 처음 내가 작성했던 코드 @BeforeEach void setUp() { 1-1. 사용자 생성에 필요한 내용 준비 1-3. 게시물 생성에 필요한 내용 준비 1-5. 댓글 생성에 필요한 내용 준비 } @DisplayName("사용자가 댓글을 작성할 수 있다.") @Test void writeComment() { // given 1-2. 사용자 생성 1-4. 게시물 생성 // when 1-6. 댓글 생성 // then 검증 } @DisplayName("사용자가 댓글을 수정할 수 있다.") @Test void updateComment() { // given 2-2. 사용자 생성 2-4. 게시물 생성 2-6. 댓글 생성 // when 2-7. 댓글 수정 // then 검증 } @DisplayName("자신이 작성한 댓글이 아니면 수정할 수 없다.") @Test void cannotUpdateCommentWhenUserIsNotWriter() { //given 3-2. 사용자1 생성 3-6. 사용자2 생성 3-6. 사용자1 게시물 생성 3-8. 사용자1의 댓글 생성 //when 3-9. 사용자2가 사용자1의 댓글 수정 시도 // then 검증 }👇 수정 한 코드  @BeforeEach void setUp() { 1-1. 사용자 생성에 필요한 내용 준비 1-2. 사용자 생성 1-3. 게시물 생성에 필요한 내용 준비 1-4. 게시물 생성 } @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 검증 }  미션 회고 처음엔 setUp()에 생성에 필요한 내용들만 배치해야한다고 생각하고 저렇게 코드를 작성했는데,댓글 도메인에 대한 테스트라는 것에 중점을 둬야한다는 공통 피드백을 듣고 다시 수정했다. 앞으로 항상 도메인을 중심으로 생각하는 습관을 들여야겠다. 넷째주 회고 벌써 4주가 지났다니 시간이 너무 빠르다. 그동안 많은 것들을 배웠는데, 처음 리팩토링 하는것부터 테스트하는것까지 다시한번 쭉 훑어봐야겠다. 개인적으로 새로 알게된 것이 많은데, 그 중에서 코드를 보는 관점을 많이 배운것 같다. 배웠던 것들을 내것으로 완전히 만들기까지 많은 시간이 걸리겠지만, 꼭 복습을 해서 스스로 적용할 수 있도록 해야겠다. 두 강의를 들으면서 스스로 더 공부를 해보고싶다는 자극을 많이 받았다. 의미있는 시간이었다.

yoon

[워밍업 클럽 2기 BE 클린코드&테스트] 4주차 회고

 들어가며테스트 코드 작성에 대해 학습하면서, 특히 Mock 사용법과 더 나은 테스트 작성 방법에 대해 깊이 있게 배울 수 있었습니다. 이 회고에서는 주요 학습 내용과 깨달음을 정리해보고자 합니다.Mock에 대한 새로운 시각Test Double의 이해처음에는 Mock과 Stub을 같은 개념으로 혼동했었는데, 이번 학습을 통해 둘의 차이점을 명확히 이해하게 되었습니다. 특히 Test Double의 다양한 종류(Dummy, Stub, Spy, Mock, Fake)를 배우면서, 각각의 사용 목적과 상황이 다르다는 것을 알게 되었습니다.Mockito 사용의 실제@Mock, @Spy, @InjectMocks의 차이점을 배우면서 특히 인상 깊었던 점은:- @Spy를 통해 실제 객체의 특정 메소드만 모킹할 수 있다는 점- BDDMockito를 사용하면 테스트 코드가 더 자연스러워진다는 점이러한 도구들을 적재적소에 활용하면 테스트의 가독성과 유지보수성을 크게 향상시킬 수 있다는 것을 깨달았습니다.더 나은 테스트를 위한 깨달음테스트 픽스처 관리의 중요성이전에는 @BeforeEach에서 모든 테스트 데이터를 준비하는 것이 좋은 방법이라고 생각했습니다. 하지만 이는 테스트의 독립성과 가독성을 해칠 수 있다는 것을 배웠습니다. 특히:1. 테스트별로 필요한 데이터만 명시적으로 준비하는 것의 중요성2. SQL 파일로 데이터를 준비하는 방식의 단점3. 테스트 간 독립성 보장의 중요성새로운 테스트 기법 발견@ParameterizedTest와 @DynamicTest를 처음 알게 되었는데, 이들이 제공하는 기능이 매우 유용하다고 느꼈습니다:- @ParameterizedTest로 여러 케이스를 간단히 테스트- @DynamicTest로 시나리오 기반 테스트 구현실무적용 시 주의점테스트 환경 통합여러 개의 테스트 환경을 하나로 통합하여 성능을 개선할 수 있다는 점이 인상적이었습니다. 특히:- 불필요한 서버 구동 최소화- MockBean 처리의 효율적인 관리Private 메소드 테스트에 대한 새로운 관점private 메소드를 테스트하고 싶은 욕구가 생길 때, 이는 객체 분리가 필요하다는 신호라는 점을 배웠습니다. 이는 더 나은 설계로 이어질 수 있는 중요한 인사이트였습니다.앞으로의 다짐1. Classicist vs Mockist 균형 잡기 - Mock은 필요한 최소한으로 사용하되, 실제 동작을 최대한 테스트하도록 노력하겠습니다.2. 테스트 품질 향상 - 한 테스트에서는 한 가지만 검증하도록 집중하겠습니다. - 테스트 간 독립성을 철저히 지키겠습니다.3. 문서로서의 테스트 - 테스트 코드가 문서의 역할을 할 수 있도록 더 명확하고 이해하기 쉽게 작성하겠습니다.마무리이번 학습을 통해 테스트 코드 작성에 대한 더 깊은 이해를 얻었습니다. 특히 Mock의 적절한 사용과 테스트 설계의 중요성을 깨달았습니다. 이러한 학습 내용을 실제 프로젝트에 적용하면서 더 나은 코드 품질을 만들어가고 싶습니다.

백엔드워밍업클럽클린코드

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

강의 요약Persistence LayerData Access의 역할비지니스 가공 로직이 포함되어서는 안된다.Data에 대한 CRUD에만 집중한 레이어 DataJpaTestJpa 관련된 Bean만 로딩한다.상대적으로 빠름기본적으로 @Transactional이 달려있다. → 자동으로 롤백SpringBootTest모든 Bean을 로딩한다.상대적으로 느림WebMvcTestController 관련 Bean만 로딩한다.상대적으로 빠름 </aside>Business Layer비지니스 로직을 구현하는 역할Persistence Layer와의 상호작용(Data를 읽고 쓰는 행위)을 통해 비지니스 로직을 전개시킨다.트랜잭션을 보장해야한다.Presentation Layer외부 세계의 요청을 가장 먼저 받는 계층파라미터에 대한 최소한의 검증을 수행한다.Test Doublehttps://martinfowler.com/articles/mocksArentStubs.htmlDummy아무것도 하지 않는 깡통 객체Fake단순한 형태로 동일한 기능은 수행하나, 프로덕션에서 쓰기에는 부족한 객체ex) FakeRepositoryStub테스트에서 요청한 것에 대해 미리 준비한 결과를 제공하는 객체그 외에는 응답하지 않는다.상태 검증SpyStub이면서 호출된 내용을 기록하여 보여줄 수 있는 객체일부는 실제 객체처럼 동작시키고 일부만 Stubbing할 수 있다.Mock행위에 대한 기대를 명세하고, 그에 따라 동작하도록 만들어진 객체행위 검증  미션 회고3개의 테스트코드에서 중복된 내용을 @BeforeEach 로 합치는 미션.단순히 중복을 없애는 것이 아니라, 각각의 테스트가 의미를 가지도록 묶어야 하는 미션이었습니다.이 미션을 통해 Fixture를 생성할 때 Fixture의 생성에 초점이 맞춰지는 것이 아닌 테스트에 초점을 맞춰 문서의 기능을 할 수 있도록 해야한다는 것을 알았습니다.@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 검증 } 느낀점실무에서 테스트코드를 짤 때 했던 고민들이 많이 해소되어서 좋았습니다.특히 어떤 테스트코드가 좋은지, 어떻게 작성하여야 문서로서의 기능을 할 수 있을지 알 수 있는 시간이었습니다. 

백엔드

하양이

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

Day 15. Spring & JPA 기반 테스트: Presentation LayerPresentation Layer외부 세계의 요청을 가장 먼저 받는 계층파라미터에 대한 최소한의 검증을 수행한다.MockMvcMock(가짜) 객체를 사용해 스프링 MVC 동작을 재현할 수 있는 테스트 프레임워크미션 - 생각하는 레이어별 특징과 테스트 방법Persistence Layer데이터 저장 및 조회를 담당데이터베이스에 연결하여 데이터 저장 및 조회가 잘 되는지 테스트Business Layer비즈니스 로직을 담당비즈니스 규칙에 맞게 올바르게 동작하는지 테스트Presentation Layer사용자와 상호작용을 담당사용자가 보낸 요청의 유효성 체크와 응답이 제대로 가는지 테스트Day 16. Mock을 마주하는 자세Test Double상태 검증 -> Stub행위 검증 -> Mock@Mock, @Spy, @InjectMocks@Mock : Mock 객체로 만듬@InjectMocks : Mock 객체를 주입해줌@Spy : 일부만 Mock 객체로 만듬BDDMockitoMockito와 동일하다.BDD 스타일로 이름만 변환.Mockito.when().thenReturn(); BDDMockito.given().willReturn();Day 17. 더 나은 테스트를 작성하기 위한 구체적 조언한 문단에 한 주제!: 하나의 테스트 코드에서 하나의 테스트만!완벽하게 제어하기: 제어 불가능한 영역은 상위 계층으로!테스트 환경의 독립성을 보장하자테스트 간 독립성을 보장하자한 눈에 들어오는 Test Fixture 구성하기: given 절을 구성할 때의 주의사항Test Fixture 클렌징테스트 수행도 비용이다. 환경 통합하기Q. private 메서드의 테스트는 어떻게 하나요?해서도 안 되고 할 필요가 없다.Q. 테스트에서만 필요한 메서드가 생겼는데 프로덕션 코드에서는 필요 없다면?만들어도 되지만 보수적으로 접근하기!Day 18. 학습 테스트 | REST Docs학습 테스트잘 모르는 기능, 라이브러리, 프레임워크를 학습하기 위해 작성하는 테스트Spring REST Docs테스트 코드를 통한 API 문서 자동화 도구Spring REST Docs : https://docs.spring.io/spring-restdocs/docs/current/reference/htmlsingle/Asciidoctor : https://asciidoctor.org/Swagger : https://swagger.io/미션 - @Mock, @MockBean, @Spy, @InjectMocks의 차이 정리@Mock: 해당 객체를 Mock 객체로 만든다.@MockBean: Spring의 ApplicationContext에 Mock 객체로 만들어 빈으로 등록한다.@Spy: 일부분만 Mock 객체로 만들어준다.@InjectMockes: Mock 객체로 만들어 주입해준다.미션 - 각 항목을 @BeforeEach, given절, when절 배치@BeforeEach void setUp() { 1-1., 2-1., 3-1. 사용자 생성에 필요한 내용 준비 1-2., 2-2., 3-2. 사용자 생성 } @DisplayName("사용자가 댓글을 작성할 수 있다.") @Test void writeComment() { // given 1-3. 게시물 생성에 필요한 내용 준비 1-4. 게시물 생성 1-5. 댓글 생성에 필요한 내용 준비 // when 1-6. 댓글 생성 // then 검증 } @DisplayName("사용자가 댓글을 수정할 수 있다.") @Test void updateComment() { // given 2-3. 게시물 생성에 필요한 내용 준비 2-4. 게시물 생성 2-5. 댓글 생성에 필요한 내용 준비 2-6. 댓글 생성 // when 2-7. 댓글 수정 // then 검증 } @DisplayName("자신이 작성한 댓글이 아니면 수정할 수 없다.") @Test void cannotUpdateCommentWhenUserIsNotWriter() { // given 3-3. 사용자2 생성에 필요한 내용 준비 3-4. 사용자2 생성 3-5. 사용자1의 게시물 생성에 필요한 내용 준비 3-6. 사용자1의 게시물 생성 3-7. 사용자1의 댓글 생성에 필요한 내용 준비 3-8. 사용자1의 댓글 생성 // when 3-9. 사용자2가 사용자1의 댓글 수정 시도 // then 검증 }회고아기다리 고기다리던 금요일 특강을 회사일때문에 참가하지 못했다.하필 저번주도 다음주도 아닌 이번주 금요일에 하필...아쉽지만 지금까지 공부하고 배운 내용을 내것으로 만들어 가야겠다.출처https://inf.run/zgJk5https://inf.run/kHiWM

백엔드워밍업클럽테스트

ronnie

백엔드 클린코드, 테스트코드 회고 4주차 마지막

해당 회고는 'Practical Testing: 실용적인 테스트 가이드' 강의에 대한 회고입니다.마지막 주벌써 4주 동안의 스터디가 끝났습니다. 그래도 무언가 마무리된다는 것은 보람차면서도 아쉽네요.이번주에 한 것들을 정리하면서 마지막 회고를 작성해보겠습니다! 배운 것들4주차에서는 Mockito와 관련된 사용과 stubbing하는 방법, 더 나은 테스트 작성하기, 학습 테스트와 Spring REST docs를 공부했습니다. Mockito로 Stubbing하기추가 기능으로 날짜와 이메일을 받고 일 총 매출 이메일로 전송해주는 것을 구현외부 네트워크를 타는 로직의 경우 실제 메일을 전송하는 것까지 테스트에 포함시켜야 할까?할 필요가 없다 시간과 비용적인 낭비다적절한 mocking으로 원활한 테스트를 가능하게 해보자! @MockBean private MailSendClient mailSendClient; @DisplayName("결제 완료 주문들을 조회하여 매출 통계 메일을 전송한다.") @Test void sendOrderStatisticsMail() { //given ... when(mailSendClient.sendEmail(any(String.class), any(String.class), any(String.class), any(String.class))) .thenReturn(true); //when ... }Test Doublestub과 Mock이 헷갈렸는데 바로 알게되었다.둘의 공통점은 어떤 행위에 대한 결과를 정해두고 그것을 리턴해주는 것차이점은 검증 목적이다. Stub은 테스트를 함에 따라 변한 상태를 검증하는 것, 테스트 후에 Stub의 상태가 어떻게 변했는지 주목Mock은 테스트를 함에 따라 동작하는 행위를 검증하는 것, 테스트를 하면 어떤 동작이 실행될 것인지에 대해서 주목순수 Mokito Extension으로 사용해보기, 어노테이션 사용해보기Mock과 Spy의 차이를 명확하게 공부하고 직접 함수를 이용해봤다. 외에도 @MockBean, @SpyBean, @InjectMocks도 학습했다. BDDMokitoMock을 사용할 때 when 함수의 경우 표기상 when절에 있는 것이 맞을 것 같은데 given절에 있어서 뭔가 표현이 매끄럽지 않은 것 같다.따라서 나온 것이 BDDMockito.모든 동작은 Mockito와 동일하다 BDD스타일로 이름만 변경한 것.앞으로 Mockito를 작성할 때는 given절에서 BDDMockito를 적극적으로 이용하자!given절에 구현되는 when절을 BDDMockito.given()으로 사용할 수 있도록 해줘서 매끄러운 표현을 할 수 있도록 해준다.@DisplayName("메일 전송 테스트") @Test void sendMail() { //given BDDMockito.given(mailSendClient.sendEmail(anyString(), anyString(), anyString(), anyString())) .willReturn(true); //when boolean result = mailService.sendMail("", "", "", ""); Classicist vs MockistMockist는Mock으로 모든 테스트를 커버하고 보장이 된 부분에 대해서는 Mocking처리를 해서 빠른 테스트를 진행하자는 주의Classicist는 실제 프로덕션 코드에서 잘 돌아간다는 보장을 하기 위해서 실제 객체로 최대한 테스트를 진행해야 하고 꼭 필요한 경우에만 Mocking을 진행하자는 주의만약 프로덕션 레벨에서 테스트의 유효성이 Mockist가 낮다면 Classicist를 따르는 것이 맞을 것 같은데 규모가 작거나 커버리지 퍼센트를 어느정도 유지하고 싶다면 Mockist 방법을 택해서 할 수도 있을 것 같다. 나은 테스트를 위한 조언하나의 문단에 하나의 주제를 가지는 것이 좋은 글쓰기인 것처럼 각 테스트메서드는 하나의 주제만 가지는 것이 바람직테스트 환경을 조성할 때 모든 환경을 제어할 수 있어야 한다.given절에서 테스트 기반 환경을 세팅할 때 다른 테스트와 결합이 생기지 않도록 독립적으로 작성하자두가지 이상의 테스트가 하나의 공유변수를 이용할 때 한 테스트가 변수의 상태를 바꾼다면 다른 테스트의 결과를 보장할 수 없다.여러가지 테스트 메서드를 정의했을 때 given에 겹치는 데이터가 생각보다 많다.문서로써의 테스트 기능을 잘 수행하도록 잘 분배해보자성능과 시간적으로 효율적이고 일괄 삭제를 해주는 deleteAllInBatch를 사용하자파라미터에 여러값을 적용해서 테스트할 수 있는 @ParameterizedTest와 공유변수로 다수의 테스트를 수행할 수 있는 @DynamicTest테스트 환경도 상위에서 관리할 수 있게 해서 환경을 통합 관리하자private 메서드 테스트를 하고 싶다면 객체 분리의 시점으로 보자. 하나의 퍼블릭 메서드에서 하는일이 너무 많은지 확인해보고 프라이빗 메서드의 기능을 별도의 객체에 위임하는 방법을 고려하자프로덕션 코드에서는 필요없는 테스트 코드에서만 사용하는 최소의 생성자나 빌더는 필요에 의한 최소범위로 만들고 무분별한 생성을 지양하자 학습테스트학습테스트는 테스트를 학습의 용도로 이용하는 것이다.Guava라는 라이브러리를 테스트메서드로 학습해보았다. 실제 동작적인 확인을 하기에 매우 좋은 것 같고 뭔가 나만의 동적인 Docs를 남기고 공유하고 싶을 때 이용하기 좋은 방법인 것 같다. Spring REST Docs프로젝트 때 비슷한 swagger를 사용해봤다. 제대로 잘 익혀놓으면 다음 개발때 잘 이용해 볼 수 있을 것 같다. 진짜 마무리 회고많은 분들에게 동기부여받고 학습했던 한 달이었습니다. 배움에는 끝이 없다는 것을 늘 느끼고 앞으로도 꾸준히 열심히 도전하고 학습하고 싶습니다. 인프런 워밍업 클럽 짱 

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

허수빈

[인프런 워밍업 클럽 2기 클린코드 & 테스트 코드] Day18 과제

해당 글은 [인프런 워밍업 클럽 2기 클린 코드 & 테스트 코드]에 참가하여 박우빈님의 <Readable Code: 읽기 좋은 코드를 작성하는 사고법> 강의를 듣고 작성한 글입니다. @Mock는 독립적인 단위 테스트에서 가짜 객체를 생성할 때 사용한다. 이때, @Mock으로 생성된 가짜 객체를 @InjectMocks 객체에 자동으로 의존성 주입해준다. @MockBean은 주로 통합 테스트에서 사용되며 가짜 객체를 생성하여 스프링 컨텍스트에 등록하여 빈으로 사용할 수 있게 해준다. @Spy는 단위 테스트에서 사용되고, 가짜 객체를 생성하는 것이 아니라 실제 구현체를 사용하여 특정 메서드만 모킹할 수 있다. 즉, 특정 메서드의 동작을 원하는 대로 바꿀 수 있다. @SpyBean은 @Spy와 비슷하지만 실제 스프링 컨텍스트에 등록된 빈을 사용한다.   @BeforeEach void setUp() { 사용자 생성에 필요한 내용 준비 게시물 생성에 필요한 내용 준비 댓글 생성에 필요한 내용 준비 } @DisplayName("사용자가 댓글을 작성할 수 있다.") @Test void writeComment() { // given 1-2. 사용자 생성 1-4. 게시물 생성 // when 1-6. 댓글 생성 // then 검증 } @DisplayName("사용자가 댓글을 수정할 수 있다.") @Test void updateComment() { // given 2-2. 사용자 생성 2-4. 게시물 생성 2-6. 댓글 생성 // when 2-7. 댓글 수정 // then 검증 } @DisplayName("자신이 작성한 댓글이 아니면 수정할 수 없다.") @Test void cannotUpdateCommentWhenUserIsNotWriter() { // given 3-2. 사용자1 생성 3-4. 사용자2 생성 3-6. 사용자1의 게시물 생성 3-8. 사용자1의 댓글 생성 // when 3-9. 사용자2가 사용자1의 댓글 수정 시도 // then 검증 }

웹 개발워밍업클럽

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

* 주간 요약 * 테스트 Mock 관련 어노테이션들의 차이점 학습 * 레이어드 아키텍처의 각 계층별 테스트 방법 이해 * 테스트 코드 구조화와 재사용성 향상 방법 학습* 학습 회고 * 칭찬할 점 * Mock 관련 어노테이션들의 차이점을 명확하게 이해했습니다. * @BeforeEach를 활용한 테스트 코드 재사용성 개선을 달성했습니다. * 레이어드 아키텍처의 각 계층 특성에 맞는 테스트 방법을 파악했습니다. * 아쉬운 점 * Spy와 SpyBean의 실제 활용 사례를 더 실습해보지 못했습니다. * 각 레이어의 경계를 명확히 구분하는 테스트 설계가 부족했습니다. * 보완하고 싶은 점 * 실제 프로젝트에서 다양한 Mock 어노테이션 활용해보기 * 각 레이어의 특성을 고려한 테스트 케이스 설계 강화 * Mock/Spy 객체를 활용한 복잡한 의존성 처리 연습 * 레이어 간 통합 테스트 작성 연습* 주간 미션 * 접근 * Mock 관련 어노테이션들의 차이점을 명확히 정리했습니다. * 테스트 코드의 재사용성을 고려한 구조 설계를 진행했습니다. * 레이어드 아키텍처의 각 계층 특성을 분석했습니다. * 과정 * Mock 어노테이션 비교 분석 * 각 어노테이션의 특징과 사용 목적 정리 * 실제 사용 시나리오 구상 * 테스트 코드 구조화 * 공통 테스트 준비 코드 @BeforeEach로 추출 * given-when-then 패턴에 맞춘 코드 재배치 * 레이어드 아키텍처 테스트 전략 * 각 레이어의 특징과 책임 분석 * 레이어별 적절한 테스트 방식 도출 * 결과 * Mock 관련 어노테이션들의 용도와 차이점을 명확히 이해 * 효율적인 테스트 코드 구조 설계 능력 향상 * 레이어드 아키텍처에 대한 이해도 증가

나는뉴비

워밍업 클럽 스터디 2기 4주차 발자국

강의Practice Testing: 실용적인 테스트 가이드강의 수강섹션 6. Spring & JPA 기반 테스트 - Business Layer, Presentation Layer Business Layer, Presentation Layer에서는 어떠한 부분을 고려하며 테스트를 진행해야 하는지 학습하고 실습 섹션 7. Mock을 마주하는 자세Mock과 관련된 기본적인 개념, 애노테이션 및 Junit에서의 사용법에 대해 학습Classicist와 Mockist에 대한 개념 학습 섹션 8. 더 나은 테스트를 작성하기 위한 구체적 조언테스트 작성 시 되새기면 좋을 다양한 조언에 대한 학습섹션 9. AppendixSpring Rest Docs를 활용한 문서화에 대한 필요성, 설명 및 실습 진행 섹션 10. Outro테스트를 어떤 식으로 접근해야 할지, 진행해야 할지, 어떤 마음가짐을 가져야 하는지에 대해 학습 미션Day 15Layered Architecture에 어떤 종류의 Layer가 있는지, 각 Layer 간 어떤 테스트가 적절한지 정리강의를 복습하는 느낌으로 나만의 용어로 정리 Day 18Mock과 관련된 애노테이션의 용도가 무엇인지 정리 회고주변에서 듣기만 하고 제대로 사용해본 적 없는 테스트에 대해 지식을 얻을 수 있었다 강의를 듣고 미션을 통해 테스트 코드를 작성하면서 어려움을 느꼈고, 꾸준히 연습해야 한다는 필요성을 체감할 수 있었다

웹 개발워밍업

sdsd988

워밍업 클럽 2기 백엔드 클린코드&테스트 Day 18 미션

1. @Mock, @MockBean, @Spy, @SpyBean, @InjectMocks 의 차이 @Mock, @Spy 차이- '가짜'이냐 '진짜'이냐의 차이- @Spy' 진짜' 객체라면, 객체 내부의 메서드가 실행된다.- @Mock '가짜' 객체라면, 객체 내부의 메서드가 실행되지 않는다. @Mock과 @MockBean 차이@Mock은 Spring과 독립적으로, 단위 테스트에서 객체의 특정 메서드를 모킹할 때 사용!@MockBean은 Spring Boot 통합 테스트나 Spring의 의존성 주입이 필요한 상황에서 사용되며, Spring 컨텍스트에 Mock 객체를 주입하여 해당 객체를 사용!  @Spy: Mockito 스파이 객체를 테스트 클래스 내부에서만 사용하며, Spring 컨텍스트와는 무관합니다. 단위 테스트에서 사용됩니다.@SpyBean: Spring 애플리케이션 컨텍스트에 스파이 객체를 주입하여 Spring의 Bean과 상호작용할 수 있게 합니다. Spring 통합 테스트에서 사용됩니다. @InjectMocks@Mock 객체에 필요한 의존성을 주입해주는 역할을 수행한다. 2. 테스트 코드 문서화핵심은 중복 제거가 아닌, 도메인사용자, 게시물은 간접적이므로 setUp, 댓글은 직접적으로 given절@BeforeEach void setUp() { 1,2,3-1. 사용자 생성에 필요한 내용 준비 1,2,3-2. 사용자 생성 1,2,3-3. 게시물 생성에 필요한 내용 준비 1,2.3-4. 게시물 생성 } @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 검증 }   

백엔드백엔드인프런워밍업클럽테스트코드스프링

워밍업 클럽 2기 BE 클린코드&테스트코드 DAY 18 미션

1. @Mock, @MockBean, @Spy, @SpyBean, @InjectMocks 의 차이를 한번 정리해 봅시다. @Mock가짜 객체를 생성하여 단위 테스트에 사용메서드의 예상 결과를 지정할 수 있음 (stubbing 가능)@MockBeanSpring Context에 Mock 객체를 주입하여 통합 테스트에서 사용Application Context에 포함되어 다른 Bean에 의해 주입될 수 있음@Spy실제 객체를 감시하고, 호출된 메서드만 Mocking 가능일부 메서드는 실제 동작을 하고, 나머지는 Mocking 가능@SpyBeanSpring Context에 실제 객체를 주입하고 필요한 메서드만 Mocking 가능기존 Bean의 기능을 유지하면서 특정 메서드를 Mocking 가능@InjectMocksMock 객체들을 주입받을 실제 객체를 생성주입된 Mock 객체를 사용하는 클래스의 실제 동작을 테스트 가능 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 3-3. 사용자2 생성에 필요한 내용 준비 3-4. 사용자2 생성 3-7. 사용자1의 댓글 생성에 필요한 내용 준비 3-8. 사용자1의 댓글 생성 // when 3-9. 사용자2가 사용자1의 댓글 수정 시도 // then 검증 }

백엔드

hhw0850

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

Readable Code: 읽기 좋은 코드를 작성하는 사고법 수강 후 작성한 2주차 발자국입니다. 2주차 강의 정리좋은 주석우리가 리팩토링할 때 정말 큰 난관 중 하나는 히스토리를 전혀 알 수 없는 코드다.후대에 전해야할 의사결정의 히스토리를 도저히 코드로 표현할 수 없을때 주석으로 상세하게 설명한다.자주 변하는 정보는 최대한 지양해서 작성한다.관련 정책이 변하거나 코드가 변경되었다면 주석도 함께 업데이트한다.우리가 가진 모든 표현 방법을 총동원해 코드에 의도를 녹여내고, 그럼에도 불구하고 전달해야 할 정보가 남았을때 사용하는 주석변수와 메서드의 나열 순서변수는 사용하는 순서대로 나열한다.인지적 경제성메서드의 순서객체는 협력을 위한 존재이다공개 메서드를 상단에 배치하는것을 선호공개 메서드끼리도 기준을 가지고 배치하는 것이 좋다상태변경 >> 판별 ≥ 조회비공개 메서드는 공개 메서드에서 언급된 순서대로 배치한다중요한것은 나열 순서로도 의도와 정보를 전달할 수 있다는 것패키지 나누기패키지는 문맥으로써의 정보를 제공할 수 있다.대규모 패키지 변경은 팀원과의 합의를 이룬 시점에 하자알고리즘 교체하기재귀를 사용한 DFS도 결국 Stack이다.→ 스레드마다 생기는 스택 영역에는, 함수를 호출할 때마다 frame이 쌓인다.→ frame은 지역 변수, 연산을 위한 정보 등을 담고있다.→ 스택 영역은 결국 크기가 제한되어 있다.IDE의 도움 받기코드 포맷 정렬ctrl + alt + l코드 품질Sonarlint포맷 규칙.editorconfig2주차 강의, 미션 회고강의를 듣고 미션을 수행는 내내 강의를 처음부터 다시 돌려봐야겠다..는 생각이 계속 들었다. 강의는 들었어도 이걸 실제로 적용하려니까 머리가 백지장이 되어버렸다. 지금까지 지뢰찾기 게임을 리팩토링하며 여러가지 스킬들을 배웠는데 내가 놓쳤던 점은 그냥 이런 개념이 있구나,, 받아들이기만 했다는 점이다. 이제는 그냥 받아들이지만 말고 왜 이 개념을 여기에 적용할 수 밖에 없는지, 적용 전과 후가 어떻게 달라졌는지,,까지 사고의 흐름도 완벽하게 파악해야겠다고 생각했다. 이제 다음주부턴 테스트코드 강의 시작이다. 1주차와는 다른 마음가짐으로! 강의 듣고 더 열심히 해야겠다.. 

hhw0850

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

Practical Testing: 실용적인 테스트 가이드 수강 후 작성한 3주차 발자국입니다. 3주차 강의 정리 테스트를 작성하는 역량주니어 개발자에게 가장 기대하는 요소 중 하나채용 시 구현 과제 등에서 테스트 작성 여부, 테스트 코드 구현 방식을 확인소프트웨어 품질을 보증하는 방법으로, 그 중요성을 알고있는지를 확인무엇을 학습?테스트 코드가 필요한 이유좋은 테스트 코드란 무엇일까?실제 실무에서 진행하는 방식 그대로 테스트를 작성해가면서 API를 설계하고 개발하는 방법정답은 없지만 오답은 있다! 구체적인 이유에 근거한 상세한 테스트 작성 팁 테스트를 왜 해야하는가?내가 개발한 기능이 내가 의도한대로 정상 동작하는지 확인되어야한다.이걸 사람이 수동으로 검증하는게 아니라 자동화시키자는것개발한 소프트웨어의 신뢰성을 높일수있다테스트 코드가 엉망, 복잡함→ 부작용→ 잘짜야한다…테스트 코드를 작성하지 않는다면변화가 생기는 매순간마다 발생할 수 있는 모든 case를 고려해야한다.변화가 생기는 매순간마다 모든 팀원이 동일한 고민을 해야한다.빠르게 변화하는 소프트웨어의 안정성을 보장할 수 없다.테스트 코드가 병목이 된다면프로덕션 코드의 안정성을 제공하기 힘들어진다.테스트 코드 자체가 유지보수하기 어려운, 새로운 짐이 된다.잘못된 검증이 이루어질 가능성이 생긴다.올바른 테스트 코드는자동화 테스트로 비교적 빠른 시간 안에 버그를 발견할 수 있고, 수동 테스트에 드는 비용을 크게 절약할 수 있다.소프트 웨어의 빠른 변화를 지원한다.팀원들의 집단 지성을 팀 차원의 이익으로 승격시킨다.가까이 보면 느리지만, 멀리보면 가장 빠르다 단위테스트 (Unit test)작은 코드단위를 독립적으로 검증하는 테스트 (클래스, 메서드)검증 속도가 빠르고, 안정적이다.JUnit 5단위 테스트를 위한 테스트 프레임워크XUnit - Kent BeckAssertJ테스트 코드 작성을 원활하게 돕는 테스트 라이브러리풍부한 API, 메서드 체이닝 지원테스트 케이스 세분화하기질문하기 : 암묵적이거나 아직 드러나지 않은 요구사항이 있는가?해피케이스예외케이스 - 음료 수량은 음수로 입력한다면, 0을 입력한다면 경계값 테스트 (범위, 구간, 날짜 등)경계값이 존재한다면 테스트는 항상 경계값에서 테스트 하는게 좋다.예를들어 3이상일때 A라는 조건을 만족해야한다. 는 요구사항이 있다면 해피케이스 테스트는 3으로 하는것이 좋다. 4나 5보다.. 예외케이스는 2로 하는게 좋다. 테스트하기 어려운 영역을 구분하고 분리하기관측할 때마다 다른 값에 의존하는 코드현재 날짜/시간, 랜덤값, 전역 변수/함수, 사용자 입력 등외부 세계에 영향을 주는 코드표준 출력, 메시지 발송, 데이터 베이스에 기록하기 등@Data, @Setter, @AllArgsConstructor 지양 TDD : Test Driven Development프로덕션 코드보다 테스트 코드를 먼저 작성하여 테스트가 구현 과정을 주도하도록 하는 방법론red - green - refactor실패하는 테스트 작성해서 빨간불보기테스트 통과하는 최소한의 코딩해서 초록불보기초록불을 유지하면서 리팩토링 구현코드 개선TDD의 핵심가치 → 피드백내가 작성하는 코드에 대해서 빠르게 피드백을 받을 수 있다는 장점기존의 선 기능 구현 후 테스트 작성하는 방식테스트 자체의 누락 가능성특정 테스트 케이스만 검증할 가능성 (해피케이스만..)잘못된 구현을 다소 늦게 발견한 가능성선 테스트 작성 후 기능 구현복잡도가 낮은 테스트 가능한 코드로 구현할 수 있게 한다.쉽게 발견하기 어려운 엣지 케이스를 놓치지 않게 해준다.구현에 대한 빠른 피드백을 받을 수 있다.과감한 리팩토링이 가능해진다. 테스트는 문서다프로덕션 기능을 설명하는 테스트 코드 문서다양한 테스트 케이스를 통해 프로덕션 코드를 이해하는 시각과 관점을 보완어느 한 사람이 과거에 경험했던 고민의 결과물을 팀 차원으로 승격시켜서, 모두의 자산으로 공유할 수 있다.DisplayName을 섬세하게테스트 메서드가 어떤 역할을 하는지 이름 지을 수 있다.ex)음료 1개 추가 테스트→ 음료를 1개 추가할 수 있다명사의 나열보다 문장으로 작성하기~테스트 지양하기음료를 1개 추가할 수 있다→ 음료를 1개 추가하면 주문 목록에 담긴다.테스트 행위에 대한 결과까지 기술하기특정 시간 이전에 주문을 생성하면 실패한다→ 영업 시작 시간 이전에는 주문을 생성할 수 없다.도메인 용어를 사용하여 한층 추상화된 내용을 담기메서드 자체의 관점보다 도메인 정책 관점으로테스트의 현상을 중점으로 기술하지 말 것성공한다 실패한다는 피하기 BDD: Behavior Driven DevelopmentTDD에서 파생된 개발 방법함수 단위의 테스트에 집중하기보다, 시나리오에 기반한 테스트 케이스 자체에 집중하여 테스트한다.개발자가 아닌 사람이 봐도 이해할 수 있을 정도의 추상화 수준을 권장Given / When / ThenGiven : 시나리오 진행에 필요한 모든 준비 과정 (객체, 값, 상태 등)When : 시나리오 행동 진행Then : 시나리오 진행에 대한 결과 명시, 검증어떤 환경에서(given)어떤 행동을 진행했을 때(when)어떤 상태 변화가 일어난다.(then)→ DisplayName에 명확하게 작성할 수 있다. Spring & JPA 기반 테스트Layered Architecture 레이어드 아키텍쳐스프링 MVC 기반에서 가장 많이 사용되는 아키텍쳐 왜 레이어를 구분하는가? → 관심사의 분리사용자의 요청이 왔을때 각 레이어별로 역할을 할당테스트 하기 복잡해보인다는 생각이 들 수 있다.여러 객체가 협력해서 하나의 기능을 동작하게 하는 경우는 어떻게 테스트 할 것인가, 단위 테스트만으로는 커버 못함→ 통합 테스트가 필요하다 (Integration test)여러 모듈이 협력하는 기능을 통합적으로 검증하는 테스트일반적으로 작은 범위의 단위 테스트만으로는 기능 전체의 신뢰성을 보장할 수 없다.풍부한 단위 테스트 & 큰 기능 단위를 검증하는 통합 테스트Spring / JPASpringLibrary vs Framework라이브러리는 내 코드가 주체가 돼서 필요한 기능이 있다면 외부에서 끌어와서 사용. 외부에서 끌어오는걸 라이브러리라고 표현한다.프레임워크는 이미 프레임이 있는것. 동작할 수있는 환경이 있음, 내 코드가 수동적으로 환경에 들어가서 동작스프링은 프레임워크로써 제공하는 환경이 있고 그거에 맞춰서 코드를 작성하면 동작하는 구조 스프링 3대 개념IoC (Inversion of Control)객체에 대한 생명주기 관리는 제 3자가 하는것,, 제어의 역전이 일어남.DI (Dependency Injection)컨테이너라는 제 3자가 주입해준 객체를 사용한다.AOP (Aspect Oriented Programming)비즈니스 흐름과 관련없는 부분을 관점이라는 용어로 부르고JPA (Java Persistence API)ORM (Object-Relational Mapping)orm 의 한 종류로 jpa가 존재함ORM객체 지향 패러다임과 관계형 DB 패러다임의 불일치이전에는 개발자가 객체의 데이터를 한땀한땀 매칭하여 DB에 저장 및 조회ORM을 사용함으로써 개발자는 단순 작업을 줄이고, 비즈니스 로직에 집중할 수 있다.JPAJava 진영의 ORM 기술 표준인터페이스이고 여러 구현체가 있지만 보통 Hibernate를 많이 사용한다.반복적인 CRUD SQL을 생성 및 실행해주고, 여러 부가 기능들을 제공한다.편리하지만 쿼리를 직접 작성하지 않기 때문에 어떤 식으로 쿼리가 만들어지고 실행되는지 명확하게 이해하고 있어야 한다.Spring 진영에서는 JPA를 한번 더 추상화한 Spring Data JPA 제공QueryDSL과 조합하여 많이 사용한다. (타입체크, 동적쿼리)JPA에서 주고 사용되는 어노테이션들@Entity, @Id, @Column@ManyToOne, @OneToMany, @OneToOne, @ManyToMany 3주차 회고이번주엔 테스트 코드에 대해 학습했는데 개발자로 취업하고 테스트 코드를 제대로 작성해본 것은 처음이었다. 지금 회사에서는 테스트코드를 작성하지 않는다. IT관련 미디어에서 테스트 코드 작성해야한다. TDD 해야한다. 이런 말을 많이 하는데 회사에선 안하니까 계속 묵혀두기만 했었다. 입사 처음엔 테스트 코드에 대한 필요성을 잘 못느끼다가 요즘 들어서는 점점 느끼고 있고 공부의 필요성을 느꼈다. 기존에 있었던 기능에 대해서 코드를 수정하면 기존에 잘 돌아가던 기능도 에러가 발생할까 걱정되었고, 코드를 다 작성하고도 혹시나 내가 못찾은 버그는 없을까 불안한 마음이 생겼었다. 또 테스트 시 입력해야 할 항목이 많은 경우는 하나하나 선택하고 테스트 해봐야 하는게 정말 불편했다. 지금은 수동으로 하나하나 테스트 하고 있긴 한데 적합한 방법은 아닌 것 같다는 생각이 계속 들고 있다. 이번 테스트코드 과정을 통해 지금까지 회피하고 묵혀뒀던것들을 어느 정도라도 해소할 수 있었으면 좋겠다. 

채널톡 아이콘