우아한테크코스

"프리코스 1주 차 회고" 프리코스에 적응하기

kanado 2024. 10. 21. 14:12


📝 오늘의 Todo 리스트 체크

1. 1주차 회고 작성
     - 어떤 것이 제일 어려웠는지 생각해보기 ✅
     - 배운점이나 깨달은 것들을 정리하기

     - 지난 일주일을 돌아보며 앞으로 계획 세우기

2. 마지막 검토 및 최종 제출

     - PR링크 제대로 들어가지는지 확인하기

     - 우테코 사이트에서 회고 작성 및 제출


목차

- 일주일을 돌아보기
- 나만의 회고 양식 구성

- 생각의 흔적들
     - 기능 목록에 들어가야할 기능들의 기준점이 뭘까?
     - 예외 생각해보기 (커스텀 구분자를 어디까지 허용해야할까?)
     - 내가 설정한 프리코스 목표대로 잘하고 있는걸까?
     - MVC 구조 설계하면서 지켰던 규칙들

     - 예외를 확인하는 함수를 누가 책임지는 것이 맞는가?

     - 개행 문자 "\n" 처리 어떻게 해야할까? ⭐️

- Refactoring

     - 설계단계에서 놓친 단일 책임 원칙(SRP)을 위반하는 클래스 발견

     - 단순한 유틸리티 클래스 생각해보기

     - 디미터 법칙 (Law of Demeter) 위반 코드 발견
     - Tell, don't ask 원칙 위반 코드 발견

- 배운것들
    - USE CASE 시나리오/다이어그램
    - JDK 17에서 21까지의 주요 변경사항들
    - TDA(Tell, Don’t Ask) 원칙
    - 단일 책임 원칙 SRP
    - 디미터 법칙 (Law of Demeter)
    - 클래스 다이어그램

- 마무리 및 앞으로의 Plan

 


[ 일주일을 돌아보기 ]

[우아한테크코스] - "프리코스 시작" 새로운 도전을 향한 출발

[우아한테크코스] - "프리코스 2일차" 기능 목록 작성(예외 생각하기), 프리코스 커뮤니티 참여

[우아한테크코스] - "프리코스 3일차" 나의 프리코스 목표 check, MVC 설계, 커뮤니티에서 지식 공유

[우아한테크코스] - "프리코스 4일차" JDK 17~21 주요 변경사항들, 커밋 기준, 코드 구현 시작

[우아한테크코스] - "프리코스 5일차" 개행 문자 "\n" 해결 방법, 커스텀 구분자 정의, MVC 업데이트

[우아한테크코스] - "프리코스 6일차" 리팩토링(Law of Demeter, TDA 원칙), 클래스 다이어그램

 

프리코스 첫 주차를 앞두고 설렘, 기대, 두려움과 같은 다양한 감정들이 끊임없이 교차했던 것 같아. 새로운 도전에 대한 기대감이 컸지만, 동시에 잘 해낼 수 있을지에 대한 두려움도 있었다. 하지만 프리코스 첫 주차를 끝낸 지금은 스스로 한 단계 성장했다는 뿌듯함과 함께, 배움의 즐거움만을 느끼고 있다.  

 

1주 차 첫날 화요일에 앞으로 일주일 동안의 계획을 간략하게 세웠다. 그리고 매일 매일 블로그에 그날의 기록을 남기면서 마지막에는 내일 해야 할 일들과 학습할 것들로 작은 데일리 목표를 설정했다. 그리고 다음 날, 그 목표 중 어느 정도를 완료했는지 체크하면서 스스로의 진척 상황을 점검했다. 이러한 과정을 통해 매일 꾸준히 학습하고, 목표를 하나씩 달성해나갔다.


[ 나만의 회고 양식 구성 ]

