Skip to content

Conversation

@Timothy-Y-H-Lee
Copy link

1주차 과제: 구분자로 자른 문자열의 숫자값 덧셈

Timothy added 14 commits October 14, 2025 21:27
…alysis

# 프로젝트의 기능 요구사항 및 기능 목록 초안 작성 (문제 핵심 파악 포함)
# feat(#1): MVC & TDD - Store user input in the model

- Model: 사용자의 입력값을 생성자를 통해서 저장
  # Model: Save user input via constructor

- ModelTest: 사용자의 입력값을 기본 구분자(",:")로 분리 후
  모델에 저장한 뒤, 이를 꺼냈을 때 값이 동일한지 테스트
  # ModelTest: Split user input using default delimiters (",:");
  # store it in the model and verify retrieved values match the original
# 기능목록 업데이트

- MVC & TDD - use Service to save user input into the Model
# MVC & TDD - Service를 이용해서 모델에 사용자의 입력값을 저장
# feat(#2): Use Service to store user input into the model

- 싱글톤을 이용해서, 입력값인 문자열에 기본 구분자들(쉼표(,)와 콜론(:))이 포함되어 있는지 체크
# Using a singleton, check if the input string contains the default delimiters (comma ',' and colon ':')
# feat(#2): Use Service to store user input into the model

- 싱글톤을 이용해서, 입력값인 문자열에 "//"와 "\n" 사이의 커스텀 구분자가 있는지 체크
# Using a singleton, check if the input string contains a custom delimiter between "//" and "\n"
# docs(#2): update feature list

- 서비스, 컨트롤러, 뷰의 기능목록을 업데이트
  # Updated the feature list of Service, Controller, and View
# refactor(#2): move CalculatorService to a new package location

- 변경된 패키지 위치: calculator.service.CalculatorService
  # Updated package location: calculator.service.CalculatorService
# feat(#2): complete MVC structure

- 나머지 MVC 구조 제작 후, "커스텀_구분자_사용" 테스트 케이스 통과
  # After completing the remaining MVC components, the "custom_delimiter_usage" test case passed
# docs(#2): update feature list – add test case to ensure only positive input values are accepted

- 기능 목록 추가 사항: "입력값이 양수만 입력이 가능하도록 테스트 케이스 처리"
  # Added feature list item: test case ensuring only positive numbers can be entered
# feat(#2): handle test case to allow only positive input values

- "예외_테스트()" 테스트 케이스를 통해, 입력값이 양수만 입력이 가능하도록 테스트 케이스 처리
  # Through the "exception_test()" test case, ensure that only positive input values are allowed
…스 처리

# docs(#2): update feature list - add test case allowing both default and custom delimiters in user input

- 기능목록 업데이트: 사용자의 입력값에서 기본 구분자와 커스텀 구분자를 함께 사용이 가능하도록 테스트 케이스 처리
  # Updated feature list: test case ensuring both default and custom delimiters can be used together in user input
# feat(#2): add test case to allow both default and custom delimiters in user input

- As-Is: 기존에는 사용자의 입력값 중에 커스텀 구분자와 기본 구분자를 함께 사용할 수 없었음.
  # As-Is: User input could not contain both custom and default delimiters.
- To-Be: 사용자의 입력값에서 기본 구분자와 커스텀 구분자를 함께 사용이 가능하도록 테스트 케이스 처리
  # To-Be: Added a test case to ensure that user input supports both default and custom delimiters.
# docs(#2): update feature list – actually use Model to store and retrieve a list of numbers separated by delimiters

- 사용자의 입력값을 Model을 사용해서 구분자로 정리된 숫자 목록을 저장 후, 꺼내어 사용
  # Used the Model to store the list of numbers separated by delimiters and retrieve them when needed
# feat(#2): actually use Model to store and retrieve a list of numbers separated by delimiters

- As-Is: 기존에는 사용자의 입력값을 모델에 저장하지 않음.
  # As-Is: The user input was not stored in the model.

- To-Be: 사용자의 입력값을 Model을 사용해서 구분자로 정리된 숫자 목록을 저장 후, 꺼내어 사용
  # To-Be: Use the Model to store the list of numbers separated by delimiters and retrieve them when needed.
Copy link

@KennyKim33 KennyKim33 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

코드 전체적으로 잘 보았습니다.
특히 TDD 방식으로 테스트를 먼저 작성하고, 이를 기반으로 기능을 구현해 나가신 점이 매우 인상 깊었습니다.
TDD 경험이 많지 않은 저에게도 좋은 학습 예시가 되어서 많이 배웠습니다.

