diff --git a/README.md b/README.md
index 13420b29..8fbb9e01 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,103 @@
-# javascript-calculator-precourse
\ No newline at end of file
+# 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를 사용해 숫자로 변환.
+
+## ⭐️ 실행 결과
+
+### 옳은 입력
+
+- `,`를 구분자로 사용한 경우
+
+
+- `:`를 구분자로 사용한 경우
+
+
+- 커스텀 구분자를 입력한 경우
+
+
+### 잘못된 입력 시
+
+- 양수가 아닌 문자를 입력한 경우
+
+
+- 양수가 아닌 음수를 입력한 경우
+
+
+### 테스트 결과
+
+
diff --git a/src/App.js b/src/App.js
index 091aa0a5..204c73a1 100644
--- a/src/App.js
+++ b/src/App.js
@@ -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;
diff --git a/src/controller/CalculatorController.js b/src/controller/CalculatorController.js
new file mode 100644
index 00000000..096738c2
--- /dev/null
+++ b/src/controller/CalculatorController.js
@@ -0,0 +1,24 @@
+import ConsoleView from "../view/ConsoleView.js";
+import Calculator from "../model/Calculator.js";
+
+class CalculatorController {
+ constructor() {
+ this.view = new ConsoleView();
+ 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;
\ No newline at end of file
diff --git a/src/model/Calculator.js b/src/model/Calculator.js
new file mode 100644
index 00000000..c9d2060f
--- /dev/null
+++ b/src/model/Calculator.js
@@ -0,0 +1,44 @@
+class Calculator {
+ parseInput(input){
+ let numbersPart = input;
+ const customSeperator = this.getCustomSeperator(input);
+
+ if(customSeperator) {
+ 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) {
+ throw new Error("[ERROR]");
+ }
+ });
+ }
+
+ sum(numbers) {
+ return numbers.reduce((sum, value) => sum + Number(value), 0);
+ }
+}
+
+export default Calculator;
\ No newline at end of file
diff --git a/src/view/ConsoleView.js b/src/view/ConsoleView.js
new file mode 100644
index 00000000..f88028c7
--- /dev/null
+++ b/src/view/ConsoleView.js
@@ -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;
\ No newline at end of file