일주일동안 매일 작성했던 블로그의 내용을 보면서 1주 차 회고를 본격적으로 시작했다. 회고의 양식이 자유롭다 보니 어떻게 구성해야 할지 고민이 많았다. 그래서 내가 고민했던 것들, 궁금했던 것들, 가장 어려웠던 것들을 하나의 섹션인 '생각의 흔적들'로 묶어보는 것이 어떨까 생각했다. 이어서는 리팩토링 과정에서 발생했던 문제점들과 코드 개선 과정을 상세히 정리하려고 한다. 그 다음으로는 일주일동안 배운것들을 정리하고, 마지막으로, 우테코 프리코스 첫 주차를 경험하면서 느꼈던 점들과 생각들을 바탕으로 앞으로의 계획을 세워보려고 한다.


[ 생각의 흔적들 ] 

1. 기능 목록에 들어가야할 기능들의 기준점이 뭘까?

기능 목록을 작성하기 전에, 하나의 시스템 내에 포함될 수 있는 기능의 종류가 많고 다양하기 때문에 명확한 기준점을 설정하는 것이 중요하다고 생각했다. "소프트웨어 공학의 모든 것"이라는 책에서 읽었던 기능 요구와 비기능 요구에 대한 내용이 떠올라, 이를 참고했다.

약해서 말하자면 소프트웨어 프로젝트에서 기능 요구와 비기능 요구를 명확하게 정의하는 것은 시스템의 완성도와 품질을 높이는 데 필수적이다. 기능 요구는 시스템의 기본적인 동작을 정의하고, 비기능 요구는 그 동작을 보다 효과적이고 안전하게 만들기 위해 필요한 속성을 설정한다. 즉, 비기능 요구 시스템의 안정성, 성능, 보안 등을 다루고, 기능 요구는 소프트웨어가 사용자와 상호작용하며 수행해야 하는 구체적인 작업이나 행동을 설명한다.

따라서 나는 기능 요구의 개념을 기준으로 기능 목록을 작성하기로 결정했다. 총 4가지 기능이 나왔다.
1) 양수로 구성된 문자열 입력 받기
2) 커스텀 구분자 여부 확인

3) 피연산자들의 합 계산
4) 결과 출력

 

2. 예외 생각해보기 ( 커스텀 구분자를 어디까지 허용해야할까? )

예외를 생각했을 때 두가지로 나눠서 생각했다. 피연산자 입력에서 발생할 수 있는 예외 그리고 커스텀 구분자 입력에서 발생할 수 있는 예외들로 나누었다.

 

1) 양수로 구성된 문자열을 입력받을 때 발생할 수 있는 예외를 고려해본 결과, 문자열 내에서 구분자로 분리된 값이 양수(자연수)가 아닐 경우 모두 예외로 처리해야 한다고 판단했다. 이러한 경우 문자열, 빈 문자열(스페이스바), 음수가 해당되며, 이 모든 경우를 "자연수가 아니다"라는 하나의 조건으로 처리할 수 있을 것이라고 생각했다.

 

2) 커스텀 구분자를 확인하는 과정에서는 처음에 특수 기호만 구분자로 생각했지만 문자열, 문자, 숫자도 구분자로 사용할 수 있을까?라는 의문이 생겼다. 그래서 먼저 구분자의 개념을 명확히 하기 위해 조사를 진행했는데, 결과는 다음과 같았다. "구분자는 문자열에서 특정 대상을 다른 대상과 구분하기 위한 기호를 의미하며, 구분문자라고도 한다." 즉, 구분자는 문자 특수 기호로 이루어질 수 있다는 말이였다.

 

하지만 그래도 1주차 미션 "기능 요구 사항"에서는 구분자 정의에 대한 별말이 없어서 "숫자도 구분자로 사용할 수 있지 않을까?"라는 생각이 들었다. 이유는 숫자가 문자열 안에 들어가면, 시스템은 "abc"와 "123"을 동일하게 문자열로 처리할 것이기 때문이다. 그러나 온전히 연산식으로만 봤을 때는 숫자를 구분자로 허용했을 때 문제가 발생할 수 있다. 숫자들이 연산식에 포함되면 "123412351235"와 같은 형태로 출력될 수 있는데, 이 경우 연산식 내에서 연산자와 피연산자가 명확하게 구분되지 않기 때문이다. 구분자가 숫자로 설정되면, 코드가 이를 혼동해 예상하지 못한 결과를 초래할 수 있어 구분자로는 숫자를 제외하기로 판단했다.

 

이에 따라 다음과 같이 예외를 정리했다.
- "//"와 "\n" 사이에 아무것도 없을 경우

- "//"와 "\n" 사이에 숫자가 있을 경우

- "//"와 "\n" 둘 다 없거나 둘 중 하나만 있을 경우

 

3. 내가 설정한 프리코스 목표대로 잘하고 있는걸까?

프리코스를 진행하면서 문득 생각이 들었다. 지원서를 작성할 때 내가 설정했던 프리코스 목표를 제대로 수행하고 있는가? 이를 확인하기 위해 다시 한 번 내가 설정한 목표를 점검해보았다.

 

1) 문제 해결 과정에서 주도적으로 학습하고 해결하기

2) 매일 작은 학습 목표를 설정하기

3) 학습 또는 문제 해결 과정에서 어떤 접근 방식을 사용했는지와 어떤 것을 고민했는지 기록하기

4) 코드를 작성하는 것에 그치지 않고, 문제의 본질을 이해하기

 

1),2),3)번은 잘 하고 있는 것 같았다.😌

4)번은 코드 관점에서는 문자열을 다룬 경험이 많을수록 난이도가 다르게 느껴졌을 거라고 생각했다. 그리고 코드 관점만이 아니라, 이번 첫 번째 미션의 더 큰 목적에 대해서도 생각해봤다. 단순히 미션을 완료하고 그 과정에서 배운 점만으로 충분할까? 그러기에는 첫주차 미션이 조금 쉽다(?)라는 생각을 했다. 그렇다면 첫 주차에 수료생들이 어떤 것을 얻어가길 바라면서 우테코 멘토분들이 이렇게 미션을 구성했을까? 어떤 의도와 목적이 담겨 있을까? 생각해봤을 때 "적응하기"가 떠올랐다. 

 

적응에는 여러 가지가 있을 수 있다. 예를 들어, IDE 사용법을 익히는 것부터 git commit과 push를 해보는 것까지 다양하다. 더 나아가, 프리코스 커뮤니티를 둘러보며 다른 사람들과 소통하고, 지식을 공유하며 서로의 목표와 이야기를 나누는 시간도 적응 과정에 포함된다고 생각했다. 그리고 가장 중요하다고 생각하는 MVC 구조도 적응 과정에 포함된다고 본다. MVC 구조로 코드를 작성하는 것이 익숙하지 않은 사람들에게는 처음에 매우 어렵고 부담스러울 수 있다. 그래서 이번 첫 번째 간단한 미션을 통해 MVC 구조에 대한 이해를 높이고, 이를 적용해보는 기회를 제공하려는 것이 아닐까 생각한다. 

 

4. MVC 구조 설계하면서 지켰던 규칙들

"문자열 덧셈 계산기" 미션에 대해 MVC 구조를 설계할 때 다음과 같은 규칙을 준수했다.
1. TDA(Tell, Don’t Ask) 원칙을 준수하기

2. 단일 책임 원칙(Single Responsibility Principle, SRP) 준수하기

3. 최대한 클래스, 메소드, 변수 이름을 축약하지 않기

4. 각 메소드가 "뭐뭐 하기"로 설명 가능하게 설계하기

TDA(Tell, Don’t Ask) 원칙과 단일 책임 원칙(Single Responsibility Principle, SRP)은 객체 지향 프로그래밍에서 가장 먼저 떠오르고 적용한 중요한 기본 원칙이다.

 

미션을 진행하면서 클래스, 메소드, 변수 이름을 최대한 축약하지 않고 명확하게 작성하려고 했다. 그 이유는 코드의 가독성 유지보수성을 높이기 위해서다. 이름을 축약하면 다른 개발자가 코드를 확인할 때는 의미를 파악하기 어려워질 수 있음으로 이름이 명확해야 코드의 목적과 역할을 쉽게 이해할 수 있다. 따라서 클래스와 메소드, 변수의 이름은 해당 코드가 무엇을 수행하는지 명확하게 설명하도록 작성하는 것이 중요하다고 생각해서 최대한 축약하지 않았다.

메소드를 설계할 때는 각 메소드가 어떤 역할을 수행하는지 쉽게 설명할 수 있도록 구조를 잡았다. 즉, 메소드 이름이 "뭐뭐 하기"와 같은 형태로 설명될 수 있어야 한다는 원칙을 적용했다. 이렇게 하면 코드의 목적이 명확해져, 메소드가 하는 일을 직관적으로 파악할 수 있다. 또한, 이 원칙을 따르면 설계 단계에서 한 메소드가 두 가지 이상의 일을 수행하지 않도록 방지할 수 있었다.

 

5. 예외를 확인하는 함수를 누가 책임지는 것이 맞는가?

MVC 구조를 설계하면서 가장 고민이 되었던 것은 "예외를 확인하는 함수를 누가 책임지는 것이 맞는가?"였다. 처음에는 예외 확인 함수를 View의 입력을 받는 클래스에 넣으려고 했다. 입력을 받으면서 동시에 유효성 검사를 수행하는 것이 맞다고 생각했기 때문이다. 하지만 단일 책임 원칙(SRP)을 고려했을 때, View 클래스는 입력과 출력의 역할에만 집중해야 하며 예외 처리를 담당하게 되면 역할이 중복되어 응집도가 떨어질 수 있다. 이에 따라 예외 확인 로직은 별도의 Validator 클래스를 만들어, 해당 클래스가 예외를 검증하고 관리하도록 책임을 분리하는 것이 더 적절하다고 판단했다.

 

6. 개행 문자 "\n" 처리 어떻게 해야할까? ⭐️

문자열에서 구분자를 추출하기 위해 여러개의 방법을 사용해보았다. 처음에는 Pattern.compile()를 이용해 두 문자열("//", "\n") 사이에 있는 커스텀 구분자를 추출하는 과정에서, 개행 문자 "\n"를 처리하는 데 오류가 발생했다. 단순하게 Pattern.compile() 자체가 문제의 원인이라고 생각해서 문자열 추출을 위해 다른 방법을 찾았다. 

 

Pattern.compile()보다 더 가본적이고 단순한 방법으로 시도해보았다. substring() 메서드를 적용해보니 간단하게 인덱스로도 쉽게 커스텀 구분자를 추출할 수 있었다. 먼저 checkCustomDelimiter() 메서드에서 "\n"의 인덱스를 반환한다. 그 다음에 getCustomDelimiter() 메서드에서 "\n"의 인덱스를 delimiterEndIndex 변수로 받고 formula 문자열에서 2번째 인덱스("//")부터 delimiterEndIndex("\n")까지의 부분 문자열을 추출한다. 즉, 아무리 긴 문자열로 구성된 커스텀 구분자를 쉽게 추출할 수 있다.

하지만!!! 위에서 발생했던 개행 문자 "\n"를 처리하는 데 오류가 여전히 발생했다.

이 문제를 다시 정의하면 //;\\n1;2;3로 입략했음에도 불구하고 콘솔에서 입력받은 문자열이 실제로는 기행 문자"\n"를 포함하지 않는다. 콘솔에서 //;\n1;2;3를 입력하면 자바 프로그램은 이것을 실제로는 //;\\n1;2;3로 인식한다. 즉, \n이 하나의 개행 문자가 아니라 두 개의 문자 '\'와 'n'으로 처리된다! 하지만 코드에서는 기행 문자"\n"를 기다리고 있어서 오류가 나고 있었다.

 