한 가지 커밋 메시지 관련해서 궁금한 점이 있습니다.
모든 커밋이 feat(#2) 형태로 작성되어 있던데, 혹시 특정 이슈 번호와 연결하기 위한 용도였을까요?

추가로 제안드리고 싶은 부분은,
feat(#2)처럼 모든 커밋을 동일한 태그로 작성하기보다는,
feat(기능명) 혹은 feat(관련 패키지명)처럼 구체적인 의미를 드러내도 좋을 것 같습니다.
이렇게 하면 커밋 히스토리를 나중에 확인할 때도
“어떤 부분에 대한 기능 추가였는지”를 더 빠르게 파악할 수 있다는 장점이 있을 것 같습니다.

Comment on lines 21 to 36
public static String extractCustomDelimiter(String userInput) {
String startDelimiter = "//";
String endDelimiter = "\\n";

Integer startIndex = userInput.indexOf(startDelimiter) + startDelimiter.length();
Integer endIndex = userInput.indexOf(endDelimiter);
if (endIndex == -1) {
// 실제 줄바꿈 문자를 인식하도록 처리
endDelimiter = "\n";
endIndex = userInput.indexOf(endDelimiter);
}

return (startIndex != -1 && endIndex != -1 && startIndex < endIndex)
? userInput.substring(startIndex, endIndex) : "";
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

startDelimiter와 endDelimiter는 매직 스트링으로 보이는데, 상수로 분리해두면 의미가 명확해지고 재사용성이 높아질 것 같습니다.
예: private static final String START_DELIMITER = "//";

삼항 연산자를 활용한 부분은 간결하지만, 조건이 길어지면서 가독성이 조금 떨어질 수 있습니다.
조건식을 별도의 변수에 담거나 메서드로 분리하면 읽기가 더 편해질 것 같습니다.

Comment on lines +86 to +97
// 숫자 유효성 검사: 숫자가 아니거나 음수인 경우 예외 발생
public static void validateNumber(String validateNumber) {
try {
Integer number = Integer.parseInt(validateNumber);
if (number < 0) {
throw new IllegalArgumentException("양수만 입력 가능합니다." + validateNumber);
}
} catch (NumberFormatException e) {
throw new IllegalArgumentException("숫자가 아닙니다. " + validateNumber);
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사용자에게 입력을 받는 부분은 enum을 사용해서 처리를 해주셨던 거 같은데, 예외를 던지는 메시지 같은 경우도 상수로 처리하거나 enum을 사용하는 건 어땠을까요?

개인적으로는 통일성있는 코드 구조를 선호하다보니 읽다가 궁금증이 생겼습니다. 의도하신게 있으실까요?

public static List<String> splitByDelimiter(String userInput, String delimiter) {
return Arrays.stream(userInput.split(delimiter))
.map(String::trim) // 공백 제거
.peek(CalculatorService::validateNumber) // 숫자 유효성 검사

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제가 알기론 streampeek 은 디버깅을 사용할 때 유용하게 쓰는 메서드로 알고 있습니다.

현재처럼 중요한 검증 로직을 peek 안에 넣게 되면 의도가 잘 드러나지 않아,
나중에 코드를 읽을 때 혼동을 줄 수 있을 것 같습니다.

오히려 validate와 같이 중요한 로직을 검증하는 것이라면, 중간에 빼서 따로 사용하는게 더 좋지 않았을까 하는 생각이 듭니다.

Comment on lines 65 to 69
// Model 단에 사용자의 입력값을 저장
calculatorModel = new CalculatorModel(splitByDelimiter(content, delimiter));

// 숫자로 변환한 후 합계 계산
return numbers.stream()
return calculatorModel.getUserInputList().stream()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사용자 입력값을 CalculatorModel에 한 번 저장한 뒤,
다시 그 값을 꺼내서 계산하는 흐름이 다소 번거롭게 느껴졌습니다.

혹시 이렇게 구성하신 데에 특별한 의도가 있으실까요?

입력 문자열로부터 CalculatorModel을 생성하는 단계와,
생성된 CalculatorModel을 파라미터로 받아 계산하는 로직을 각각 메서드로 분리하면
역할이 더 분명해지고, 테스트나 재사용 관점에서도 이점이 있을 것 같다는 생각이 들었습니다.

return numbers.stream()
return calculatorModel.getUserInputList().stream()
.map(Integer::parseInt) // 문자열을 Integer로 변환
.reduce(0, Integer::sum); // 합계

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제가 알기로는 .map(Integer::parseInt)는 Stream를 만들어서
sum()를 사용할 수 없는 구조라서 reduce를 쓰신 것 같습니다.

Integer 스트림보다는 mapToInt(Integer::parseInt)를 활용해
primitive IntStream으로 변환하면 .sum()을 바로 사용할 수 있어
더 간결하고 박싱 오버헤드도 줄일 수 있을 것 같습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants