Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
5a36a23
update README.md
yerimming Oct 19, 2025
742e3c6
docs: update README.md
yerimming Oct 19, 2025
ef9af01
feat(ConsoleView): 문자열을 입력받는 파일 추가
yerimming Oct 19, 2025
751c88e
feat(CalculatorController): CalculatorController 기본 구조 및 ConsoleView …
yerimming Oct 19, 2025
f1ac463
feat(App): CalculatorController 실행 로직 구현
yerimming Oct 19, 2025
e14b6b6
feat(Calculator): 입력값을 계산하는 Calculator.js 파일 추가
yerimming Oct 19, 2025
d6d1b07
refactor(Calculator): parseInt으로 통합해 커스텀 구분자 처리 및 splitNumbers 메서드 추가
yerimming Oct 19, 2025
aba99e9
feat(CalculatorController): Calculator 모델에 입력값을 전달하는 기능 추가
yerimming Oct 20, 2025
5dc4ce5
feat(Calculator): 구분한 값이 양수인지 확인하는 validateNumbers 메서드 추가
yerimming Oct 20, 2025
bebbd22
feat(Calculator): 구분한 숫자를 저장한 배열에 있는 값들을 더하는 sum 메서드 추가
yerimming Oct 20, 2025
d4e605e
refector(Calculator): sum 메서드의 reduce 내 변수명을 sum과 value로 변경
yerimming Oct 20, 2025
0ccf51a
feat(ConsoleView): 결과와 에러 메시지를 출력하는 printResult, printError 메서드 추가
yerimming Oct 20, 2025
a3da97a
refactor(ConsoleView): 입력 예외 처리 및 에러 메시지 형식 수
yerimming Oct 20, 2025
d5e7fd0
feat(CalculatorController): 계산 흐름 관리하는 기능 추가
yerimming Oct 20, 2025
efb11af
refator: 에러 메시지 수정
yerimming Oct 20, 2025
99a2cb5
refactor: 에러 메시지 수정
yerimming Oct 20, 2025
39ea419
refactor: 에러 메시지 수정
yerimming Oct 20, 2025
fb4791d
refactor: 필요없는 모듈 import 삭제
yerimming Oct 20, 2025
e29ec19
docs: update README.md
yerimming Oct 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 103 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,103 @@
# javascript-calculator-precourse
# javascript-calculator-precourse

## ✅ 기능 구현 목록

- [x] 문자열 입력 받기
- [x] 구분자를 기준으로 구분하기
- [x] `,`, `:` 기준으로 구분하기
- [x] 커스텀 구분자 기준으로 구분하기
- [x] 구분한 숫자가 양수인지 확인
- [x] 잘못된 값일 시 에러 처리 후 종료
- [x] 구분한 숫자 더하기
- [x] 결과 출력하기

## 💻 구현 내용

### 커스텀 구분자 처리

```
getCustomSeperator(input){
if(!input.startsWith("//")) return null;
const match = input.match(/^\/\/(.*?)\\n/);
return match ? match[1] : null;
}
```