이스케이프 문자가 자바 문자열에서 특수한 의미를 가진다. 콘솔에서 //1\n21415를 입력하면 (콘솔에서 \n을 입력하면), 자바는 이를 개행 문자로 처리하지 않고 문자 '\'와 'n'으로 인식하기 위해 프로그램 내부에서는 "//1\\n21415"로 받아들여지게 된다. 즉, 자바는 이 문자열을 문자 그대로 //1\\n21415로 처리한다.⭐️⭐️⭐️

 

그래서 해결 방법으로 입력받은 문자열에서 \\n을 \n으로 대체하여 처리하면 문제를 해결할 수 있다. 이를 위해 CustomDelimiter 클래스의 생성자에서 replace() 함수로 입략된 "\\n"를 "\n"으로 대체하도록 수정했다.


[ Refactoring ]

1. 설계단계에서 놓친 단일 책임 원칙(SRP)을 위반하는 클래스 발견

MVC 설계 당시 Calculator 클래스에 커스텀 구분자 관련 함수, 문자열 split 함수, 그리고 더하기 함수까지 포함했는데, 코드를 구현하는 과정에서 이 클래스가 단일 책임 원칙(SRP)을 위반하고 있다는 것을 깨달았다. 그래서 세 가지 클래스로 분리했다. 연산식을 담당하는 FormulaHandler 클래스, 문자열 분할을 위한 Splitter 클래스, 그리고 더하기 연산을 처리하는 Calculator 클래스. 이를 통해 각 클래스가 하나의 명확한 책임을 가지도록 설계를 개선했다.

 

단일 책임 원칙(SRP)을 고려하며 MVC 구조를 설계했음에도 불구하고, 실제로 코드를 구현하는 과정에서 원칙이 잘 지켜지지 않는 부분이 있었다. 이는 설계와 구현 사이의 미세한 차이에서 비롯된 것일까? 아니면 내가 아직 실력이 부족한건가? 생각이 들었다. 단순한 설계만으로는 모든 문제를 미리 예측하기 어렵다는 점을 다시 한 번 느꼈고 앞으로 설계할 때 더 신중하게 단일 책임 원칙(SRP)을 고려해야겠다.😭

 

2. 단순한 유틸리티 클래스 생각해보기

구현 완료하고 제일 거슬려 보였던 부분은 바로 MainController가 너무 많은 객체 속성을 가지고 있던 것이다. 다시 생각해보니 InputView, OutputView 클래스가 속성을 가지고 있지않고 순수 메서드만 가지고 있는 단순한 유틸리티 클래스다. Calculator 클래스도 마찬가지다. 그래서 이 3개의 클래스가 가진 메서드를 static으로 바꾸고 MainController에서 그 클래스들의 객체를 속성으로 선언하지 않고 메소드를 정적 호출로 사용하도록 수정했다.

3. 디미터 법칙 (Law of Demeter) 위반 코드 발견

MainController클래스의 calculate() 메서드와 printSumToUser() 메서드 사이에 최소 지식 원칙을 위반하는 코드를 발견했다. calculate() 메서드 안에서 Splitter 객체의 getSplittedNumbers() 메소드를 통해 피연산자들을 split하고, 그 결과를 printSumToUser() 메서드 안에 있는 plus() 메서드에게 전달하고 있었다.

 

해당 코드 부분에서 최소 지식 원칙이 위반된 이유는, calculate 메서드안에서 Splitter 객체의 getSplittedNumbers() 메소드를 통해 Splitter의 내부 상태(즉, splitter가 가지고 있는 데이터)를 외부에서 직접 접근하고 있다는 점이다. 최소 지식 원칙은 객체 간의 관계를 최소화하여 객체가 자신의 책임에 대해서만 알도록 하는 원칙으로 위 코드에서 calculate() 메소드는 splitter.getSplittedNumbers()를 통해 Splitter 객체의 세부 사항에 직접 접근함으로써, Splitter 객체의 내부 구조에 의존하게 된다. 이로 인해 코드의 유지보수가 어려워질 수 있고, 객체 간의 결합도가 높아진다.

 

 

