우아한테크코스/프리코스

[우테코/프리코스] Week1. 1주차 프리코스 회고

lumana 2024. 11. 5. 13:14

우테코 Week 1 회고

#우테코

미션 수행 전

화요일에 미션이 열리기 전에, 우테코 깃허브에 가서 여러 docs들을 읽어봤다.
먼저 봤던건 PR_CheckList에 나와있는 내용이였다. 여기에는 클린 코드를 위한 체크리스트가 있었다.

  • 자바 코드 컨벤션

  • 들여쓰기

  • else 예약어 금지

  • 원시값과 문자열 포장

  • 일급 콜렉션 적용

  • 인스턴스 변수를 3개 이하로 줄이자

  • DTO를 제외하고 getter/setter 없이 구현

  • 메서드의 인자 수를 제한

  • 코드 한 줄에 점(.) 하나만 쓰자

  • 메서드가 하나의 일만 담당하도록 구현

  • 클래스를 작게 유자하기 위해 노력

    위 내용 중에서 평소에 신경쓰면서 코딩했던 부분은 “setter를 사용 x”, “메서드 인자 수 제한”, “메서드가 하나의 일만 담당하도록 구현”, “else 줄이기” 정도였던 것 같다. “일급 콜렉션”에 대해서는 처음 들어봤고, getter 없이 코드를 구현해본적도 없어서, 왜 이러한 규칙을 지켜야하는지에 대해 많은 궁금증이 생겼다. 구글링을 해보니 많은 자료들이 있어서 어떠한 이유에서 이런 규칙들이 적용되는지 이해가 어느정도 되긴 했지만, 스스로 많은 경험을 통해 깨우쳐나가는 것이 중요하다는 생각이 들었다. 이 외에도 클린 코드를 위한 여러가지 가이드라인이 있을 것이라 생각한다. 이번 프리코스를 진행하면서 공부해보려 한다.

자바 코드 컨벤션

자바 코드 컨벤션에 대해서는 [우테코/프리코스] Week0. 구글 자바 스타일 가이드에 정리해봤다.
내 코드 스타일과 다르거나 평소에 신경쓰지 않았던 부분은 다음과 같았다.

  • Tab 대신 스페이스 사용하기
  • 임포트는 정적 임포트비정적 임포트를 별도의 블록으로 구분하여 정렬해야 한다.
  • 클래스 내의 멤버와 초기화 블록의 순서는 논리적이어야 한다.
  • if, else, for, do, while 문에서는 블록이 비어 있거나 단일 문장만 포함할 경우에도 중괄호를 사용해야 한다.
  • K & R 스타일
    • 열림 중괄호 { 앞에 줄 바꿈을 하지 않고, { 다음에 줄바꿈 해야 한다.
    • 닫힘 중괄호 } 앞에 줄 바꿈 해야 한다. (문장을 종료하거나 메서드, 생성자, 클래스의 본문을 종료하는지에 따라 결정)
  • 한 줄에 한 문장
  • 자바 코드는 한 줄에 최대 100자까지 작성
  • 줄바꿈 기준
  • 애노테이션, 배열 초기화 등 특정 예외를 제외하고 중괄호 여는 모든 경우에 공백 사용
    • 배열 선언문 사이에서 공백은 Optional 하다
  • 우선순위 연산자가 명확하더라도 소괄호로 감싸는것을 Recommend 한다
  • 메서드가 없는 간단한 열거형 클래스는 배열 초기화 형식으로 작성할 수 있다.
  • 지역 변수는 가능한 한 사용되는 지점 가까이에 선언해야 한다. 변수의 범위도 최소화 한다.
  • C 스타일 배열 선언 금지
  • switch-case문에서 다음 케이스로 "fall-through"될 경우, 이를 주석으로 명시해야 한다.
  • 한 줄에는 하나의 애노테이션만
    • 필드에 적용되는 애노테이션은 제외
  • 멀티라인 /* ... / 주석은 각 줄이 별도의 \로 시작하도록 작성해야 한다
  • 상수 이름에는 UPPER_SNAKE_CASE 사용해야 한다.
  • Javadoc 작성 방법

물론 일관성 있는 코드 스타일을 유지하기 위한 요소들도 있었지만, 프로그래머의 실수를 방지하고 간결한 코드 작성을 위한 가이드가 많은 것 같다. 평소에 PS를 꾸준히 해왔다보니 코드 스타일이 많이 더러웠는데, 이번 기회에 좋은 코드 스타일로 프로그램을 작성하는 습관을 길러야겠다.

1주차 미션 진행

구현 기능 목록 작성

1주차 미션의 요구사항이 얼마 되지 않는 것을 보고 꽤 간단하다고 느꼈다. 지금까지 어떤 프로젝트를 할 때 기능들을 나열해오긴 했었다. 예를 들면, “게시글의 수정 기능을 구현” 이런식으로 되게 추상적으로 기능 목록을 정리했었다. 하지만 이렇게 추상적으로 기능 목록을 작성하고 프로젝트를 하니 항상 구현 단계에서 문제가 발생했었다. 비록 기능 요구사항이 간단하지만 최대한 디테일하게 구현할 기능 목록을 작성해보았다.

기능 분석

  • 문자열을 입력받아야 한다.
  • 입력받은 문자열에서 커스텀 구분자를 찾아야 한다.
    • 형식에 맞지 않는 문자열이 들어오는 경우 예외를 발생시킨다.
  • 문자열에서 커스텀 구분자를 제외한 수식 부분만 분리해낸다.
    • 형식에 맞지 않는 문자열이 들어오는지 validation 검사를 진행한다.
  • 분리해낸 문자열에서 숫자를 추출한다.
  • 추출된 숫자를 가지고 결과를 얻는다.
  • 계산 결과를 출력한다.

이렇게 디테일하게 기능을 분석하다보니 설계 단계에서 추상적으로 제시된 요구사항을 발견하고, 내 스스로 구체화시킬 수 있었다. 예를 들면, 커스텀 구분자는 1개만 존재하는지, 아니면 여러 개 존재하는지 요구사항에 명확히 들어나있지 않음을 파악하고, 여러 개의 커스텀 구분자가 가능하다고 가정하고 기능 분석을 진행하였다. 만약 이를 구현단계에서 발견했다면, 다시 기능 분석을 뜯어 고쳐야 하는 상황에도 이를 수 있다고 생각된다.

기능 목록 단위로 커밋하기

과거에 학교에서 “소프트웨어공학” 수업에서 교수님이 커밋 로그를 보고 기능 단위로 커밋을 하는 습관을 기르라고 하셨는데 잘 지키지 못했던 기억이 있다. 항상 하나의 기능을 구현하고 나면 신나서 커밋을 하지 않고 다음 기능을 구현하려고 했던 것 같다. 이번 1주차 미션에서도 평소보다 지키려고 노력했으나 일부 기능을 구현할 때 기능 단위로 커밋하는 것을 놓쳤다. 이번 미션에서 아쉬웠던 부분 중 하나였다.
기능을 전부 구현하고 PR을 날리고 나서, 다른 분들이 PR 날린 것들을 살펴보는데, 기능 목록이나 요구사항을 체크리스트로 만들고 하나씩 체크해나가시는 분들이 계셨다. 되게 좋은 습관이라고 생각이 들어서 다음 미션부터는 기능 목록, 요구사항을 체크리스트로 만들어서 미션을 진행해보겠다.

설계

이번 1주차에서 가장 고민이 많았던 부분이다. 평소에 웹 Application을 만들 때 Layered Architecture를 적용해 Service, Repository, Entity, Controller를 만들었다. 그런데 이번 프리코스 미션 요구사항의 기능을 구현할 때 과연 이런 구조가 필요할까? 라는 생각이 들었다. 기능이나 비즈니스 로직의 확장성을 고려해서 프로그래밍 하는게 맞을까? 라는 고민을 하게 되었다.
그래서 처음에는 Service, Repository, Domain, Controller, View를 만들고 코드를 작성했다. 의존관계 주입을 위해서 AppConfig 클래스도 만드는 등 확장성을 고려하고 프로그래밍을 시작했다. 그런데 Repository를 만들 쯤에 든 생각이 “저장이나 수정하는 기능이 없는데 굳이 Repository를 만들어야 하나?”라는 고민이 들었다. 그래서 리팩토링을 해서 Controller, View, Service는 그대로 남기고, 기능에 대한 책임별로 클래스를 만들었다.
토요일까지 기능을 전부 구현하고 예제 테스트까지 통과했다. 그리고 나서 내 코드를 다시 돌아보았다.
현재 내 코드에서는 ExpressionParser라는 클래스가 구분자, 숫자, 구분자를 제외한 문자열 이렇게 총 3개의 필드에 의존하는 구조이다. 하지만 이렇게 필드를 최소화하여 단순히 파라미터로 메서드에 필요한 값만 넘기는 식으로 구현했다면 클래스별로 의존관계를 줄이고 SRP를 최대화할 수 있을 것이란 생각이 들었다. 앞으로는 내가 구현할 Application의 의도가 무엇인지 파악하고 이에 맞게 클래스 설계를 해야겠다.

1주차를 마치며

어떤 식으로 프리코스가 진행되는지 익숙해질 수 있는 한 주였다. 요구사항이 간단했지만 스스로 고민해볼 것들이 많았던 한 주 였다. 1주차 미션 제출이 마감되고 커뮤니티가 열린다면 크루분들에게 코드 리뷰를 받으면서 내가 고민하고 결정했던 부분들이 어떤 장점과 단점이 있는지 분석해보고 싶다.