- 정규표현식을 사용해 `//`와 `\n` 사이에 있는 문자를 추출.
- match 메서드로 추출한 값이 있는 경우, 두 번째 값이 커스텀 구분자이므로 index 1번 값을 반환.
- match 메서드에 매치되는 결과가 없는 경우에는 null 반환.
- `\n`이 줄바꿈을 의미하는 이스케이프 문자로 인식되어 제대로 인식되지 않는 문제가 있었는데 앞에 `\`을 붙여 `\\n`으로 사용하니 `\n`을 그냥 문자로 사용할 수 있었음.
- `/`도 마찬가지로 인식되지 않는 문제가 있었는데 앞에 `\`을 붙여 사용하니 인식됨.

### 문자열 구분자로 구분

```
splitNumbers(numbersPart, customSeperator = null) {
let delimiters = ",:";

if(customSeperator) {
delimiters += customSeperator;
}

const regex = new RegExp(`[${delimiters}]`);
return numbersPart.split(regex);
}
```

- `,`,`:`, 커스텀 구분자를 사용해 문자열을 분리.
- 배열로 저장된 분리한 문자열을 반환.

### 입력값 잘못된 경우 에러 처리 후 종료

```
validateNumbers(numbers) {
numbers.forEach((value) => {
const num = Number(value);
if(isNaN(num) || num < 0) {
throw new Error("[ERROR]");
}
});
}
```

- 입력값이 구분자와 양수 외에 다른 문자로 이루어져 있는지 확인하는 메서드.
- 구분자로 구분한 값이 저장되어 있는 배열 numbers를 forEach로 순환하면서 확인.
- Number 메서드를 사용했을 때 숫자로 변경되지 않는 문자면 NaN이 저장되므로 isNaN 메서드를 사용해서 숫자인지 아닌지 확인.
- 변경된 숫자는 음수인지 아닌지 확인
- 두 조건 중 하나라도 만족하지 않으면 `throw new Error()`를 사용해 메시지와 함께 에러를 발생시킨 후 애플리케이션을 종료.

### 추출한 숫자 더하기

```
sum(numbers) {
return numbers.reduce((sum, value) => sum + Number(value), 0);
}
```

- reduce 메서드를 사용해 배열을 돌면서 배열의 값들을 모두 더해 반환.
- 배열에 있는 값들이 문자열이기 때문에 Number를 사용해 숫자로 변환.

## ⭐️ 실행 결과

### 옳은 입력

- `,`를 구분자로 사용한 경우
<img width="487" height="130" alt="Image" src="https://github.com/user-attachments/assets/6e2b88ec-b890-490a-93fc-02843194e6d9" />

- `:`를 구분자로 사용한 경우
<img width="537" height="133" alt="Image" src="https://github.com/user-attachments/assets/d2416705-a6d6-482e-9c81-04c0f21b65ca" />

- 커스텀 구분자를 입력한 경우
<img width="476" height="131" alt="Image" src="https://github.com/user-attachments/assets/092f4ef2-536c-4e1a-889d-1818407f1986" />

### 잘못된 입력 시

- 양수가 아닌 문자를 입력한 경우
<img width="579" height="117" alt="Image" src="https://github.com/user-attachments/assets/1f7545b4-22e7-45a7-a58a-9a5156053d30" />

- 양수가 아닌 음수를 입력한 경우
<img width="557" height="115" alt="Image" src="https://github.com/user-attachments/assets/0eb369b1-9ae1-4829-833c-4ad180d6cee3" />

### 테스트 결과

<img width="1656" height="712" alt="Image" src="https://github.com/user-attachments/assets/01186a9e-e698-4d2d-b265-c83746ce533c" />
7 changes: 6 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import CalculatorController from "./controller/CalculatorController.js";

class App {
async run() {}
async run() {
const controller = new CalculatorController();
await controller.run();
}
}

export default App;
24 changes: 24 additions & 0 deletions src/controller/CalculatorController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import ConsoleView from "../view/ConsoleView.js";
import Calculator from "../model/Calculator.js";

class CalculatorController {
constructor() {
this.view = new ConsoleView();
Copy link

@iftype iftype Oct 22, 2025

Choose a reason for hiding this comment

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

// 정적메소드로 변경 시
// controller/CalculatorController.js
    import ConsoleView from "../view/ConsoleView.js";
    // this.view = new ConsoleView(); 제거 
    // ...
    ConsoleView.printResult(result);
// view/ConsoleView.js
  class ConsoleView {
    static printResult() {
    //...
    }
}

ConsoleView 클래스의 메소드들은 인스턴스 상태를 사용할 필요가 없어보여서
static method 로 만들어서 호출하는게 좋아보입니다..!

9.7 airbnb
mdn-staitc-this

this.calculator = new Calculator();
}

async run() {
try{
const input = await this.view.getInput();
const numbers = this.calculator.parseInput(input);
this.calculator.validateNumbers(numbers);
const result = this.calculator.sum(numbers);
this.view.printResult(result);
} catch(error) {
this.view.printError(error);
throw error;
}
}
}

export default CalculatorController;
44 changes: 44 additions & 0 deletions src/model/Calculator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
class Calculator {
parseInput(input){
let numbersPart = input;
const customSeperator = this.getCustomSeperator(input);

if(customSeperator) {
Copy link

Choose a reason for hiding this comment

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

    //let numbersPart = input; 삭제  
    const customSeperator = this.getCustomSeperator(input);  

    if (customSeperator) {  
      const numbersPart = input.split(`\\n`)[1];  
      return this.splitNumbers(numbersPart, customSeperator);  
    }  
    //...  

이 경우 early return 을 사용하면 const로 바꿀 수 있어보입니다!

numbersPart = input.split(`\\n`)[1];
}

return this.splitNumbers(numbersPart, customSeperator);
}

getCustomSeperator(input){
if(!input.startsWith("//")) return null;
const match = input.match(/^\/\/(.*?)\\n/);
return match ? match[1] : null;
}

splitNumbers(numbersPart, customSeperator = null) {
let delimiters = ",:";

if(customSeperator) {
delimiters += customSeperator;
}

const regex = new RegExp(`[${delimiters}]`);
return numbersPart.split(regex);
}

validateNumbers(numbers) {
numbers.forEach((value) => {
const num = Number(value);
if(isNaN(num) || num < 0) {
Copy link

Choose a reason for hiding this comment

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

Number.isNaN 을 권장하고있습니다!
MDN Number.isNaN()
velog-isNan()

throw new Error("[ERROR]");
}
});
}

sum(numbers) {
Copy link

Choose a reason for hiding this comment

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

import { sum } from "./utils.js";
export function sum(numbers){
        //...
    }

인스턴스를 사용하지 않는 간단한 함수는 유틸폴더로 빼서 클래스의 크기를 줄이는 방법도 있습니다!

return numbers.reduce((sum, value) => sum + Number(value), 0);
}
}

export default Calculator;
23 changes: 23 additions & 0 deletions src/view/ConsoleView.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Console } from "@woowacourse/mission-utils";

class ConsoleView {
async getInput() {
try {
const input = await Console.readLineAsync("덧셈할 문자열을 입력해 주세요\n");
return input;
} catch {
throw new Error("[ERROR]");
}

}

printResult(result) {
Console.print(`결과 : ${result}`);
}

printError(error){
Console.print("[ERROR]" + error.message);
}
}

export default ConsoleView;