Post

Spring을 위한 객체 지향 연습 1-1. 시작

Intro

이전 글에서 나름의 객체 지향 개발 프로세스를 정리해 봤습니다. 바로 해보고싶었지만, 팀 프로젝트하느라 민폐되지 않게 쉼 없이 달리고 이제 좀 정리가 되어 다시 진행하려고 합니다.

1. 문제 파악 및 정의

효과적인 학습에 관심이 많습니다. 그래서 학습에 있어서 제 개인적인 문제를 먼저 파악하면서 시작해 보겠습니다.

개인적으로 학습에서 발생하는 문제

개인적으로 학습하면서 힘든 점들을 나열해 보겠습니다.

  1. 기억 유지를 위해 효율적인 복습 간격을 설정하는 것이 어렵다.
    • 너무 짧은 간격은 시간 소모가 많고, 너무 긴 간격은 기억 유지가 안된다. 그렇다고 최대 간격의 제한을 두면 하루에 복습해야 할 양이 너무 많아져서 감당이 안된다.
  2. 나만의 학습 콘텐츠(요약 노트, 단권화 등)를 만드는데 시간이 오래 걸린다.
    • 학습 목적이 시험이라면 시험 일정에 맞춰 효율적으로 복습하기 위해 시간이 걸려도 개인적인 학습 콘텐츠를 만드는게 더 시간을 아끼는 일이지만, 실용적인 지식 습득 및 활용이 목적이라면 시간을 투자하는게 부담스럽다.
  3. 효과적인 학습 콘텐츠를 만드는 것이 어렵다.
    • 학습 콘텐츠의 효과는 개인마다 차이가 크다. 예를들어 중요하지도 않은 syslog 포트 번호는 514인데 딱 한 번보고 외웠고 잊혀지지도 않는다. 내 생일이 5월 14일이기 때문이다. 그렇다고 매번 이렇게 나와 연관된 기억을 찾아내고 연관시키는 것도 많은 시간이 소모된다.
  4. 단순 반복만으로는 훈련형 시험(코딩테스트 등)에서 좋은 성과 얻기가 힘들다.
    • 지식의 반복 사용으로 코딩테스트에서 필요로 하는 지식은 어느정도 채울 수 있지만, 지식만으로 코딩테스트 문제를 잘 풀 수는 없다.
  5. 집중력 유지가 어렵다.
    • 컨디션에 따라 집중력이 달라지기도 하고, 상황에 따라 달라지기도 한다. 그리고 오래는 앉아 있지만 진짜 집중하는 시간은 얼마 안될 것 같다.
  6. 내가 모르는 것을 파악하기 어렵다.
    • 지식을 받아들일 때는 이해했다고 생각했는데, 나중에 지나서 보면 전혀 아님을 발견할 때가 있다.

최근에 학습하면서 불만이 있었던 ‘복습 간격, 플래시카드 문제 만들기 귀찮음 + 만들었는데도 효과가 없는 경우가 있음, 훈련형 시험 성과가 잘 안남, 집중 안됨, 잘못 이해함’에 대해 풀어서 적어봤습니다. 어느 정도 깊이까지 공부할 것인가에 대한 문제 등 굉장히 많은 문제가 있지만, 더 일반적인 학습 문제를 찾아보기 위해 개인적인 것은 여기서 마무리 하겠습니다.

일반적으로 학습에서 발생하는 문제

어렸을 때는 놀고 싶어서 중요한 시험을 앞두고도 제대로 집중하지 못하는 경우가 있었는데, 굉장히 과거의 기억이다보니 인터넷을 검색하면서 기억을 떠올려 봤습니다.

  1. 시험을 앞두고 다른 짓을 하게 된다.
    • 시험이 가까워질수록 보지않던 뉴스조차 너무 재밌다. 아마 좋은 결과를 얻지 못할 것 같은 두려움에 나쁜 결과에 대한 변명거리를 만들기 위함이 아닌가 싶다.
  2. 외롭다.
    • 친구들이 공부할 때는 같이 하면 되는데, 혼자 듣는 과목을 공부할 때면 외롭다.
  3. 외로워서 스터디를 하면 친목 모임으로 변질된다.
    • ㅅ터디