이 문제를 해결하기 위해 Calculator.plus() 메소드 내부에서 Splitter가 getSplittedNumbers() 메소드를 호출하는 방식은 그대로 유지하되, 외부에서 Splitter에 직접 접근하지 않도록 하였다. 즉, calculate() 메소드에서 Splitter 객체를 생성하고 getSplittedNumbers() 메소드를 호출하는 것이 아니라, plus() 메소드가 Splitter 객체의 책임을 모두 처리하게 하였습니다. 이를 통해 피연산자를 split하는 책임이 Calculator 클래스에만 의존하게 되어, 외부에 불필요하게 많은 정보를 노출하지 않게 되다. 이로 인해 MainController클래스의 calculate() 메서드가 plus()메서드를 실행하고, printSumToUser() 메서드는 오직 결과물을 사용자에서 보여주는 역할만 담당하게 되어각 메서드의 역할이 더욱 더 명확해졌다.

 

4. Tell, don't ask 원칙 위반 코드 발견

Tell, don't ask 원칙이 위반되고 있는 코드를 Splitter 클래스에서 발견했다. Splitter 클래스의 속성을 직접 get하는 메서드로 다른 클래스에서 이를 사용할 수 있게 구현되어있었다. 이를 방지하기 위해서 다음과 같이 수정했다.

 

수정된 코드는 Tell, don't ask 원칙을 따르기 위해 내부 상태를 제거하고, splitNumbers 메서드를 static으로 변경하여 객체 생성 없이 호출할 수 있게 했다. 이제는 문자열 분리 작업은 FormulaHandler에서 필요한 정보(숫자 부분과 커스텀 구분자)를 받아서 처리하며, 기본 구분자(쉼표와 콜론)에 커스텀 구분자가 있을 경우 이를 추가하여 문자열을 분리한다. 이를 통해 객체의 상태를 외부에서 가져오지 않고, 필요한 작업을 메서드 내에서 직접 처리한다.


[ 배운것들 ]

1. USE CASE 시나리오/다이어그램

 

"소프트웨어 공학의 모든 것" 책에서 읽은 유스케이스(Use Case)는 소프트웨어 설계에서 시스템이 사용자와 상호작용하는 방식을 설명하는 일종의 시나리오다. 유스케이스는 주로 시스템의 요구사항을 정의하고, 이를 기반으로 시스템의 기능적 요구를 명확히 하기 위해 사용된다. 예를 들어, "사용자가 로그인한다"라는 유스케이스는 사용자가 로그인 화면에 접근하여 아이디와 비밀번호를 입력하고, 시스템이 이를 인증하는 과정을 시나리오로 설명한다.
유스케이스 다이어그램은 시스템이 제공하는 기능(유스케이스)과 이를 사용하는 사용자(액터) 간의 관계를 시각적으로 표현한 UML 다이어그램이다. 

 

2. JDK 17에서 21까지의 주요 변경사항들

우테코 프리코스에서 요구되는 JDK 버전이 작년까지만해도 17이였지만 올해부터는 21로 바뀌게 되었다. 그래서 오늘 코드 구현을 시작하기전에 JDK 17에서 21까지 어떤 주요 변경사항들이 있었는지 알아보려고 한다.

 

우선 주요변경 사항으로 줄여도 내용이 좀 많을 것 같아서 이번 프리코스에서 고려해야할 것들만 정리하자면

1. switch 문에서 패턴 매칭이 가능해지면서 case 레이블에 타입 패턴과 조건부 패턴이 등장
▶️ 새로운 case 문법에 대한 들여쓰기, 줄 바꿈, 공백 사용 등 포맷팅 규칙이 Google Java Style Guide에 안 나와 있는 것 같아서, 만약에 사용하게 되면 조심해야겠다.

 

