으아아아아아 수료했다아아아아🔥🔥🔥🎉🥳
약 2달전에 NEXTSTEP 에서 진행하는 "ATDD, 클린 코드 with Spring 7기" 라는 교육을 수강했다! (https://edu.nextstep.camp/)
1달 반정도 같이있었던 첫 개발 사회생활의, 첫 번째 사수님이 수강하셨고 추천해주셨던 강의인데,,
그때 당시 "단위 테스트도 잘 못하는데 무슨 인수테스트냐;;" 라는 생각에 꼭 나중에 들어봐야지 다짐하고 1년이 지난 지금 드디어 수강을했고, 수료를 했다
넥스트스텝은 다양한 주제의 시즌제(?) 강의들이 존재하는 교육 플랫폼이다.
사수님 덕분에 알게되었지만, 큰 관심을 가지게된건 여러가지 복합적인 이유가 있지만 가장 큰건 catsbi 님의 회고글 이였다.
(신기하게도 catsbi 님도 리뷰어 중에 있었다! 물론 나는 리뷰를 못 받았지만?!)
되게 흥미롭게 읽었고, 한창 TDD 나 객체지향에 관심을 가지고 구글링을 해보면 양질의 자료는 NEXTSTEP이 출처인 경우가 종종 있었다.
catsbi 님의 회고글을 읽고 TDD → ATDD → 인프라공방 이 순으로 꼭 수강해야지! 했지만 가격이 상당히 쎄기에,,, TDD는 패스!
자! 이제 약 6주간 ATDD 를 수강하면서 배운것을 짧막하게 정리하면서 회고글을 써보고자 합니다😄
[목차]
- ATDD 교육 소개
- 배운점
- try?
1. ATDD 미션 소개
교육은 약 6주간 매 주차의 미션을 수행하는 형식으로 진행된다.
강의는 매주 목요일마다 있었고, 해당 주차의 미션 리뷰, 질문, 피드백, 다음주차 미션 소개, 그 사이의 짤막한 지식, 키워드, 미션 힌트를 위한 강의 등을 알려주신다.
→ 근데 6주가 지났는데, 수강자들의 리뷰가 활발하다고 1주 더 빠른 리뷰 받을 수 있게 교육기간을 늘려주기도 했습니다.
괜히 유명한 교욱이 아니라는 생각이 들었다😂
1) ATDD 미션
미션의 베이스 목표는 지하철 노선도를 구현하는 것
1주차
- 주제 : 인수 테스트와 E2E 테스트
- 목표 : 인수테스트 이해하기 + RestAssured 로 통합테스트 환경 구축하기
- https://github.com/thalals/atdd-subway-map/tree/thalals
2~3주차
- 주제 : 인수 테스트와 TDD
- 목표
- 요구사항에서 인수 조건 추출
- 테스트 기반, 요구사항 변경에 따른 기존 코드 리팩토링
- Rich Domain Model 학습 (내가 느끼기에)
- https://github.com/thalals/atdd-subway-path/tree/thalals
4주차
- 주제 : 인수테스트와 인증
- 목표 : 인증 및 인가가 필요한 API 인수테스트 (feat OAuth)
- https://github.com/thalals/atdd-subway-favorite/tree/thalals
5주차
- 주제 : 인수 테스트와 리팩터링
- 목표 : RestAssured 로 API 문서화 (RestDocs)
- https://github.com/thalals/atdd-subway-fare/tree/thalals
📌 좋았던 점은, 미션 위주지만, 해당 미션을 수행하는게 목적이 아닌, 더 나은 방법으로 수행이 목적이였다.
5주차의 미션을 보면, RestDocs의 문서화가 주된 목적이지만,
미션세부사항에 "문서화를 위한 코드와 인수테스트를 위한 코드가 중복 해결" 등과 같은 실제 업무에서도 사용할 수 있을정도의 강도로 교육이 진행되었다.
2) ATDD 강의 후기
→ 사실 내가 생각했던 완전(?) 강의는 아니였다.
약간 학교나, 세미나, 혹은 지식 전달의 강의일줄 알았는데 "정보 공유의 장" 느낌이 나에게는 강하게 들었다.
강사님은 거의 모든 질문에 답변을 해주셨다.
실시간 질문뿐만 아니라 매 주차 강의 전에 구글폼으로 질문을 와장창 받으시고, 이걸 강의에 꼭 Q&A를 해주시는게 참 신기했다
장점
- 현업에서 일하시는, 굉장한 커리어를 가지시는 분이 모든 질문에 친절하게 눈높이를 낮춰서 답을 해주시고, 같이 답을 찾아나갈려고 하시니까 듣는 재미가 있었다.
- 솔직히 이렇게 어떤 상황(미션 코드 or 주제)을 공유하면서, 모르거나 확신을 못가졌던 관점에 대해 물어볼 수 있는 기회가 생가보다 별로 없는데 이 부분은 너무 좋았다.
- 또, 강의를 같이 수강하시는 분들이 대부분 현직자분들이다보니 수준이 상당히 높다고 느껴졌다.
질문에 대해 같이 토론하시는데 답변들이 하나같이 굉장(?)했다.
단점
- 이 교육이 매 주차의 미션위주이고, 강의또한 미션에 맞춰지기 때문에 어쩔수없이 다른 미션 진행자분들의 진행률에 따라 강의가 밀리는 느낌도 있었다.
- 이 부분은 누군가에게는 장점일 수도 있고, 단점이 될 수도 있다 생각하는데,, 나는 너무 밀리는 느낌도 받지않았고 녹강도 제공해주셔서 솔직히 좋았다!
2. 교육기간동안 배운 것 정리
솔직히 너무 많아서 키워드만이라도 정리하자는 마음으로 적어봅니당
내가 배운거
- 인수테스트란, 인수테스트 하는법, ATDD, TDD
- 개발 프로세스
- 요구사항으로 인수조건 도출 → 문서화 → 인수 테스트 → 로직 구현 → 단위테스트 → 로직 구현(반복) → 인수테스트 검증
- 리뷰하는 법?
- PR 보내는 방법
- 커밋 쪼개기 (작게, 작게)
그 외에 뭐 도메인 주도 아키텍쳐, 기술들 많이 배웠지 정리 잘하자
- 리치도메인
- 도메인 주도 아키텍쳐
- 패키지 의존성 개선
- 직접 참조 vs 간접 참조
- 책임연쇄 패턴의 적용
- HandlerArgumentResolver (@AuthenticationPrincipa 구현체 Custom)
1. 인수테스트란
ATDD 란 Acceptance Test Driven Development 를 의미합니다.
Acceptance는 사전적인 의므로 "허락"을 뜻합니다. 즉 인수테스트란 마지막 허가를 위한 테스트로 저는 이해를 이했습니다.
1) Acceptance Test (in extreme programming)
✔️ 애자일(xp)에서의 인수테스트
- 사용자 스토리를 검증하는 "기능 테스트" 를 인수테스트라 지칭합니다.
- 사용자 스토리(기획)로 테스트할 시나리오를 지정 후 → 시나리오 기반의 요구사항을 테스트하는 과정을 거칩니다.
✔️ 원래 인수테스트 의미
- 소프트웨어 이외 다른 분야에서도 사용되는 용어
- 보통 마지막 단계에서 수행하는 테스트를 의미 → 승인을 위해 (👏🏻 마지막 단계에서 Accpetance 되기 전에 수행하는 테스트라고 추정)
- 👏🏻 즉, 최종 단계에서 작업을 종료 시켜도 되는지 검증하는 테스트가 인수테스트 !!
📌 교육 미션 진행시에도 → 실제 운영환경과 유사한 테스트환경을 구현하여, 해당 기능이 동작했을때 의도했던데로 잘 동작하는지 E2E 테스를 작성하여 진행합니다.
- 즉, 인수테스트 = 등대 테스트 = 수용 테스트 = 통합 테스트 = 인수 테스트
- 어떤 관점으로 바라보는가, or 테스트의 목적이 무엇인가에 따라서 부르는 이름은 얼마든지 달라질 수 있다고 생각합니다.
- 교육에서의 인수테스트는, 개발자가 아닌 기획자와 함께 바라볼 수 있게! 라는 목적도 포함하였습니다.
(그래서 한글 메소드 사용 + 가독성 중시)
2) ATDD를 하는 이유
- 구현전에 인수 테스트를 수행하는 경우 팀의 생산성이 2배가 되는 것을 확인했다. - 제프 서덜런드
- 개발 자체의 기간은 늘어날 수 있다. (솔직히 작업량이 꽤 생기는거 같음)
- 단, 요구사항을 명확하게 인지하면서 개발하기 때문에 → 불필요한 수정 과정을 줄일 수 있다.
- ATDD는 작업의 명확한 시작과 끝을 제시한다. → 테스트가 성공되는 순간. 작업이 끝나는 것.
- TDD의 부족한 부분 보완 가능
- TDD는 도메인도 개발해나가면 단위테스트로 기능의 수행을 검증하는데 매우 뛰어나지만
- 전체적인 흐름이나 시나리오를 놓치게되는 경우가 생김
- 빠른 피드백
- 구현한 기능을 배포하지 않고 테스트로 확인 가능
→ 인수테스트가 결국 E2E 테스트이기때문에 메모리 디비(H2) 로 내가 수행할려는 상황을 먼저 세팅해주어야 하기 때문에 이부분이 상당히 귀찮았다.
→ 하지만, 그럼에도 불구하고 통합테스트시, post-man 으로 내가 확인하는거보다 코드상으로 남기고, 확인하는게 편할때도 있었다.
→ 📌 코드로 남긴다는게 중요한거 같음
3) ATDD (인수테스트 주도 개발) 프로세스
✔️ 요구사항 분석 → 인수조건 도출 → 문서화 → 인수 테스트 → 로직 구현 → 단위테스트 → 로직 구현(반복) → 인수테스트 검증
(예시)
인수 조건 정의
- 사용자 스토리 (누가/무엇을/왜)
- 인수 테스트가 충족해야하는 조건
- 인수 조건을 표현하는 시나리오 기반 표현 방식 사용(ex. Given/When/Then)
- 인수 조건 작성 방법
- 검증하고자 하는 when 구문 먼저 작성
- 기대 결과를 의미하는 then 구문 작성
- when과 then에 필요한 정보를 given을 통해 제공
/**
* Feature: 지하철 경로 검색
* Scenario: 두 역의 최소 시간 경로를 조회
* Given
* 지하철역이 등록되어있음 And 지하철 노선이 등록되어있음 And 지하철 노선에 지하철역이 등록되어있음
* When
* 출발역에서 도착역까지의 최소 시간 기준으로 경로 조회를 요청
* Then
* 최소 시간 기준 경로를 응답 And 총 거리와 소요 시간을함께 응답함 And 지하철 이용 요금도 함께 응답함
*/
인수 테스트 작성
- 인수 조건을 검증하는 테스트
- 실제 요청/응답 환경과 유사하게 테스트 환경 구성
@DisplayName("두 역의 최소 시간 경로 조회")
@Test
void findPathByDuration() {
//given
교대역 = 지하철역_생성_요청("교대역").jsonPath().getLong("id");
강남역 = 지하철역_생성_요청("강남역").jsonPath().getLong("id");
양재역 = 지하철역_생성_요청("양재역").jsonPath().getLong("id");
남부터미널역 = 지하철역_생성_요청("남부터미널역").jsonPath().getLong("id");
이호선 = 지하철_노선_생성_요청_후_id_추출("2호선", "green", 교대역, 강남역, 10, 30);
신분당선 = 지하철_노선_생성_요청_후_id_추출("신분당선", "red", 강남역, 양재역, 10, 10);
삼호선 = 지하철_노선_생성_요청_후_id_추출("3호선", "orange", 교대역, 남부터미널역, 2, 20);
지하철_노선에_지하철_구간_생성_요청(삼호선, createSectionCreateParams(남부터미널역, 양재역, 3, 30));
// when
var response = 두_역의_타입에따른_경로_조회를_요청(교대역, 양재역, PathType.DURATION.name());
// then
assertThat(response.jsonPath().getList("stations.id", Long.class)).containsExactly(교대역, 강남역, 양재역);
assertThat(response.jsonPath().getInt("distance")).isEqualTo(20);
assertThat(response.jsonPath().getInt("duration")).isEqualTo(40);
assertThat(response.jsonPath().getInt("fare")).isEqualTo(DEFAULT_FARE + 200);
}
4) ATDD 테스트 도구
Spring Boot Test
- 테스트에 사용할 ApplicationContext를 쉽게 지정하게 도와줌 → 실제 어플리케이션에 등록된 빈을 테스트 환경에서도 쓸 수 있게 해준다.
- 기존 @ContextConfiguration 의 발전된 기능
- SpringApplication에서 사용하는 ApplicationContext 를 생성해서 작동
- 참고 : [Spring] 테스트 환경 격리 시키기
RestAssured
- REST-assured는 Rest API 의 테스트 도구
- 지금까지 MockMvc만 썻는데, RestAssured가 가독성과 문서화에서의 중복제거면에서는 훨씬 좋았다.
JsonPath
- RestAssured랑 같이 사용하면 불필요한 Response 객체를 만들 필요성이 사라짐
2. 관리 의존성 vs 비관리 의존성
관리 의존성
- 의존하는 대상이 어플리케이션 내부에서만 접근할 수 있는 경우
- 내 어플리케이션이 관리할 수 있기 떄문에 관리 의존성 !
비관리 의존성
- 의존하는 대상이 내부 뿐만 아니라 외부에서도 접근이 가능한 경우 → 비관리 의존성의 경우 테스트가 매우 힘듬
- 👏🏻 강의에서는 비관리 의존성은 대체(mocking)을 관리 의존성은 실제 협력객체를 추천한다고 함
의존성 테스트 방법
- 실제 외부 의존성 사용
- 비관리 의존성은 실제 외부 의존성을 사용할 경우 속도도 느리고, 외부 동작에 의존적인 테스트가 됨
- 실제 의존이 불가능 하기도 함 → 결제 테스트
- Fake
- ex 깃허브 로그인
- 깃허브 로그인 시 호출하는 외부 API를 실제 깃허브에 보내지 않음
- 테스트용 properties를 이용하여 테스트 서버에 요청 보내게 하기
- ex 깃허브 로그인
- Stub
3. 리팩토링의 원칙
- 인수테스트가 있으면 → 리팩토링 하다가 hot fix 처리건이 와도 안전하게 인수테스트가 성공했던 시점의 커밋으로 언제든 돌아올 수 있다.
- 인수테스트가 없다면 → 인수테스트를 작성하고 → 리팩토링 하고자하는 프로덕션 코드의 단위테스트를 수정해야한다.
- 프로덕션 코드를 보호하는 단위테스트를 유지하기 위해 (복붙) 을 추천
TDD 사이클
- 구조를 설계하기
- 요구사항에 맞춰 구조를 설계하는게 먼저이다. (테스트 전에 요구사항 기반으로 설계가되어야한다.)
- 그런 다음 확장성을 고려하여 구조를 설계하는데 → 이때 TDD 가 큰 도움이 된다.
- 새로운 테스트 만들기
- 기존 프로덕션 코드와, 테스트 코드를 두고 새로운 테스트 코드를 만든다.
- 기능 구현하기 (테스트 성공 후 리팩터링)
- 새로운 테스트코드를 먼저 작성하고 → 테스트에 성공하는 코드로 리팩토링한다
4. 커밋 작게 쪼개기
미션을 진행하면서, 리뷰어님의 리뷰를 받기위해 반나절~하루를 기다려야하기 때문에
한번 받을때 알차게(?) 리뷰를 받고싶었습니다
📌 커밋에 대해서 크게 신경써본적이 없어서 그냥저냥 커밋 컨벤션만 맞춰서 작업이 끝나면 일괄적으로 파일만 나눠서 아래처럼 커밋을하는 버릇이 있었는데
리뷰할떄 내 개발흐름을 보여줄 수 있으면 리뷰어님들도 리뷰하기 편하지 않을까?
더 좋은 리뷰를 받을 수 있지 않을까? 라는 생각에 커밋 잘하기를 시도해 보았습니다.
- 커밋을 작은 단위로
- 작업 끝 커밋이 아닌 → 개발 도중도중 커밋
- 내 개발 흐름을 알 수 있도록 번호 붙히기
↓
👏🏻 훨씬 깔끔하고 보기 좋은 커밋이 된거 같습니당
점진적으로 커밋을 작게 → 흐름을 알 수있도록 개선해 나갔는데
"커밋 내역에 따라, 더 자세하고 소프트적인 리뷰를 받을 수 있었습니다 (느낌적인 느낌?)"
+ PR 잘보내기
미션이 진행되고 과제가 어려워질수록 좋은 리뷰를 받기위해, PR 도 신경써서 보내게 되었습니다.
- 처음에는 "PR 후 → 리뷰를 받으면 궁금한 점 질문" 이런식이여서 답답한감이 있었습니다.
- 그래서 추후에는 → PR 자체가 하나의 리포트인 것처럼 먼저 궁금한 부분이나 봐줬으면 좋겠다 싶은 부분에 코멘트를 남겨놓았습니다
+
❗️추가적으로 ATDD 교육의 장점 중 하나가 같은 요구사항을 수행하는 다른 개발자분들을 PR 훔쳐보기(?) 인데
취준때 같이 스파르타 부트캠프를 진행했던분의 PR 을 보고 많은 반성을 하게 되었다.(링크)
이런 PR 을 받으면 진짜 리뷰할 맛 나고,,, 너무 좋을거같다는 생각이 들었고,, 이런게 같이 일하고싶은 개발자겠구나 생각이 들었다.. 배우자
3. 회고 KPT
Keep
- 이 교육이 시작한다고 떴을 때. 여유로운 상황이 아니였기 때문에 할까말까 망설이다 냅다 결제부터 했는데, 참 잘한거 같다
- 망설이다가 또 못들었으면 다음 교육도 못들었을거라는 확신이 든다.
- 역시 무서워도 도전해야, 죽이되든 밥이되든 결과가 나오는 것 같다.
- 아무것도 하지않으면 아무일도 일어나지 않으니,, 앞으로도 냅다 갈겨버리자!
2. 솔직히 미션하다가,, 나쁜마음 계속 들었는데, 그래도 계속 계속 조금씩 커밋했다.
- 끝까지 해서 수료하니까 얻어갈 수 있는게 참 많이 생겼다.
- ex) "이거 리뷰 다 반영해야할까..? 귀찮은데... 어려울거같은데.. 내가 한 방법도 리뷰어님이 틀린건 아니라고 했는데,,"
Problem
- 없다! 열심히 했고 재밌게 했다!
- 굳이 아쉬운 점을 뽑자면, 매주 배운것을 정리하지 못했다는 점?
- 하지만 체력이 안되었던 걸!
Try
- 기억은 금방 사라진다. 잊기 전에 블로그에 잘 정리하자 꼭!
- 인수테스트는 도구일 뿐! 내 코드에 필요한 부분 잘 생각해서 적용해보자, 안 써도 문제는 없지만 썻을 때 편한점도 느꼈잖아?!
- 커밋 쪼개는 습관 앞으로도 잊지말고 들이자
- 돈 많이 벌어서 인프라공방도 수강하자~~ 끝!
2023-06-26(월) ~ 2023-08-09(수) 꽉 채워 겨우 수료해서 받은 나의 수료증! 야호
'회고 > 일상 후기 회고' 카테고리의 다른 글
[회고] "간헐적 메모리 장애" 삽질부터 트러블 슈팅까지 (10) | 2023.11.02 |
---|---|
[YOUTHCON'23] 유스콘 2023 오프라인 참가 후기 (2) | 2023.08.28 |
2022년 회고. 26살, 내가 개발자가 되기까지의 기록 (7) | 2023.01.25 |
모의면접 (0) | 2021.12.04 |
데브코스에 떨어졌다. 나만의 일정을 계획하자 (0) | 2021.07.28 |