스터디가 나오면 스터디의 문제점만 따로 다뤄도 어마어마하게 많아지기 때문에 여기서 끊어가는게 좋겠습니다.

정리

뜬금포로 기억에 남는 문장으로 정리를 시작해 봅니다.

이상적으로는 해결해야 하는 문제를 온전히 정의한 후 이를 해결해야 하는 완벽한 아키텍처를 설계할 수 있습니다. 물론 현실은 그렇지 않습니다. - 『개발자에서 아키텍트로』 63p.

생각나는 문제들이 많지만 단계를 매번 마무리 짓는게 아니므로, 일단은 작성한 것을 기반으로 문제 정의를 해보겠습니다.

  1. 학습자는 최대한 적게 공부하고 최대한 많은 지식을 머릿속에 넣고 싶지만, 방법을 모른다.
  2. 학습자는 머릿속에 있는 지식을 활용하고 싶지만, 활용하는 방법을 모른다.
  3. 학습자는 공부에 방해되는 감정(두려움, 외로움 등)을 해소하고 싶지만, 감정을 해소하려다 공부를 제대로 못하게 된다.

‘문제를 정의한다는 것은 무엇인가’에 대해 혼란이 있어 GPT-4를 통해 예시를 보고 그에 맞춘 형식으로 정리해봤습니다.

1-1. 개인적으로 생각해본 문제 해결 방법

정확한 근거를 바탕으로 문제를 해결하려면, 뇌과학부터 시작해서 학습 실험 관련 논문까지 섭렵하는 수밖에 없지 않나 싶습니다. 지금 당장 만들어야할 어플리케이션에는 그러한 시간이 없기 때문에 개인적인 경험과 다른 서비스를 잘 참고해서 해결 방법을 정리해보겠습니다.

위에서 정의한 문제를 다시 간단하게 정리해보자면 아래와 같습니다.

  1. 효율적인 학습 방법 모름
  2. 지식 활용 방법 모름
  3. 감정 해소 방법 모름

효율적인 학습 방법

학습을 효율적으로 한다는 것을 최소한의 시간과 노력으로 최대한 많은 지식과 스킬을 얻으려는 행위라고 정의해 보겠습니다.

그리고 학습한 것을 활용하는 모든 행위를 시험(test) 이라고 정의해볼 때, 개인적으로 시험의 종류를 암기형 시험과 훈련형 시험으로 나누고 있습니다. 각각에 대해 살펴보겠습니다.


먼저 개인적으로 암기형 시험을 준비하면서 수행하는 절차를 크게 보면 아래와 같습니다.

  1. 읽기/듣기 등을 통한 지식 인지
  2. 인지한 지식을 자신만의 언어로 정리하여 학습 콘텐츠 생성
  3. 생성한 콘텐츠로 복습
  4. 문제를 풀면서 잘못알고 있었던 지식 수정 또는 안다고 생각했지만 실제로는 몰랐던 지식 발견하여 학습 콘텐츠 생성
  5. 1.~ 4. 반복

1번에서 지식 인지 과정을 개선하려면 행동 교정이 필요하므로, 제가 해결 대상으로 삼을만한 것은 아닌 것 같습니다.

그렇다면 소요되는 시간과 노력을 줄이기 위해 현재 개선해볼만 한 것은 콘텐츠 생성 시간과 노력 그리고 잘못알고 있던 지식과 안다고 착각했던 지식을 발견하는데 들어가는 시간과 노력을 줄이는게 되겠습니다.

생각나는 서비스가 있네요. 산타토익.

혼자서 산타토익 수준의 서비스를 만들 수는 없고, 학교 다닐 때 친구와 서로 문제 내주고 모르는 것을 발견하던 것을 제가 애정하는 플래시카드에 도입해 보는게 좋겠습니다. 친구가 만든 콘텐츠를 사용해서 콘텐츠를 만드는데 드는 시간을 줄이는 효과도 있을 것으로 기대됩니다.


훈련형 시험에서는 이렇다할 성과를 거두어 본적이 없어서, 여기에 제가 생각하는 학습 수행 절차를 적기에는 부적합한 것 같습니다. 다른 사람의 문제 해결 과정 혹은 사고 과정을 절차화하고 따라하면서 몸에 익히는게 좋겠다고 생각은 하고 있습니다. 시험보는 환경과 같은 환경을 경험하는 것도 중요하겠죠.

하지만 아직 검증을 해보지 못했기 때문에, 일단은 훈련형 시험에서 필요한 지식들을 친구와 서로 나눌 수 있게 하는게 좋겠습니다. 당장은 암기형, 훈련형 구분 없이 같이 공부하는 친구와 플래시카드를 공유할 수 있는 기능이 필요하겠습니다.

지식 활용 방법

이상적인 상황은 지식을 배우고, 배운 지식을 바로 현실에 적용 가능한 능력을 갖는 거겠지만… 지금의 제가 해결할 수 있는 주제가 아닌 것 같아서 넘어갑니다.

감정 해소 방법

심리학자 분들이 추천하는 감정 해소 방법은 이미 좋은 어플리케이션이 과학적인 근거를 바탕으로 잘 만들어져 있으므로, 친구와의 공간을 제공하는 것보다 개념을 넓혀서 타인과의 스터디 공간을 온라인에 개설해서 온라인 스터디를 통해 감정을 해소 할 수 있게 해야겠습니다.

정리

간단히 정리해서 추상적인 요구사항으로 만들어보면 아래와 같습니다.

  1. 공유 가능한 플래시카드
  2. 온라인 스터디 공간

기승전 플래시카드!

2. 요구사항 분석

위 요구사항을 어떻게 풀어가느냐에 따라 많은 것들이 달라지겠지만, 이번에 필요한 만큼만 간단하게 생각해 보겠습니다.

비기능적 요구사항

품질 속성을 고려하면 또 하나의 긴 글을 작성해야하고, 객체 지향 설계 실습이 가장 큰 목적이므로 이번에는 넘어갑니다.

기능적 요구사항

다시 요구사항을 불러와 보겠습니다.

  1. 공유 가능한 플래시카드
  2. 온라인 스터디 공간

만약 실제 서비스까지 한다고 해도 시작부터 스터디를 구성할 수 있는 사람을 찾을 만큼의 사용자가 없을테니, 우선순위를 개인 학습 기능인 플래시카드에 두고 플래시카드 기능 중 생각나는 것만 이번 사이클에서 고려하겠습니다.

공유 가능한 플래시카드는 공유 가능플래시카드를 별도로 봐야합니다.

공유 가능한 대상은 친구, 그리고 Anki, Quizlet과 같이 카드를 만든 사람이 원한다면 불특정 다수에게도 공유할 수 있게 하려고 합니다. 복습 간격도 Anki와 동일한 SM-2 알고리즘을 사용할 계획입니다. 더 개선됐다고 주장하는 알고리즘(링크)이 있기는 한데, 제가 해결을 원하는 것은 너무 간격이 길어졌을 때 어떻게 해결할 것인가이기 때문에 더 많은 지표를 가지고 정밀한 간격을 계산한다고 해결될 것으로 판단되지는 않습니다. 추후에 알고리즘을 선택사항으로 확장해도 무리가 없을 것으로 판단됩니다.

그러면 플래시카드의 기능적인 면에서는 Anki를 그대로 벤치마킹하고, 추가로 친구 추가 기능 및 친구와 공동 관리할 수 있는 카드 저장소가 필요하겠습니다.

  1. 플래시카드 생성/수정/삭제 기능
  2. 플래시카드 반복 기능(반복 간격 계산은 SM-2 알고리즘 사용)
  3. 회원가입 기능
  4. 친구 추가 기능
  5. 공동 저장소 기능
  6. 공동 저장소에서 특정 카드만 내 저장소로 가져올 수 있는 기능
  7. Anki 파일을 import 하는 기능

지금 생각나는 기능은 이정도 입니다. 이번 사이클에서는 플래시카드 생성/수정/삭제 기능을 구현해 봐야겠습니다.

기술적인 제약사항

Spring 공부를 위한 객체 지향 공부이므로, 현재 제가 주로 사용하는 언어인 Java를 사용합니다.

아키텍처

아키텍처에 대한 지식이 부족해서 현재 Monolithic 으로 시작할 수 밖에 없긴 하지만, 나중에 지식이 쌓이면 가용성이 높다는 Microservice 로 전환해볼 계획입니다. 너무 먼 미래의 일인 것 같기는 합니다.


어느정도 마무리가 되었으니 GPT-4 에서 간단하게 사용자 시나리오와 스토리를 만들어봤습니다. 친절하게도 사용자 시나리오와 사용자 스토리가 뭔지부터 설명해줍니다.


먼저, 웹앱에서의 사용자 시나리오와 사용자 스토리를 작성하기 전에 두 가지 개념에 대해 설명하겠습니다.

  • 사용자 시나리오(User Scenario): 사용자가 어떻게 제품을 사용하게 될 것인지에 대한 자세한 설명입니다. 이는 사용자의 목적, 사용자가 제품을 사용하기 위해 경험해야 하는 단계, 그리고 사용자의 기대치를 포함합니다.

  • 사용자 스토리(User Story): 사용자의 관점에서 제품의 기능이나 목표를 정의합니다. 보통 “As a [role], I want [goal/desire] so that [benefit]”라는 형태로 작성됩니다.

이를 바탕으로 플래시카드 생성/수정/삭제 기능에 대한 사용자 시나리오와 사용자 스토리를 작성하겠습니다.

사용자 시나리오

사용자 이름: 제인

사용자 목표: 새로운 언어 학습을 위한 플래시카드를 생성하고, 필요에 따라 수정 또는 삭제하고 싶다.

스텝:

  1. 제인은 웹앱에 로그인한다.
  2. 제인은 “플래시카드 생성” 버튼을 클릭한다.
  3. 제인은 플래시카드에 들어갈 질문과 답을 입력한다.
  4. 제인은 “생성” 버튼을 클릭하여 플래시카드를 저장한다.
  5. 필요에 따라, 제인은 “플래시카드 수정” 또는 “플래시카드 삭제” 버튼을 클릭하여 플래시카드를 수정하거나 삭제한다.

사용자 스토리

  1. 플래시카드 생성: As a language learner, I want to create flashcards so that I can practice my vocabulary.
    • Acceptance Criteria:
      • User should be able to input a question and an answer.
      • User should be able to save the flashcard.
  2. 플래시카드 수정: As a language learner, I want to edit my flashcards so that I can update or correct the information on them.
    • Acceptance Criteria:
      • User should be able to select a flashcard to edit.
      • User should be able to change the question and/or answer on the flashcard.
      • User should be able to save the changes.
  3. 플래시카드 삭제: As a language learner, I want to delete flashcards so that I can remove those that are no longer needed or relevant.
    • Acceptance Criteria:
      • User should be able to select a flashcard to delete.
      • User should be able to confirm the deletion.

이런 식으로 다른 기능들에 대해서도 사용자 시나리오와 사용자 스토리를 작성하면 됩니다. 사용자 시나리오는 사용자의

경험을 개선하는 데 도움이 되며, 사용자 스토리는 개발 팀이 사용자의 관점에서 기능을 이해하는 데 도움이 됩니다.


손수 명사와 동사를 추출하기는 귀찮으니, 또 맡겨봅니다.


명사와 동사는 시스템의 주요 구성 요소 및 기능을 파악하는데 중요한 역할을 합니다. 이를 추출하면 다음과 같습니다.

명사 (시스템의 주요 구성 요소)

  1. 사용자 (User)
  2. 웹앱 (Web App)
  3. 플래시카드 (Flashcard)
  4. 질문 (Question)
  5. 답변 (Answer)
  6. 생성 버튼 (Create Button)
  7. 수정 버튼 (Edit Button)
  8. 삭제 버튼 (Delete Button)
  9. 저장 (Save)

동사 (시스템의 기능)

  1. 로그인한다 (Login)
  2. 클릭한다 (Click)
  3. 입력한다 (Input)
  4. 생성한다 (Create)
  5. 수정한다 (Edit)
  6. 삭제한다 (Delete)
  7. 저장한다 (Save)
  8. 선택한다 (Select)
  9. 변경한다 (Change)
  10. 확인한다 (Confirm)

위 목록은 사용자 시나리오와 사용자 스토리에서 파생된 핵심 명사와 동사를 나타냅니다. 이를 바탕으로 시스템의 주요 구성 요소와 동작을 더 잘 이해하고 도메인 모델링을 수행할 수 있습니다.


기대한 것 보다는 꽤 만족스럽습니다. 그럼 다음 단계인 도메인 모델 설계로 넘어가 봐야겠습니다.

3. 도메인 모델 설계 / 협력 설계

개인적인 객체 지향 개발 프로세스를 작성할 때 도메인 모델 설계와 협력 설계를 순차적으로 수행하는 것으로 적어 놨는데, 도메인 모델 다이어그램이 공통 결과물로 나오므로 하나로 수행하는게 맞는 것 같습니다.

명사에서 객체로

플래시카드를 생성/수정/삭제하기 위해 필요한 객체들이 무엇이 있을지 명사부터 다시 살펴보겠습니다.

  1. 사용자 (User)
  2. 웹앱 (Web App)
  3. 플래시카드 (Flashcard)
  4. 질문 (Question) -> 앞면(Front)
  5. 답변 (Answer) -> 뒷면(Back)
  6. 생성 버튼 (Create Button)
  7. 수정 버튼 (Edit Button)
  8. 삭제 버튼 (Delete Button)
  9. 저장 (Save)

객체로서 필요한 것이 아닌 ‘버튼’, ‘저장’을 제외하였습니다. ‘웹앱’은 시스템 자체를 가리키므로 넓은 의미의 객체이긴 하지만 도메인 모델에 그려넣을 것은 아니므로 제외하였습니다. ‘질문’과 ‘답변’은 플래시카드에 포함(Composition)된 객체가 되겠습니다. 그런데 플래시카드가 단순히 질문과 답변으로 구성하지는 않으므로, 앞면과 뒷면으로 변경하였습니다.

‘사용자’는 아직 회원가입 기능이 없으므로 제외합니다.

동사에서 메시지로

  1. 로그인한다 (Login)
  2. 클릭한다 (Click)
  3. 입력한다 (Input)
  4. 생성한다 (Create)
  5. 수정한다 (Edit)
  6. 삭제한다 (Delete)
  7. 저장한다 (Save)
  8. 선택한다 (Select)
  9. 변경한다 (Change)
  10. 확인한다 (Confirm)

회원가입 기능은 나중에 하기로 했으므로, 동사 중에 ‘로그인한다’는 제외합니다. 그리고 ‘변경한다’는 ‘수정한다’와 동일한 의미이기 때문에 제외합니다. ‘확인한다’는 삭제하는 행동을 했을 때 그에 대한 반응이므로 별도의 메시지는 아니지만 ‘삭제한다’에 대한 반응으로 생각하는게 좋겠습니다.

‘클릭한다’, ‘입력한다’ 는 생성/수정/삭제를 위한 부수적인 행위로 제외하고, ‘저장한다’ 도 생성/수정/삭제에 포함된 것이므로 제외합니다.

다이어그램 그리기

  • 명사: 플래시카드, 앞면, 뒷면
  • 동사: 생성한다, 수정한다, 삭제한다, 선택한다

diagram

음… 너무 작게하려고 해서 그런가 딱히 고민할게 많이 없어보입니다. 그런데 뭔가 잘못된거 같은 냄새가 나는데, 명확히 어딘지 짚기가 힘들어 이후에 구현을 하면서 수정해 보겠습니다.

4. API 설계

테이블은 안그릴려고 했는데, 별로 어려운 일은 아니라 정리 차원에서 그려봅니다.

public interface Flashcard  
booleancreate(FlashcardFace front, FlashcardFace back)카드 생성하기
booleaneditCardFront(FlashcardFace front)카드 앞면 수정하기
booleaneditCardBack(FlashcardFace back)카드 뒷면 수정하기
booleandelete()카드 삭제하기
FlashcardFacegetCardFront()카드 앞면 내용 불러오기
FlashcardFacegetCardBack()카드 뒷면 내용 불러오기
  • Anki에서는 단순히 하나의 앞, 뒤만 존재하는 것은 아니며, 저도 다른 유형의 카드를 많이 활용하고 있기 때문에, 여러가지 변형된 flashcard를 만들 수 있도록 inteface로 만들 계획입니다.
  • 앞면뒷면을 별개의 객체로 앞에서 그렸었는데, 본질적으로는 같다고 판단하여 FlashcardFace라는 별도의 타입을 만들었습니다. 현실의 간단한 예를 생각해봐도, 한쪽 면의 영어단어의 뜻을 보고 다른쪽 면의 영어 단어를 맞출 수도 있고, 반대로 영어단어를 보고 그 뜻을 맞출 수도 있습니다.

Outro

다음은 테스트 구현으로 구현을 해야하니 글을 한 번 끊어서 가려고합니다.

취업용 포트폴리오의 시발점으로 삼을 것인가 고민했는데(그래서 시나리오에 웹앱이 튀어나오기도 합니다), 그렇게 되면 앞으로 남아있는 추가적인 팀 프로젝트를 하면서 ‘난 어차피 취업용 포트폴리오 따로만들거야’ 하면서 대충하게 될 것 같아서 학습용으로 쭉 가기로 했습니다.

잡썰

editCardFront 와 editCardBack 에서 edit를 쓸 것인가 modify를 쓸 것인가 고민하다가, edit를 사용하기로 했습니다.

검색해보니 원어민도 혼란스러워하는 것 같기도하고, editor를 사용해서 편집하니까 edit! 결정!

추가로 GPT-3.5 에 물어보니 아래와 같은 설명을 하기도 합니다. 요즘은 소설은 아닐까 하는 의심부터 들어서 그냥 그렇구나 정도로 봅니다.

“Edit”와 “modify”는 모두 어떤 것을 변경하거나 수정하는 것을 의미하는 동사입니다. 그러나 미묘한 차이가 있을 수 있습니다.

“Edit”는 주로 문서, 텍스트, 사진 또는 비디오와 같은 콘텐츠를 편집하거나 수정하는 것을 의미합니다. 예를 들어, 텍스트 문서의 내용을 변경하거나 사진을 잘라내거나 텍스트나 사진을 추가하는 작업을 “edit”라고 할 수 있습니다. “Edit”는 원본을 기초로 하여 일부 요소를 변경하거나 개선하는 것을 의미합니다.

반면에 “Modify”는 더 일반적으로 사용되며, 어떤 것의 특정한 부분을 변경하거나 수정하는 것을 나타냅니다. “Modify”는 주어진 항목이나 시스템의 특정 측면을 조정하거나 변형하는 것을 의미합니다. 예를 들어, 컴퓨터 프로그램의 설정을 수정하거나 차량의 디자인을 수정하는 것을 “modify”라고 할 수 있습니다. “Modify”는 더 일반적인 의미로 사용되며, 콘텐츠뿐만 아니라 시스템, 제품, 구성 요소 등을 변경하는 데 사용될 수 있습니다.

요약하자면, “edit”는 콘텐츠의 수정과 관련하여 주로 사용되며, “modify”는 일반적인 변경 또는 수정 작업을 의미하는 데 사용됩니다.

역시나 이름 짓는건 너무 어렵습니다.

This post is licensed under CC BY 4.0 by the author.