2. JDK 18부터 모든 기본 문자 인코딩이 UTF-8로 통일

▶️ Google Java Style Guide의 "2.2 파일 인코딩: UTF-8" 항목이 기본 설정으로 되었다.

 

3. 문자열 템플릿 기능이 도입되어 텍스트 블록과 변수를 결합하는 과정을 더 직관적이고 안전하게 처리 가능

public class StringTemplateExample {
    public static void main(String[] args) {
        String name = "Jinwoo";
        int age = 25;
        String message = STR."""
                          Hello, \{name}! 
                          You are \{age} years old.
                          """;

        System.out.println(message);
    }
}

▶️ 이 기능을 사용하면 더 직관적인 방식으로 문자열과 변수를 조합할 수 있겠다.

 

4. 레코드 패턴(Record Patterns): 패턴 매칭에서 레코드 패턴을 사용하여 객체의 필드를 직접 매칭 가능

public record Point(int x, int y) {}

Object obj = new Point(10, 20);

if (obj instanceof Point(int x, int y)) {
    System.out.println("x: " + x + ", y: " + y);
}

▶️ public record Line(Point start, Point end) {} 선언은 생성자, 필드 선언, 접근자 메서드 등을 자동으로 제공하여 코드를 간결하고 명확하게 만들어준다. 레코드 패턴을 사용하면 객체의 타입 확인과 동시에 필드 값을 추출하여 사용할 수 있다.

레코드 패턴을 사용하면 코드를 더 간결하고 명확하게 작성할 수 있겠구나~

 

3. TDA(Tell, Don’t Ask) 원칙

