├── .gitignore ├── README.md ├── codereview ├── README.md ├── images │ ├── add_commit_1.png │ ├── add_commit_2.png │ ├── add_upstream.png │ ├── approve_pr.png │ ├── checkout_delete.png │ ├── checkout_step1.png │ ├── checkout_step2.png │ ├── clone_repository.png │ ├── create_branch.png │ ├── etc │ │ ├── branch_github.png │ │ ├── create_branch.png │ │ ├── fork.png │ │ ├── fork_main_check.png │ │ ├── import1.png │ │ ├── import2.png │ │ ├── my_mission_repository.png │ │ ├── no_branch_github.png │ │ ├── pull_request_1.png │ │ ├── pull_request_2.png │ │ ├── request_review.png │ │ └── start_mission.png │ ├── fetch_upstream.png │ ├── fork_my_repo.png │ ├── no_branch.png │ ├── pull_request.png │ ├── push1.png │ ├── push2.png │ └── rebase_upstream.png ├── review-step1.md ├── review-step2.md └── review-step3.md ├── ent-precourse ├── README.md └── images │ ├── add_commit.png │ ├── checkout_javajigi.png │ ├── clone_repository.png │ ├── fork.png │ ├── fork_my_repo.png │ ├── import1.png │ ├── import2.png │ ├── pull_request.png │ ├── pull_request_1.png │ ├── pull_request_2.png │ └── push.png ├── playground ├── README.md └── images │ ├── add_commit.png │ ├── checkout_javajigi.png │ ├── clone_repository.png │ ├── fork.png │ ├── fork_my_repo.png │ ├── import.png │ ├── mission_baseball.png │ └── push.png ├── precourse ├── README.md └── images │ ├── add_commit.png │ ├── checkout_javajigi.png │ ├── clone_repository.png │ ├── fork.png │ ├── fork_my_repo.png │ ├── import1.png │ ├── import2.png │ ├── precourse_apply_01.jpeg │ ├── precourse_apply_02.jpeg │ ├── pull_request.png │ ├── pull_request_1.png │ ├── pull_request_2.png │ └── push.png ├── reviewguide ├── README.md ├── atdd-spring │ ├── acceptance-test-auth.md │ ├── acceptance-test-refactoring.md │ ├── acceptance-test-tdd.md │ └── acceptance-test.md ├── career-nextstep │ └── README.md ├── cleancode │ ├── README.md │ ├── bowling.md │ ├── feedback │ │ ├── README.md │ │ ├── class.md │ │ ├── constant.md │ │ ├── enum.md │ │ ├── function.md │ │ ├── naming.md │ │ └── test.md │ ├── ladder.md │ ├── lms.md │ ├── lotto.md │ └── racingcar.md ├── flutter-begin │ ├── card-flip.md │ ├── movie-list.md │ └── sample.md ├── fw-java │ ├── README.md │ ├── aop.md │ ├── di.md │ ├── library.md │ ├── mvc.md │ └── was.md ├── greetings.md ├── infra-workshop │ ├── README.md │ ├── kubernetes.md │ ├── monitoring.md │ ├── performance-refactoring.md │ └── subway-deploy.md ├── kakao │ ├── README.md │ ├── lotto.md │ ├── racingcar.md │ ├── roomesacape-auth.md │ ├── roomesacape-reservation.md │ ├── roomesacape-waiting.md │ └── was.md ├── review_process.png ├── spring-learning-test │ ├── spring-cart.md │ ├── spring-racingcar.md │ ├── spring-roomescape-waiting.md │ ├── spring-roomescape-member.md │ ├── spring-roomescape-reservation.md │ └── spring-subway.md └── wootecamp-pro │ ├── README.md │ ├── acceptance-test.md │ ├── atdd-tdd.md │ ├── jpa.md │ ├── legacy-code-refactoring.md │ ├── lotto.md │ ├── monitoring.md │ ├── performance-refactoring.md │ └── subway-deploy.md └── settings ├── img.png ├── img_1.png ├── img_2.png ├── img_3.png ├── img_4.png ├── img_5.png └── slack.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.code-workspace 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NEXTSTEP 코드 리뷰 문서 2 | 3 | --- 4 | ## [NEXTSTEP의 온라인 코드 리뷰 과정](./codereview/README.md) 5 | 6 | --- 7 | ## [NEXTSTEP 플레이그라운드의 미션 진행 과정](./playground/README.md) 8 | 9 | --- 10 | ## [NEXTSTEP의 프리코스 과제 제출 방법](./precourse/README.md) 11 | -------------------------------------------------------------------------------- /codereview/README.md: -------------------------------------------------------------------------------- 1 | ## 코드리뷰 요청을 위한 준비사항 2 | 3 | --- 4 | #### git 터미널 환경 세팅 5 | - 윈도우즈 운영체제 사용자: [git for windows](https://gitforwindows.org/)를 설치 6 | - 맥 운영체제 사용자 7 | - 터미널을 실행한 후 `git --version` 명령을 실행한다. 8 | - git이 설치되어 있지 않으면 git을 설치할 것인지 물어보는 화면세어 설치 버튼을 클릭해 설치하면 된다. 9 | - [맥에 Git 설치하기](http://bkcarrier.tistory.com/35) 문서 참고 10 | 11 | --- 12 | ## 동영상으로 살펴보는 코드리뷰 요청 단계 13 | 14 | #### 코드리뷰 요청 1단계 - 미션 진행 후 github에 올리는 단계 15 | [![코드리뷰 요청 1단계](https://img.youtube.com/vi/YkgBUt7zG5k/0.jpg)](https://youtu.be/YkgBUt7zG5k) 16 | 17 | #### 코드리뷰 요청 2단계 - 코드리뷰 요청을 보내고, 피드백을 받은 후 피드백 반영 및 merge하는 단계 18 | [![코드리뷰 요청 2단계](https://img.youtube.com/vi/HnTdFJd0PtU/0.jpg)](https://youtu.be/HnTdFJd0PtU) 19 | 20 | #### 코드리뷰 요청 3단계 - 다음 단계 미션을 위해 준비하는 단계 21 | [![코드리뷰 요청 3단계](https://img.youtube.com/vi/fzrT3eoecUw/0.jpg)](https://youtu.be/fzrT3eoecUw) 22 | 23 | --- 24 | ## 텍스트와 이미지로 살펴보는 코드리뷰 요청 단계 25 | - [코드리뷰 요청 1단계](./review-step1.md): 미션 진행 후 github에 올리는 단계 26 | - [코드리뷰 요청 2단계](./review-step2.md): 코드리뷰 요청을 보내고, 피드백을 받은 후 피드백 반영 및 merge하는 단계 27 | - [코드리뷰 요청 3단계](./review-step3.md): 다음 단계 미션을 위해 준비하는 단계 28 | -------------------------------------------------------------------------------- /codereview/images/add_commit_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/add_commit_1.png -------------------------------------------------------------------------------- /codereview/images/add_commit_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/add_commit_2.png -------------------------------------------------------------------------------- /codereview/images/add_upstream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/add_upstream.png -------------------------------------------------------------------------------- /codereview/images/approve_pr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/approve_pr.png -------------------------------------------------------------------------------- /codereview/images/checkout_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/checkout_delete.png -------------------------------------------------------------------------------- /codereview/images/checkout_step1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/checkout_step1.png -------------------------------------------------------------------------------- /codereview/images/checkout_step2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/checkout_step2.png -------------------------------------------------------------------------------- /codereview/images/clone_repository.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/clone_repository.png -------------------------------------------------------------------------------- /codereview/images/create_branch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/create_branch.png -------------------------------------------------------------------------------- /codereview/images/etc/branch_github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/etc/branch_github.png -------------------------------------------------------------------------------- /codereview/images/etc/create_branch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/etc/create_branch.png -------------------------------------------------------------------------------- /codereview/images/etc/fork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/etc/fork.png -------------------------------------------------------------------------------- /codereview/images/etc/fork_main_check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/etc/fork_main_check.png -------------------------------------------------------------------------------- /codereview/images/etc/import1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/etc/import1.png -------------------------------------------------------------------------------- /codereview/images/etc/import2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/etc/import2.png -------------------------------------------------------------------------------- /codereview/images/etc/my_mission_repository.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/etc/my_mission_repository.png -------------------------------------------------------------------------------- /codereview/images/etc/no_branch_github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/etc/no_branch_github.png -------------------------------------------------------------------------------- /codereview/images/etc/pull_request_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/etc/pull_request_1.png -------------------------------------------------------------------------------- /codereview/images/etc/pull_request_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/etc/pull_request_2.png -------------------------------------------------------------------------------- /codereview/images/etc/request_review.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/etc/request_review.png -------------------------------------------------------------------------------- /codereview/images/etc/start_mission.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/etc/start_mission.png -------------------------------------------------------------------------------- /codereview/images/fetch_upstream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/fetch_upstream.png -------------------------------------------------------------------------------- /codereview/images/fork_my_repo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/fork_my_repo.png -------------------------------------------------------------------------------- /codereview/images/no_branch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/no_branch.png -------------------------------------------------------------------------------- /codereview/images/pull_request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/pull_request.png -------------------------------------------------------------------------------- /codereview/images/push1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/push1.png -------------------------------------------------------------------------------- /codereview/images/push2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/push2.png -------------------------------------------------------------------------------- /codereview/images/rebase_upstream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/codereview/images/rebase_upstream.png -------------------------------------------------------------------------------- /codereview/review-step1.md: -------------------------------------------------------------------------------- 1 | ## 온라인 코드리뷰 요청 1단계 2 | 코드리뷰 1단계는 미션을 시작, 개발 환경을 구축, 1단계 미션 완료, push를 보내는 단계까지의 과정을 다룬다. 3 | 4 | --- 5 | 1. 미션을 시작한다. 6 | - NextStep(https://edu.nextstep.camp) 에 접속해 진행하려는 미션으로 이동한다. **미션 시작*- 버튼을 클릭한다. 7 | 8 | ![start mission](./images/etc/start_mission.png) 9 | 10 | - 미션을 시작하는 순간 미션 저장소에 자신의 github id 계정에 해당하는 브랜치가 생성되고 리뷰어가 배정된다. 11 | - **나의 미션*- 버튼을 클릭해 미션을 진행할 수 있는 저장소로 이동한다. 12 | 13 | ![my mission repository](./images/etc/my_mission_repository.png) 14 | 15 | - 자신의 github 계정 브랜치가 생성되어 있으면 다음과 같이 검색이 되어야 한다. 16 | 17 | ![no branch](./images/etc/branch_github.png) 18 | 19 | - 브랜치를 생성한 후 상태는 다음과 같다. 20 | 21 | ![create branch](./images/create_branch.png) 22 | 23 | --- 24 | 2. 프로젝트를 자신의 계정으로 fork한다. 저장소 우측 상단의 fork 버튼을 활용한다. 25 | > next-step 저장소는 권한이 없기 때문에 미션을 진행한 코드를 추가할 수 없다. 26 | > 27 | > fork는 next-step의 저장소를 자신의 계정으로 복사하는 기능이다. 앞으로 모든 미션은 자신의 계정 아래에 있는 저장소를 활용해 진행한다. 28 | 29 | - fork는 next-step 저장소 우측 상단의 fork 버튼을 활용한다. 30 | 31 | ![fork](./images/etc/fork.png) 32 | 33 | - fork를 완료한 후의 상태는 다음과 같다. 34 | 35 | ![fork my repo](./images/fork_my_repo.png) 36 | 37 | --- 38 | 3. fork한 저장소를 자신의 컴퓨터로 clone한 후 디렉토리로 이동한다. 39 | > fork한 저장소는 github.com에 존재하기 때문에 바로 작업할 수 있다. 40 | > 41 | > clone 명령은 github.com에 존재하는 저장소를 자신의 노트북 또는 PC로 복사하는 과정이다. 42 | 43 | - 터미널에서 다음 명령을 입력한다. 44 | 45 | ``` 46 | git clone -b {본인_아이디} --single-branch https://github.com/{본인_아이디}/{저장소 아이디} 47 | ex) git clone -b javajigi --single-branch https://github.com/javajigi/java-racingcar 48 | ``` 49 | ``` 50 | // clone한 폴더로 이동하는 방법 51 | cd {저장소 아이디} 52 | ex) cd java-racingcar 53 | ``` 54 | 55 | - 만약 fork시 아래의 체크박스를 선택했다면 main 브랜치만 받아오게 된다. 이 경우, fork 후 깃헙 저장소에서 본인 아이디로 branch를 생성해준다. 56 | 57 | ![check main branch](./images/etc/fork_main_check.png) 58 | 59 | ![create branch](./images/etc/create_branch.png) 60 | 61 | 62 | - clone을 완료한 후의 상태는 다음과 같다. 63 | 64 | ![clone repository](./images/clone_repository.png) 65 | 66 | --- 67 | 4. 기능 구현을 위한 브랜치 생성 68 | > git은 서로 다른 작업을 하기 위한 별도의 공간을 생성할 때 브랜치를 생성할 수 있다. 69 | > 70 | > 브랜치를 생성하는 이유는 실무에서 프로젝트를 진행할 때와 같은 방법으로 기능을 구현하고, 리뷰하는 경험을 전달하기 위함이다. 71 | 72 | - 터미널에서 다음 명령을 입력해 브랜치를 생성한다. 73 | 74 | ``` 75 | git checkout -b 브랜치이름 76 | ex) git checkout -b step1 77 | ``` 78 | 79 | - 브랜치를 생성한 후의 상태는 다음과 같다. 80 | 81 | ![checkout step1](./images/checkout_step1.png) 82 | 83 | --- 84 | 5. 통합개발도구(Eclipse 또는 IntelliJ)로 가져오기(import) 85 | > 미션 진행을 위해 자신이 사용하고 있는 통합개발도구로 가져오기 한다. 이 문서는 IntelliJ를 기준으로 한다. 86 | 87 | - IntelliJ를 시작 88 | - 다음 화면에서 Import Project 89 | 90 | ![import1](./images/etc/import1.png) 91 | 92 | - 앞에서 clone한 폴더를 선택한다. 93 | - 다음 화면과 같이 "Import Project from external model" 선택 -> Gradle을 선택 -> Next 94 | 95 | ![import2](./images/etc/import2.png) 96 | 97 | - 다음 화면에서 Finish 버튼을 클릭해 가져오기를 완료한다. 98 | 99 | --- 100 | 6. 기능 구현 101 | > [edu.nextstep.camp](https://edu.nextstep.camp) 에서 미션 요구사항을 파악해 기능을 구현한다. 102 | 103 | --- 104 | 7. 기능 구현 후 add, commit 105 | > 기능 구현을 완료한 후 로컬 저장소에 변경된 부분을 반영하기 위해 add, commit 명령을 사용한다. 106 | 107 | ``` 108 | git status // 변경된 파일 확인 109 | git add -A(또는 .) // 변경된 전체 파일을 한번에 반영 110 | git commit -m "메시지" // 작업한 내용을 메시지에 기록 111 | ``` 112 | 113 | - 기능 구현을 완료하고 add, commit 명령을 실행한 후의 상태는 다음과 같다. 114 | 115 | ![add commit1](./images/add_commit_1.png) 116 | 117 | --- 118 | 8. 본인 원격 저장소에 올리기 119 | > 로컬에서 commit 명령을 실행하면 로컬 저장소에만 반영되고, 원격 github.com의 저장소에는 반영되지 않는다. 120 | 121 | ``` 122 | git push origin 브랜치이름 123 | ex) git push origin step1 124 | ``` 125 | 126 | - push 명령을 실행한 후의 상태는 다음과 같다. 127 | 128 | ![push1](./images/push1.png) 129 | 130 | ## 1단계를 모두 완료하면 [코드리뷰 요청 2단계](./review-step2.md) 를 진행한다. -------------------------------------------------------------------------------- /codereview/review-step2.md: -------------------------------------------------------------------------------- 1 | ## 온라인 코드리뷰 요청 2단계 2 | 코드리뷰 2단계는 pull request를 통해 코드 리뷰 요청을 한 후 피드백을 받고, 피드백을 반영하는 과정을 다룬다. 3 | 4 | --- 5 | 1. github 서비스에서 pull request를 보낸다. 6 | > pull request는 github에서 제공하는 기능으로 코드리뷰 요청을 보낼 때 사용한다. 7 | > 8 | > pull request는 original 저장소(next-step의 저장소)의 브랜치(자신의 github 아이디)와 앞 단계에서 생성한 브랜치 이름(앞 단계의 예에서는 step1)을 기준으로 한다. 9 | 10 | ``` 11 | ex) 미션을 진행한 javajigi/java-racingcar step1 브랜치 => next-step/java-racingcar javajigi 브랜치로 pull request를 보낸다. 12 | ``` 13 | 14 | - 브라우저에서 github 저장소에 접근한다. 15 | - 브랜치를 작업 브랜치로 변경한다(앞 단계의 예에서는 step1). 16 | - 브랜치 오른쪽에 있는 "New pull request" 버튼을 클릭한다. 17 | 18 | ![pull request 보내기](./images/etc/pull_request_1.png) 19 | 20 | - 왼쪽 next-step 저장소의 브랜치를 자신의 github 계정 브랜치로 변경한다. 21 | - 현재 미션에서 작업한 내용을 입력하고 "Create pull request" 버튼을 클릭해 pull request를 보낸다. 22 | 23 | ![pull request 브랜치 변경](./images/etc/pull_request_2.png) 24 | 25 | - pull request를 보냈을 때의 상태는 다음과 같다. 26 | 27 | ![pull request](./images/pull_request.png) 28 | 29 | --- 30 | 2. pull request를 보낸 후 리뷰어에게 리뷰 요청을 한다. 31 | - NextStep(https://edu.nextstep.camp) 에 접속해 자신이 수강하고 있는 강의로 이동한다. 32 | - 우측 상단의 `리뷰 요청` 클릭하면 자신에게 배정된 리뷰어에게 리뷰 요청 알림이 간다. 33 | 34 | ![리뷰어에게 리뷰 요청](./images/etc/request_review.png) 35 | 36 | - 리뷰 요청이 정상적으로 동작하면 리뷰어에게 slack으로 알림 요청이 간다. 37 | 38 | --- 39 | 3. pull request에 대해 승인이 되지 않고 수정 요청 피드백을 받으면 피드백 받은 내용을 반영한다. 만약, pull request가 승인이 되어 next-step 저장소에 통합(merge)이 된다면 [코드리뷰 요청 3단계](./review-step3.md)를 진행한다. 40 | 41 | --- 42 | 4. 피드백을 반영한 후 add, commit, push 명령을 실행한다. 43 | > **pull request를 보내 피드백을 받은 후 add, commit, push를 한 후 새로운 pull request를 보내지 않아도 된다.** 44 | > 45 | > 앞서 보낸 pull request가 통합(merge)되지 않은 상태이기 때문에 같은 pull request를 재활용한다. 46 | 47 | ``` 48 | git status // 변경된 파일 확인 49 | git add -A(또는 .) // 변경된 전체 파일을 한번에 반영 50 | git commit -m "메시지" // 작업한 내용을 메시지에 기록 51 | ``` 52 | 53 | ``` 54 | git push origin 브랜치이름 55 | ex) git push origin step1 56 | ``` 57 | 58 | - 새롭게 add, commit을 진행하는 경우 새로운 버전이 생성되어 상태는 다음과 같다. 59 | 60 | ![add commit2](./images/add_commit_2.png) 61 | 62 | - 새로운 버전을 push한 상태는 다음과 같다. 63 | 64 | ![push2](./images/push2.png) 65 | 66 | --- 67 | 5. 몇 번의 피드백을 주고 받은 후 승인이 되어 next-step 저장소에 통합(merge)이 된다면 [코드리뷰 요청 3단계](./review-step3.md)를 진행한다. 68 | 69 | - pull request가 승인이 되어 통합이 된 후의 상태는 다음과 같다. 70 | 71 | ![approve pr](./images/approve_pr.png) 72 | 73 | ## 2단계를 모두 완료하면 [코드리뷰 요청 3단계](./review-step3.md) 를 진행한다. -------------------------------------------------------------------------------- /codereview/review-step3.md: -------------------------------------------------------------------------------- 1 | ## 온라인 코드리뷰 요청 3단계 2 | 코드리뷰 3단계는 리뷰 요청을 보낸 후 pull request가 next-step으로 통합(merge)된 이후의 과정을 다룬다. 3 | 4 | --- 5 | 1. merge를 완료했다는 통보를 받으면 브랜치 변경 및 작업 브랜치 삭제(option)한다. 6 | > 강사에게 승인 후 merge를 완료했다는 통보를 받으면 해당 미션은 완료한 상태가 된다. 7 | > 8 | > 현재 미션을 완료했기 때문에 미션을 진행한 브랜치를 삭제하고 다음 미션을 위한 새로운 브랜치를 생성해야 한다. 9 | 10 | ``` 11 | git checkout 본인_아이디 12 | git branch -D 삭제할_브랜치이름 13 | ex) git checkout javajigi 14 | ex) git branch -D step1 15 | ``` 16 | 17 | - checkout을 통해 브랜치를 변경한 후 작업 브랜치를 삭제한 후의 상태는 다음과 같다. 18 | 19 | ![checkout delete](./images/checkout_delete.png) 20 | 21 | --- 22 | 2. 통합(merge)한 next-step 저장소와 동기화하기 위해 next-step 저장소 추가(최초 한번만) 23 | > 계정 브랜치에서 다음 미션을 이어서 진행하기 위해 브랜치를 생성하려고 한다. 24 | > 25 | > 그런데 로컬 PC의 현재 상태는 최신 코드가 아니기 때문에 미션을 이어서 진행할 수 없다. 따라서 **next-step에 통합(merge)된 코드와 동기화하는 작업을 진행**해야 한다. 26 | 27 | ``` 28 | git remote add {저장소_별칭} base_저장소_url 29 | ex) git remote add upstream https://github.com/next-step/java-racingcar.git 30 | // 위와 같이 next-step 저장소를 추가한 후 전체 remote 저장소 목록을 본다. 31 | git remote -v 32 | ``` 33 | - **git remote add*- 명령은 최초 1회만 진행하면 된다. 34 | 35 | ![add upstream](./images/add_upstream.png) 36 | 37 | --- 38 | 3. next-step 저장소에서 자기 브랜치 가져오기(또는 갱신하기) 39 | > 앞 단계의 `remote add` 명령은 로컬 PC에서 next-step 저장소에 접근할 수 있도록 이름을 부여한 것이다. 앞 단계의 예제는 upstream이라는 이름을 부여했다. 40 | > 41 | > 앞 단계에서 next-step 저장소에 이름을 부여했다면 이번 단계는 fetch 명령으로 동기화하고 싶은 next-step 저장소의 브랜치를 가져오기 해야 한다. 42 | 43 | ``` 44 | git fetch upstream {본인_아이디} 45 | ex) git fetch upstream javajigi 46 | ``` 47 | 48 | - fetch 명령을 실행한 후의 상태를 다음과 같다. 49 | 50 | ![fetch upstream](./images/fetch_upstream.png) 51 | 52 | > fetch 명령을 실행한 후 `git branch -a` 명령을 실행하면 remotes/upstream/javajigi와 같은 브랜치가 생성된 것을 확인할 수 있다. 53 | 54 | --- 55 | 4. next-step 저장소 브랜치와 동기화하기 56 | > 현재 상태는 next-step 저장소 브랜치를 가져오기는 했지만 아직까지 로컬 저장소에 최신 버전의 코드가 반영된 것은 아니다. 57 | > 58 | > rebase 명령을 실행해 next-step 저장소와 로컬 저장소의 브랜치를 동기화한다. 59 | 60 | ``` 61 | git rebase upstream/본인_아이디 62 | ex) git rebase upstream/javajigi 63 | ``` 64 | 65 | - rebase 명령을 실행한 후의 상태는 다음과 같다. 66 | 67 | ![rebase upstream](./images/rebase_upstream.png) 68 | 69 | --- 70 | 5. 새로운 미션을 진행하기 위한 브랜치 생성 71 | > 지금까지 과정을 통해 새로운 작업을 시작하기 위한 준비 작업을 마쳤다. 72 | > 73 | > 다음 단계는 [코드리뷰 요청 1단계](./review-step1.md)의 4번 항목의 checkout 명령으로 새로운 브랜치를 생성한다. 74 | 75 | ``` 76 | git checkout -b 브랜치이름 77 | ex) git checkout -b step2 78 | ``` 79 | 80 | - checkout 명령으로 새로운 브랜치를 생성한 후의 상태는 다음과 같다. 81 | 82 | ![checkout step2](./images/checkout_step2.png) 83 | 84 | > 다음 단계를 진행하기 위한 모든 준비 작업은 마쳤다. 85 | > 86 | > 지금부터 다음 단계에 도전하면 된다. 다음 단계의 도전이 끝나면 [코드리뷰 요청 1단계](./review-step1.md)의 7번 이후의 add, commit, push를 진행하고, 다시 pull request를 보내면 된다. 87 | > 88 | > 온라인 코드리뷰를 통해 프로그래밍을 즐기는 개발자가 되기를 기대해 본다. 89 | 90 | --- 91 | ## FAQ 92 | 93 | --- 94 | #### PR에서 충돌이 발생하는데 어떻게 해결하면 좋을까요? 95 | > next-step 저장소와 rebase를 하지 않은 상태에서 브랜치를 생성했더니 충돌이 발생하고 있어요. 96 | > 97 | > 충돌을 해결하려면 어떻게 해야 하나요? 98 | 99 | - `git checkout 본인_아이디`(예: git checkout javajigi) 명령을 실행해 계정 브랜치로 이동한다. 100 | - `git reset --hard upstream/본인_아이디`(예: git reset --hard upstream/javajigi) 101 | - `git checkout 기능_브랜치`(예: git checkout step2) 102 | - `git merge 본인_아이디`(예: git merge javajigi) 103 | 104 | 위 명령을 실행하면 충돌이 발생할 것이다. 충돌을 해결한 후 add, commit, push를 진행하면 PR 충돌이 해결되어 리뷰 요청을 할 수 있다. 105 | -------------------------------------------------------------------------------- /ent-precourse/README.md: -------------------------------------------------------------------------------- 1 | ## 프리코스 과제 제출 2 | 3 | --- 4 | 1. 프로젝트를 자신의 계정으로 fork한다. 저장소 우측 상단의 fork 버튼을 클릭해 fork한다. 5 | > next-step organization에 존재하는 저장소에 코드를 추가할 권한이 없기 때문에 구현한 코드를 추가할 수 없다. 6 | > 7 | > fork는 next-step organization의 저장소를 자신의 계정으로 복사하는 기능이다. 앞으로 모든 미션은 자신의 계정 아래에 있는 저장소를 활용해 진행한다. 8 | 9 | 다음 그림과 같이 next-step organization 저장소 우측 상단의 fork 버튼을 클릭해 fork한다. 10 | ![fork](./images/fork.png) 11 | 12 | fork를 완료한 후의 저장소 상태는 다음과 같다. 13 | ![fork my repo](./images/fork_my_repo.png) 14 | 15 | --- 16 | 2. fork한 저장소를 자신의 컴퓨터로 clone한 후 폴더로 이동한다. 17 | > fork한 저장소는 github.com에 존재하기 때문에 소스 코드를 추가하고, 수정하는 작업을 할 수 없다. 18 | > 19 | > clone 명령은 github.com에 존재하는 저장소를 자신의 노트북 또는 PC로 복사하는 과정이다. 20 | 21 | 터미널에서 다음 명령을 입력한다. 22 | 23 | ``` 24 | git clone https://github.com/{본인_아이디}/{저장소 아이디}.git 25 | ex) git clone https://github.com/next-step/java-baseball.git 26 | ``` 27 | 28 | ``` 29 | // clone한 폴더로 이동하는 방법 30 | cd {저장소 아이디} 31 | ex) cd java-baseball 32 | ``` 33 | 34 | clone을 완료한 후의 저장소 상태는 다음과 같다. 35 | ![clone repository](./images/clone_repository.png) 36 | 37 | --- 38 | 3. 기능 구현을 위한 브랜치 생성 39 | > git은 서로 다른 작업을 하기 위한 별도의 공간을 생성할 때 브랜치를 생성할 수 있다. 40 | 41 | 터미널에서 다음 명령을 입력해 브랜치를 생성한다. 42 | 43 | ``` 44 | git checkout -b 브랜치이름 45 | ex) git checkout -b javajigi 46 | ``` 47 | 48 | 브랜치를 생성한 후의 상태는 다음과 같다. 49 | ![checkout javajigi](./images/checkout_javajigi.png) 50 | 51 | --- 52 | 4. 통합개발도구(Eclipse 또는 IntelliJ)로 가져오기(import) 53 | > 미션 진행을 위해 자신이 사용하고 있는 통합개발도구로 가져오기 한다. 이 문서는 IntelliJ를 기준으로 한다. 54 | 55 | * IntelliJ를 시작 56 | * 다음 화면에서 Import Project 57 | 58 | ![import1](./images/import1.png) 59 | 60 | * 앞에서 clone한 폴더를 선택한다. 61 | * 다음 화면과 같이 "Import Project from external model" 선택 -> Gradle을 선택 -> Next 62 | 63 | ![import2](./images/import2.png) 64 | 65 | * 다음 화면에서 Finish 버튼을 클릭해 가져오기를 완료한다. 66 | 67 | --- 68 | 5. 기능 구현 69 | > 미션 요구사항을 파악해 기능을 구현한다. 70 | 71 | --- 72 | 6. 기능 구현 후 add, commit 73 | > 기능 구현을 완료한 후 로컬 저장소에 변경된 부분을 반영하기 위해 add, commit 명령을 사용한다. 74 | 75 | ``` 76 | git status // 변경된 파일 확인 77 | git add -A(또는 .) // 변경된 전체 파일을 한번에 반영 78 | git commit -m "메시지" // 작업한 내용을 메시지에 기록 79 | ``` 80 | 81 | 기능 구현을 완료하고 add, commit 명령을 실행한 후의 상태는 다음과 같다. 82 | ![add commit1](./images/add_commit.png) 83 | 84 | --- 85 | 7. 본인 원격 저장소에 올리기 86 | > 로컬에서 commit 명령을 실행하면 로컬 저장소에만 반영되고, 원격 github.com의 저장소에는 반영되지 않는다. 87 | 88 | ``` 89 | git push origin 브랜치이름 90 | ex) git push origin javajigi 91 | ``` 92 | 93 | push 명령을 실행한 후의 상태는 다음과 같다. 94 | ![push1](./images/push.png) 95 | 96 | --- 97 | 8. github 서비스에서 pull request를 보낸다. 98 | > pull request는 github에서 제공하는 기능으로 코드리뷰 요청을 보낼 때 사용한다. 99 | > 100 | > pull request는 original 저장소(next-step organization의 저장소)의 master 브랜치와 앞 단계에서 생성한 브랜치 이름(앞 단계의 예에서는 javajigi)을 기준으로 한다. 101 | 102 | ``` 103 | ex) 미션을 진행한 javajigi/java-baseball javajigi 브랜치 => next-step/java-baseball master 브랜치로 pull request를 보낸다. 104 | ``` 105 | 106 | * 브라우저에서 github 저장소에 접근한다. 107 | * 브랜치를 작업 브랜치로 변경한다(앞 단계의 예에서는 javajigi). 108 | * 브랜치 오른쪽에 있는 "New pull request" 버튼을 클릭한다. 109 | 110 | ![pull request 보내기](./images/pull_request_1.png) 111 | 112 | * 현재 미션에서 작업한 내용을 입력하고 "Create pull request" 버튼을 클릭해 pull request를 보낸다. 113 | 114 | ![pull request 브랜치 변경](./images/pull_request_2.png) 115 | 116 | pull request를 보냈을 때의 상태는 다음과 같다. 117 | ![pull request](./images/pull_request.png) 118 | 119 | --- 120 | 9. 이메일 보내 과제 최종 제출하기 121 | 앞 단계에서 Pull Request를 보낸 후 다음 양식으로 작성해 edu.nextstep@gmail.com 으로 메일을 보낸다. 122 | 123 | #### 메일 템플릿 124 | ``` 125 | 제목 : [$이름] 프리코스 미션 제출합니다. 126 | 내용 : 127 | 다음 두 개의 정보를 반드시 포함해 메일을 보낸다. 128 | 129 | * Pull Request URL: 130 | 131 | 미션을 진행하면서 느끼고, 배운점, 많은 시간을 투자한 부분 등도 포함하면 더 좋을 것 같아요. 132 | ``` 133 | 134 | --- 135 | #### 메일 예시 136 | ``` 137 | 제목 : [박재성] 프리코스 미션 제출합니다. 138 | 내용 : 139 | 안녕하세요. 140 | 이번 미션 생각보다 쉽지 않네요. 141 | 특히 기능을 분리하고 기능 단위로 commit하는 것이 쉽지 않다는 것을 느꼈어요. 142 | 하지만 기능을 분리하고 구현했더니 더 명확하게 구현할 수 있다는 것을 느낄 수 있는 기회가 된 것 같아요. 143 | 144 | * Pull Request URL: https://github.com/next-step/java-baseball/pull/1 145 | ``` 146 | 147 | **Pull Request만 보내고, 메일을 보내지 않으면 미션을 제출하지 않은 것으로 처리되니 착오 없기를 바랍니다.** -------------------------------------------------------------------------------- /ent-precourse/images/add_commit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/ent-precourse/images/add_commit.png -------------------------------------------------------------------------------- /ent-precourse/images/checkout_javajigi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/ent-precourse/images/checkout_javajigi.png -------------------------------------------------------------------------------- /ent-precourse/images/clone_repository.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/ent-precourse/images/clone_repository.png -------------------------------------------------------------------------------- /ent-precourse/images/fork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/ent-precourse/images/fork.png -------------------------------------------------------------------------------- /ent-precourse/images/fork_my_repo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/ent-precourse/images/fork_my_repo.png -------------------------------------------------------------------------------- /ent-precourse/images/import1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/ent-precourse/images/import1.png -------------------------------------------------------------------------------- /ent-precourse/images/import2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/ent-precourse/images/import2.png -------------------------------------------------------------------------------- /ent-precourse/images/pull_request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/ent-precourse/images/pull_request.png -------------------------------------------------------------------------------- /ent-precourse/images/pull_request_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/ent-precourse/images/pull_request_1.png -------------------------------------------------------------------------------- /ent-precourse/images/pull_request_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/ent-precourse/images/pull_request_2.png -------------------------------------------------------------------------------- /ent-precourse/images/push.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/ent-precourse/images/push.png -------------------------------------------------------------------------------- /playground/README.md: -------------------------------------------------------------------------------- 1 | ## 미션 진행 방법 2 | 3 | --- 4 | 1. 프로젝트를 자신의 계정으로 fork한다. 저장소 우측 상단의 fork 버튼을 클릭해 fork한다. 5 | > next-step organization에 존재하는 저장소에 코드를 추가할 권한이 없기 때문에 구현한 코드를 추가할 수 없다. 6 | > 7 | > fork는 next-step organization의 저장소를 자신의 계정으로 복사하는 기능이다. 앞으로 모든 미션은 자신의 계정 아래에 있는 저장소를 활용해 진행한다. 8 | 9 | 다음 그림과 같이 next-step organization 저장소 우측 상단의 fork 버튼을 클릭해 fork한다. 10 | ![fork](./images/fork.png) 11 | 12 | fork를 완료한 후의 저장소 상태는 다음과 같다. 13 | ![fork my repo](./images/fork_my_repo.png) 14 | 15 | --- 16 | 2. fork한 저장소를 자신의 컴퓨터로 clone한 후 폴더로 이동한다. 17 | > fork한 저장소는 github.com에 존재하기 때문에 소스 코드를 추가하고, 수정하는 작업을 할 수 없다. 18 | > 19 | > clone 명령은 github.com에 존재하는 저장소를 자신의 노트북 또는 PC로 복사하는 과정이다. 20 | 21 | 터미널에서 다음 명령을 입력한다. 22 | 23 | ``` 24 | git clone https://github.com/{본인_아이디}/{저장소 아이디}.git 25 | ex) git clone https://github.com/javajigi/java-baseball-playground.git 26 | ``` 27 | 28 | ``` 29 | // clone한 폴더로 이동하는 방법 30 | cd {저장소 아이디} 31 | ex) cd java-baseball-playground 32 | ``` 33 | 34 | clone을 완료한 후의 저장소 상태는 다음과 같다. 35 | ![clone repository](./images/clone_repository.png) 36 | 37 | --- 38 | 3. 미션 진행을 위한 브랜치 생성 39 | > git은 서로 다른 작업을 하기 위한 별도의 공간을 생성할 때 브랜치를 생성할 수 있다. 40 | > 41 | > 추후 피드백을 반영하기 위해 미션을 다시 시작하기 위해 새로운 브랜치를 생성해 미션 진행할 것을 추천한다. 42 | 43 | 터미널에서 다음 명령을 입력해 브랜치를 생성한다. 44 | 45 | ``` 46 | git checkout -b 브랜치이름 47 | ex) git checkout -b javajigi 48 | ``` 49 | 50 | 브랜치를 생성한 후의 상태는 다음과 같다. 51 | ![checkout javajigi](./images/checkout_javajigi.png) 52 | 53 | --- 54 | 4. 통합개발도구(Eclipse 또는 IntelliJ)로 가져오기(import) 55 | > 미션 진행을 위해 자신이 사용하고 있는 통합개발도구로 가져오기 한다. 이 문서는 IntelliJ를 기준으로 한다. 56 | 57 | - IntelliJ를 시작 58 | - 다음 화면에서 Open 버튼을 클릭해 앞에서 clone한 폴더를 선택해 프로젝트를 import한다. 59 | 60 | ![import](./images/import.png) 61 | 62 | --- 63 | 5. 기능 구현 64 | > 미션 요구사항을 파악해 기능을 구현한다. 65 | 66 | --- 67 | 6. 기능 구현 후 add, commit 68 | > 기능 구현을 완료한 후 로컬 저장소에 변경된 부분을 반영하기 위해 add, commit 명령을 사용한다. 69 | 70 | ``` 71 | git status // 변경된 파일 확인 72 | git add -A(또는 .) // 변경된 전체 파일을 한번에 반영 73 | git commit -m "메시지" // 작업한 내용을 메시지에 기록 74 | ``` 75 | 76 | 기능 구현을 완료하고 add, commit 명령을 실행한 후의 상태는 다음과 같다. 77 | ![add commit1](./images/add_commit.png) 78 | 79 | --- 80 | 7. 본인 원격 저장소에 올리기 81 | > 로컬에서 commit 명령을 실행하면 로컬 저장소에만 반영되고, 원격 github.com의 저장소에는 반영되지 않는다. 82 | 83 | ``` 84 | git push origin 브랜치이름 85 | ex) git push origin javajigi 86 | ``` 87 | 88 | push 명령을 실행한 후의 상태는 다음과 같다. 89 | ![push1](./images/push.png) 90 | 91 | --- 92 | ## 학습 효과를 높이기 위해 추천하는 미션 진행 방법 93 | 94 | --- 95 | 1. 피드백 강의 전까지 미션 진행 96 | > 피드백 강의 전까지 혼자 힘으로 미션 진행. 미션을 진행하면서 하나의 작업이 끝날 때 마다 add, commit 97 | > 예를 들어 다음 숫자 야구 게임의 경우 0, 1, 2단계까지 구현을 완료한 후 push 98 | 99 | ![mission baseball](./images/mission_baseball.png) 100 | 101 | --- 102 | 2. 피드백 앞 단계까지 미션 구현을 완료한 후 피드백 강의를 학습한다. 103 | 104 | --- 105 | 3. Git 브랜치를 main으로 변경한 후 피드백을 반영하기 위한 새로운 브랜치를 생성한 후 처음부터 다시 미션 구현을 도전한다. 106 | 107 | ``` 108 | git branch -a // 모든 로컬 브랜치 확인 109 | git checkout main 110 | 111 | git checkout -b 브랜치이름 112 | ex) git checkout -b apply-feedback 113 | ``` 114 | -------------------------------------------------------------------------------- /playground/images/add_commit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/playground/images/add_commit.png -------------------------------------------------------------------------------- /playground/images/checkout_javajigi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/playground/images/checkout_javajigi.png -------------------------------------------------------------------------------- /playground/images/clone_repository.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/playground/images/clone_repository.png -------------------------------------------------------------------------------- /playground/images/fork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/playground/images/fork.png -------------------------------------------------------------------------------- /playground/images/fork_my_repo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/playground/images/fork_my_repo.png -------------------------------------------------------------------------------- /playground/images/import.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/playground/images/import.png -------------------------------------------------------------------------------- /playground/images/mission_baseball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/playground/images/mission_baseball.png -------------------------------------------------------------------------------- /playground/images/push.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/playground/images/push.png -------------------------------------------------------------------------------- /precourse/README.md: -------------------------------------------------------------------------------- 1 | ## 프리코스 과제 제출 2 | 3 | --- 4 | 1. 프로젝트를 자신의 계정으로 fork한다. 저장소 우측 상단의 fork 버튼을 클릭해 fork한다. 5 | > next-step organization에 존재하는 저장소에 코드를 추가할 권한이 없기 때문에 구현한 코드를 추가할 수 없다. 6 | > 7 | > fork는 next-step organization의 저장소를 자신의 계정으로 복사하는 기능이다. 앞으로 모든 미션은 자신의 계정 아래에 있는 저장소를 활용해 진행한다. 8 | 9 | 다음 그림과 같이 next-step organization 저장소 우측 상단의 fork 버튼을 클릭해 fork한다. 10 | ![fork](./images/fork.png) 11 | 12 | fork를 완료한 후의 저장소 상태는 다음과 같다. 13 | ![fork my repo](./images/fork_my_repo.png) 14 | 15 | --- 16 | 2. fork한 저장소를 자신의 컴퓨터로 clone한 후 폴더로 이동한다. 17 | > fork한 저장소는 github.com에 존재하기 때문에 소스 코드를 추가하고, 수정하는 작업을 할 수 없다. 18 | > 19 | > clone 명령은 github.com에 존재하는 저장소를 자신의 노트북 또는 PC로 복사하는 과정이다. 20 | 21 | 터미널에서 다음 명령을 입력한다. 22 | 23 | ``` 24 | git clone https://github.com/{본인_아이디}/{저장소 아이디}.git 25 | ex) git clone https://github.com/next-step/java-baseball.git 26 | ``` 27 | 28 | ``` 29 | // clone한 폴더로 이동하는 방법 30 | cd {저장소 아이디} 31 | ex) cd java-baseball 32 | ``` 33 | 34 | clone을 완료한 후의 저장소 상태는 다음과 같다. 35 | ![clone repository](./images/clone_repository.png) 36 | 37 | --- 38 | 3. 기능 구현을 위한 브랜치 생성 39 | > git은 서로 다른 작업을 하기 위한 별도의 공간을 생성할 때 브랜치를 생성할 수 있다. 40 | 41 | 터미널에서 다음 명령을 입력해 브랜치를 생성한다. 42 | 43 | ``` 44 | git checkout -b 브랜치이름 45 | ex) git checkout -b javajigi 46 | ``` 47 | 48 | 브랜치를 생성한 후의 상태는 다음과 같다. 49 | ![checkout javajigi](./images/checkout_javajigi.png) 50 | 51 | --- 52 | 4. 통합개발도구(Eclipse 또는 IntelliJ)로 가져오기(import) 53 | > 미션 진행을 위해 자신이 사용하고 있는 통합개발도구로 가져오기 한다. 이 문서는 IntelliJ를 기준으로 한다. 54 | 55 | - IntelliJ를 시작 56 | - 다음 화면에서 Import Project 57 | 58 | ![import1](./images/import1.png) 59 | 60 | - 앞에서 clone한 폴더를 선택한다. 61 | - 다음 화면과 같이 "Import Project from external model" 선택 -> Gradle을 선택 -> Next 62 | 63 | ![import2](./images/import2.png) 64 | 65 | - 다음 화면에서 Finish 버튼을 클릭해 가져오기를 완료한다. 66 | 67 | --- 68 | 5. 기능 구현 69 | > 미션 요구사항을 파악해 기능을 구현한다. 70 | 71 | --- 72 | 6. 기능 구현 후 add, commit 73 | > 기능 구현을 완료한 후 로컬 저장소에 변경된 부분을 반영하기 위해 add, commit 명령을 사용한다. 74 | 75 | ``` 76 | git status // 변경된 파일 확인 77 | git add -A(또는 .) // 변경된 전체 파일을 한번에 반영 78 | git commit -m "메시지" // 작업한 내용을 메시지에 기록 79 | ``` 80 | 81 | 기능 구현을 완료하고 add, commit 명령을 실행한 후의 상태는 다음과 같다. 82 | ![add commit1](./images/add_commit.png) 83 | 84 | --- 85 | 7. 본인 원격 저장소에 올리기 86 | > 로컬에서 commit 명령을 실행하면 로컬 저장소에만 반영되고, 원격 github.com의 저장소에는 반영되지 않는다. 87 | 88 | ``` 89 | git push origin 브랜치이름 90 | ex) git push origin javajigi 91 | ``` 92 | 93 | push 명령을 실행한 후의 상태는 다음과 같다. 94 | ![push1](./images/push.png) 95 | 96 | --- 97 | 8. github 서비스에서 pull request를 보낸다. 98 | > pull request는 github에서 제공하는 기능으로 코드리뷰 요청을 보낼 때 사용한다. 99 | > 100 | > pull request는 original 저장소(next-step organization의 저장소)의 master 브랜치와 앞 단계에서 생성한 브랜치 이름(앞 단계의 예에서는 javajigi)을 기준으로 한다. 101 | 102 | ``` 103 | ex) 미션을 진행한 javajigi/java-baseball javajigi 브랜치 => next-step/java-baseball master 브랜치로 pull request를 보낸다. 104 | ``` 105 | 106 | - 브라우저에서 github 저장소에 접근한다. 107 | - 브랜치를 작업 브랜치로 변경한다(앞 단계의 예에서는 javajigi). 108 | - 브랜치 오른쪽에 있는 "New pull request" 버튼을 클릭한다. 109 | 110 | ![pull request 보내기](./images/pull_request_1.png) 111 | 112 | - 현재 미션에서 작업한 내용을 입력하고 "Create pull request" 버튼을 클릭해 pull request를 보낸다. 113 | 114 | ![pull request 브랜치 변경](./images/pull_request_2.png) 115 | 116 | pull request를 보냈을 때의 상태는 다음과 같다. 117 | ![pull request](./images/pull_request.png) 118 | -------------------------------------------------------------------------------- /precourse/images/add_commit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/precourse/images/add_commit.png -------------------------------------------------------------------------------- /precourse/images/checkout_javajigi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/precourse/images/checkout_javajigi.png -------------------------------------------------------------------------------- /precourse/images/clone_repository.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/precourse/images/clone_repository.png -------------------------------------------------------------------------------- /precourse/images/fork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/precourse/images/fork.png -------------------------------------------------------------------------------- /precourse/images/fork_my_repo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/precourse/images/fork_my_repo.png -------------------------------------------------------------------------------- /precourse/images/import1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/precourse/images/import1.png -------------------------------------------------------------------------------- /precourse/images/import2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/precourse/images/import2.png -------------------------------------------------------------------------------- /precourse/images/precourse_apply_01.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/precourse/images/precourse_apply_01.jpeg -------------------------------------------------------------------------------- /precourse/images/precourse_apply_02.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/precourse/images/precourse_apply_02.jpeg -------------------------------------------------------------------------------- /precourse/images/pull_request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/precourse/images/pull_request.png -------------------------------------------------------------------------------- /precourse/images/pull_request_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/precourse/images/pull_request_1.png -------------------------------------------------------------------------------- /precourse/images/pull_request_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/precourse/images/pull_request_2.png -------------------------------------------------------------------------------- /precourse/images/push.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/precourse/images/push.png -------------------------------------------------------------------------------- /reviewguide/README.md: -------------------------------------------------------------------------------- 1 | # NEXTSTEP 리뷰 진행 과정 및 리뷰어 가이드 2 | 3 | --- 4 | **NEXTSTEP의 리뷰 진행 과정 및 리뷰어 가이드 전체 과정을 볼 수 있기 때문에 다음 동영상을 먼저 볼 것을 추천** 5 | [![nextstep reviewer guide](https://i.vimeocdn.com/video/888298524-46d5488b36c5da6b3e205b316413936594466e95ee39f799950400aed7ace081-d?mw=1900&mh=1069)](https://vimeo.com/414995264/7299672b47) 6 | 7 | --- 8 | #### 리뷰 진행 프로세스 9 | ![](./review_process.png) 10 | 11 | --- 12 | #### 피드백 시간 및 백업 13 | - 리뷰 요청 후 24시간 이내에 피드백하는 것을 원칙으로 한다. 14 | - 24시간 이내에 리뷰 요청이 힘든 상황이 발생하면 강사에게 도움을 요청한다. 15 | - 동기 부여 측면에서 가장 좋은 시점은 수강생이 퇴근 후 미션을 진행할 수 있도록 하는 것이다. 16 | - 예를 들어 주중은 리뷰 요청한 다음 날 19시까지 피드백을 한다. 17 | 18 | --- 19 | ## 리뷰어 가이드(넥스트스텝) 20 | - 친절한 답변보다 질문을 하는 것이 리뷰이에게 더 도움이 될 수 있다. 리뷰이의 성장을 위한 질문을 하라 21 | - 한번에 나쁜 습관을 모두 바꾸려는 욕심을 버려라. 22 | - 너무 꼼꼼한 리뷰를 하느라 늦게 피드백하는 것보다 부족함이 있어도 빠른 피드백이 더 의미있을 수 있다. 23 | - 각 단계별 Request Changes는 2회 이내로 한다. 24 | - 반영할 피드백 내용이 큰 변화가 아니라면 merge 후 다음 단계에서 반영하도록 유도한다. 25 | - 부족한 점이 있더라도 merge함으로써 다음 단계에 도전하도록 유도한다. 26 | - 나쁜 습관을 바꾸는 것보다 포기하지 않도록 동기부여하는 것이 더 중요하다. 27 | - 너무 친절한 리뷰어가 있다면 슬랙의 리뷰어 파출소에 신고한다. 28 | 29 | --- 30 | ## 리뷰어 가이드(해외 서비스 자료) 31 | - 코드는 단순하게(Simplify code) 32 | - 떠먹여주지 않는 친절함을 연습하라(Practice kindness) 33 | - 이유와 함께 예시로 설명하라(Explain why&with examples) 34 | - 학습자와의 연결(Connect Learners) 35 | - 코드방식을 통일하라 (Style Consistantly) 36 | - 리뷰를 위한 리뷰를 억지로 하지마라. 대신 피드백할 게 없으면 칭찬하라. 37 | - 구현을 잘한 부분에 대해 칭찬의 메시지를 남겨라. 38 | - 내가 결정하지 말고 상대방이 선택하도록 하라. 39 | 40 | --- 41 | ## 리뷰어 선언문 42 | > 이 선언문은 리뷰어가 현장의 개발 업무와 리뷰를 병행할 수 있도록 리뷰의 부담을 줄이기 위함이다. 43 | 44 | - 하나! 가급적 질문만 하겠다. 45 | - 둘! 열심히 하는 것 같은 리뷰어를 감시하고 고발하겠다 46 | - 셋! 잘하려는 사람에게 비난을 하겠다. 47 | - 넷! 보이면 내가 먼저 선빵을 날리겠다. 48 | - 다섯! 한 pr의 코드 리뷰에 30분의 시간을 넘게 쓴 것 같으면 신고한다. 49 | - 여섯! 함께 자라기에 이어 함께 버리기 50 | - 일곱! 너무 과하게 친절한 리뷰어를 감시하고, 역질문 스킬을 공유한다. 51 | 52 | --- 53 | ## 리뷰어 파출소(슬랙 채널)에 신고할 목록 54 | - 3회 이상 핑퐁 멈춰! ✋🏻 55 | - 코드를 제외하고 5줄 이상의 친절한 답변 스톱! 🚫 56 | - 스텝1에서 코멘트가 20개 이상 멈춰! 🕺🏻 57 | - 질문채널로 질문을 안보내면 어쩔티비! 📺 58 | - 지나치게 열린 질문 또는 답을 요구하는데 역질문 안한다고! 59 | 60 | --- 61 | ## 리뷰 팁 62 | 63 | --- 64 | #### IntelliJ에서 PR에다 바로 코드리뷰하기 65 | - GitHub의 PR에서 리뷰할 수도 있지만 IntelliJ에서 PR에다 바로 코드리뷰하는 것이 가능함 66 | - IntelliJ에서 미션 코드도 실행해 보고 코드 리뷰도 가능함 67 | - [IntelliJ에서 PR에다 코드리뷰하기 문서 참고](https://blog.jetbrains.com/idea/2020/05/intellij-idea-2020-2-early-access-program-is-starting) 68 | 69 | --- 70 | #### 반복적인 피드백 정리하기 71 | - 코드 리뷰를 하다보면 반복적인 코드 리뷰가 발생한다. 72 | - 매번 같은 메시지를 반복적으로 타이핑하기보다 한번 작성한 후에 copy & paste로 해결한다. 73 | 74 | **예시** 75 | ``` 76 | 우승자를 구하는 로직도 복잡한데 이에 대한 테스트 코드 구현을 도전해 보면 어떨까? 77 | 자동차 race가 모두 끝난 상태의 자동차 목록을 객체의 인자로 전달해 테스트 가능하도록 설계해 본다. 78 | 즉, List를 객체의 생성자로 전달하고 전달한 Car 데이터에 따라 우승자를 구하는 방식으로 새로운 객체를 추가해 본다. 79 | Car의 경우 생성자에 `Car(String name, int position)`을 가지는 생성자가 있다면 테스트할 때 임의로 위치 값을 지정할 수 있지 않을까? 80 | ``` 81 | 82 | --- 83 | ## FAQ 84 | 85 | --- 86 | #### NEXTSTEP의 리뷰 목표가 요청 후 24시간 이내인데요. 24시간 이내에 리뷰할 수 없는 상황이면 어떻게 하나요? 87 | 먼저 수강생에게 양해를 구할 것을 추천합니다. 88 | 개인적인 사정 때문에 24시간 내에 리뷰하기 힘들고, 언제 가능한지를 공유하는 것이 좋아요. 89 | 만약 개인적인 사정 때문에 48시간 내에 리뷰하기 힘든 상황이 발생하면 교육 설계자(박재성)에게 도움을 요청하세요. 90 | 91 | --- 92 | #### 수강생들의 미션 진행은 하나의 미션이 종료되어야만 다음 미션을 진행 가능한가요? 93 | 아닙니다. 94 | 동시에 2개 이상의 미션을 진행할 수 있습니다. 95 | 리뷰어 피드백이 늦을 수도 있기 때문에 2개 정도의 미션을 동시에 진행하는 것을 추천하고 있어요. 96 | 97 | --- 98 | #### 리뷰어 한명당 담당하게 되는 수강생은 미션당 몇 명이 되나요? 99 | 리뷰어들이 회사일과 병행하기 때문에 현재는 5명을 기본으로 하고 있어요. 100 | 단, 리뷰어들의 요청에 따라 리뷰이의 수는 5명에서 가감될 수 있습니다. 101 | 102 | --- 103 | ## 🔗 참고 링크 104 | - [NEXTSTEP 리뷰어 분의 리뷰어 활동 후기- 회사 눈치 안 보고 투잡하기](https://woowabros.github.io/woowabros/2019/08/22/code-reviewer.html) 105 | - [카카오 신입사원 교육 리뷰어 분의 활동 후기 - 뉴크루 온보딩 코드 리뷰어로 참여하기](https://tech.kakao.com/2021/04/08/welcome-new-krew3) 106 | -------------------------------------------------------------------------------- /reviewguide/atdd-spring/acceptance-test-auth.md: -------------------------------------------------------------------------------- 1 | ## 1단계: 즐겨찾기 기능 완성 2 | - ATDD+TDD 전체 사이클 경험 3 | - 즐겨찾기 기능개선이 잘 되었는지? 4 | - 기존에는 모든 사람이 공유하는 즐겨찾기였는데 토큰을 이용하여 개일별로 관리할 수 있도록 수정을 잘하였는지? 5 | - 토큰을 이용하여 요청을 보내는 인수 테스트를 잘 작성했는지? 6 | - 예외 상황을 잘 검증하고 테스트를 잘 작성 했는지? 7 | - ex) 내가 등록하지 않은 즐겨 찾기를 제거 하려고 할 경우, 연결이 되지 않는 경로의 즐겨찾기를 추가하려고 시도했는지 등 8 | - Member와 Favorite 관계에 따라서 서비스 로직이 달라질 수 있음 9 | - 직접 참조 vs 간접 참조 10 | - 둘 중 하나로 했다면 반대편 방법에 대해서 제시하고 고민할 수 있도록 가이드 11 | 12 | --- 13 | 14 | ## 2단계: 깃헙 로그인 인수 테스트 15 | 16 | - 외부 서비스에 대한 의존이 있는 로그인 기능을 잘 구현했는지? 17 | - 해당 기능을 검증할 수 있는 테스트는 외부 서비스에 대한 의존을 어떻게 처리했는지? 18 | - 실제 Github에 요청을 보낸 경우 수행 시간이 오래 걸리고 테스트 구성이 어려우므로 다른 방법으로 대체해 볼 수 있도록 가이드 19 | - Stubbing을 통해 Github에 대한 요청/응답을 처리하는 객체를 대체한 경우 mock을 이용하기 때문에 스프링 컨테이너 재사용이 어렵고 프로덕션 코드에 직접 의존적이기 때문에 Fake방식으로 제안 20 | - 테스트 전용 Profile을 이용해 깃헙으로 보내는 요청을 자체적으로 처리할 수 있도록 가이드 21 | - 테스트용 Controller를 구축해도 좋고 TestContainer나 다른 도구를 사용해도 좋음(리뷰어가 각자 생각에 편한 방식으로 가이드 주기) 22 | - 테스트용 코드를 어디서 어떻게 관리하는게 좋을 지 질문 던지기 23 | 24 | --- 25 | 26 | ## 3단계: 패키지 리팩터링 27 | 28 | - 인증관련 패키지와 멤버 관련 패키지가 잘 분리되었는지 29 | - 리팩터링 시 기존 기능들이 인수 테스트로 잘 보호되고 있었는지?(테스트가 빈약할 경우 코멘트 남기기) 30 | - 패키지 간의 의존성 방향이 양방향인지? 단방향인지, 불필요한 양방향은 아닌지? 31 | -------------------------------------------------------------------------------- /reviewguide/atdd-spring/acceptance-test-refactoring.md: -------------------------------------------------------------------------------- 1 | ## 0단계: Cucumber 전환 2 | 3 | - 기존 인수 테스트 중 일부를 Cucumber로 전환했는지 확인 4 | - DataTable을 이용하여 여러 값을 동시에 검증할 수 있는지? 5 | - 파라미터를 활용하여 스텝을 재사용 했는지? 6 | - 스텝 간 정보 공유를 어떻게 했는지? 공유 객체를 활용 했는지? 7 | - Cucumber 에서 데이터 초기화는 어떻게 했는지? 8 | 9 | --- 10 | 11 | ## 1단계: 경로 조회 타입 추가 12 | 13 | - 기존 기능을 잘 유지하면서 리팩터링을 하였는가? 14 | - 기존 기능과 중복되는 로직이나 구조를 얼마나 잘 추상화 하였는가? 15 | - 인수 조건과 인수 테스트를 잘 작성하였는가? 16 | - 커밋 로그를 통해 TDD를 진행하였는지 파악할 수 있는가? 17 | 18 | --- 19 | 20 | ## 2단계: 요금 조회 기능 21 | 22 | - 인수 테스트 -> 문서화 -> 기능 구현 싸이클 연습하는 단계 23 | - 기존 기능을 유지한 채로 신규 기능 구현하는 연습(목표는 3주차와 비슷) 24 | 25 | --- 26 | 27 | ## 3단계: 요금 정책 추가 28 | 29 | - 경로 조회 시 로그인 사용자의 나이를 알기 위해서는 경로 조회 컨트롤러 메서드에 @AuthenticationPrincipal를 이용해 LoginMember 객체를 받아야 함 30 | - 하지만 비로그인 사용자도 사용할 수 있게 해야함 31 | - @AuthenticationPrincipal 설정값으로 `boolean required`을 두어 required값이 false일 때 로그인 객체가 없다면 빈 값이 응답될 수 있게 가이드 하기 32 | - 요금별 정책 로직에 대해 집중적으로 코드 리뷰하면 좋을 듯 33 | -------------------------------------------------------------------------------- /reviewguide/atdd-spring/acceptance-test-tdd.md: -------------------------------------------------------------------------------- 1 | ## 공통 2 | 3 | - 인수 테스트는 시나리오 기반으로 작성하게 함 4 | - 단위 테스트를 통해 업무 규칙(예외 등)을 검증하도록 가이드 5 | - 서비스 단위 테스트는 작성하기 어려워서 도메인 단위 테스트 보다는 중요도를 낮춰도 됨 6 | - 테스트 작성 우선순위를 다음과 같이 가이드 7 | - 인수 테스트 > 도메인 레이어 테스트 > 서비스 레이어 테스트 8 | 9 | --- 10 | 11 | ## 1단계: 단위 테스트 연습 12 | 13 | - 기능 요구사항에 제시되어있는 내용을 모두 만족하여 테스트를 작성했는가? 14 | - 테스트는 프로덕션 코드의 명세임을 인지 시키고 가급적이면 단위 테스트를 많이 작성하게 가이드 15 | - 비즈니스 로직을 도메인 레이어에 위치할 수 있도록 가이드 16 | 17 | ## 1,2 단계: 구간 추가/제거 요구사항 변경 18 | 19 | - 요구 사항 변경에 따른 인수 테스트 관리 및 프로덕션 코드 관리를 경험하기 위한 미션 20 | - 예외사항에 대한 테스트(인수 테스트 포함)도 할 수 있도록 가이드 21 | 22 | --- 23 | 24 | ## 3단계: 경로 조회 / 외부 라이브러리 활용한 미션 25 | 26 | - 외부 라이브러리를 활용한 코드를 테스트할 때는 실제 객체를 활용하여 하도록 가이드 27 | - 미션 수행에 어려움을 겪는다면 경로 조회 부분과 그 결과를 맵핑하는 부분, 두 부분을 나눠서 생각해보라고 가이드 28 | - 경로 조회 기능 구현 시 경로 조회를 수행하는 단위 테스트와 경로 조회 인수 테스트가 검증하는 기능이 겹칠 수 있는데 인수 테스트는 해피케이스에 대한 검증을 위주로, 단위 테스트는 세부적인 케이스나 예외 상황을 검증을 해보라고 가이드 29 | - 인수 테스트는 작성 및 수행 비용이 단위 테스트보다 높기 때문에 효율적인 테스트를 구성할 수 있음 30 | -------------------------------------------------------------------------------- /reviewguide/atdd-spring/acceptance-test.md: -------------------------------------------------------------------------------- 1 | ## 0단계 - 리뷰 요청 실습 2 | 3 | - 첫 강의 전 까지 0단계 리뷰 요청을 보내야 하는 요구사항이 있음 4 | - “https://google.com”로 요청을 보낼 경우 200응답 코드가 오는지를 검증하는 테스트 작성 여부 확인 5 | - 코드리뷰 프로세스를 경험하기 위한 과정 6 | 7 | --- 8 | 9 | ## 1단계: 구현된 기능을 인수 조건에 따라 인수 테스트로 검증 10 | 11 | - 작성한 인수 테스트가 미리 구현된 기능을 인수 조건에 따라 잘 검증하는가? 12 | - 인수 테스트의 가독성과 재사용성을 고려하여 리팩터링을 했는가? 13 | - 눈에 띄는 내용만 피드백 후 머지하여 빠르게 다음 단계 진행하도록 가이드 14 | - 인수 테스트 격리는 다음 단계에서 고민할 수 있도록 가이드 15 | 16 | --- 17 | 18 | ## 2단계: 제공되는 인수 조건에 따라 인수 테스트를 작성하고 기능 구현 19 | 20 | - 작성한 인수 테스트가 제공된 인수 조건을 잘 검증하는가? 21 | - 각 인수 테스트 검증 결과가 다른 인수 테스트에 영향을 끼치지는 않는가? 22 | - 인수 테스트 격리 방법에 따라 깨지기 쉬운 테스트가 될 수 있고 테스트의 비용이 달라질 수 있음을 가이드 23 | - 인수 테스트의 가독성과 재사용성을 고려하여 리팩터링을 했는가? 24 | - 인수 테스트에서 중복해서 사용되는 코드를 분리하여 재사용할 수 있도록 가이드 25 | 26 | --- 27 | 28 | ## 3단계: 인수 테스트 주도 개발 사이클 경험 29 | 30 | - 요구사항에 맞게 인수 조건이 잘 정의되었는가? 31 | - 인수 테스트로 해당 기능의 스펙을 유추할 수 있도록 작성했는가? 32 | - 새롭게 추가되고 제거되는 구간에 따라 역 목록 기능이 잘 동작 하는가? 33 | - 에러가 발생하는 케이스를 인수 테스트로 잘 검증하고 있는가? 34 | - 객체 지향 생활 체조와 클린 코드 가이드가 잘 지켜지고 있는가? 35 | -------------------------------------------------------------------------------- /reviewguide/career-nextstep/README.md: -------------------------------------------------------------------------------- 1 | # 커리어 NEXTSTEP 소개 2 | 3 | ## 커리어 NEXTSTEP 학습 목표 4 | - 단순히 학습을 하는 것이 아니라 실무와 병행하여 개발자로서 성장과 그러한 성장을 통한 실무의 업무 성과를 높일 수 있는 과정을 진행한다. 5 | - 교육과정이나 기술 학습이 현업에서 하고 있는 업무에서 효율적으로 사용할 수 있도록 적용하는 계획을 교육기간 동안 경험 해 본다. 6 | - 평소에 관심이 있었던 기술에 대하여 어떻게 업무에 적용하여 사용할 수 있을지 접근 방법 고민하고 적용해 볼 수 있도록 한다. 7 | - 처음부터 완벽한 계획 보다는 작은 부분에서 시작 할 수 있도록 한다. 8 | - 본인의 커리어를 그려보고 본인이 원하는 개발자가 되기 위한 실행 계획을 만들어 본다. 9 | 10 | 11 | --- 12 | ## 미션별 리뷰어 가이드 13 | - 기본적으로 전체 [리뷰어 가이드](https://github.com/next-step/nextstep-docs/tree/master/reviewguide)를 따른다. 14 | ### career-goal 15 | - 목표한 커리어가 수강생이 성장하기위한 기술학습이나 경험을 정의 할 수 있는지 확인한다. ( action item이 나올 수 있는 수준이 되도록 안내한다.) 16 | - 목표를 달성하기 위한 todo가 목표에 맞는 기술이나 경험인지 확인한다. (부족한 부분은 'XX같은 역량이 필요하지 않을까요?' 라고 안내한다.) 17 | ### career-domain 18 | #### 도메인 모델링 19 | - 작성된 도메인 모델에 대한 이해가 되는지 확인 한다. (이해 되지 않는 부분에 대한 문의를 review에 남김) 20 | - UML에 대한 문법이나 표현에 대한 부분은 수정요청을 하지 않고 개선을 하는 Tip을 전달하는 수준으로 진행한다. 21 | #### 프로파일링 22 | - 작성된 sequence flow에 대한 이해가 되는지 확인 한다. (이해 되지 않는 부분에 대한 문의를 review에 남김) 23 | - Spring Transactional에 대한 생성 문서에서 AOP의 동작 방식과 commit rollback 처리에 대한 동작기제가 있는지 확인한다. 24 | ### career-architecture 25 | - 작성된 system architecture에 대한 이해가 되는지 확인한다. 26 | - 개선해야할 과제가 4주 정도의 기간에 가능한 범위인지 확인한다. 27 | ### career-WBS 28 | - 작성된 task들의 사이즈가 너무 편차가 크다면 더 작게 나눠 볼 수 있도록 훈려한다. 29 | - 3자의 관점에서 일정이 너무 도전적이거나 비합리적인 부분이 있다면 이유를 물어본다. 30 | - 전체적인 일정이 과정내에 소화가 가능할지 확인한다. 31 | ### career-project 32 | - 개선 과제의 예상 성과가 수강생의 시간을 확보해주거나 기술적 경험에 도움이 될 수 있는지 확인한다. 33 | - 개선 과제가 4주 정도의 기간에 가능한 범위인지 확인한다. 34 | - 개선 과제가 수강생 외에 다른의존성(회사내 동료...) 의존성 있다면 의존성이 없도록 요청한다. 35 | - 최대한 작은 성공을 경험할 수 있도록 한다. 36 | --- 37 | ## 리뷰어 -> 수강생 상호 평가 38 | - 이 과정에서는 필요없을 것 같음 39 | 40 | --- 41 | 42 | --- 43 | ## 수강생 -> 리뷰어 상호 평가 44 | - 리뷰가 도움이 되었나요? 45 | -------------------------------------------------------------------------------- /reviewguide/cleancode/README.md: -------------------------------------------------------------------------------- 1 | # 클린코드 with Java 소개 2 | 3 | ## 클린코드 with Java 학습 목표 4 | #### 기술적인 측면 5 | 1. TDD, 리팩터링, 클린코드 6 | 2. 순수 자바로 객체지향 프로그래밍 7 | 3. 레거시 코드 리팩터링 8 | 9 | #### 기술 외적인 측면 10 | 1. 프로그래밍 자체가 얼마나 재미있는 활동인지 경험 11 | 2. 효과적으로 프로그래밍을 학습하는 방법을 경험 12 | 3. 프로그래머로 어떻게 성장하고, 어떻게 살아갈 것인지 13 | 14 | --- 15 | ## 미션별 리뷰어 가이드 16 | - [자동차 경주 - 단위 테스트](./racingcar.md) 17 | - [로또 - TDD](./lotto.md) 18 | - [사다리타기 - FP, OOP](./ladder.md) 19 | - [수강신청 - 레거시 코드 리팩터링](./lms.md) 20 | 21 | --- 22 | ## 리뷰어 -> 수강생 상호 평가 23 | - 팀 동료로 채용한다면 같이 일하고 싶은 개발자인가?(10점 만점) 24 | - 코드 리뷰를 하면서 느낀 점이 있다면 의견을 남겨주세요.(예. 피드백을 반영하는 역량이 뛰어나 앞으로 성장 가능성이 높아 보인다. 리뷰를 하면서 의견을 주고 받는 시간이 너무 즐거웠다.) 25 | 26 | --- 27 | #### 팀 동료로 채용한다면 같이 일하고 싶은 개발자인가?(현재 역량 파악, 성장 잠재력) 28 | - 9점 ~ 10점: 강한 인사이트를 주는 코드와 온라인 토론을 통해 같이 성장하는 느낌을 받는 경우. 리뷰어와 비슷한 수준의 역량이라고 판단되는 경우 29 | - 정말 같이 일하고 싶은 느낌이 들게 하는 수강생. 온라인 토론을 커뮤니케이션 역량 또한 좋다는 느낌을 받는 경우 30 | - 이미 일정 수준의 역량을 보유하고 있는 상태이면서, 간혹 작은 피드백이 나오면 깊게 고민하는 역량을 갖춘 경우 31 | - 7점 ~ 8점: 특별히 부족한 점은 없지만 그렇다고 특출난 점이 보이지 않는 경우 32 | - 리뷰어의 역량 또는 리뷰어와 같이 일하고 있는 회사 개발자들의 역량에 비해 다소 부족한 역량이라 판단되는 경우 33 | - 현재는 부족한 점이 있지만 로드맵을 제시하고, 피드백을 준다면 빠르게 성장할 가능성이 높아 보이는 수강생 34 | - 5점 ~ 6점: 스스로의 힘으로 성장하기 보다 단순 피드백에 의존해 개선되는 느낌을 받는 경우. 35 | - 반복적인 피드백을 통해 조금씩 개선되는 느낌을 받는 경우 36 | - 미션을 마무리하는 단계에도 부족한 부분이 많다고 생각하는 경우 37 | - 1점 ~ 4점: 피드백을 통해 개선의 여지가 없어 보이는 경우 38 | 39 | --- 40 | ## 수강생 -> 리뷰어 상호 평가 41 | - 팀원으로 일할 수 있는 기회가 있다면 같이 일하고 싶은 리뷰어인가?(10점 만점) 42 | - 리뷰어의 성장을 위한 피드백이 있다면 남겨 주세요.(예. 피드백을 꼼꼼히 주어 실력을 향상하는데 많은 도움이 되었다. 정답을 미리 알려주기보다 정답을 찾아갈 수 있도록 방향만 정해주면 좋겠다.) 43 | -------------------------------------------------------------------------------- /reviewguide/cleancode/bowling.md: -------------------------------------------------------------------------------- 1 | # 볼링 게임 점수판 2 | 3 | --- 4 | ## 리뷰어 가이드 5 | 1단계 미션이 레거시 코드 리팩터링하는 미션으로 서비스 레이어의 코드를 도메인 객체로 리팩터링하는 미션이다. 6 | 지금까지 학습한 내용을 실무에 적용해보는 상당히 중요한 미션인 만큼 도메인 객체로 로직 분리를 잘 하도록 리뷰한다. 7 | 가능하면 리뷰어가 판단하기에 만족하는 수준이 될 때까지 피드백을 남긴다. 8 | QnaService의 결과 코드는 다음과 같은 구조가 되도록 피드백 하면 좋겠다. 9 | 10 | ```java 11 | @Transactional 12 | public void deleteQuestion(User loginUser, long questionId) throws CannotDeleteException { 13 | Question question = findQuestionById(questionId); 14 | List deleteHistories = question.delete(loginUser); 15 | deleteHistoryService.saveAll(deleteHistories); 16 | } 17 | ``` 18 | 19 | 2단계 이후부터는 지난 세 개의 미션 진행 동안 가이드했던 내용들을 잘 지키고 있는지만 확인하고 피드백한다. 20 | 21 | --- 22 | #### 사다리타기 미션 중점 피드백 내용 23 | - 자바8의 스트림, 람다, Optional을 적절히 사용해 구현했는가? 24 | - 객체 설계가 적절한가? 25 | - 메소드(함수)의 인자를 2개 이하로 구현했는가? 3개 이상인 경우 줄이도록 피드백한다. 26 | - 객체지향 생활체조 규칙 중 다음 규칙에 대한 피드백 27 | - 규칙 4: 한 줄에 점을 하나만 찍는다.(디미터 법칙을 지키는 것을 의미한다.) 28 | - 규칙 6: 모든 엔티티를 작게 유지한다. 29 | - 규칙 7: 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다. 30 | - 규칙 9: 게터/세터/프로퍼티를 쓰지 않는다. 31 | 32 | --- 33 | #### 로또 미션 중점 피드백 내용 - 클래스 분리 34 | - 클래스를 작은 단위로 잘 분리했는가? 35 | - 객체지향 생활체조 규칙 중 다음 규칙에 대한 피드백 36 | - 규칙 3: 모든 원시값과 문자열을 포장한다. 37 | - 규칙 5: 줄여쓰지 않는다(축약 금지). 38 | - 규칙 8: 일급 콜렉션을 쓴다. 39 | - 도메인 객체에 대한 단위 테스트가 모두 존재하는가? 40 | - TDD로 구현했을 경우 도메인 객체에 대한 단위 테스트는 존재해야 한다. 41 | 42 | --- 43 | #### 자동차 경주 게임미션 중점 피드백 내용 - 메소드 분리 44 | - todo list를 잘 작성했는가? 45 | - 각 기능 단위로 commit log를 잘 남겼는가? 46 | - 코딩 컨벤션을 잘 지키면서 프로그래밍 했는가? 47 | - 메소드를 작은 단위로 잘 분리했는가?(인덴트를 1로 잘 유지했는가? 포함) 48 | - else 예약어를 쓰지 않았는가? 49 | - 함수(또는 메소드)의 길이가 10라인을 넘어가지 않도록 구현했는가? 50 | - 도메인 객체에 대한 단위 테스트를 잘 구현했는가? 51 | - MVC 구조에 맞도록 객체 분리를 했는가? 52 | -------------------------------------------------------------------------------- /reviewguide/cleancode/feedback/README.md: -------------------------------------------------------------------------------- 1 | # 반복적인 피드백 2 | - 리뷰를 하다 보면 비슷한 패턴의 코드가 보이면서 반복적인 피드백을 하게 된다. 3 | - 매번 타이핑하려니까 귀찮기도 하고 메시지를 빼먹기도 한다. 내용 정리가 필요하다. 4 | - 미리 작성된 메시지를 남겨서 리뷰 시간을 줄이자. 5 | - 리뷰이가 추가 학습 할 수 있도록 참고 도서를 알려주자. 6 | - 잘 정리된 메시지를 전달해서 리뷰이가 의도를 잘 파악할 수 있도록 하자. 7 | 8 | --- 9 | ## 차례 10 | - [네이밍, 의미 있는 이름](./class.md) 11 | - [클래스](./class.md) 12 | - [함수](./function.md) 13 | - [테스트](./test.md) 14 | - [상수](./constant.md) 15 | - [Enum, 열거타입](./enum.md) 16 | 17 | --- 18 | ## 피드백 참고 도서 19 | - 클린 코드 20 | - 이펙티브 자바 3판 21 | - 객체지향의 사실과 오해 22 | - 리팩토링 2판 23 | -------------------------------------------------------------------------------- /reviewguide/cleancode/feedback/class.md: -------------------------------------------------------------------------------- 1 | ## 클래스 2 | 3 | ### xxxxUtil이라고 이름 붙인 클래스가 있다 4 | - 단일 책임 원칙(SRP)을 어긴 클래스다. 5 | - 클린코드 175p 6 | > 클래스 이름은 해당 클래스 책임을 기술해야 한다. 실제로 작명은 클래스 크기를 줄이는 첫 번째 관문이다. 7 | 간결한 이름이 떠오르지 않는다면 필경 클래스 크기가 너무 커서 그렇다. 8 | 클래스 이름이 모호하다면 필경 클래스 책임이 너무 많아서다. 9 | 예를 들어, 클래스 이름에 Processor, Manager, Super 등과 같이 모호한 단어가 있다면 클래스에다 여러 책임을 떠안겼다는 증거다. 10 | 11 | > 단일 책임 원칙(Single Responsibility Principle, SRP)은 클래스나 모듈을 변경할 이유가 하나, 단 하나뿐이어야 한다는 원칙이다. 12 | SRP는 '책임'이라는 개념을 정의하며 적절한 클래스 크기를 제시한다. 13 | 클래스는 책임, 즉 변경할 이유가 하나여야 한다. 14 | 15 | ### 왜 xxxxUtil을 쓰면 안되는지 물어볼 때. 또는 SRP가 무엇인지 물어볼 때 16 | - 클린코드 p176 17 | > SRP는 객체 지향 설계에서 더욱 중요한 개념이다. 또한 이해하고 지키기 수월한 개념이기도 하다. 18 | 하지만 이상하게도 SRP는 클래스 설계자가 가장 무시하는 규칙 중 하나다. 19 | 우리는 수많은 책임을 떠안은 클래스를 꾸준하게 접한다. 왜일까? 20 | 21 | > 소프트웨어를 돌아가게 만드는 활동과 소프트웨어를 깨끗하게 만드는 활동은 완전히 별개다. 22 | 우리들 대다수는 두뇌 용량에 한계가 있어 '깨끗하고 체계적인 소프트웨어'보다 '돌아가는 소프트웨어'에 초점을 맞춘다. 23 | 전적으로 올바른 태도다. 관심사를 분리하는 작업은 프로그램만이 아니라 프로그래밍 활동에서도 마찬가지로 중요하다. 24 | 25 | > 문제는 우리들 대다수가 프로그램이 돌아가면 일이 끝났다고 여기는 데 있다. 26 | '깨끗하고 체계적인 소프트웨어'라는 다음 관심사로 전환하지 않는다. 27 | 프로그램으로 되돌아가 만능 클래스를 단일 책임 클래스 여럿으로 분리하는 대신 다음 문제로 넘어가버린다. 28 | - 클린코드 p177 29 | > 규모가 어느 수준에 이르는 시스템은 논리가 많고도 복잡하다. 이런 복잡성을 다루려면 체계적인 정리가 필수다. 30 | 그래야 개발자가 무엇이 어디에 있는지 쉽게 찾는다. 31 | 그래야 (변경을 가할 때) 직접 영향이 미치는 컴포넌트만 이해해도 충분하다. 32 | 큼직한 다목적 클래스 몇 개로 이뤄진 시스템은 (변경을 가할 때) 당장 알 필요가 없는 사실까지 들이밀어 개발자를 방해한다. 33 | 34 | --- 35 | ### 인스턴스 변수가 3개 이상이다. 36 | - `규칙 7: 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다.` 원칙 위반 37 | > 인스턴스 변수가 너무 많다. 인스턴스 변수를 줄여본다. 38 | 중복되는 인스턴스 변수는 없는지 검토해 본다. 39 | 객체지향 설계 원칙의 "규칙 7: 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다." 원칙을 따라본다. 즉, 2개까지 허용한다. 40 | 41 | --- 42 | ### 인스턴스 변수를 default, protected, public 접근 제어자로 구현했다. 43 | - 캡슐화 위반 44 | > 인스턴스 변수는 특별한 이유는 없는 한 private으로 구현한다. 45 | 객체 외부에서 상태 값을 임의로 변경할 수 있도록 하는 것은 캡슐화 위반이다. 46 | 47 | --- 48 | ### 핵심 비지니스 로직과 UI 로직이 같은 클래스에 구현되어 있다. 49 | - 단일 책임 원칙(SRP)을 어긴 클래스다. 50 | > 핵심 로직을 구현하는 부분(상태 변경 등과 같은)과 View 로직(System.in을 통해 값 입력, System.out을 통해 값 출력)을 분리한다. 51 | 한 객체에 이 두 가지 로직이 같이 구현되어 있는 경우 추후 View가 되었을 때 핵심 로직을 구현하는 코드를 재사용할 수 없다. 52 | 또한 View에 종속되는 순간 테스트하기도 힘들다. 53 | 이 연습은 웹 프로그래밍을 할 때 DB에 종속된 코드와 DB에 종속되지 않은 코드를 분리함으로써 테스트 가능하도록 구현하는 것과 같은 연습이다. 54 | -------------------------------------------------------------------------------- /reviewguide/cleancode/feedback/constant.md: -------------------------------------------------------------------------------- 1 | ## 상수 2 | 3 | ### 상수를 대문자로 쓰지 않았다 4 | - 구글 자바 스타일 가이드 참고 5 | - https://google.github.io/styleguide/javaguide.html#s5.2.4-constant-names 6 | 7 | ### for문의 시작 index도 상수화를 해야하는건가요? 8 | - 클린코드 p31 9 | > 문자 하나만 사용하는 변수 이름은 문제가 있다. 루프에서 반복 횟수를 세는 변수 i, j, k는 괜찮다. (l은 절대 안 된다!) 10 | 단, 루프 범위가 아주 작고 다른 이름과 충돌하지 않을 때만 괜찮다. 11 | 루프에서 반복 횟수 변수는 전통적으로 한 글자를 사용하기 때문이다. 12 | 그 외에는 대부분 적절하지 못하다. 13 | 독자가 실제 개념으로 변환해야 하니까. 14 | -------------------------------------------------------------------------------- /reviewguide/cleancode/feedback/enum.md: -------------------------------------------------------------------------------- 1 | ## enum 열거타입 2 | 3 | ### 안티패턴인 정수 열거 패턴을 사용한다. 4 | - 언어에서 제공하는 열거 타입(Enum Type)을 사용하라. 5 | - 이펙티브 자바 3판 아이템 34 int 상수 대신 열거 타입을 사용하라 208p 6 | > 정수 열거 패턴(int enum pattern)은 기법에는 단점이 많다. 7 | 타입 안전을 보장할 방법이 없으며 표현력도 좋지 않다. 8 | 9 | > 정수 열거 패턴을 사용한 프로그램은 깨지기 쉽다. 10 | 평범한 상수를 나열한 것뿐이라 컴파일하면 그 값이 클라이언트 파일에 그대로 새겨진다. 11 | 따라서 상수의 값이 바뀌면 클라이언트도 반드시 다시 컴파일해야 한다. 12 | 다시 컴파일하지 않은 클라이언트는 실행이 되더라도 엉뚱하게 동작할 것이다. 13 | 14 | > 정수 상수는 문자열로 출력하기가 다소 까다롭다. 15 | 그 값을 출력하거나 디버거로 살펴보면 (의미가 아닌) 단지 숫자로만 보여서 썩 도움이 되지 않는다. 16 | 같은 정수 열거 그룹에 속한 모든 상수를 한 바퀴 순회하는 방법도 마땅치 않다. 17 | 심지어 그 안에 상수가 몇 개인지도 알 수 없다. 18 | 19 | > 정수 대신 문자열 상수를 사용하는 변형 패턴도 있다. 20 | 문자열 열거 패턴(string enum patter)이라 하는 이 변형은 더 나쁘다. 21 | 상수의 의미를 출력할 수 있다는 점은 좋지만, 경험이 부족한 프로그래머가 문자열 상수의 이름 대신 문자열 값을 그대로 하드코딩하게 만들기 때문이다. 22 | 이렇게 하드코딩한 문자열에 오타가 있어도 컴파일러는 확인할 길이 없으니 자연스럽게 런타임 버그가 생긴다. 23 | 문자열 비교에 따른 성능 저하 역시 당연한 결과다. 24 | -------------------------------------------------------------------------------- /reviewguide/cleancode/feedback/function.md: -------------------------------------------------------------------------------- 1 | ## 함수 2 | 3 | ### 메서드 또는 함수가 10줄이 넘어가고 여러 가지 처리를 한다. 4 | - 클린코드 44p 5 | > 한 가지만 해라! 6 | 함수는 한 가지를 해야 한다. 그 한 가지를 잘 해야 한다. 그 한 가지만을 해야 한다. 7 | - 클린코드 45p 8 | > 지정된 함수 이름 아래에서 추상화 수준이 하나인 단계만 수행한다면 그 함수는 한 가지 작업만 한다. 9 | 어쨌거나 우리가 함수를 만드는 이유는 큰 개념을 (다시 말해, 함수 이름을) 다음 추상화 수준에서 여러 단계로 나눠 수행하기 위해서가 아니던가 10 | 11 | > 따라서, 함수가 '한 가지'만 하는지 판단하는 방법이 하나 더 있다. 12 | 단순히 다른 표현이 아니라 의미 있는 이름으로 다른 함수를 추출할 수 있다면 그 함수는 여러 작업을 하는 셈이다. 13 | 14 | > 함수 당 추상화 수준은 하나로! 15 | 함수가 확실히 '한 가지' 작업만 하려면 함수 내 모든 문장의 추상화 수준이 동일 해야 한다. 16 | ... 17 | 한 함수 내에 추상화 수준을 섞으면 코드를 읽는 사람이 헷갈린다. 18 | 특정 표현이 근본 개념인지 아니면 세부사항인지 구분하기 어려운 탓이다. 19 | 하지만 문제는 이 정도로 그치지 않는다. 20 | 근본 개념과 세부사항을 뒤섞기 시작하면, 깨어진 창문처럼 사람들이 함수에 세부사항을 점점 더 추가한다. 21 | 22 | --- 23 | ### setter 메서드를 사용해 구현한다. 24 | - `규칙 9: 게터/세터/프로퍼티를 쓰지 않는다.` 원칙 위반 25 | > 상태 값을 가지는 클래스의 상태를 setter 메소드를 통해 외부에서 변경하지 마라. 26 | 상태 값을 가지는 객체 자신이 자신의 상태 값을 변경하도록 하는 것이 객체지향 프로그래밍 관점에서 맞다. 27 | setter 메소드를 추가하지 않고 구현해 본다. 28 | 29 | --- 30 | ### getter 메서드를 사용해 구현한다. 31 | - `규칙 9: 게터/세터/프로퍼티를 쓰지 않는다.` 원칙 위반 32 | > 상태를 가지는 객체의 데이터를 꺼내려(get)하지 말고 객체에 메시지를 보내라는 원칙에 따라 구현한다. 33 | 이와 같이 구현했을 때 테스트 관점에서 어떤 장점이 있을까? 34 | 코드 재사용 측면에서 어떤 장점이 있을까? 35 | 36 | --- 37 | ### 메소드(함수)에 인자가 너무 많다. 38 | - 인자의 수를 최소화한다. 39 | > 메소드(함수)에 인자가 너무 많다. 다음 원칙에 따라 메소드를 구현한다. 40 | 메소드(함수)에서 이상적인 인자 개수는 0개(무항)이다. 다음은 1개이고, 다음은 2개이다. 41 | 3개는 가능한 피하는 편이 좋다. 4개 이상은 특별한 이유가 있어도 사용하면 안된다. 42 | 43 | --- 44 | ### 메소드(함수)가 NULL을 반환한다. 45 | - `클린코드: null을 반환하지 마라` 46 | > null을 반환하는 메소드(함수)는 호출하는 함수에서 null 체크를 강제하도록 한다. 47 | 이는 코드의 가독성을 떨어뜨리며 실수를 유발하기 쉽다. 48 | null 대신 예외를 던지거나 특수 객체(ex. Collections.emptyList())를 반환하는 것이 좋다. -------------------------------------------------------------------------------- /reviewguide/cleancode/feedback/naming.md: -------------------------------------------------------------------------------- 1 | ## 의미 있는 이름 2 | 3 | ### 클래스, 메서드, 변수명에 의도를 알기 어려운 이름을 붙였다 4 | - 클린코드 p32 5 | > 클래스 이름 6 | 클래스 이름과 객체 이름은 명사나 명사구가 적합하다. Customer, WikiPage, Account, AddressParser 등이 좋은 예다. Manager, Processor, Data, Info 등과 같은 단어는 피하고, 동사는 사용하지 않는다. 7 | - 클린코드 p49 8 | > 서술적인 이름을 사용하라! 9 | 코드를 읽으면서 짐작했던 기능을 각 루틴이 그대로 수행한다면 깨끗한 코드라 불러도 되겠다. 10 | 11 | ### get, set을를 잘못 사용하는 케이스 12 | - 클린코드 p32 13 | > 메서드 이름 14 | 접근자(Accessor), 변경자(Mutator), 조건자(Predicate)는 javabean 표준에 따라 값 앞에 get, set, is를 붙인다. 15 | 16 | ### 클래스, 변수명에 List를 붙이는 케이스 17 | - 클린코드 p24 18 | > 그릇된 정보를 피하라 19 | 여러 계정을 그룹으로 묶을 때, 실제 List가 아니라면, accountList라 명명하지 않는다. 20 | 프로그래머에게 List라는 단어는 특수한 의미다. 21 | 계정을 담는 컨테이너가 실제 List가 아니라면 프로그래머에게 그릇된 정보를 제공하는 셈이다. 22 | (주석1 - 나중에 살펴보겠지만, 실제 컨테이너가 List인 경우라도 컨테이너 유형을 이름에 넣지 않는 편이 바람직하다.) 23 | 그러므로 accountGroup, bunchOfAccounts, 아니면 단순히 Accounts라 명명한다. 24 | -------------------------------------------------------------------------------- /reviewguide/cleancode/feedback/test.md: -------------------------------------------------------------------------------- 1 | ## 테스트 2 | 3 | ### 테스트 코드에서 의미 없는 변수명을 사용한다 (ex. station1, station2 ...) 4 | - 클린코드 25p 5 | > 의미 있게 구분하라 6 | 컴파일러나 인터프리터만 통과하려는 생각으로 코드를 구현하는 프로그래머는 스스로 문제를 일으킨다. 7 | 예를 들어, 동일한 범위 안에서 다른 두 개념에 같은 이름을 사용하지 못한다. 8 | 9 | > 컴파일러를 통과할지라도 연속된 숫자를 덧붙이거나 불용어(noise word)를 추가하는 방식은 적절하지 못하다. 10 | 이름이 달라야 한다면 의미도 달라져야 한다. 11 | 12 | > 연속적인 숫자를 덧붙인 이름(a1, a2 ... aN)은 의도적인 이름과 정반대다. 13 | 이런 이름은 그릇된 정보를 제공하는 이름도 아니며, 아무런 정보를 제공하지 못하는 이름일 뿐이다. 14 | 저자 의도가 전혀 드러나지 않는다. 15 | - 클린코드 157p 16 | > 테스트 코드는 실제 코드 못지 않게 중요하다. 테스트 코드는 이류 시민이 아니다. 17 | 테스트 코드는 사고와 설계와 주의가 필요하다. 18 | 실제 코드 못지 않게 깨끗하게 짜야한다. 19 | 20 | > 테스트는 유연성, 유지보수성, 재사용성을 제공한다. 테스트 케이스가 있으면 변경이 쉬워지기 때문이다. 21 | 따라서 테스트 코드가 지저분하면 코드를 변경하는 능력이 떨어지며 코드 구조를 개선하는 능력도 떨어진다. 22 | 테스트 코드가 지저분할수록 실제 코드도 지저분해진다. 23 | 결국 테스트 코드를 잃어버리고 실제 코드도 망가진다. 24 | 25 | --- 26 | ### 모든 경우의 수를 테스트하고 있다. 27 | - 경계값을 테스트하도록 가이드한다. 28 | > 테스트 코드 또한 유지보수해야할 코드이다. 29 | 모든 경우의 수에 대해 테스트하는 것이 바람직하지 않다. 30 | 최소 경우의 수로 모든 경우를 테스트할 수 있는 방법을 찾는다. 31 | 경계 값에 대한 테스트를 철저히 한다. 32 | 33 | --- 34 | ### 테스트하기 힘든 구조로 구현하고 있다. 35 | - 테스트 가능한 부분과 가능하지 않은 부분을 분리하도록 가이드한다. 36 | > 이 메소드는 테스트하기 힘들다. 37 | 테스트 가능하도록 구현하려면 어떻게 구현하면 될까? 38 | 테스트하기 쉬운 부분과 테스트하기 어려운 부분을 분리해라. 39 | -------------------------------------------------------------------------------- /reviewguide/cleancode/ladder.md: -------------------------------------------------------------------------------- 1 | # 사다리 타기 2 | 3 | --- 4 | ## 리뷰어 가이드 5 | 이 미션의 핵심 목표는 두 번째 미션인 로또와 같이 TDD와 객체 설계 연습이 주 목적이다. 6 | 사다리타기 미션이 도메인 객체를 분리하는 것이 쉽지 않을 수 있는데 가능한 작은 단위로 분리할 수 있도록 피드백한다. 7 | 8 | ## 1단계 - 자바8 스트림, 람다, Optional 9 | 1단계는 간단하게 피드백 몇 개 남기고 바로 merge한 후 피드백 내용은 다음 단계에서 반영하도록 가이드한다. 10 | 11 | ## 2단계 - 사다리 타기 12 | 본격적인 코드 리뷰는 2단계이다. 13 | 단, 2단계의 경우 사다리 타기를 그리는 단계로 그리 복잡한 로직은 없다. 14 | 따라서 특별한 이슈가 없는 한 피드백 후 바로 merge해도 된다. 15 | 16 | ## 3단계, 4단계 - 사다리 타기 17 | 사다리 타기 미션에서 코드 리뷰를 집중한 단계는 사다리 타기를 실행하는 3단계이다. 18 | 단, 3단계의 경우도 피드백이 많지 않다면 4단계에서 리팩터링할 수 있도록 빠르게 merge한다. 19 | 20 | 사다리타기 미션과 관련해 추가로 피드백할 내용은 다음과 같다. 21 | 22 | #### 사다리타기 미션 중점 피드백 내용 23 | - 자바8의 스트림, 람다, Optional을 적절히 사용해 구현했는가? 24 | - 객체 설계가 적절한가? 25 | - 메소드(함수)의 인자를 2개 이하로 구현했는가? 3개 이상인 경우 줄이도록 피드백한다. 26 | - 객체지향 생활체조 규칙 중 다음 규칙에 대한 피드백 27 | - 규칙 4: 한 줄에 점을 하나만 찍는다.(디미터 법칙을 지키는 것을 의미한다.) 28 | - 규칙 6: 모든 엔티티를 작게 유지한다. 29 | - 규칙 7: 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다. 30 | - 규칙 9: 게터/세터/프로퍼티를 쓰지 않는다. 31 | 32 | 사다리타기 미션 피드백할 때 앞 단계 미션의 피드백 내용 또한 포함한다. 33 | 34 | #### 로또 미션 중점 피드백 내용 - 클래스 분리 35 | - 클래스를 작은 단위로 잘 분리했는가? 36 | - 객체지향 생활체조 규칙 중 다음 규칙에 대한 피드백 37 | - 규칙 3: 모든 원시값과 문자열을 포장한다. 38 | - 규칙 5: 줄여쓰지 않는다(축약 금지). 39 | - 규칙 8: 일급 콜렉션을 쓴다. 40 | - 도메인 객체에 대한 단위 테스트가 모두 존재하는가? 41 | - TDD로 구현했을 경우 도메인 객체에 대한 단위 테스트는 존재해야 한다. 42 | 43 | #### 자동차 경주 게임미션 중점 피드백 내용 - 메소드 분리 44 | - todo list를 잘 작성했는가? 45 | - 각 기능 단위로 commit log를 잘 남겼는가? 46 | - 코딩 컨벤션을 잘 지키면서 프로그래밍 했는가? 47 | - 메소드를 작은 단위로 잘 분리했는가?(인덴트를 1로 잘 유지했는가? 포함) 48 | - else 예약어를 쓰지 않았는가? 49 | - 함수(또는 메소드)의 길이가 10라인을 넘어가지 않도록 구현했는가? 50 | - 도메인 객체에 대한 단위 테스트를 잘 구현했는가? 51 | - MVC 구조에 맞도록 객체 분리를 했는가? 52 | -------------------------------------------------------------------------------- /reviewguide/cleancode/lms.md: -------------------------------------------------------------------------------- 1 | # LMS - 수강신청 2 | 3 | --- 4 | 5 | ## 리뷰어 가이드 6 | ## 1단계 7 | 1단계 미션이 레거시 코드 리팩토링하는 미션으로 서비스 레이어의 코드를 도메인 객체로 리팩토링하는 미션이다. 8 | 지금까지 학습한 내용을 실무에 적용해보는 상당히 중요한 미션인 만큼 도메인 객체로 로직 분리를 잘 하도록 리뷰한다. 9 | 가능하면 리뷰어가 판단하기에 만족하는 수준이 될 때까지 피드백을 남긴다. 10 | QnaService의 결과 코드는 다음과 같은 구조가 되도록 피드백 하면 좋겠다. 11 | 12 | ``` 13 | @Transactional 14 | public void deleteQuestion(User loginUser, long questionId) throws CannotDeleteException { 15 | Question question = findQuestionById(questionId); 16 | List deleteHistories = question.delete(loginUser); 17 | deleteHistoryService.saveAll(deleteHistories); 18 | } 19 | ``` 20 | 21 | ## 2단계 22 | 2단계 요구사항에 대한 비지니스 로직을 도메인 모델 객체에 구현하는 경험이다. 23 | 기존에 비지니스 레이어(Service 또는 Manager라 불리는 클래스)에 로직을 구현하는 것이 일반적이다. 24 | 1단계 경험과 같이 비지니스 로직을 도메인 객체에 잘 구현하는지에 대해 집중해서 피드백한다. 25 | 2단계는 데이터베이스에 대한 CRUD는 없다. 26 | 27 | ## 3단계 28 | 3단계는 2단계에서 구현한 도메인 객체를 데이터베이스와 매핑하고, CRUD를 진행하는 단계이다. 29 | 3단계에서 집중적으로 피드백할 부분은 2단계에서 구현한 도메인 객체를 최대한 깨트리지 않으면서 데이터베이스와 매핑하는 부분을 집중 피드백한다. 30 | 31 | ## 4단계 32 | 현장에서 자주 발생하는 테이블 칼럼에 변경사항이 발생했을 때의 레거시 코드 리팩터링 경험을 하는 단계이다. 33 | 요구사항이 변경되면서 데이터베이스 테이블의 칼럼에 변화가 있는 경우이다. 34 | 코드 리팩터링과 같이 테이블에 변경이 발생하더라도 점진적인 리팩터링을 하는 것이 이 단계의 핵심 목표이다. 35 | 점진적이고, 안정적으로 레거시 코드를 리팩터링하려면 항상 AS-IS와 TO-BE 데이터가 공존하는 순간이 필요하다. 36 | 37 | 리뷰이와 소통할 때 점진적인 리팩터링을 어떻게 진행했는지에 대해 이야기 나눠보면 서로의 성장에 도움이 될 것이다. 38 | 39 | -------------------------------------------------------------------------------- /reviewguide/cleancode/lotto.md: -------------------------------------------------------------------------------- 1 | # 로또 2 | 3 | --- 4 | ## 리뷰어 가이드 5 | 로또 미션의 핵심 목표는 TDD 기반으로 프로그래밍하는 경험과 클래스를 분리하는 리팩터링 경험이다. 6 | 특히 클래스 분리에 대한 두려움과 거부감이 있기 때문에 가능한 작은 단위로 분리하도록 피드백한다. 7 | TDD 기반으로 프로그래밍한 경험은 도메인 객체에 대한 단위 테스트를 포함하고 있는지 확인한다. 8 | 9 | ## 1단계 - 문자열 계산기 10 | 1단계는 단위 테스트의 테스트 케이스를 작은 단위로 분리했는지 확인한다. 11 | 간단하게 피드백 몇 개 남기고 바로 merge한 후 피드백 내용은 다음 단계에서 반영하도록 가이드한다. 12 | 13 | ## 2단계, 3단계, 4단계 - 로또 14 | 본격적인 코드 리뷰는 2단계부터이다. 15 | 로또 미션에서 코드 리뷰를 집중한 단계는 2단계와 3단계이다. 16 | 도메인 객체에 대한 단위 테스트가 있는지도 중요하지만 그 보다 도메인 객체를 작은 단위로 잘 분리하고 있는지 확인한다. 17 | 18 | 두 번째 미션인 로또에서 중점적으로 리뷰할 내용은 다음과 같다. 19 | 20 | #### 로또에서 추가적으로 봤으면 하는 내용 21 | - 클래스를 작은 단위로 잘 분리했는가? 22 | - 객체지향 생활체조 규칙 중 다음 규칙에 대한 피드백 23 | - 규칙 3: 모든 원시값과 문자열을 포장한다. 24 | - 규칙 5: 줄여쓰지 않는다(축약 금지). 25 | - 규칙 8: 일급 콜렉션을 쓴다. 26 | - 도메인 객체에 대한 단위 테스트가 모두 존재하는가? 27 | - TDD로 구현했을 경우 도메인 객체에 대한 단위 테스트는 존재해야 한다. 28 | 29 | #### 자동차경주 게임의 모든 내용은 기본으로 포함 30 | - todo list를 잘 작성했는가? 31 | - 각 기능 단위로 commit log를 잘 남겼는가? 32 | - 코딩 컨벤션을 잘 지키면서 프로그래밍 했는가? 33 | - 메소드를 작은 단위로 잘 분리했는가?(인덴트를 1로 잘 유지했는가? 포함) 34 | - else 예약어를 쓰지 않았는가? 35 | - 함수(또는 메소드)의 길이가 10라인을 넘어가지 않도록 구현했는가? 36 | - 도메인 객체에 대한 단위 테스트를 잘 구현했는가? 37 | - MVC 구조에 맞도록 객체 분리를 했는가? 38 | -------------------------------------------------------------------------------- /reviewguide/cleancode/racingcar.md: -------------------------------------------------------------------------------- 1 | # 자동차 경주 게임 2 | 3 | --- 4 | ## 리뷰어 가이드 5 | 자동차 경주 게임 미션의 핵심 목표는 단위 테스트 경험과 메소드를 분리해보는 경험이다. 6 | 클래스 분리는 다소 부족하더라도 메소드 분리와 관련해 집중적으로 피드백주시면 좋겠다. 7 | 8 | ## 1단계 9 | 1단계는 Github 기반으로 온라인 코드 리뷰하는 경험과 JUnit 사용법을 익혀 단위 테스트하는 경험이 주 목적이다. 10 | 1단계 리뷰 요청은 1, 2개의 피드백 후 바로 approve & merge한다. 11 | 1단계는 좋은 피드백보다 가능한 빠르게 merge하는 것이 주 목적이다. 12 | 13 | ## 2단계 - 문자열 덧셈 계산기 14 | 2단계는 단위 테스트를 구현하고, 메소드를 분리하는 리팩터링 경험이 주 목적이다. 15 | 단위 테스트와 메소드를 분리에 대한 피드백 몇 개 남기고 바로 merge한 후 피드백 내용은 다음 단계에서 반영하도록 가이드 주면 좋겠다. 16 | 1단계와 2단계 사이클을 빠르게 경험해 온라인 코드 리뷰가 가능하도록 하는 것이 더 중요하다. 17 | 18 | ## 3단계 - 자동차 경주 게임 19 | 본격적인 코드 리뷰는 3단계부터 진행하면 된다. 20 | 단, 3단계의 경우 그리 복잡한 로직은 없다. 21 | 따라서 특별한 이슈가 없는 한 피드백 후 바로 merge해도 된다. 22 | 23 | ## 4단계, 5단계 - 자동차 경주 게임 24 | 자동차 경주 게임 미션에서 코드 리뷰를 집중한 단계는 우승자 로직을 포함하고 있는 4단계이다. 25 | 단, 4단계의 경우도 피드백이 많지 않다면 5단계에서 리팩터링할 수 있도록 빠르게 merge한다. 26 | 27 | 첫 번째 미션인 자동차 경주 게임에서 중점적으로 리뷰할 내용은 다음과 같아요. 28 | 29 | - todo list를 잘 작성했는가? 30 | - 각 기능 단위로 commit log를 잘 남겼는가? 31 | - 코딩 컨벤션을 잘 지키면서 프로그래밍 했는가? 32 | - 메소드를 작은 단위로 잘 분리했는가?(인덴트를 1로 잘 유지했는가? 포함) 33 | - else 예약어를 쓰지 않았는가? 34 | - 함수(또는 메소드)의 길이가 10라인을 넘어가지 않도록 구현했는가? 35 | - 도메인 객체에 대한 단위 테스트를 잘 구현했는가? 36 | - MVC 구조에 맞도록 객체 분리를 했는가? 37 | 38 | 이 두가지 원칙을 통해 메소드를 분리해 메소드가 한 가지 작업만 담당하도록 구현하는 연습을 목표로 한다. 39 | 이 같은 원칙 아래에서 **메소드의 라인 수를 15라인**이 넘지 않도록 구현한다. 40 | -------------------------------------------------------------------------------- /reviewguide/flutter-begin/card-flip.md: -------------------------------------------------------------------------------- 1 | ### 1단계 2 | - `Stream` 이용시 불편한 부분 잘 유도 3 | - Stream은 getter로 처리하도록 https://github.com/next-step/flutter-card-flip/pull/1#discussion_r962332628 4 | - 데이터를 전달하기보다는 `State` 객체를 만들어서 전달하도록 유도. (추후에 bloc으로 교체할 때 더 자연스럽게 전환) 5 | 6 | ### 2단계 7 | - Cubit과 Bloc의 개념 및 용도 차이 설명 https://github.com/next-step/flutter-card-flip/pull/2#pullrequestreview-1098398775 8 | - 굳이 Bloc 사용으로 유도하지 않으셔도 됩니다.(3주차 3단계 과제) -------------------------------------------------------------------------------- /reviewguide/flutter-begin/movie-list.md: -------------------------------------------------------------------------------- 1 | ### 1단계 2 | - model, repository, bloc 디렉토리 구조를 잘 지켰는지 3 | - context.read() 설명 4 | - flutter_bloc 적용. Cubit 권장. (3단계에서 Bloc 이용 권장) 5 | - bloc으로 다양한 케이스 처리할 때 method로 처리하였다면 Builder Widget을 구현해보도록 유도. 1단계에 코멘트가 많다면 이 내용은 2단계에 해주셔도 좋습니다. 6 | 7 | ### 2단계 8 | - Navigator 사용. 화면 전환시 파라미터 전달하는 법 9 | 10 | ### 3단계 11 | - Bloc과 Cubit에 대한 설명 https://github.com/next-step/flutter-movie-list/pull/4#discussion_r976607134 -------------------------------------------------------------------------------- /reviewguide/flutter-begin/sample.md: -------------------------------------------------------------------------------- 1 | ### 1단계 2 | - 1주차는 Dart 언어에 익숙해지는 시기로 생각합니다. 따라서 [https://dart.dev/guides/language/effective-dart](https://dart.dev/guides/language/effective-dart) 를 참고해주시면 좋을 것 같습니다. 3 | - buildMethod -> Class로 변경하면서 named paramter 부분 설명이 있으면 좋겠습니다. 4 | https://dart.dev/guides/language/language-tour#parameters 5 | - private 필드 생성자로 초기화하기 6 | 7 | ```dart 8 | SampleClass({required Int data}) 9 | : _data = data; 10 | ``` 11 | 12 | ### 2단계 13 | - 위젯을 적절한 위치에서 잘 위치하고 있는지, `context` 역할 14 | - https://github.com/next-step/flutter-cart-sample/pull/2 15 | 16 | ### 3단계 17 | - `dispose` 사용 하도록 18 | - `Provider`, `Provider.value` 동작 차이 -------------------------------------------------------------------------------- /reviewguide/fw-java/README.md: -------------------------------------------------------------------------------- 1 | # 만들면서 배우는 Spring 소개 2 | 3 | ## 만들면서 배우는 Spring 학습 목표 4 | #### 기술적인 측면 5 | 1. 웹 서버를 직접 만들어 보는 경험을 통해 HTTP에 대한 이해도를 높인다. 6 | 2. MVC, Bean 컨테이너, AOP를 직접 구현해 보는 경험을 통해 Spring 프레임워크의 내부 동작 원리에 대한 이해도를 높인다. 7 | 3. 나만의 라이브러리를 직접 구현해 보는 경험을 통해 업무에서 발생하는 중복 코드를 제거하는 역량을 쌓는다. 8 | 4. 웹 서버, 라이브러리, 프레임워크를 구현하면서 TDD, 클린 코드, 객체지향설계에 대한 연습을 한다. 9 | 10 | #### 기술 외적인 측면 11 | 1. 프로그래밍 자체가 얼마나 재미있는 활동인지 경험 12 | 2. 효과적으로 프로그래밍을 학습하는 방법을 경험 13 | 3. 프로그래머로 어떻게 성장하고, 어떻게 살아갈 것인지 14 | 15 | --- 16 | ## 미션별 리뷰어 가이드 17 | - [HTTP 이해 - 웹 서버 구현](./was.md) 18 | - [MVC - @MVC 프레임워크 구현](./mvc.md) 19 | - [나만의 라이브러리 구현](./library.md) 20 | - [DI - DI 프레임워크 구현](./di.md) 21 | - [Aspect OP](./aop.md) 22 | 23 | --- 24 | ## 리뷰어 -> 수강생 상호 평가 25 | - 팀 동료로 채용한다면 같이 일하고 싶은 개발자인가?(10점 만점) 26 | - 코드 리뷰를 하면서 느낀 점이 있다면 의견을 남겨주세요.(예. 피드백을 반영하는 역량이 뛰어나 앞으로 성장 가능성이 높아 보인다. 리뷰를 하면서 의견을 주고 받는 시간이 너무 즐거웠다.) 27 | 28 | --- 29 | #### 팀 동료로 채용한다면 같이 일하고 싶은 개발자인가?(현재 역량 파악, 성장 잠재력) 30 | - 9점 ~ 10점: 강한 인사이트를 주는 코드와 온라인 토론을 통해 같이 성장하는 느낌을 받는 경우. 리뷰어와 비슷한 수준의 역량이라고 판단되는 경우 31 | - 정말 같이 일하고 싶은 느낌이 들게 하는 수강생. 온라인 토론을 커뮤니케이션 역량 또한 좋다는 느낌을 받는 경우 32 | - 이미 일정 수준의 역량을 보유하고 있는 상태이면서, 간혹 작은 피드백이 나오면 깊게 고민하는 역량을 갖춘 경우 33 | - 7점 ~ 8점: 특별히 부족한 점은 없지만 그렇다고 특출난 점이 보이지 않는 경우 34 | - 리뷰어의 역량 또는 리뷰어와 같이 일하고 있는 회사 개발자들의 역량에 비해 다소 부족한 역량이라 판단되는 경우 35 | - 현재는 부족한 점이 있지만 로드맵을 제시하고, 피드백을 준다면 빠르게 성장할 가능성이 높아 보이는 수강생 36 | - 5점 ~ 6점: 스스로의 힘으로 성장하기 보다 단순 피드백에 의존해 개선되는 느낌을 받는 경우. 37 | - 반복적인 피드백을 통해 조금씩 개선되는 느낌을 받는 경우 38 | - 미션을 마무리하는 단계에도 부족한 부분이 많다고 생각하는 경우 39 | - 1점 ~ 4점: 피드백을 통해 개선의 여지가 없어 보이는 경우 40 | 41 | --- 42 | ## 수강생 -> 리뷰어 상호 평가 43 | - 팀원으로 일할 수 있는 기회가 있다면 같이 일하고 싶은 리뷰어인가?(10점 만점) 44 | - 리뷰어의 성장을 위한 피드백이 있다면 남겨 주세요.(예. 피드백을 꼼꼼히 주어 실력을 향상하는데 많은 도움이 되었다. 정답을 미리 알려주기보다 정답을 찾아갈 수 있도록 방향만 정해주면 좋겠다.) 45 | -------------------------------------------------------------------------------- /reviewguide/fw-java/aop.md: -------------------------------------------------------------------------------- 1 | # AOP 구현 2 | 3 | --- 4 | ## 학습 목표 5 | - AOP 구현을 통해 AOP와 Proxy에 대한 이해도를 높인다. 6 | - AOP 구현을 통해 JDK Proxy와 CGlib Proxy 대한 이해도를 높인다. 7 | - Spring에서 FactoryBean과 ProxyFactoryBean의 동작 원리를 이해한다. 8 | - @Transactional의 동작 원리와 세부 속성을 이해한다. 9 | 10 | --- 11 | ## 리뷰어 가이드 12 | 이번 미션의 핵심 목표는 AOP 구현을 통해 AOP 개념에 대한 이해도를 높이는데 있다. 13 | Spring 프레임워크를 사용하다보면 자주 등장하는 Proxy, Aspect, Advice, PointCut와 같은 AOP 용어를 이해하는데 있다. 14 | 15 | AOP 구현에서 중점적으로 리뷰할 내용은 다음과 같다. 16 | 17 | - 1단계는 요구사항을 JDK Proxy와 CGlib Proxy로 구현했는지에 대해 확인하는 것만으로 충분하다. 18 | - 2단계는 앞 미션에서 구현한 Bean 컨테이너에 FactoryBean을 통해 다른 Type의 Bean을 주입하는지 확인하는 것만으로 충분한다. 19 | - 3단계는 AOP 미션 중 난이도가 가장 높은 단계로 @Transactional 설정이 정상 동작하는지만 확인하면 된다. 20 | - 4단계는 @ControllerAdvice가 정상 동작하는지 확인하면 된다. 21 | - 3, 4단계의 경우 프레임워크 구현에서 그치지 않고 사용자 관리, 질문/답변 게시판에 적용했는지 유무까지 확인해야 한다. 22 | 23 | 이 미션은 마지막 단계에 있는 미션이기도 하지만 난이도가 높은 미션이라 요구사항을 만족하는 것만으로도 충분히 의미있는 경험이다. 24 | 따라서 객체지향 설계, 클린 코드 구현, 테스트 코드 구현에 대한 우선 순위를 낮추고 요구사항을 만족하는지 확인하는데 집중한다. 25 | -------------------------------------------------------------------------------- /reviewguide/fw-java/di.md: -------------------------------------------------------------------------------- 1 | # DI 프레임워크 구현 2 | 3 | --- 4 | ## 학습 목표 5 | - Spring 프렝미워크의 Bean 컨테이너 동작 원리를 이해한다. 6 | - Spring 프렝미워크의 @Configuration 동작 방식과 필요성을 이해한다. 7 | 8 | --- 9 | ## 리뷰어 가이드 10 | 이번 미션의 핵심 목표는 Bean 컨테이너 구현을 통해 Spring 프레임워크의 Bean 컨테이너 동작 원리를 이해하는데 있다. 11 | 3, 4단계를 통해 @Configuration의 동작 원리를 이해하는 것도 중요하지만 1, 2단계의 Bean 컨테이너 구현만으로도 충분히 의미있다. 12 | 13 | DI 프레임워크 구현에서 중점적으로 리뷰할 내용은 다음과 같다. 14 | 15 | - 1, 3단계 구현에 대한 피드백은 객체지향 설계, 클린 코드 관점에서 부족한 부분을 집중적으로 피드백한다. 16 | - 1단계를 통해 Bean 컨테이너를 구현했는가? 17 | - 1, 2단계에서 구현한 Bean 컨테이너를 사용자 관리 서비스, 질문/답변 게시판에 적용했는가? 18 | - 3단계를 통해 @Configuration을 활용해 설정이 가능하도록 구현했는가? 19 | - 3, 4단계에서 구현한 부분을 바탕으로 DataSource를 설정하도록 적용했는가? 20 | 21 | 객체지향 설계, 클린 코드 관점에서 정말 심각하지 않다면 바로 merge 후 피드백한 내용 + 2, 4단계의 힌트를 참고해 리팩토링하도록 유도한다. 22 | 특히 프레임워크만 구현하고 적용하지 않는 수강생이 종종 있는데 2, 4단계 코드 리뷰할 때 적용 여부를 판단하고 피드백할 것을 추천한다. 23 | 24 | 객체지향 설계, 클린 코드 구현에 약간의 우선 순위를 두고 피드백하고, 일부 테스트 코드는 미리 제공하기 때문에 테스트 코드 구현에 대한 우선 순위는 조금 낮추어도 괜찮다. 25 | -------------------------------------------------------------------------------- /reviewguide/fw-java/library.md: -------------------------------------------------------------------------------- 1 | # 나만의 라이브러리 구현 2 | 3 | --- 4 | ## 학습 목표 5 | - 나만의 라이브러리를 구현하는 경험을 함으로써 중복을 제거하는 연습을 한다. 6 | - Spring MVC에서 View의 동작 원리를 이해한다. 7 | - Interceptor의 역할을 이해한다. 8 | 9 | --- 10 | ## 리뷰어 가이드 11 | 이번 미션의 핵심 목표는 JDBC의 중복을 제거하기 위해 나만의 JDBC 라이브러리를 구현해 보는 경험이다. 12 | 물론 1단계를 통해 View의 동작 원리, 4단계를 통해 Interceptor의 동작 원리를 이해하는 것도 중요하지만 2, 3단계가 이번 미션의 핵심이다. 13 | 14 | 나만의 라이브러리 구현에서 중점적으로 리뷰할 내용은 다음과 같다. 15 | 16 | - @MVC 프레임워크에 JsonView를 추가해 JSON 응답이 가능한가?(1단계) 17 | - 2, 3단계를 통해 JDBC의 중복을 모두 제거 했는가? 18 | - 특히 한 건의 데이터를 조회하는 queryForObject와 n건의 데이터를 조회하는 query에 중복을 제거했는가? 19 | - 나만의 라이브러리를 사용하는 개발자가 사용하기 편하도록 같은 역할을 하지만 다양한 인자를 전달하는 update 메서드를 제공하는가? 20 | - 오버로딩을 통해 다양한 인자를 전달해 같은 기능을 구현하지만 중복 코드는 없어야 한다. 21 | - 2, 3단계를 빠르게 진행했다면 자바 객체와 테이블 칼럼 이름이 같을 경우 자동으로 매팅해 주는 RowMapper를 추가하도록 추가 요구사항을 제시하는 것도 좋겠다. 22 | - 4단계는 Controller 전/후에 공통 작업을 처리하기 위한 Interceptor가 잘 동작하는가? 23 | 24 | 피드백을 할 때 고려할 1순위는 2, 3단계를 통해 나만의 라이브러리를 중복 코드 없이 사용하기 편하도록 구현했는가이다. 25 | 따라서 객체지향 설계, 클린 코드 구현, 테스트 코드 구현에 대한 우선 순위는 조금 낮추어도 괜찮다. 26 | -------------------------------------------------------------------------------- /reviewguide/fw-java/mvc.md: -------------------------------------------------------------------------------- 1 | # MVC - @MVC 프레임워크 구현 2 | 3 | --- 4 | ## 학습 목표 5 | - 레거시 MVC 코드 분석을 통해 서블릿 컨테이너의 동작 원리를 이해한다. 6 | - @MVC 프레임워크 구현을 통해 MVC 구조와 MVC의 각 역할을 이해한다. 7 | - 서로 다른 프레임워크를 통합하면서 점진적으로 리팩토링하는 경험을 한다. 8 | 9 | --- 10 | ## 리뷰어 가이드 11 | 이번 미션의 핵심 목표는 애노테이션 기반으로 MVC(이하 @MVC) 프레임워크를 구현하는데 있다. 12 | 자바 reflection API를 활용해 @MVC를 구현하고, Controller 인자 매핑을 함으로써 MVC의 동작 원리를 이해하는 것만으로도 충분한다. 13 | 14 | 1단계는 자바 reflection API를 활용하는 경험이기 때문에 피드백이 있더라도 바로 merge해도 된다. 15 | 1단계는 가능한 빠르게 merge해 주면 좋겠다. 16 | 17 | @MVC 프레임워크 구현에서 중점적으로 리뷰할 내용은 다음과 같다. 18 | 19 | - 2, 3단계를 @MVC 프레임워크가 동작 가능하도록 구현을 잘 했는가? 20 | - @MVC 프레임워크와 레거시 MVC 프레임워크가 함께 동작 가능하도록 구현했는가? 21 | - 힌트의 HandlerMapping 인터페이스와 같은 구조를 통해 통합했는가? 22 | - 이를 확인하는 가장 좋은 방법은 Controller의 일부 기능은 레거시 MVC에서 동작하고, 일부 기능은 @MVC에서 동작하는지를 확인한다. 23 | - 일부 수강생들은 @MVC 프레임워크만 구현하고 사용자 기능의 Controller를 새로 구현한 @MVC를 적용하지 않는 경우가 종종 있다. 24 | - @MVC 프레임워크가 Spring MVC의 구조와 유사한 구조로 구현했는가? 25 | - 힌트의 HandlerMapping, HandlerAdapter, HandlerExecution과 같은 구조로 구현했는가? 26 | - 4단계의 Controller 인자 매핑은 ArgumentResolver와 같은 인터페이스를 추가한 후 인자 타입에 따라 구현체를 구현했는가? 27 | 28 | 피드백을 할 때 고려할 1순위는 @MVC 프레임워크 구현을 통해 Spring MVC의 내부 동작 원리를 이해하도록 하는 것이다. 29 | 2순위는 기존의 프레임워크를 새로운 프레임워크로 점진적으로 리팩토링하도록 설계하고 구현하는 것이다. 30 | 따라서 1, 2순위 피드백에 집중하고, 객체지향 설계, 클린 코드 구현, 테스트 코드 구현에 대한 우선 순위는 조금 낮추어도 괜찮다. 31 | -------------------------------------------------------------------------------- /reviewguide/fw-java/was.md: -------------------------------------------------------------------------------- 1 | # HTTP 이해 - 웹 서버 구현 2 | 3 | --- 4 | ## 학습 목표 5 | - NEXTSTEP의 온라인 코드 리뷰 방법을 이해한다. 6 | - 웹 서버 구현을 통해 HTTP 이해도를 높인다. 7 | - 웹 서버 구현을 통해 서블릿 컨테이너의 역할과 내부 구조를 이해한다. 8 | - TDD로 웹 서버를 구현하면서 객체지향 설계 경험을 한다. 9 | 10 | --- 11 | ## 리뷰어 가이드 12 | 이번 미션의 핵심 목표는 웹 서버 구현을 통해 HTTP 이해도를 높이고, 서블릿 컨테이너의 내부 구조를 이해하는데 있다. 13 | 또한 웹 서버를 구현하면서 HTTP의 각 요소를 객체로 추상화하는 연습을 하기도 좋은 미션이다. 14 | 따라서 웹 서버를 서블릿 컨테이너 구조로 구현하고, 객체지향 설계 원칙을 지키면서 구현하도록 피드백하는 것에 집중한다. 15 | TDD도 주요 목표 중의 하나이지만 테스트 코드에 대한 피드백에 집중하지 않아도 된다. 16 | 17 | 1단계 리뷰 요청은 온라인 코드 리뷰를 경험하고, TDD를 맛보기하는 단계이기 때문에 피드백이 있더라도 바로 merge하는 것을 추천한다. 18 | 1단계는 가능한 빠르게 merge해 주면 좋겠다. 19 | 20 | 웹 서버 구현에서 중점적으로 리뷰할 내용은 다음과 같다. 21 | 22 | - 각 요구사항 단위로 commit log를 잘 남겼는가? 23 | - 코딩 컨벤션을 잘 지키면서 프로그래밍 했는가? 24 | 25 | 위 두 가지는 모든 미션에 공통으로 적용하는 요구사항이다. 26 | 27 | 이번 미션에서 중점적으로 코드 리뷰할 부분은 2, 3단계로 다음 내용에 집중해 리뷰한다. 28 | - 다형성을 활용해 클라이언트 요청 URL에 대한 분기 처리를 했는가?(힌트의 Map과 Controller 인터페이스) 29 | - 요청(힌트의 HttpRequest)과 응답(힌트의 HttpResponse)을 객체로 추상화했는가? 30 | - HTTP 요청과 응답의 각 요소들을 객체로 잘 추상화했는가? 31 | 32 | `테스트 가능한 부분과 테스트하기 어려운 부분을 잘 분리한 후 테스트 가능한 부분에 대한 테스트 코드가 있는가?`에 대해서는 우선 순위를 낮추어도 된다. 33 | 34 | 4단계까지 위 기준으로 피드백하고, 5단계의 경우는 Java에서 기본으로 제공하는 ThreadPoolExecutor를 활용해 ThreadPool 기능을 추가하는 경험을 하는 것이기 때문에 특별한 피드백 없이 미션을 마무리해도 된다. 35 | -------------------------------------------------------------------------------- /reviewguide/greetings.md: -------------------------------------------------------------------------------- 1 | ## 어떻게 활용할까요? 2 | 1) 상황에 맞는 인사말을 Ctrl+C, Ctrl+V 해 써먹습니다. 3 | 4 | ### 미션 시작 5 | - 00 님과 함께 할 수 있게 되어 무척 기쁜 마음입니다. :) 6 | 7 | ### 미션 종료 8 | - 00 님과의 시간이 정말 좋은 경험으로 남게 될 것 같아요. 00 님에게도 넥스트스탭과의 시간이 부디 그러하길 바랍니다. :) 9 | - 그동안 너무 고생하셨고, 오늘만큼은 발 쭉 뻗고 푹 주무시길 바랄게요. 10 | 11 | ### 코로나 시국 😷 12 | - 사회적 거리 두기가 다시 격상되었네요, 하지만 우리에겐 코딩할 시간이 늘어난 거겠죠. 13 | - 아마도 집에서 보내게 될 주말이지만, 넥스트스탭과 함께 명랑하고 활기차시길 바랍니다. -------------------------------------------------------------------------------- /reviewguide/infra-workshop/README.md: -------------------------------------------------------------------------------- 1 | ## 인프라공방 소개 2 | [인프라공방](https://edu.nextstep.camp/c/VI4PhjPA) 과정은 NEXTSTEP이 진행하는 재직자를 위한 인프라 교육 과정이다. 3 | 4주간 웹 서비스를 위한 인프라를 직접 만들어보며 필요한 지식을 학습하고 적용해본다. 이를 통해 현재의 아키텍처가 최선인지 반문하는 자세를 갖도록 과정을 설계했다. 4 | 5 | ## 인프라공방 학습 목표 6 | 1. 인프라를 구성해보며 필요한 OS, Network 등의 지식을 학습해본다. 7 | 2. 인프라를 운영하며 확인해야 할 요소들을 학습하고 직접 테스트해본다. 8 | 3. 안정적인 인프라를 구성해가며 성능 튜닝, SQL 최적화 등을 경험한다. 9 | 4. 쿠버네티스를 활용하여 장애내성있는 서비스를 구성하고 배포 파이프라인을 구성하여 지속적 통합을 경험해본다. 10 | 11 | --- 12 | ## 미션별 리뷰어 가이드 13 | - 1주차: [그럴듯한 인프라 만들기](./subway-deploy.md) 14 | - 2주차: [성능 진단하기](./monitoring.md) 15 | - 3주차: [안정적인 인프라 만들기](./performance-refactoring.md) 16 | - 4주차: [확장하는 인프라 만들기](./kubernetes.md) 17 | 18 | --- 19 | ## 리뷰어/수강생간 상호 평가 20 | 21 | --- 22 | #### 리뷰어 -> 수강생 평가 23 | - [현재 역량 파악]기술적인 역량으로 판단할 때 같이 일하고 싶은가?(5점 만점) 24 | - [성장 잠재력]피드백을 통해 성장하는 모습으로 볼 때 같이 일하고 싶은가?(5점 만점) 25 | - 리뷰를 하면서 느낀 점이 있다면 의견을 남겨주세요.(예. 피드백을 반영하는 역량이 뛰어나 앞으로 성장 가능성이 높아 보인다. 리뷰를 하면서 의견을 주고 받는 시간이 너무 즐거웠다.) 26 | 27 | --- 28 | #### 기술적인 역량으로 판단할 때 같이 일하고 싶은가?(현재 역량 파악) 29 | - 5점: 강한 인사이트를 주는 설계와 온라인 토론을 통해 같이 성장하는 느낌을 받는 경우 30 | - 정말 같이 일하고 싶은 느낌이 들게 하는 수강생. 온라인 토론을 커뮤니케이션 역량 또한 좋다는 느낌을 받는 경우 31 | - 4점: 회사 개발자 또는 팀 동료들과 비슷한 수준의 역량이라 판단되는 경우 32 | - 현재 자신이 일하고 있는 회사 동료들과 비슷한 역량을 가지고 있다고 판단되는 경우 33 | - 3점: 특별히 부족한 점은 없지만 그렇다고 특출난 점이 보이지 않는 경우 34 | - 현재 자신이 일하고 있는 회사 개발자들의 역량에 비해 다소 부족한 역량이라 판단되는 수강생 35 | - 2점: 스스로의 힘으로 성장하기 보다 단순 피드백에 의존해 개선되는 느낌을 받는 경우 36 | - 1점: 미션을 마무리하는 단계에도 부족하다 생각하는 경우 37 | 38 | --- 39 | #### 피드백을 통해 성장하는 모습으로 볼 때 같이 일하고 싶은가?(성장 잠재력) 40 | - 5점: 시작 단계부터 끝까지 피드백할 내용은 따로 없는 상태로 이미 일정 역량을 갖추었으며, 수강생의 추가적인 질문들로 유의미한 토론이 이루어진 경우 41 | - 이미 일정 수준의 역량(기술적인 역량 질문에서 4, 5점을 받은 분)을 보유하고 있는 상태이면서, 간혹 작은 피드백이 나오면 깊게 고민하는 역량을 갖춘 경우 42 | - 4점: 시작 단계는 부족한 점이 많았지만 피드백을 통해 빠르게 성장하는 경우 43 | - 현재는 부족한 점(기술적인 역량 질문에서 3, 4점을 받은 분)이 있지만 로드맵을 제시하고, 피드백을 준다면 빠르게 성장할 가능성이 높아 보이는 수강생 44 | - 3점: 시작 단계는 부족한 점이 많았지만, 피드백을 통해서만 개선되는 느낌을 받는 경우 45 | - 예를 들어 한 단계에서 1번 request changes 이하 혹은 DM 등의 소통으로도 단계를 소화하는 경우. 역량을 향상시키기 위해 노력하지만 성장하는 모습이 잘 보이지 않는 수강생 46 | - 2점: 반복적인 피드백을 통해 조금씩 개선되는 느낌을 받는 경우 47 | - 예를 들어 한 단계에서 2번 이상의 request changes 혹은 DM 등의 소통으로 단계를 소화하는 경우 48 | - 1점: 피드백을 통해 개선의 여지가 없어 보이는 경우 49 | 50 | --- 51 | #### 수강생 -> 리뷰어 평가 52 | - 팀원으로 일할 수 있는 기회가 있다면 같이 일하고 싶은 리뷰어인가?(10점 만점) 53 | - 리뷰어의 성장을 위한 피드백이 있다면 남겨 주세요.(예. 피드백을 꼼꼼히 주어 실력을 향상하는데 많은 도움이 되었다. 정답을 미리 알려주기보다 정답을 찾아갈 수 있도록 방향만 정해주면 좋겠다.) 54 | -------------------------------------------------------------------------------- /reviewguide/infra-workshop/kubernetes.md: -------------------------------------------------------------------------------- 1 | ## 확장하는 인프라 만들기 2 | 3 | ### 1. 쿠버네티스로 구성하기 4 | - 쿠버네티스 구성요소 (Pod, Service, Ingress 등을 활용하여) 애플리케이션을 서비스하고 있는지 5 | 6 | - 쿠버네티스 클러스터에 대해 스트레스 테스트를 진행하였는지 7 | 8 | - 쿠버네티스 클러스터 구성이 합리적인지 9 | 10 | ### 2. 클러스터 운영하기 11 | 12 | - 모니터링 시스템 알림 설정 기준이 합리적인지 13 | 14 | - hpa, auto scaling 설정이 합리적인지 15 | - 설정 후 Stress Test를 진행해보았는지 16 | 17 | - ResourceQuota, PodDisruptionBudget, Affinity 설정이 합리적인지 18 | 19 | - 부하 테스트, Stress 테스트 결과를 제대로 이해하고 있는지 20 | -------------------------------------------------------------------------------- /reviewguide/infra-workshop/monitoring.md: -------------------------------------------------------------------------------- 1 | ## 서비스 진단하기 2 | 3 | ### 1. 인프라 운영하기 4 | - 애플리케이션 로그를 작성했는지 5 | - 회원가입, 로그인 등에 로깅을 추가했는지 6 | - JSON 로그를 사용하여 도메인 이벤트 로그를 수집했는지 7 | - 로깅레벨을 적절히 설정했는지 8 | - log rotate 설정을 했는지 9 | 10 | - Cloudwatch 대시보드를 구성했는지 11 | 12 | ### 2. 성능 테스트 13 | - 웹 성능 예산을 정한 기준이 합리적인지 14 | 15 | - 개선방안을 웹 성능 예산을 바탕으로 합리적으로 도출했는지 16 | 17 | - 시나리오를 작성하고 올바르게 Smoke Test를 진행했는지 18 | 19 | - 부하테스트 목표값(rps)에 맞춰 부하테스트를 진행했는지 20 | 21 | - Stress Test를 통해 현재 인프라의 한계치를 확인했는지 22 | -------------------------------------------------------------------------------- /reviewguide/infra-workshop/performance-refactoring.md: -------------------------------------------------------------------------------- 1 | ## 안정적인 서비스 만들기 2 | 3 | ### 1. 화면 응답 개선하기 4 | - HTTP 캐싱 적용 요구사항을 수행했는지 5 | 6 | - 개선방안을 각각 적용하고 부하테스트를 통해 계측했는지 7 | 8 | - Load Test, Stress Test 목적에 맞게 결과를 도출했는지 9 | - 개선 후 Load Test를 동일하게 진행했을 경우 latency가 어느정도 개선되었는지를 확인 10 | - 개선 후 Stress Test를 진행했을 때 한계점이 증가되었음을 확인 11 | 12 | - 웹 서버 13 | - 정적 파일 캐싱을 적용했는지 14 | - http2 적용했는지 15 | - gzip 적용했는지 16 | - worker connection 수치를 조정했는지 17 | - was 18 | - 경로찾기에 대해 redis 설정을 적용했는지 19 | 20 | ### 2. 조회 성능 개선하기 21 | - 즐겨찾기 페이지에 페이징 쿼리를 적절히 적용했는지 22 | 23 | - 데이터베이스 이중화를 구성했는지 24 | - 조회 메서드에 @Transactional(readOnly = true)를 적용했는지 25 | - 부하테스트를 진행해보고 변화를 계측했는지 26 | - 부하테스트 중에 master를 stop 시켜보았는지 27 | 28 | - 인덱스 실습에 대한 해설은 강의자료를 통해 스스로 학습할 수 있도록 구성해두었어요. 29 | -------------------------------------------------------------------------------- /reviewguide/infra-workshop/subway-deploy.md: -------------------------------------------------------------------------------- 1 | ## 그럴듯한 서비스 만들기 목표 2 | 3 | - 리뷰를 주고 받는 사이클을 경험해봅니다. 4 | - 망을 구성하고 개발 / 배포 환경을 구성해봅니다. 5 | - pem 키는 구글 드라이브로 관리 6 | 7 | ### 1. 망 구성하기 (네트워크 구성) 8 | 9 | - ping, port, http 요청 확인 10 | 11 | - URL로 서버에 접속 가능한지 확인 12 | - 외부망을 위한 라우팅 테이블에만 인터넷 게이트웨이가 연결되어 있는지 13 | 14 | - 요구사항에 맞게 서브네팅했는지 확인 15 | 16 | - SG이 적절하게 설정되었는지 확인 17 | - 외부망/내부망은 관리망에만 22번 포트를 오픈했는지 18 | - 관리망은 특정 IP에 대해서만 22번 포트를 오픈했는지 19 | - 전체 대역대에 80, 8080 등의 포트만 오픈했는지 20 | 21 | 22 | ### 2. 배포하기 (개발 환경 세팅, 컨테이너) 23 | 24 | - TLS 설정 확인 25 | - 외부망 SG는 443만 오픈했는지, 만약 다른 포트를 오픈했다면 443 리다이렉트 설정을 했는지 26 | - HTTPS로 정상적으로 연결되는지 27 | 28 | - 운영 DB를 내부망에 구성했는지 29 | 30 | - Junit Test, 로컬, 운영 환경에 따라 설정을 나눠서 관리하는지 31 | 32 | - flyway를 사용하여 스키마 버전관리를 하고 있는지 33 | -------------------------------------------------------------------------------- /reviewguide/kakao/README.md: -------------------------------------------------------------------------------- 1 | ## 학습 목표 2 | #### 기술적인 측면 3 | 1. TDD 기반으로 애플리케이션을 개발하는 경험. 4 | 2. 클린코드를 통해 유지보수하기 좋은 코드를 구현하는 경험. 5 | 3. Spring 프레임워크 기반으로 웹 애플리케이션을 개발하는 경험. 6 | 7 | #### 기술 외적인 측면 8 | 1. 프로그래밍 자체가 얼마나 재미있는 활동인지 경험 9 | 2. 효과적으로 프로그래밍을 학습하는 방법을 경험 10 | 3. 프로그래머로 어떻게 성장하고, 어떻게 살아갈 것인지 11 | 12 | --- 13 | ## 미션별 리뷰어 가이드 14 | - [자동차 경주 - 단위 테스트](./racingcar.md) 15 | - [로또 - TDD](./lotto.md) 16 | - [웹 애플리케이션 서버 - HTTP 이해](./was.md) 17 | - [방탈출 예약 관리 - Spring Basic](./roomesacape-reservation.md) 18 | - [방탈출 인증 관리 - Spring Web MVC](./roomesacape-auth.md) 19 | - [방탈출 예약 대기 - Spring Core](./roomesacape-waiting.md) -------------------------------------------------------------------------------- /reviewguide/kakao/lotto.md: -------------------------------------------------------------------------------- 1 | # 로또 2 | 3 | --- 4 | ## 리뷰어 가이드 5 | 이번 주차의 가장 큰 목표는 TDD 경험과 클래스를 극단적으로 분리해 객체지향 설계 경험을 하는 것이다. 6 | 특히 도메인 객체에 대한 단위 테스트가 빠진 부분은 없는지, 7 | 객체의 상태 데이터를 꺼내지(get) 않고 객체에 메시지를 잘 보내고 있는지, 8 | 객체지향 생활체조 원칙을 잘 지키면서 클래스를 분리했는지 집중적으로 피드백한다. 9 | 10 | ## 자동차 경주 게임의 모든 내용은 기본으로 포함 11 | * todo list를 잘 작성했는가? 12 | * 각 기능 단위로 commit log를 잘 남겼는가? 13 | * 코딩 컨벤션을 잘 지키면서 프로그래밍 했는가? 14 | * 메소드를 작은 단위로 잘 분리했는가?(인덴트를 1로 잘 유지했는가? 포함) 15 | * else 예약어를 쓰지 않았는가? 16 | * 함수(또는 메소드)의 길이가 10라인을 넘어가지 않도록 구현했는가? 17 | * 도메인 객체에 대한 단위 테스트를 잘 구현했는가? 18 | * MVC 구조에 맞도록 객체 분리를 했는가? 19 | 20 | ## 로또에서 추가적으로 봤으면 하는 내용 21 | * 클래스를 작은 단위로 잘 분리했는가? 22 | * 객체지향 생활체조 규칙 중 다음 규칙에 대한 피드백 23 | * 규칙 3: 모든 원시값과 문자열을 포장한다. 24 | * 규칙 5: 줄여쓰지 않는다(축약 금지). 25 | * 규칙 8: 일급 콜렉션을 쓴다. 26 | * 도메인 객체에 대한 단위 테스트가 모두 존재하는가? 27 | * TDD로 구현했을 경우 도메인 객체에 대한 단위 테스트는 존재해야 한다. 28 | 29 | --- 30 | ## 경험해야할 학습 목표 31 | - TDD 기반으로 프로그래밍하는 경험 32 | - 메소드 분리 + 클래스를 분리하는 리팩토링 경험 33 | - 점진적으로 리팩토링하는 경험 34 | 35 | --- 36 | ## 경험할 객체지향 생활 체조 원칙 37 | - 규칙 1: 한 메서드에 오직 한 단계의 들여쓰기만 한다. 38 | - 규칙 2: else 예약어를 쓰지 않는다. 39 | - **규칙 3: 모든 원시값과 문자열을 포장한다.** 40 | - **규칙 5: 줄여쓰지 않는다(축약 금지).** 41 | - **규칙 8: 일급 콜렉션을 쓴다.** 42 | -------------------------------------------------------------------------------- /reviewguide/kakao/racingcar.md: -------------------------------------------------------------------------------- 1 | # 자동차 경주 게임 2 | 3 | --- 4 | ## 리뷰어 가이드 5 | 첫 번째 미션의 가장 큰 목표는 TDD 경험과 메소드를 분리해보는 경험이다. 6 | 클래스 분리는 다소 부족하더라도 메소드 분리와 관련해 집중적으로 피드백주시면 좋겠다. 7 | 8 | 구현한 코드가 정말 심각한 수준이 아니라면 다음과 같이 진행할 것을 추천한다. 9 | * 1차 피드백을 남기면서 merge. 피드백을 다음 단계 진행할 때 반영하도록 가이드. 10 | * 2차 리뷰 요청에 대해서는 리뷰어분들이 만족하는 수준까지 핑퐁을 주고 받은 후 merge 11 | 12 | 첫 번째 미션인 자동차 경주 게임에서 중점적으로 리뷰할 내용은 다음과 같아요. 13 | 14 | - todo list를 잘 작성했는가? 15 | - 각 기능 단위로 commit log를 잘 남겼는가? 16 | - 코딩 컨벤션을 잘 지키면서 프로그래밍 했는가? 17 | - 메소드를 작은 단위로 잘 분리했는가?(인덴트를 1로 잘 유지했는가? 포함) 18 | - else 예약어를 쓰지 않았는가? 19 | - 함수(또는 메소드)의 길이가 10라인을 넘어가지 않도록 구현했는가? 20 | - 도메인 객체에 대한 단위 테스트를 잘 구현했는가? 21 | - MVC 구조에 맞도록 객체 분리를 했는가? 22 | 23 | --- 24 | ## 경험해야할 학습 목표 25 | - Github 기반으로 온라인 코드 리뷰하는 경험 26 | - JUnit 사용법을 익혀 단위 테스트하는 경험 27 | - 자바 code convention을 지키면서 프로그래밍하는 경험 28 | - 메소드를 분리하는 리팩토링 경험 29 | 30 | --- 31 | ## 경험할 객체지향 생활 체조 원칙 32 | 이번 과정을 통해 연습할 원칙은 다음 두 가지이다. 33 | 34 | - 규칙 1: 한 메서드에 오직 한 단계의 들여쓰기만 한다. 35 | - 규칙 2: else 예약어를 쓰지 않는다. 36 | 37 | 이 두가지 원칙을 통해 메소드를 분리해 메소드가 한 가지 작업만 담당하도록 구현하는 연습을 목표로 한다. 38 | 이 같은 원칙 아래에서 **메소드의 라인 수를 15라인**이 넘지 않도록 구현한다. 39 | -------------------------------------------------------------------------------- /reviewguide/kakao/roomesacape-auth.md: -------------------------------------------------------------------------------- 1 | # 방탈출 - 인증 관리 2 | 3 | --- 4 | ## 리뷰어 가이드 5 | 이번 주차의 가장 큰 목표는 웹 애플리케이션에서 인증을 구현하고 이를 이용한 추가 기능을 구현하는 것이다. 6 | 방탈출 예약 관리 기능이 뺘대 코드로 제공되며 인증을 구현하여 사용자가 직접 예약을 하게 하고 관리자 전용 기능을 구분하게 한다. 7 | 인증을 구현할 때 Spring Web MVC를 이용하게 되는데 인증 프로세스가 잘 구현되었는지를 확인하면서 Spring Web MVC 기능이 적절하게 사용되었는지를 함께 피드백한다. 8 | 9 | --- 10 | ## 경험해야할 학습 목표 11 | - 인증 기능을 구현하여 인증 프로세스에 대한 이해도 향상 12 | - Spring Web MVC에서 제공하는 기능의 필요성을 경험하고 효과적으로 활용하는 경험 13 | - 학습 테스트를 통해 스프링 프레임워크를 익히고 미션을 통해 실제로 적용해보는 경험 14 | 15 | --- 16 | ## 리뷰 포인트 17 | 18 | 구현한 코드가 정말 심각한 수준이 아니라면 다음과 같이 진행할 것을 추천한다. 19 | * 1차 피드백을 남기면서 merge. 피드백을 다음 단계 진행할 때 반영하도록 가이드. 20 | * 2차 리뷰 요청에 대해서는 리뷰어분들이 만족하는 수준까지 핑퐁을 주고 받은 후 merge 21 | 22 | ### 1, 2단계 23 | - 토큰을 생성하고 토큰을 읽어오는 기능이 잘 구현되었는지를 확인하고 이 부분 위주로 피드백 24 | - 추가 기능 요구사항의 예외처리가 잘 구현되는지 확인 25 | - 인증 처리 시 HandlerMethodArgumentResolver 등 스프링이 제공하는 적절한 기능을 사용하는지 확인 26 | 27 | ### 3단계 28 | - 현업에서 피드백을 준다고 생각하고 본인 팀의 코딩 컨벤션이나 스타일에 맞게 리뷰 29 | - 기능 요구사항 추가로 변경되는 부분을 Controller Test를 통해 검증할 수 있음을 피드백 30 | - 인증 처리 시 HandlerInterceptor 등 스프링이 제공하는 적절한 기능을 사용하는지 확인 31 | -------------------------------------------------------------------------------- /reviewguide/kakao/roomesacape-reservation.md: -------------------------------------------------------------------------------- 1 | # 방탈출 - 예약 관리 2 | 3 | --- 4 | ## 리뷰어 가이드 5 | 이번 주차의 가장 큰 목표는 스프링 프레임워크를 이용하여 웹 애플리케이션을 만들어 보는 경험을 하는 것이다. 6 | 이를 위해 대 코드로 제공되는 콘솔 애플리케이션을 웹 애플리케이션으로 전환하고 추가 기능을 구현하는 미션이 제공된다. 7 | 스프링 프레임워크를 처음 접하거나 경험이 적은 경우 맹목적으로 작성하는 패턴화된 코드를 만드는 경우가 많은데, 8 | 각 코드와 패키지들이 어떠한 목적으로 만들어졌는지를 생각할 수 있게 피드백한다. 9 | 10 | --- 11 | ## 경험해야할 학습 목표 12 | - 뼈대 코드로 제공되는 콘솔 애플리케이션을 웹 애플리케이션으로 전환하고 추가 기능을 구현하는 경험 13 | - 특정 프레임워크에 의존하는 코드를 작성하는 경우 확장에 어려움을 겪을 수 있다는 깨달음 14 | - 스프링이 제공해주는 기능의 필요성을 경험하고 없는 경우 무엇이 불편한지를 경험 15 | - 학습 테스트를 통해 스프링 프레임워크를 익히고 미션을 통해 실제로 적용해보는 경험 16 | 17 | --- 18 | ## 리뷰 포인트 19 | 20 | 구현한 코드가 정말 심각한 수준이 아니라면 다음과 같이 진행할 것을 추천한다. 21 | * 1차 피드백을 남기면서 merge. 피드백을 다음 단계 진행할 때 반영하도록 가이드. 22 | * 2차 리뷰 요청에 대해서는 리뷰어분들이 만족하는 수준까지 핑퐁을 주고 받은 후 merge 23 | 24 | ### 1단계 25 | - 웹 요청/응답 처리 시 스프링이 제공하는 적절한 기능을 사용하는지 확인 26 | - 콘솔 애플리케이션과 웹 애플리케이션의 중복 코드는 허용(다음 단계에서 다룰 예정) 27 | 28 | ### 2단계 29 | - 데이터베이스 접근 시 스프링이 제공하는 적절한 기능을 사용하는지 확인 30 | - 미리 계층을 나누어 구현 할 경우 왜 필요한지 물어봐서 맹목적으로 작성하는 패턴화된 코드에 대한 경각심을 주기 31 | 32 | ### 3단계 33 | - 콘솔 애플리케이션과 웹 애플리케이션에서의 중복코드가 적절히 제거되었는지 확인 34 | - 비즈니스 로직이 콘솔이나 웹에 의존적이여서 재사용에 용이하지 않은 코드가 있는 경우 확인 35 | - 코드 재사용 시 역할(웹 처리/디비 처리 등)별로 계층을 나누어 구현할 수 있음을 코멘트로 전달 36 | -------------------------------------------------------------------------------- /reviewguide/kakao/roomesacape-waiting.md: -------------------------------------------------------------------------------- 1 | # 방탈출 - 예약 대기 2 | 3 | --- 4 | ## 리뷰어 가이드 5 | 이번 주차의 가장 큰 목표는 복잡한 요구사항을 가진 웹 애플리케이션 구현을 경험하는 것이다. 6 | 추가 기능 구현 시 발생하는 코드 수정과 예외 처리를 Test로 검증할 수 있도록 피드백하고, 7 | Spring Configuration, Data Access 등의 기능을 학습하고 설계와 리팩터링도 함께 고민할 수 있도록 피드백한다. 8 | 9 | --- 10 | ## 경험해야할 학습 목표 11 | - Spring Configuration, Data Access 학습을 바탕으로 한 설계 및 리팩터링 경험 12 | - 요구사항 변경으로 발생하는 코드 수정을 Spring Test를 활용하여 검증하는 경험 13 | - 학습 테스트를 통해 스프링 프레임워크를 익히고 미션을 통해 실제로 적용해보는 경험 14 | 15 | --- 16 | ## 리뷰 포인트 17 | 18 | 구현한 코드가 정말 심각한 수준이 아니라면 다음과 같이 진행할 것을 추천한다. 19 | * 1차 피드백을 남기면서 merge. 피드백을 다음 단계 진행할 때 반영하도록 가이드. 20 | * 2차 리뷰 요청에 대해서는 리뷰어분들이 만족하는 수준까지 핑퐁을 주고 받은 후 merge 21 | 22 | ### 1단계 23 | - 인증 관련 코드에서 서비스 코드에 대한 의존을 제거하여 패키지 분리를 하였는지 확인 24 | - Java Configuration을 활용한 스프링 빈 설정 시 스프링이 제공하는 적절한 기능을 사용하는지 확인 25 | - 불필요한 패키지간의 의존성이 확실히 제거되었는지 확인 26 | 27 | ### 2, 3단계 28 | - 현업에서 피드백을 준다고 생각하고 본인 팀의 코딩 컨벤션이나 스타일에 맞게 리뷰 29 | - 도메인이 객체지향적으로 잘 설계 되었는지에 대한 피드백 30 | - 검증하고자하는 대상의 기능 혹은 코드에 따라 적절하게 테스트를 작성했는지 확인 31 | - 새로운 요구사항을 추가하면서 겪은 어려움이나 개선 포인트에 대해 이야기해볼 수 있도록 유도 32 | -------------------------------------------------------------------------------- /reviewguide/kakao/was.md: -------------------------------------------------------------------------------- 1 | # 웹 애플리케이션 서버 2 | 3 | --- 4 | ## 리뷰어 가이드 5 | 이번 미션의 핵심 목표는 웹 서버 구현을 통해 HTTP 이해도를 높이고, 서블릿 컨테이너의 내부 구조를 이해하는데 있다. 6 | 또한 웹 서버를 구현하면서 HTTP의 각 요소를 객체로 추상화하는 연습을 하기도 좋은 미션이다. 7 | 따라서 웹 서버를 서블릿 컨테이너 구조로 구현하고, 객체지향 설계 원칙을 지키면서 구현하도록 피드백하는 것에 집중한다. 8 | TDD도 주요 목표 중의 하나이지만 테스트 코드에 대한 피드백에 집중하지 않아도 된다. 9 | 10 | * 서블릿 표준의 HttpServlet과 같은 인터페이스를 추출해 새로운 기능이 추가되었을 때 다른 코드에 영향을 미치지 않으면서 확장 가능하도록 구현했는가? 11 | * InputStream/OutputStream과 HTTP 요청과 응답 처리에 대한 로직을 분리해 단위 테스트 했는가? 12 | * WAS(서블릿 컨테이너)가 제공하는 기능(HTTP 요청과 응답 처리)과 애플리케이션 개발자가 구현하는 애플리케이션 로직을 잘 분리했는가? 13 | * handlebars.java template engine을 적용해 UI 화면을 구현했는가? 14 | 15 | * 객체지향생활체조 원칙을 지키면서 구현했는가? 16 | * 규칙 1: 한 메서드에 오직 한 단계의 들여쓰기(indent)만 한다. 17 | * 규칙 2: else 예약어를 쓰지 않는다. 18 | * 규칙 3: 모든 원시값과 문자열을 포장한다. 19 | * 규칙 4: 한 줄에 점을 하나만 찍는다. 20 | * 규칙 5: 줄여쓰지 않는다(축약 금지). 21 | * 규칙 6: 모든 엔티티를 작게 유지한다. 22 | * 규칙 7: 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다. 23 | * 규칙 8: 일급 콜렉션을 쓴다. 24 | * 규칙 9: 게터/세터/프로퍼티를 쓰지 않는다. 25 | -------------------------------------------------------------------------------- /reviewguide/review_process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/reviewguide/review_process.png -------------------------------------------------------------------------------- /reviewguide/spring-learning-test/spring-cart.md: -------------------------------------------------------------------------------- 1 | # 장바구니 2 | 3 | --- 4 | ## 미션 소개 5 | 이번 주차의 목표는 Spring Web MVC에서 제공하는 기능을 바탕으로 인증 기능을 구현하는 경험과 API 설계를 경험을 하는 것이다. 6 | 미션의 요구사항으로는 `상품 목록 조회`와 `장바구니 기능`을 포함한 사용자 페이지 구현, 그리고 `상품을 관리`하는 관리자 페이지 구현이 있다. 7 | 8 | --- 9 | ## 경험해야할 학습 목표 10 | - Spring Web MVC에서 제공하는 기능의 필요성을 경험하고 효과적으로 활용하는 경험 11 | - 인증 기능을 구현하여 인증 프로세스에 대한 이해도 향상 12 | - API를 설계하고 이에 맞는 기능을 구현하는 경험 13 | - 스프링 기반의 테스트 도구를 학습하고 이를 바탕으로 통합 테스트를 구현하는 경험 14 | 15 | --- 16 | ## 리뷰 포인트 17 | 18 | 구현한 코드가 정말 심각한 수준이 아니라면 다음과 같이 진행할 것을 추천한다. 19 | * 1차 피드백을 남기면서 merge. 피드백을 다음 단계 진행할 때 반영하도록 가이드. 20 | * 2차 리뷰 요청에 대해서는 리뷰어분들이 만족하는 수준까지 핑퐁을 주고 받은 후 merge 21 | 22 | ### 1단계 23 | - 상품 관리 CRUD API가 RESTful 하게 설계 되었는지 확인 24 | - 구현한 기능을 검증할 수 있는 테스트가 적절하게 작성되었는지 확인 25 | - 요구사항의 예외처리가 잘 구현되는지 확인 26 | 27 | ### 2단계 28 | - 서버로 요청 시 인증 정보가 잘 담겨서 요청되는지와 인증 기능이 잘 동작하는지 확인 29 | - 인증 처리 시 HandlerInterceptor, HandlerMethodArgumentResolver 등 스프링이 제공하는 적절한 기능을 사용하는지 확인 30 | - 장바구니 도메인 설계 시 상품 도메인과의 의존을 고려한 도메인 설계에 대해 피드백 31 | - 현업에서 피드백을 준다고 생각하고 본인 팀의 코딩 컨벤션이나 스타일에 맞게 리뷰 32 | -------------------------------------------------------------------------------- /reviewguide/spring-learning-test/spring-racingcar.md: -------------------------------------------------------------------------------- 1 | # 웹 자동차 경주 2 | 3 | --- 4 | ## 리뷰어 가이드 5 | 이번 주차의 가장 큰 목표는 스프링 프레임워크를 이용하여 웹 애플리케이션을 만들어 보는 경험을 하는 것이다. 6 | 이를 위해 뼈대 코드로 제공되는 콘솔 애플리케이션을 웹 애플리케이션으로 전환하고 추가 기능을 구현하는 미션이 제공된다. 7 | 스프링 프레임워크를 처음 접하거나 경험이 적은 경우 맹목적으로 작성하는 패턴화된 코드를 만드는 경우가 많은데, 8 | 각 코드와 패키지들이 어떠한 목적으로 만들어졌는지를 생각할 수 있게 피드백한다. 9 | 10 | --- 11 | ## 경험해야할 학습 목표 12 | - 뼈대 코드로 제공되는 콘솔 애플리케이션을 웹 애플리케이션으로 전환하고 추가 기능을 구현하는 경험 13 | - 특정 프레임워크에 의존하는 코드를 작성하는 경우 확장에 어려움을 겪을 수 있다는 깨달음 14 | - 스프링이 제공해주는 기능의 필요성을 경험하고 없는 경우 무엇이 불편한지를 경험 15 | - 학습 테스트를 통해 스프링 프레임워크를 익히고 미션을 통해 실제로 적용해보는 경험 16 | 17 | --- 18 | ## 리뷰 포인트 19 | 20 | 구현한 코드가 정말 심각한 수준이 아니라면 다음과 같이 진행할 것을 추천한다. 21 | * 1차 피드백을 남기면서 merge. 피드백을 다음 단계 진행할 때 반영하도록 가이드. 22 | * 2차 리뷰 요청에 대해서는 리뷰어분들이 만족하는 수준까지 핑퐁을 주고 받은 후 merge 23 | 24 | ### 1단계 25 | - 웹 요청/응답 처리 시 스프링이 제공하는 적절한 기능을 사용하는지 확인 26 | - 콘솔 애플리케이션과 웹 애플리케이션의 중복 코드는 허용(다음 단계에서 다룰 예정) 27 | - 데이터베이스 접근 시 스프링이 제공하는 적절한 기능을 사용하는지 확인 28 | - 미리 계층을 나누어 구현 할 경우 왜 필요한지 물어봐서 맹목적으로 작성하는 패턴화된 코드에 대한 경각심을 주기 29 | 30 | ### 2단계 31 | - 콘솔 애플리케이션과 웹 애플리케이션에서의 중복코드가 적절히 제거되었는지 확인 32 | - 비즈니스 로직이 콘솔이나 웹에 의존적이여서 재사용에 용이하지 않은 코드가 있는 경우 확인 33 | - 코드 재사용 시 역할(웹 처리/디비 처리 등)별로 계층을 나누어 구현할 수 있음을 코멘트로 전달 34 | - 비즈니스 로직을 Service 객체로 도출 하여 중복 제거 35 | - 메모리로 관리하는 부분과 디비로 관리하는 부분을 Dao를 추상화 하도록 가이드 36 | - 추가적으로 중복제거 요소에 대해 코멘트 남기기 37 | -------------------------------------------------------------------------------- /reviewguide/spring-learning-test/spring-roomescape-waiting.md: -------------------------------------------------------------------------------- 1 | # 방탈출 예약 대기 2 | 3 | --- 4 | 5 | ## 리뷰어 가이드 6 | 7 | 이번 미션은 복잡한 도메인의 웹 애플리케이션 개발에 대해 고민을 할 수 있도록 설계되었습니다. 8 | JPA를 적용하고 이에 필요한 엔티티 매핑과 연관관계 매핑을 하면서 다양한 도메인 모델을 다루게 됩니다. 9 | 특히, 예약 대기 승인 기능의 경우 크루들이 기능 동작의 방식을 직접 결정해서 구현하게 10 | 요구사항에서 구현 방법을 제한하지 않기 때문에 더 다양한 도메인 설계가 나올 것으로 기대하고 있습니다. 11 | 12 | 또한, JPA를 적용하게 되면서 Dao와 Repository에 대한 고민부터 도메인 객체와 엔티티 객체를 분리해서 생각한다던지, 13 | 제3의 계층이 하나 더 발생한다던지와 같은 예상하지 못하거나 흔히 구현되지 않는 색다른 방식으로 구현을 하는 리뷰이도 생길 것이라 예상하고 있습니다. 14 | 보편적으로 많이 사용되는 방식을 코멘트 하는 것도 방법이지만, 주장에 대한 논리가 타당하다면 그 시도를 지지해주세요. 15 | 16 | --- 17 | 18 | ## 경험해야할 학습 목표 19 | 20 | - JPA 이해 및 활용 21 | - 요구사항에 맞는 연관관계 매핑 22 | - 적절한 테스트 작성 23 | 24 | --- 25 | 26 | ## 리뷰 포인트 27 | 28 | ### 1단계 29 | - 엔티티 매핑 및 연관관계 매핑이 잘 되었는가? 30 | - 기대하는 대로 테이블이나 쿼리가 잘 생성되는지? 31 | 32 | ### 2~3단계 33 | - 검증이 필요한 부분 혹은 중요 로직에 테스트가 잘 작성이 되어있는가? 34 | - 로직상 예외가 발생할 수 있는 부분에 대해 기능 구현이 잘 되어있는가? 또, 테스트는 잘 작성 되어있는가? 35 | -------------------------------------------------------------------------------- /reviewguide/spring-learning-test/spring-roomescape-member.md: -------------------------------------------------------------------------------- 1 | # 방탈출 사용자 인증 2 | 3 | --- 4 | 5 | ## 경험해야할 학습 목표 6 | 7 | - Spring Web MVC에서 제공하는 기능의 필요성을 경험하고 효과적으로 활용하는 경험 8 | - 인증 기능을 구현하여 인증 프로세스에 대한 이해도 향상 9 | - API를 설계하고 이에 맞는 기능을 구현하는 경험 10 | - 스프링 기반의 테스트 도구를 학습하고 이를 바탕으로 통합 테스트를 구현하는 경험 11 | 12 | --- 13 | 14 | ## 리뷰 포인트 15 | 구현한 코드가 정말 심각한 수준이 아니라면 다음과 같이 진행할 것을 추천 16 | 17 | - 1차 피드백을 남기면서 merge. 피드백을 다음 단계 진행할 때 반영하도록 가이드. 18 | - 2차 리뷰 요청 이후 부터는 리뷰어분들이 만족하는 수준까지 핑퐁을 주고 받은 후 merge 19 | 20 | ### 1단계 21 | 22 | - API를 보편적으로 이해 가능하게 설계 하였는가? (테마 관리, 예약 추가) 23 | - 요청에서의 HTTP Method와 URL이 의미에 맞게 사용되었는가? 24 | - 응답에서의 HTTP Status Code가 적절하게 사용되었는가? 25 | - 구현한 기능을 검증할 수 있는 API 레벨의 통합 테스트를 작성하였는가? 26 | - 이전 미션에서는 제공된 테스트 코드를 사용했다면, 이번에는 스스로 작성하는 것이 목표 27 | - 특정 계층에 대한 단위 테스트는 필수 요구사항이 아님 28 | - 인증/인가의 개념에 대해 정확히 이해하고 구현하였는가? 29 | - 인증 요청과 응답, 이후의 요청에 대한 flow를 잘 설명할 수 있는가? 30 | 31 | ### 2, 3단계 32 | 33 | - 인증/인가 처리 시 HandlerInterceptor, HandlerMethodArgumentResolver 등 스프링이 제공하는 적절한 기능을 사용하였는가? 34 | - 현업에서 피드백을 준다고 생각하고 본인 팀의 코딩 컨벤션이나 스타일에 맞게 리뷰 35 | -------------------------------------------------------------------------------- /reviewguide/spring-learning-test/spring-roomescape-reservation.md: -------------------------------------------------------------------------------- 1 | # 방탈출 예약 관리 2 | 3 | --- 4 | 5 | ## 경험해야할 학습 목표 6 | 7 | - 스프링부트 프레임워크를 사용해 웹 요청을 받고 응답하기 8 | - 웹 애플리케이션에서 DB에 데이터를 저장하고 조회하기 9 | - 스프링 빈의 의존성 주입이 무엇인지 알고, 코드에 적용 10 | - 소프트웨어 개발에 일반적으로 적용되는 계층형 아키텍쳐(Layered Architecture)를 알고, 코드에 적용 11 | - `학습 테스트`를 활용해 새로운 기능을 학습 12 | 13 | --- 14 | 15 | ## 리뷰 포인트 16 | 구현한 코드가 정말 심각한 수준이 아니라면 다음과 같이 진행할 것을 추천 17 | 18 | - 1차 피드백을 남기면서 merge. 피드백을 다음 단계 진행할 때 반영하도록 가이드. 19 | - 2차 리뷰 요청에 대해서는 리뷰어분들이 만족하는 수준까지 핑퐁을 주고 받은 후 merge 20 | 21 | ### 1단계 22 | 23 | - 웹 요청/응답 처리 시 스프링이 제공하는 적절한 기능을 사용하는지 확인 24 | - 데이터베이스 접근 시 스프링이 제공하는 적절한 기능을 사용하는지 확인 25 | - 미리 계층을 나누어 구현 할 경우 왜 필요한지 물어봐서 맹목적으로 작성하는 패턴화된 코드에 대한 경각심을 주기 26 | - 객체 관리를 위해 스프링이 제공하는 기능을 정확하게 사용하는가? 27 | - 코드의 구조가 일관성을 가지고 있는가? 28 | 29 | ### 2단계 30 | 31 | - 새로운 기능 추가로 인해 기존 기능이 영향을 받지는 않았는지를 고려했는지 확인 32 | - 테스트가 없었다면 이 부분을 강조해서 테스트의 필요성을 언급하기 33 | - 계층의 역할을 이해하는지, 그 이해에 맞도록 구조를 설계했는지 확인 34 | - Http 스펙(ex. Http Status Code)에 대해서 어색한 부분이 있는지? 있다면 어떤 기준으로 설계했는지 확인 35 | - 요구사항에서 발생할 수 있는 예외에 대한 처리가 잘 되어있는가? 36 | - 부족하다면 놓친 부분에 대한 언급을, 과하다면 과한 이유에 대해 묻기 37 | - 예를 들어, 시간 관리에서 시간이 중복되는 경우에 대한 처리가 잘 되어있는가? 38 | - @ExceptionHandler 나 @ControllerAdvice를 사용하여 예외 처리를 하였는가? 39 | -------------------------------------------------------------------------------- /reviewguide/spring-learning-test/spring-subway.md: -------------------------------------------------------------------------------- 1 | # 지하철 2 | 3 | ## 리뷰어 가이드 4 | 이번 주차의 주요 목표는 웹 애플리케이션을 개발하는 과정에서 복잡한 도메인인 지하철 정보를 다루는 경험을 하는 것이다. 5 | 객체지향적인 설계를 통해 복잡한 도메인 규칙을 잘 구현했는지, 그리고 이 과정에서 필요한 테스트를 충분히 작성했는지에 초점을 맞춰서 피드백한다. 6 | 7 | ## 경험해야할 학습 목표 8 | - 웹 애플리케이션에서 복잡한 도메인을 설계하고 구현하는 경험 9 | - 다양한 종류의 테스트를 작성하는 경험 (예: 단위 테스트, 통합 테스트) 10 | - Java Configuration을 통해 스프링 메타데이터를 설정하는 방법을 경험 11 | - 추가되는 요구사항을 구현하면서 변경에 유연한 설계에 대해 다시 고민해보는 경험 12 | 13 | ## 리뷰 포인트 14 | 15 | 구현한 코드가 정말 심각한 수준이 아니라면 다음과 같이 진행할 것을 추천한다. 16 | * 1차 피드백을 남기면서 merge. 피드백을 다음 단계 진행할 때 반영하도록 가이드. 17 | * 2차 리뷰 요청에 대해서는 리뷰어분들이 만족하는 수준까지 핑퐁을 주고 받은 후 merge 18 | 19 | ### 1단계 20 | - 지하철 역과 노선 객체 사이의 관계가 잘 표현되었는지 피드백 21 | - 노선에 포함된 지하철 역과 역 사이의 관계인 구간 객체를 잘 도출했는지 확인 22 | - API레벨의 통합 테스트를 필요한 기능별로 구현했는지 확인 23 | - 비즈니스 로직이 단위 테스트로 잘 검증이 되는지 확인 (가능하면 커밋 기록을 참고해서 TDD 사이클을 잘 경험했는지도 확인하면 좋음) 24 | 25 | ### 2단계 26 | - 외부 라이브러리를 Java Configuration 사용해 Bean으로 설정했는지 확인. 만약 다른 방식으로 사용했다면 왜 그렇게 했는지 설명을 요청 27 | - profile을 이용하여 환경별 데이터베이스 경로 설정이 되었는지 확인(prod: local path, test: in-memory) 28 | - 새로운 정책 추가로 인해 변경이 많았는지 확인. 그리고 그 이유에 대해 생각을 공유하도록 코멘트 29 | -------------------------------------------------------------------------------- /reviewguide/wootecamp-pro/README.md: -------------------------------------------------------------------------------- 1 | ## 우아한테크캠프 Pro 소개 2 | [우아한테크캠프 Pro](https://edu.nextstep.camp/c/lqsBs7x0) 과정은 우아한형제들과 NEXTSTEP이 협력해 운영하는 재직자 교육 과정이다. 3 | 재직자 교육 과정을 운영하는 이유는 `많은 개발자들은 좋은 회사에 취업하기 힘들다고 하고, 일반 사용자용 소프트웨어를 개발하는 회사들은 채용할 개발자가 없어 힘들어하고 있다.` 이에 대한 불일치를 해소하기 위함이다. 개발자와 회사 간의 불일치가 발생하는 가장 큰 원인은 일반 사용자용 소프트웨어를 개발하는 회사들이 요구하는 역량을 쌓을 기회가 부족하기 때문이다. 이 과정은 소프트웨어 장인으로 성장해 나가는 과정의 로드맵을 제시하고, 어떤 개발자로 성장해 나갈 것인지를 제시하는 과정이다. 4 | 5 | ## 우아한테크캠프 Pro 학습 목표 6 | 1. 클린코드를 통해 유지보수하기 좋은 코드를 구현하는 경험. 7 | 2. JPA 기반으로 웹 애플리케이션을 개발하는 경험. 8 | 3. 단위, 인수 테스트를 기반으로 웹 애플리케이션을 개발하는 경험. 9 | 4. 레거시 코드를 안정적으로 리팩터링하는 경험. 10 | 5. 시스템 아키텍처를 설계하고 운영하는 경험. 11 | 6. 대용량 데이터에 대해 최적화할 대상을 살펴보고, 서버를 튜닝하는 경험. 12 | 7. 이력서와 면접을 리팩토링하는 경험 13 | 14 | --- 15 | ## 미션별 리뷰어 가이드 16 | - 1주차: [TDD, 클래스 분리 - 로또](./lotto.md) 17 | - 2주차: [JPA](./jpa.md) 18 | - 3주차: [인수테스트 주도 개발](./acceptance-test.md) 19 | - 4주차: [그럴듯한 서비스 만들기](./subway-deploy.md) 20 | - 5주차: [ATDD 내에서 TDD](./atdd-tdd.md) 21 | - 6주차: [서비스 진단하기](./monitoring.md) 22 | - 7주차: [레거시 코드 리팩터링](./legacy-code-refactoring.md) 23 | - 8주차: [안정적인 서비스 만들기](./performance-refactoring.md) 24 | 25 | --- 26 | ## 리뷰어 -> 수강생 상호 평가 27 | - [현재 역량 파악]기술적인 역량으로 판단할 때 같이 일하고 싶은가?(5점 만점) 28 | - [성장 잠재력]피드백을 통해 성장하는 모습으로 볼 때 같이 일하고 싶은가?(5점 만점) 29 | - 코드 리뷰를 하면서 느낀 점이 있다면 의견을 남겨주세요.(예. 피드백을 반영하는 역량이 뛰어나 앞으로 성장 가능성이 높아 보인다. 리뷰를 하면서 의견을 주고 받는 시간이 너무 즐거웠다.) 30 | 31 | --- 32 | #### 기술적인 역량으로 판단할 때 같이 일하고 싶은가?(현재 역량 파악) 33 | - 5점: 강한 인사이트를 주는 코드와 온라인 토론을 통해 같이 성장하는 느낌을 받는 경우 34 | - 정말 같이 일하고 싶은 느낌이 들게 하는 수강생. 온라인 토론을 커뮤니케이션 역량 또한 좋다는 느낌을 받는 경우 35 | - 4점: 회사 개발자 또는 팀 동료들과 비슷한 수준의 역량이라 판단되는 경우 36 | - 현재 자신이 일하고 있는 회사 동료들과 비슷한 역량을 가지고 있다고 판단되는 경우 37 | - 3점: 특별히 부족한 점은 없지만 그렇다고 특출난 점이 보이지 않는 경우 38 | - 현재 자신이 일하고 있는 회사 개발자들의 역량에 비해 다소 부족한 역량이라 판단되는 수강생 39 | - 2점: 스스로의 힘으로 성장하기 보다 단순 피드백에 의존해 개선되는 느낌을 받는 경우 40 | - 1점: 미션을 마무리하는 단계에도 부족하다 생각하는 경우 41 | 42 | --- 43 | #### 피드백을 통해 성장하는 모습으로 볼 때 같이 일하고 싶은가?(성장 잠재력) 44 | - 5점: 시작 단계부터 끝까지 피드백할 내용은 따로 없는 상태로 이미 일정 역량을 갖추었으며, 수강생의 추가적인 질문들로 유의미한 토론이 이루어진 경우 45 | - 이미 일정 수준의 역량(기술적인 역량 질문에서 4, 5점을 받은 분)을 보유하고 있는 상태이면서, 간혹 작은 피드백이 나오면 깊게 고민하는 역량을 갖춘 경우 46 | - 4점: 시작 단계는 부족한 점이 많았지만 피드백을 통해 빠르게 성장하는 경우 47 | - 현재는 부족한 점(기술적인 역량 질문에서 3, 4점을 받은 분)이 있지만 로드맵을 제시하고, 피드백을 준다면 빠르게 성장할 가능성이 높아 보이는 수강생 48 | - 3점: 시작 단계는 부족한 코드였고, 피드백을 통해서만 개선되는 느낌을 받는 경우 49 | - 예를 들어 한 단계에서 1번 request changes 이하로 단계를 소화하는 경우. 역량을 향상시키기 위해 노력하지만 성장하는 모습이 잘 보이지 않는 수강생 50 | - 2점: 반복적인 피드백을 통해 조금씩 개선되는 느낌을 받는 경우 51 | - 예를 들어 한 단계에서 2번 이상의 request changes하는 경우 52 | - 1점: 피드백을 통해 개선의 여지가 없어 보이는 경우 53 | 54 | --- 55 | #### 1:1 코드 리뷰 과정 없이 미션 수행 여부(pass/fail)만 판단하는 미션의 경우 56 | - 5점: 모든 요구사항을 만족해도 5점을 부여하지 않음 57 | - 4점(현재 역량 파악, 성장 잠재력 모두): 미션에서 요구하는 모든 요구사항을 만족하는 경우 58 | - 3점(현재 역량 파악, 성장 잠재력 모두): 2개 이하의 요구사항을 만족하지 못한 경우 59 | - 2점(현재 역량 파악, 성장 잠재력 모두): 3개 이상의 요구사항을 만족하지 못한 경우 60 | - 1점: 1점은 부여하지 않음 61 | 62 | --- 63 | ## 수강생 -> 리뷰어 상호 평가 64 | - 팀원으로 일할 수 있는 기회가 있다면 같이 일하고 싶은 리뷰어인가?(10점 만점) 65 | - 리뷰어의 성장을 위한 피드백이 있다면 남겨 주세요.(예. 피드백을 꼼꼼히 주어 실력을 향상하는데 많은 도움이 되었다. 정답을 미리 알려주기보다 정답을 찾아갈 수 있도록 방향만 정해주면 좋겠다.) 66 | -------------------------------------------------------------------------------- /reviewguide/wootecamp-pro/acceptance-test.md: -------------------------------------------------------------------------------- 1 | # 인수 테스트 주도 개발 미션 리뷰어 가이드 2 | 3 | --- 4 | ## 1단계: 구현된 기능을 인수 조건에 따라 인수 테스트로 검증 5 | - 작성한 인수 테스트가 미리 구현된 기능을 인수 조건에 따라 잘 검증하는가? 6 | - 인수 테스트의 가독성과 재사용성을 고려하여 리팩터링을 했는가? 7 | - 눈에 띄는 내용만 피드백 후 머지하여 빠르게 다음 단계 진행하도록 가이드 8 | - 인수 테스트 격리는 다음 단계에서 고민할 수 있도록 가이드 9 | 10 | --- 11 | ## 2단계: 제공되는 인수 조건에 따라 인수 테스트를 작성하고 기능 구현 12 | - 작성한 인수 테스트가 제공된 인수 조건을 잘 검증하는가? 13 | - 각 인수 테스트 검증 결과가 다른 인수 테스트에 영향을 끼치지는 않는가? 14 | - 인수 테스트 격리 방법에 따라 깨지기 쉬운 테스트가 될 수 있고 테스트의 비용이 달라질 수 있음을 가이드 15 | - 인수 테스트의 가독성과 재사용성을 고려하여 리팩터링을 했는가? 16 | - 인수 테스트에서 중복해서 사용되는 코드를 분리하여 재사용할 수 있도록 가이드 17 | 18 | --- 19 | ## 3, 4단계: 인수 테스트 주도 개발 사이클 경험 20 | - 요구사항에 맞게 인수 조건이 잘 정의되었는가? 21 | - 인수 테스트로 해당 기능의 스펙을 유추할 수 있도록 작성했는가? 22 | - 새롭게 추가되고 제거되는 구간에 따라 역 목록 기능이 잘 동작 하는가? 23 | - 에러가 발생하는 케이스를 인수 테스트로 잘 검증하고 있는가? 24 | - 복잡한 요구사항에 맞는 단위 테스트가 작성되었는가? 25 | - 비즈니스 로직은 가급적 도메인에 위치하고 있는가? 26 | - 객체 지향 생활 체조와 클린 코드 가이드가 잘 지켜지고 있는가? 27 | -------------------------------------------------------------------------------- /reviewguide/wootecamp-pro/atdd-tdd.md: -------------------------------------------------------------------------------- 1 | # 인수 테스트 기반 TDD 미션 리뷰어 가이드 2 | 3 | --- 4 | ## 1단계: 인수 테스트 기반 리팩터링 5 | - 인수 조건 기반으로 인수 테스트가 작성되었는가? 6 | - 비즈니스 로직이 서비스 레이어에서 도메인 레이어로 잘 옮겨졌는가? 7 | - 비즈니스 로직의 단위 테스트가 작성되었는가? 8 | 9 | ## 2단계: 경로 조회 기능 10 | - 외부 라이브러리를 활용한 코드를 테스트 시 가짜 객체가 아닌 실제 객체를 활용하여 하도록 가이드 11 | - 미션 수행에 어려움을 겪는다면 경로 조회 부분과 그 결과를 맵핑하는 부분, 두 부분을 나눠서 생각해보라고 가이드 12 | - 인수 테스트는 시나리오 기반으로 작성하게 하고 단위 테스트를 통해 업무 규칙(예외 등)을 검증하도록 가이드 13 | 14 | ## 3단계: 인증을 통한 기능 구현 15 | - 단위 테스트를 이용하여 Interceptor 구현 연습 16 | - 테스트 구동을 통해 기능이 정상 동작하는지 여부를 바탕으로 가이드 17 | - 눈에 띄는 내용만 피드백 후 머지하여 빠르게 다음 단계 진행하도록 가이드 18 | 19 | ## 4단계: 요금 조회 20 | - 경로 조회 시 로그인 사용자의 나이를 알기 위해서는 경로 조회 컨트롤러 메서드에 @AuthenticationPrincipal를 이용해 LoginMember 객체를 받아야 함 21 | - 하지만 비로그인 사용자도 사용할 수 있게 해야함 22 | - @AuthenticationPrincipal 설정값으로 `boolean required`을 두어 required값이 false일 때 로그인 객체가 없다면 빈 값이 응답될 수 있게 가이드 하기 23 | - 요금별 정책 로직에 대해 집중적으로 코드 리뷰하면 좋을 듯 24 | -------------------------------------------------------------------------------- /reviewguide/wootecamp-pro/jpa.md: -------------------------------------------------------------------------------- 1 | JPA 미션의 학습 목표는 도메인 객체와 테이블 간의 매핑과 레거시 코드 리팩토링을 경험하는 것이다. 2 | 3 | - DDL에 따라 엔티티 클래스를 매핑하였는가? 4 | - `@Lob`, `@Enumerated`, `@CreatedDate` 등 적절한 애너테이션을 사용해야 한다. 5 | - 중복 코드를 분리하기 위해 `@MappedSuperclass`를 사용하였는가? 6 | - 엔티티 클래스의 매개 변수가 없는 생성자에 대한 접근 제한자 (JSR 338) 7 | - getter와 setter를 쓰지 않는다. 8 | - 기존 DDL을 해치지 않고 연관 관계 매핑을 하였는가? 9 | - 객체는 자유롭게 객체 그래프를 탐색할 수 있어야 한다. 10 | - 리팩터링 후 핵심 비즈니스 로직을 도메인 객체가 담당하고 있는가? 11 | - 도메인 객체에 대한 단위 테스트가 모두 존재해야 한다. 12 | -------------------------------------------------------------------------------- /reviewguide/wootecamp-pro/legacy-code-refactoring.md: -------------------------------------------------------------------------------- 1 | 레거시 코드 리팩터링의 학습 목표는 실제 데이터가 존재하는 레거시를 멀티 모듈로 리팩터링하는 것이다. 2 | 3 | - 기술적인 내용보다는 처음 보는 사람도 쉽게 읽을 수 있도록 요구 사항을 정리하였는가? 4 | - 누락된 요구 사항이 없어야 한다. 5 | - 요구 사항을 기반으로 테스트 코드를 잘 작성하였는가? 6 | - `@DisplayName` 등을 사용하여 테스트의 의미를 한글로 잘 풀어내야 한다. 7 | - 무엇을 테스트하고자 하는지 테스트 코드를 통해 잘 드러나야 한다. 8 | - [테스트를 작성하는 방법](https://blog.kingbbode.com/52) 9 | - Lombok을 사용하지 않는다. 10 | - 도메인 객체가 핵심 비즈니스 로직을 담당하는가? 11 | - 스키마 구조가 변경되었을 때 기존 데이터를 손상하지 않고 Flyway를 통해 안전하게 마이그레이션하였는가? 12 | - 클래스와 클래스 간, 패키지와 패키지 간의 의존성은 단방향인가? 13 | - 단, JPA의 성능 향상을 위해 양방향으로 할 수 있다. 14 | - 이벤트를 사용할 수 있지만 필수는 아니며, 데이터의 흐름은 단방향이어야 한다. 15 | - 불변식이 보장되는가? 16 | - 함께 생성되고 함께 삭제되는 객체들을 함께 묶어라. 17 | - 불변식을 지켜야 하는 객체들을 함께 묶어라. 18 | - 그 외는 가능하면 분리하라. 19 | - 멀티 모듈을 적용하는 데 의의가 있다. 컨텍스트 간 독립 모듈로 만드는 것을 권장하지만, 계층 간 독립 모듈로 만들 수도 있다. 20 | -------------------------------------------------------------------------------- /reviewguide/wootecamp-pro/lotto.md: -------------------------------------------------------------------------------- 1 | 로또 미션의 학습 목표는 클래스 분리 연습과 TDD 연습이다. 2 | 3 | 로또 미션 1단계는 문자열 덧셈 계산기 구현 실습이다. 4 | 1단계는 NEXTSTEP의 리뷰요청 사이클을 경험하는 단계이기 때문에 간단하게 피드백 한 두개 남기고 바로 merge하는 것을 추천한다. 5 | 아래 리뷰어 가이드 기준에 따른 본격적인 코드 리뷰는 2단계부터 진행하면 좋겠다. 6 | 7 | ## 프리코스 기준은 기본으로 포함 8 | - todo list를 잘 작성했는가? 9 | - 각 기능 단위로 commit log를 잘 남겼는가? 10 | - 코딩 컨벤션을 잘 지키면서 프로그래밍 했는가? 11 | - 메소드를 작은 단위로 잘 분리했는가?(인덴트를 1로 잘 유지했는가? 포함) 12 | - else 예약어를 쓰지 않았는가? 13 | - 함수(또는 메소드)의 길이가 10라인을 넘어가지 않도록 구현했는가? 14 | - 도메인 객체에 대한 단위 테스트를 잘 구현했는가? 15 | - MVC 구조에 맞도록 객체 분리를 했는가? 16 | 17 | ## 로또에서 추가적으로 봤으면 하는 내용 18 | - 클래스를 작은 단위로 잘 분리했는가? 19 | - 객체지향 생활체조 규칙 중 다음 규칙에 대한 피드백 20 | - 규칙 3: 모든 원시값과 문자열을 포장한다. 21 | - 규칙 5: 줄여쓰지 않는다(축약 금지). 22 | - 규칙 8: 일급 콜렉션을 쓴다. 23 | - 도메인 객체에 대한 단위 테스트가 모두 존재하는가? 24 | - TDD로 구현했을 경우 도메인 객체에 대한 단위 테스트는 존재해야 한다. 25 | -------------------------------------------------------------------------------- /reviewguide/wootecamp-pro/monitoring.md: -------------------------------------------------------------------------------- 1 | ## 서비스 진단하기 2 | 3 | 4 | ### 1. 웹 성능 테스트 5 | - 웹 성능 예산을 정한 기준이 합리적인지 6 | 7 | - 개선방안을 웹 성능 예산을 바탕으로 합리적으로 도출했는지 8 | 9 | 10 | ### 2. 부하 테스트 11 | - 시나리오를 작성하고 올바르게 Smoke Test를 진행했는지 12 | 13 | - 부하테스트 목표값(rps)에 맞춰 VUser 값을 적절히 도출하고 부하테스트를 진행했는지 14 | - 응답시간은 latency - 2 입니다. 15 | - 별도의 지연시간(a) 를 염두하지 않는다면, VUser Iteration (T) = 시나리오 내 요청 수 (R) - 응답시간 (http_req_duration) 입니다. 16 | - 따라서, VUser = (목표 rps - T) / R = 목표 rps - http_req_duration 입니다. 17 | - 목표 rps 와 VUser 는 동일한 값이 아닙니다. 18 | 19 | - Stress Test를 통해 현재 인프라의 한계치를 확인했는지 20 | - 부하테스트와 스트레스 테스트를 구분하지 않는 경우들이 종종 있습니다. 스트레스 테스트는 피크타임의 부하를 테스트하는 것이 아닙니다. 21 | 22 | 23 | ### 3. 로깅, 모니터링 24 | - 애플리케이션 로그를 작성했는지 25 | - 회원가입, 로그인 등에 로깅을 추가했는지 26 | - JSON 로그를 사용하여 도메인 이벤트 로그를 수집했는지 27 | - 로깅레벨을 적절히 설정했는지 28 | - log rotate 설정을 했는지 29 | 30 | - Cloudwatch 대시보드를 구성하였는지(시스템 모니터링이 가능한지) 31 | -------------------------------------------------------------------------------- /reviewguide/wootecamp-pro/performance-refactoring.md: -------------------------------------------------------------------------------- 1 | ## 안정적인 서비스 만들기 2 | 3 | ### 1. 화면 응답 개선하기 4 | 5 | 6 | - 개선방안을 각각 적용하고 부하테스트를 통해 계측했는지 7 | 8 | - Load Test, Stress Test 목적에 맞게 결과를 도출했는지 9 | - 개선 후 Load Test를 동일하게 진행했을 경우 latency가 어느정도 개선되었는지를 확인 10 | - http_req_duration max 값을 기준으로 개선여부를 판단합니다. 11 | - 개선 후 Stress Test를 진행했을 때 한계점이 증가되었음을 확인 12 | - 부하테스트 결과를 보고는 성능이 개선되었다고 이야기하고, 스트레스테스트 결과를 보고는 최대 허용 가능한 VUser 가 xx 로 증가했다고 이야기를 합니다. 13 | 14 | - 웹 서버 15 | - 정적 파일 캐싱을 적용했는지 16 | - http2 적용했는지 17 | - gzip 적용했는지 18 | - worker connection 수치를 조정했는지 19 | - was 20 | - 경로찾기에 대해 redis 설정을 적용했는지 21 | 22 | ### 2. 스케일 아웃 23 | 24 | - HTTP 캐싱 적용 요구사항을 수행했는지 25 | 26 | - 부하테스트를 통해 계측했는지 (cloudwatch 그래프도 포함하였는지) 27 | - cpu 부하 실행에 따른 auto scaling 을 경험해보았는지 28 | - auto scaling group 종료 정책을 구성했는지 29 | 30 | 31 | ### 3. 쿼리 최적화 32 | 33 | - 인덱스를 추가하지 않고도 응답시간이 1s 내인지 (m1은 2s) 34 | - 실행계획 확인시, 조인을 적절히 구성했는지 35 | - 드라이빙, 드리븐 테이블 구성이 적절한지 (record 테이블의 rows를 적게 탐색하기 위해 조인 선후관계가 적절한지) 36 | - 드라이빙 테이블(인라인뷰)의 모수를 줄이려는 노력을 했는지 (filtered 참고) 37 | - 질문이나 피드백하기 어려운 경우가 있다면, 이동규 에게 dm 주세요. 38 | 39 | 40 | ### 4. 인덱스 설계 41 | 42 | - 학생 분들 답변대로 인덱스를 추가했을 때 응답시간이 100 ms인지 (m1은 200ms) 43 | - 질문이나 피드백하기 어려운 경우가 있다면, 이동규 에게 dm 주세요. 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /reviewguide/wootecamp-pro/subway-deploy.md: -------------------------------------------------------------------------------- 1 | ## 그럴듯한 서비스 만들기 목표 2 | 3 | - 리뷰를 주고 받는 사이클을 경험해봅니다. 4 | - 망을 구성하고 개발 / 배포 환경을 구성해봅니다. 5 | - pem 키는 구글 드라이브로 관리 6 | 7 | ### 1. 망 구성하기 (네트워크 구성) 8 | 9 | - ping, port, http 요청 확인 10 | 11 | - URL로 서버에 접속 가능한지 확인 12 | - 외부망을 위한 라우팅 테이블에만 인터넷 게이트웨이가 연결되어 있는지 13 | 14 | - 요구사항에 맞게 서브네팅했는지 확인 15 | 16 | - SG이 적절하게 설정되었는지 확인 17 | - 외부망/내부망은 관리망에만 22번 포트를 오픈했는지 18 | - 관리망은 특정 IP에 대해서만 22번 포트를 오픈했는지 19 | - 전체 대역대에 80, 8080 등의 포트만 오픈했는지 20 | 21 | 22 | ### 2. 배포하기 (개발 환경 세팅, 컨테이너) 23 | 24 | - TLS 설정 확인 25 | - 외부망 SG는 443만 오픈했는지, 만약 다른 포트를 오픈했다면 443 리다이렉트 설정을 했는지 26 | - HTTPS로 정상적으로 연결되는지 27 | 28 | - 운영 DB를 내부망에 구성했는지 29 | 30 | - Junit Test, 로컬, 운영 환경에 따라 설정을 나눠서 관리하는지 31 | 32 | 33 | ### 3. 배포스크립트 작성하기 34 | 35 | - 2단계 미션을 진행하는데 필요한 명령어들이 모두 포함되어 있는지 36 | 37 | -------------------------------------------------------------------------------- /settings/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/settings/img.png -------------------------------------------------------------------------------- /settings/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/settings/img_1.png -------------------------------------------------------------------------------- /settings/img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/settings/img_2.png -------------------------------------------------------------------------------- /settings/img_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/settings/img_3.png -------------------------------------------------------------------------------- /settings/img_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/settings/img_4.png -------------------------------------------------------------------------------- /settings/img_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/next-step/nextstep-docs/b5f3348870c6df44a1f71f1eef52863f34d89fe2/settings/img_5.png -------------------------------------------------------------------------------- /settings/slack.md: -------------------------------------------------------------------------------- 1 | # Slack username 설정 2 | 1. 넥스트스텝 멤버스 slack 에 로그인한다. 3 | 2. 우측 상단의 자신의 아이디를 클릭한다. 4 | 3. Profile 메뉴를 클릭한다. 5 | 6 | ![img.png](img.png) 7 | 8 | 4. 우측 화면에서 Set status 우측의 ... 을 클릭한다. 9 | 5. Account settings 메뉴를 클릭한다. 10 | 11 | ![img_1.png](img_1.png) 12 | 13 | 6. Settings 탭의 Username의 expand 버튼을 클릭한다. 14 | 15 | ![img_3.png](img_3.png) 16 | 17 | 7. Slack Username을 GitHub ID로 변경하고 저장한다. 18 | 단, GitHub ID에 대문자가 포함되어 있으면 소문자로 변경한다.(예. JavaJiGi -> javajigi) 19 | 20 | ![img_4.png](img_4.png) 21 | 22 | # Slack display name 설정 23 | 24 | 1. 넥스트스텝 멤버스 slack 에 로그인한다. 25 | 2. 우측 상단의 자신의 아이디를 클릭한다. 26 | 3. Profile 메뉴를 클릭한다. 27 | 28 | ![img.png](img.png) 29 | 30 | 4. 우측 화면에서 이름 우측의 Edit을 클릭한다. 31 | 32 | ![img_2.png](img_2.png) 33 | 34 | 5. Display name 항목을 “github id(이름)” 형식으로 작성한다. 35 | 36 | ![img_5.png](img_5.png) --------------------------------------------------------------------------------