묻지 말고, 시켜라(Tell, don't ask) 원칙은 객체가 자신의 상태를 외부에서 물어보는 대신, 필요한 작업을 직접 수행하게 해야 한다는 개념이다. 이를 통해 객체의 자율성을 보장하고, 캡슐화를 유지하여 비즈니스 로직이 객체 내부에서 관리되도록 한다. 이 원칙을 지키기 위해 클래스가 자기의 속성에 대한 직접적인 Getter, Setter 메서드가 없어야한다.

 

4. 단일 책임 원칙 SRP

단일 책임 원칙(SRP, Single Responsibility Principle)은 객체 지향 설계의 중요한 원칙 중 하나로, 클래스나 모듈은 오직 하나의 책임만을 가져야 한다는 원칙을 의미한다. 여기서 '책임'이란 클래스가 변경되는 이유를 말하며 SRP는 클래스가 변경되는 이유가 단 하나여야 한다는 것을 강조한다. 즉, 하나의 클래스는 하나의 기능 또는 역할만을 수행해야 하며 다른 기능이나 역할은 다른 클래스에 위임해야 한다.

 

SRP를 위반하는 클래스는 여러 책임을 동시에 담당하게 되어, 특정 책임이 변경될 때 다른 책임과 얽혀 예기치 않은 영향을 미칠 수 있다. 이는 시스템의 응집도를 낮추고, 의존성이 불필요하게 복잡해져 유지보수가 어려워진다. 반면, SRP를 준수하면 각 클래스가 명확한 책임을 가지므로 코드의 가독성유연성이 높아지며 특정 기능의 수정이나 확장이 필요한 경우 해당 클래스만 변경하면 되어 변경의 파급효과를 줄일 수 있다.

 

5. 디미터 법칙 (Law of Demeter)

디미터 법칙(Law of Demeter)은 객체 간의 결합도를 낮추기 위한 객체 지향 설계 원칙으로 "친구와만 대화하라"라는 개념으로도 설명된다. 이 법칙에 따르면, 객체는 직접적으로 자신과 상호작용하는 객체에 대해서만 알고 있어야 하며 간접적으로 접근할 수 있는 객체나 내부 구조에 대해 깊게 알아서는 안 된다. 즉, 객체는 자신이 소유하거나, 생성하거나, 전달받은 객체에 대해서만 상호작용해야 한다는 것이다.

 

6. 클래스 다이어그램

"소프트웨어 공학의 모든 것" 책에서 프로젝트 설계 단계에서 사용되는 여러 가지 다이어그램에 대해 알게 되었다. 클래스 다이어그램은 객체지향 설계에서 클래스 간의 구조적 관계를 표현하는 UML(Unified Modeling Language) 다이어그램이다. 클래스 다이어그램은 클래스의 속성, 메서드, 그리고 클래스 간의 상속, 연관, 집합 관계 등을 시각적으로 나타낸다. 이를 통해 클래스 간의 상호작용과 책임을 명확하게 보여주며 설계와 구현 과정에서 코드의 구조를 이해하는 데 중요한 역할을 한다.

 

모델링 과정에서 가장 마지막에 설계되는 다이어그램이 클래스 다이어그램이다. 따라서 모든 구현이 끝난 시점에서 클래스 다이어그램을 그릴 수 있는데, 그 목적은 설계보다는 내가 구현한 애플리케이션의 클래스 간 관계를 쉽게 시각화하고 이해하는 데 있다. 이를 통해 코드 구조를 명확히 파악할 수 있어, 나중에 코드 리뷰를 받을 때 다른 사람들이 전체적인 구조를 한눈에 이해하는 데도 도움이 될 것이다.


[ 마무리 및 앞으로의 Plan ] 

이번 1주 차 동안 "적응하기" 주였던 것 같아. 이에 맞게 문제 해결하는 것에만 적응하는게 아니라 우테코 프리코스의 커뮤니티 문화에도 적응해보았다. 다양한 주제로 소통할 수 있는 채널들이 많아서 매우 유익했고, 같은 목표를 가진 사람들과 함께 참여하고 있다는 사실이 신기하게 다가왔다. 이 긴 여정을 함께하는 동료들이 있다는 느낌을 받았고, 그 덕분에 더 큰 동기부여를 얻었다. 특히, 함께-나누기 채널과 토론하기 채널에서 많은 유익한 포스팅과 블로그 글들을 접할 수 있었던 점이 좋았다.

 

그래서 나도 어떤 분이 올려주신 글을 읽고, 내가 생각을 꼭 남기고 싶어서 용기 내어 답변글을 남겼다.

 

 

그리고 프리코스 3일차 때는 댓글이 아닌 더 큰 용기를 내어 내가 직접 포스트를 올렸다.😆 

 

MVC를 설계하던 중 발견한 자바 변수 네이밍에 관한 재미있고 유익한 블로그였는데, 많은 분들이 공감해주고 감사하다는 댓글을 남겨주셨다. 몇몇 사람들은 자신의 의견을 덧붙여 주기도 했다. 이를 보면서 내가 누군가에게 도움이 되었다는 생각에 뿌듯함을 느꼈고, 이맛에 프리코스 코뮤니티를 하구나 생각이 들었다. 얼른 다른 사람들과 코드 리뷰도 해보고 싶다.🤩

 

앞으로도 지식 공유와 코드 리뷰를 통해 프리코스를 같이 달려가고 있는 사람들과 같이 하며 다양한 의견을 나누고, 배우는 과정을 통해 서로에게 긍정적인 영향을 주며 더 나은 개발자로서 한 걸음씩 나아가고 싶다.

 

나의 프리코스 2주차 가장 큰 목표는 단위 테스트 TDD를 공부하여 미션에 적용해보는 것이다. TDD(Test-Driven Development)는 코드를 작성하기 전에 테스트를 먼저 작성하는 방식으로, 코드의 안정성을 높이고 리팩토링을 용이하게 할 수 있는 중요한 방법론이다. 제대로 배워본 경험이 없어서 이번 기회에 깊이 있게 학습하고자 한다.

 

끝.