<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>apple-juice.log</title>
        <link>https://velog.io/</link>
        <description>코어의 서버 탐험기</description>
        <lastBuildDate>Sat, 03 Dec 2022 09:03:04 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>apple-juice.log</title>
            <url>https://velog.velcdn.com/images/apple-juice/profile/e57df133-e13a-4475-be64-d8bdbc2fa449/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. apple-juice.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/apple-juice" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[우아한테크코스 5기 - 프리코스 4주차 미션[bridge]]]></title>
            <link>https://velog.io/@apple-juice/%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4-5%EA%B8%B0-%ED%94%84%EB%A6%AC%EC%BD%94%EC%8A%A4-4%EC%A3%BC%EC%B0%A8-%EB%AF%B8%EC%85%98bridge</link>
            <guid>https://velog.io/@apple-juice/%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4-5%EA%B8%B0-%ED%94%84%EB%A6%AC%EC%BD%94%EC%8A%A4-4%EC%A3%BC%EC%B0%A8-%EB%AF%B8%EC%85%98bridge</guid>
            <pubDate>Sat, 03 Dec 2022 09:03:04 GMT</pubDate>
            <description><![CDATA[<h1 id="서론">서론</h1>
<p>3주 차 미션에서는 클래스 분리, 단위 테스트를 시작해 보는 것으로 과제를 진행했지마, 이번 4주 차 미션에서 작성하는 실습 과정의 목표는 다음과 같다.</p>
<ol>
<li>클래스(객체)를 분리하는 연습</li>
<li>리펙터링</li>
</ol>
<p>3주 차에서는 클래스를 분리하는 연습에 있어서 많은 어려움을 겪었지만, 이번 4주 차에서는 클래스를 분리하는 연습을 하는 것에 있어서 큰 어려움을 느끼면서 진행할 것 같은 느낌은 들지 않았다. 좀 더 자신감 있게 과제를 진행할 수 있을 것 같다.</p>
<p>이번에는 하나의 기능을 만들어 놓고 테스트를 할 수 있으면 테스트를 해서 그 기능이 정상적으로 동작하는지 확인해가면서 과제를 진행하였다.</p>
<p>코드의 내용을 다 설명을 하게 되면 글이 너무 길어질 것 같아서 어떤 과정으로 과제를 해결했는지 설명하겠다.</p>
<hr>
<h1 id="기능-구현-유의사항">기능 구현 유의사항</h1>
<p>문제 풀기에 앞서 다음과 같은 진행 방식을 유의하면서 기능을 구현해야 한다.</p>
<ul>
<li><p>미션은 기능 요구 사항, 프로그래밍 요구 사항, 과제 진행 요구 사항 세 가지로 구성되어 있다.</p>
</li>
<li><p>세 개의 요구 사항을 만족하기 위해 노력한다. 특히 기능을 구현하기 전에 기능 목록을 만들고, 기능 단위로 커밋 하는 방식으로 진행한다.</p>
</li>
<li><p>기능 요구 사항에 기재되지 않은 내용은 스스로 판단하여 구현한다.</p>
<h2 id="🚀-기능-요구-사항">🚀 기능 요구 사항</h2>
<p>위아래 둘 중 하나의 칸만 건널 수 있는 다리를 끝까지 건너가는 게임이다.</p>
</li>
<li><p>위아래 두 칸으로 이루어진 다리를 건너야 한다.</p>
<ul>
<li>다리는 왼쪽에서 오른쪽으로 건너야 한다.</li>
<li>위아래 둘 중 하나의 칸만 건널 수 있다.</li>
</ul>
</li>
<li><p>다리의 길이를 숫자로 입력받고 생성한다.</p>
<ul>
<li>다리를 생성할 때 위 칸과 아래 칸 중 건널 수 있는 칸은 0과 1 중 무작위 값을 이용해서 정한다.</li>
<li>위 칸을 건널 수 있는 경우 U, 아래 칸을 건널 수 있는 경우 D값으로 나타낸다.</li>
<li>무작위 값이 0인 경우 아래 칸, 1인 경우 위 칸이 건널 수 있는 칸이 된다.</li>
</ul>
</li>
<li><p>다리가 생성되면 플레이어가 이동할 칸을 선택한다.</p>
<ul>
<li>이동할 때 위 칸은 대문자 U, 아래 칸은 대문자 D를 입력한다.</li>
<li>이동한 칸을 건널 수 있다면 O로 표시한다. 건널 수 없다면 X로 표시한다.</li>
</ul>
</li>
<li><p>다리를 끝까지 건너면 게임이 종료된다.</p>
</li>
<li><p>다리를 건너다 실패하면 게임을 재시작하거나 종료할 수 있다.</p>
<ul>
<li>재시작해도 처음에 만든 다리로 재사용한다.</li>
<li>게임 결과의 총 시도한 횟수는 첫 시도를 포함해 게임을 종료할 때까지 시도한 횟수를 나타낸다.</li>
</ul>
</li>
<li><p>사용자가 잘못된 값을 입력할 경우 IllegalArgumentException를 발생시키고, &quot;[ERROR]&quot;로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다.</p>
<ul>
<li><code>Exception</code>이 아닌 <code>IllegalArgumentException</code>, <code>IllegalStateException</code> 등과 같은 명확한 유형을 처리한다.<h3 id="입출력-요구-사항">입출력 요구 사항</h3>
</li>
</ul>
</li>
<li><p><em>입력*</em></p>
</li>
<li><p>자동으로 생성할 다리 길이를 입력 받는다. 3 이상 20 이하의 숫자를 입력할 수 있으며 올바른 값이 아니면 예외 처리한다.</p>
</li>
<li><p>라운드마다 플레이어가 이동할 칸을 입력 받는다. U(위 칸)와 D(아래 칸) 중 하나의 문자를 입력할 수 있으며 올바른 값이 아니면 예외 처리한다.</p>
</li>
<li><p>게임 재시작/종료 여부를 입력 받는다. R(재시작)과 Q(종료) 중 하나의 문자를 입력할 수 있으며 올바른 값이 아니면 예외 처리한다.</p>
</li>
</ul>
<p><strong>출력</strong></p>
<ul>
<li>게임 시작 문구<pre><code>다리 건너기 게임을 시작합니다.</code></pre></li>
<li>게임 종료 문구<pre><code>최종 게임 결과
[ O |   |   ]
[   | O | O ]
</code></pre></li>
</ul>
<p>게임 성공 여부: 성공
총 시도한 횟수: 2</p>
<pre><code>- 사용자가 이동할 때마다 다리 건너기 결과의 출력 형식은 실행 결과 예시를 참고한다.
  - 이동할 수 있는 칸을 선택한 경우 O 표시
  - 이동할 수 없는 칸을 선택한 경우 X 표시
  - 선택하지 않은 칸은 공백 한 칸으로 표시
  - 다리의 시작은 [, 다리의 끝은 ]으로 표시
  - 다리 칸의 구분은 |(앞뒤 공백 포함) 문자열로 구분
  - 현재까지 건넌 다리를 모두 출력
- 예외 상황 시 에러 문구를 출력해야 한다. 단, 에러 문구는 &quot;[ERROR]&quot;로 시작해야 한다.</code></pre><p>[ERROR] 다리 길이는 3부터 20 사이의 숫자여야 합니다.</p>
<pre><code>
**실행 결과 예시**</code></pre><p>다리 건너기 게임을 시작합니다.</p>
<p>다리의 길이를 입력해주세요.
3</p>
<p>이동할 칸을 선택해주세요. (위: U, 아래: D)
U
[ O ]
[   ]</p>
<p>이동할 칸을 선택해주세요. (위: U, 아래: D)
U
[ O | X ]
[   |   ]</p>
<p>게임을 다시 시도할지 여부를 입력해주세요. (재시도: R, 종료: Q)
R
이동할 칸을 선택해주세요. (위: U, 아래: D)
U
[ O ]
[   ]</p>
<p>이동할 칸을 선택해주세요. (위: U, 아래: D)
D
[ O |   ]
[   | O ]</p>
<p>이동할 칸을 선택해주세요. (위: U, 아래: D)
D
[ O |   |   ]
[   | O | O ]</p>
<p>최종 게임 결과
[ O |   |   ]
[   | O | O ]</p>
<p>게임 성공 여부: 성공
총 시도한 횟수: 2</p>
<pre><code>## 🎯 프로그램 요구 사항
- JDK 11 버전에서 실행 가능해야 한다. JDK 11에서 정상적으로 동작하지 않을 경우 0점 처리한다.
- 프로그램 실행의 시작점은 Application의 main()이다.
- build.gradle 파일을 변경할 수 없고, 외부 라이브러리를 사용하지 않는다.
- [Java 코드 컨벤션](https://github.com/woowacourse/woowacourse-docs/tree/main/styleguide/java)  가이드를 준수하며 프로그래밍한다.
- 프로그램 종료 시 System.exit()를 호출하지 않는다.
- 프로그램 구현이 완료되면 ApplicationTest의 모든 테스트가 성공해야 한다. 테스트가 실패할 경우 0점 처리한다.
- 프로그래밍 요구 사항에서 달리 명시하지 않는 한 파일, 패키지 이름을 수정하거나 이동하지 않는다.
- indent(인덴트, 들여쓰기) depth를 3이 넘지 않도록 구현한다. 2까지만 허용한다.
  - 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다.
- 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 된다.
- 3항 연산자를 쓰지 않는다.
- 함수(또는 메서드)가 한 가지 일만 하도록 최대한 작게 만들어라.
- JUnit 5와 AssertJ를 이용하여 본인이 정리한 기능 목록이 정상 동작함을 테스트 코드로 확인한다.
- else 예약어를 쓰지 않는다.
  - 힌트: if 조건절에서 값을 return 하는 방식으로 구현하면 else를 사용하지 않아도 된다.
  - else를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다.
- 도메인 로직에 단위 테스트를 구현해야 한다. 단, UI(System.out, System.in, Scanner) 로직은 제외한다.
  - 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 분리해 구현한다.


## ✏️ 과제 진행 요구 사항
- 기능을 구현하기 전 ```docs/README.md```에 구현할 기능 목록을 정리해 추가한다.
- Git의 커밋 단위는 앞 단계에서 ```docs/README.md```에 정리한 기능 목록 단위로 추가한다.


    - [커밋 메시지 컨벤션 가이드](https://gist.github.com/stephenparish/9941e89d80e2bc58a153)를 참고해 커밋 메시지를 작성한다.

- - -
# 진행 과정
이번에도 작성한 코드에 대한 설명을 다 진행하기에는 글이 너무 길어질 것 같아서 과제를 진행하면서 있었던 일들 위주로 소개를 하려고 한다.

## 주요 기능에 대한 목록 고찰
문제 요구 사항대로 최대한 한 가지의 기능을 담당할 수 있도록 목록을 고찰하려고 노력하였다.
예를 들어서 게임 시작 문구 출력 기능이 있으면 그것에 대한 메서드를 만들고 출력 관련 기능을 담당하는 클래스에 담는 방식으로 생각하면서 기능 목록을 구상하였다.

지금까지 계속 기능 목록을 작성해봤으므로 기능 목록을 정리하는데는 크게 어려움이 없었다.

## 기능 구현 후 테스트 코드 작성 병행
지난 3주 차에서는 모든 기능들을 구현 후 그에 따른 테스트 코드를 한번에 작성하는 방식으로 진행했었다면 이번 4주 차 과제에서는 기능을 생성하고 그 기능이 제대로 동작하는지 테스트 코드를 작성하는 방식으로 과제를 진행했다.
테스트 코드를 통해서 기능 오류가 발견되면 기능을 수정하고 커밋 컨벤션에 따라서 커밋을 하였다.

## 기능 목록 수정이 있을 때마다 작성했던 기능 목록을 고치기
기능 목록은 처음부터 항상 완벽하진 않기에 코드 작성시 중간에 항상 추가적으로 필요한 기능이 있는 경우도 있었고, 기능의 역할 수정이 필요한 경우도 있었다.
예를 들어서 단순히 다리를 생성하는 기능을 기능 목록에 처음에 작성했었다면, 다리를 생성하기 위해서 세부적으로 어떤 기능이 필요할지 추가적으로 기능이 필요했다. 그에 따른 추가 가능 사항들을 다시 정리하고 기능 목록을 항상 라이브성을 유지하기 위해서 실시간으로 업데이트 하는 방식으로 과제를 진행했다.

## 파일 구조를 변경하는 등 리펙토링 작업 진행
주어진 클래스 파일을 다른 패키지로 이동하는 작업 및 코드 변수명 변경 등의 리펙토링 작업과 클래스 내에서 작성했던 메서드를 다른 클래스로 옮기는 리펙토리 작업을 하며 과제를 진행했다.


## 과제 진행 중 어려웠던 사항
### 주어진 클래스 및 메서드를 활용하기 위한 고찰의 어려움
3주 차 과제는 단순히 자기 자신만의 힘으로 클래스와 메서드를 알아서 구현해서 문제를 해결하면 됐으나, 4주 차는 몇 개의 클래스와 메서드가 주어진다.

각 클래스에 대한 요구 사항(기능 구현 유의 사항 설명에는 기재하지 않았다. 생성자, 필드 등의 요구 사항)과 그 클래스가 가지고 있는 메서드를 활용해서 어떻게 내가 구상한 기능들을 구현을 해야할지 고민하는데 많은 시간이 걸렸다.

### 다리 건너기 게임의 결과 출력에 대한 구현
다리를 생성하고 다리 건너기를 진행하기 위한 기능 구현은 어렵지 않았다.
다만 다리 건너기 게임 진행 중 현재 내가 건너고 있는 다리의 상황을 출력으로 나타낼 때 어떤 방식을 사용해야 할지 고민을 했지만 쉽게 방법이 떠오르지 않았다.

## 어려웠던 과정들을 해결하기 위한 노력
처음에는 아무것도 작성할 수가 없을 만큼 막막하고 멍때리는 경우가 많았다. 한편으로는 내가 생각했던 방식으로 작성을 했는데 작성하는 과정 중에서 또다른 오류가 발생하거나 막히면 곤란할 것 같다는 그 불안감이 나의 코드 작성에 영향을 미치면서 무기력한 상황에 처해지기도 하였다.
그렇지만 무기력하게 아무것도 하지 않으면 처음부터 과제를 안하는 상황과 다름없기에 일단은 이것저것 부딪혀보고 왔던 길을 되돌아가면서 피드백을 차차 쌓아가며 코드 작성을 하는 것이 낫겠다는 생각이 들었다. 
그래서 일단은 계속 작성을 해보고 이 코드는 어떤 방식으로 구현 방식을 하는 것이 좋을지 보완하는 방식으로 코드를 작성하였다.
그런 방식으로 코드를 완성도 있게 작성할 수 있는 단계까지 도달하여 좌절을 딛을 수 있다는 성취감을 가질 수 있었고, 4주 차 과제도 내 자신만의 힘으로 해결할 수 있었다.

</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[우아한테크코스 5기 - 프리코스 3주차 미션[lotto]]]></title>
            <link>https://velog.io/@apple-juice/%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4-5%EA%B8%B0-%ED%94%84%EB%A6%AC%EC%BD%94%EC%8A%A4-3%EC%A3%BC%EC%B0%A8-%EB%AF%B8%EC%85%98lotto</link>
            <guid>https://velog.io/@apple-juice/%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4-5%EA%B8%B0-%ED%94%84%EB%A6%AC%EC%BD%94%EC%8A%A4-3%EC%A3%BC%EC%B0%A8-%EB%AF%B8%EC%85%98lotto</guid>
            <pubDate>Sat, 19 Nov 2022 05:58:30 GMT</pubDate>
            <description><![CDATA[<h1 id="서론">서론</h1>
<p>2주 차 미션에서는 함수를 분리하고 각각의 함수마다 기능 테스트 코드 작성하는 실습 진행하는 것을 목표로 진행했다.</p>
<p>이번 3주 차 미션에서는 2주 차에서 진행한 내용에서 다음과 같은 목표가 추가된다.
<strong>1. 클래스(객체)를 분리하는 연습</strong>
<strong>2. 도메인 로직에 대한 단위 테스트를 작성하는 연습</strong></p>
<p>자발적으로 객체를 분리하면서 기능 구현을 별로 해본 경험이 없는 나로써는 딱 안성맞춤인 과제였다. 하지만 기능 구현을 완료하고 그에 따라 테스트 코드를 작성하는 습관이 아직 덜 들여진 것 같다. 좀 더 많은 작업을 하면서 테스트 코드를 습관적으로 작성할 줄 아는 습관을 빨리 들일 수 있도록 해야겠다.</p>
<hr>
<h1 id="기능-구현-유의사항">기능 구현 유의사항</h1>
<p>문제 풀기에 앞서 다음과 같은 진행 방식을 유의하면서 기능을 구현해야 한다.</p>
<ul>
<li><p>미션은 기능 요구 사항, 프로그래밍 요구 사항, 과제 진행 요구 사항 세 가지로 구성되어 있다.</p>
</li>
<li><p>세 개의 요구 사항을 만족하기 위해 노력한다. 특히 기능을 구현하기 전에 기능 목록을 만들고, 기능 단위로 커밋 하는 방식으로 진행한다.</p>
</li>
<li><p>기능 요구 사항에 기재되지 않은 내용은 스스로 판단하여 구현한다.</p>
<h2 id="🚀-기능-요구-사항">🚀 기능 요구 사항</h2>
<p>로또 게임 기능을 구현해야 한다. 로또 게임은 아래와 같은 규칙으로 진행된다.
```TEXT</p>
</li>
<li><p>로또 번호의 숫자 범위는 1~45까지이다.</p>
</li>
<li><p>1개의 로또를 발행할 때 중복되지 않는 6개의 숫자를 뽑는다.</p>
</li>
<li><p>당첨 번호 추첨 시 중복되지 않는 숫자 6개와 보너스 번호 1개를 뽑는다.</p>
</li>
<li><p>당첨은 1등부터 5등까지 있다. 당첨 기준과 금액은 아래와 같다.</p>
<ul>
<li>1등: 6개 번호 일치 / 2,000,000,000원</li>
<li>2등: 5개 번호 + 보너스 번호 일치 / 30,000,000원</li>
<li>3등: 5개 번호 일치 / 1,500,000원</li>
<li>4등: 4개 번호 일치 / 50,000원</li>
<li>5등: 3개 번호 일치 / 5,000원
```</li>
</ul>
</li>
<li><p>로또 구입 금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다.</p>
</li>
<li><p>로또 1장의 가격은 1,000원이다.</p>
</li>
<li><p>당첨 번호와 보너스 번호를 입력받는다.</p>
</li>
<li><p>사용자가 구매한 로또 번호와 당첨 번호를 비교하여 당첨 내역 및 수익률을 출력하고 로또 게임을 종료한다.</p>
</li>
<li><p>사용자가 잘못된 값을 입력할 경우 IllegalArgumentException를 발생시키고, &quot;[ERROR]&quot;로 시작하는 에러 메시지를 출력 후 종료한다.</p>
<h2 id="🎯-프로그램-요구-사항">🎯 프로그램 요구 사항</h2>
</li>
<li><p>JDK 11 버전에서 실행 가능해야 한다. JDK 11에서 정상적으로 동작하지 않을 경우 0점 처리한다.</p>
</li>
<li><p>프로그램 실행의 시작점은 Application의 main()이다.</p>
</li>
<li><p>build.gradle 파일을 변경할 수 없고, 외부 라이브러리를 사용하지 않는다.</p>
</li>
<li><p><a href="https://github.com/woowacourse/woowacourse-docs/tree/main/styleguide/java">Java 코드 컨벤션</a> 가이드를 준수하며 프로그래밍한다.</p>
</li>
<li><p>프로그램 종료 시 System.exit()를 호출하지 않는다.</p>
</li>
<li><p>프로그램 구현이 완료되면 ApplicationTest의 모든 테스트가 성공해야 한다. 테스트가 실패할 경우 0점 처리한다.</p>
</li>
<li><p>프로그래밍 요구 사항에서 달리 명시하지 않는 한 파일, 패키지 이름을 수정하거나 이동하지 않는다.</p>
</li>
<li><p>indent(인덴트, 들여쓰기) depth를 3이 넘지 않도록 구현한다. 2까지만 허용한다.</p>
<ul>
<li>예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다.</li>
</ul>
</li>
<li><p>3항 연산자를 쓰지 않는다.</p>
</li>
<li><p>함수(또는 메서드)가 한 가지 일만 하도록 최대한 작게 만들어야 한다.</p>
</li>
<li><p>JUnit 5와 AssertJ를 이용하여 본인이 정리한 기능 목록이 정상 동작함을 테스트 코드로 확인한다.</p>
</li>
</ul>
<h3 id="추가된-요구-사항">추가된 요구 사항</h3>
<ul>
<li>함수(또는 메서드)의 길이가 15라인을 넘어가지 않도록 구현한다.</li>
</ul>
<ul>
<li><p>함수(또는 메서드)가 한 가지 일만 잘 하도록 구현한다.</p>
<ul>
<li><p>else 예약어를 쓰지 않는다.</p>
</li>
<li><p>힌트: if 조건절에서 값을 return하는 방식으로 구현하면 else를 사용하지 않아도 된다.
else를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다.</p>
</li>
<li><p>Java Enum을 적용한다.</p>
</li>
<li><p>도메인 로직에 단위 테스트를 구현해야 한다. 단, UI(System.out, System.in, Scanner) 로직은 제외한다.</p>
</li>
</ul>
</li>
<li><p>핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 분리해 구현한다.</p>
</li>
<li><p>단위 테스트 작성이 익숙하지 않다면 test/java/lotto/LottoTest를 참고하여 학습한 후 테스트를 구현한다.</p>
</li>
</ul>
<h3 id="라이브러리">라이브러리</h3>
<ul>
<li><code>camp.nextstep.edu.missionutils</code>에서 제공하는 <code>Randoms</code> 및 <code>Console</code> API를 사용하여 구현해야 한다.</li>
<li>Random 값 추출은 <code>camp.nextstep.edu.missionutils.Randoms</code>의 <code>pickUniqueNumbersInRange()</code>를 활용한다.
사용자가 입력하는 값은 <code>camp.nextstep.edu.missionutils.Console</code>의 <code>readLine()</code>을 활용한다.</li>
</ul>
<h3 id="lotto-클래스를-사용하며-구현해야-한다">LOTTO 클래스를 사용하며 구현해야 한다.</h3>
<h2 id="✏️-과제-진행-요구-사항">✏️ 과제 진행 요구 사항</h2>
<ul>
<li>기능을 구현하기 전 <code>docs/README.md</code>에 구현할 기능 목록을 정리해 추가한다.</li>
<li>Git의 커밋 단위는 앞 단계에서 <code>docs/README.md</code>에 정리한 기능 목록 단위로 추가한다.</li>
</ul>
<pre><code>- [커밋 메시지 컨벤션 가이드](https://gist.github.com/stephenparish/9941e89d80e2bc58a153)를 참고해 커밋 메시지를 작성한다.</code></pre><hr>
<h1 id="진행-과정의-순서">진행 과정의 순서</h1>
<h2 id="⭐️-객체-분리를-위한-디자인-패턴-공부">⭐️ 객체 분리를 위한 디자인 패턴 공부</h2>
<p>그냥 무작정 객체를 분리했다간 오류가 났을 때 다시 처음부터 짜야할 것 같다는 생각에 객체를 잘 분리하기 위한 효율적인 방법들은 어떤 것들이 있을지 생각해보았다.</p>
<p>검색을 통해 확인을 해봤는데 객체를 분리하기 위한 패턴은 정말 다양하다는 것을 알았다. 싱글톤 패턴, 빌더 패턴, 전략 패턴, 어댑터 패턴 등등... 그렇게 다양한 패턴이 존재하고 있다는 것을 알았지만 실제로 이 패턴들 중에서 어떤 방식이 적합할 지 감이 오지 않았다.</p>
<p>그래서 일단 각 기능을 만들 때 한 가지 일만 함녀서 만드는 것에 집중하면서 객체를 분리해보기로 하였다. </p>
<h2 id="💻-인스턴스형-객체와-클래스형-객체에-대한-공부">💻 인스턴스형 객체와 클래스형 객체에 대한 공부</h2>
<p>코드를 작성하기에 앞서 어떤 클래스 함수 앞에 <code>static</code>키워드가 앞에 붙고 어떤 함수 앞에는 안 붙어 있는 경우를 볼 수가 있었다. 나는 클래스를 분리하고 함수를 만들기 위해서는 <code>static</code>키워드의 역할을 제대로 알아야 할 필요가 있다는 생각이 들었다.</p>
<p>Java에서는 메모리 영역이 존재하는데 메모리 영역은 <code>static 영역</code>과 <code>heap 영역</code>으로 나누어져 있다는 것을 알았다.</p>
<p>핵심 부분을 정리하자면 다음과 같다.</p>
<h3 id="1-static-영역">1. static 영역</h3>
<ul>
<li><strong>Garbage Collector가 관리하는 영역은 아니며</strong> 단순히 <strong>class만 모여 있는 공간을 의미</strong>(객체가 아니다.)한다. 그래서 static 영역의 메모리를 무분별하게 사용하면 메모리 누수가 발생할 수 있다.</li>
<li><strong>class 안에 존재하는 필드(class 변수)가 static으로 지정</strong>이 된다면(static 멤버) <strong>이 멤버는 동일한 클래스의 모든 객체들에 의해 공유</strong>가 되고(클래스가 생성될 때마다 각각 생성이 되는 것이 아니라 단 하나로 생성이 되기 때문), <strong>객체가 사라져도 이 멤버는 사라지지 않는다.</strong></li>
<li><strong>static 메서드는 static 멤버들만 접근 가능하고, 객체가 생성되지 않는 상황에서도 사용 가능하다.</strong></li>
<li><strong>static 메서드</strong>는 <strong>this 키워드를 사용할 수 없다.</strong></li>
<li><strong>static 메서드에 대하여 오버라이딩이 불가능</strong>하다.</li>
</ul>
<h3 id="2-heap-영역">2. heap 영역</h3>
<ul>
<li><strong>Garbage Collector가 관리하는 영역</strong>이며 <strong>객체들이 모여 있는 공간(new 연산을 통해 생성)</strong>이다. 메모리 누수의 걱정은 없다.</li>
</ul>
<h2 id="🖥️-프로그램-기능-구현-시작">🖥️ 프로그램 기능 구현 시작</h2>
<p>사전 공부를 마치고 기능 구현에 들어갔다. 기능 구현을 하면서 필요한 클래스 및 패키지를 분리했고, 클래스를 만들어 기능별 구현을 시작했다. 코드까지 첨부하면서 설명하면 내용이 길어질 것 같아서 내가 구현했던 기능 목록들만 나열하겠다.</p>
<h4 id="✅-구입금액을-입력해-주세요-출력-기능--구입-금액-입력-기능수정">✅ ”구입금액을 입력해 주세요.” 출력 기능,  구입 금액 입력 기능(수정)</h4>
<h4 id="✅-문자열로-입력-받은-금액에-대한-검증-후-정수형으로-반환-기능">✅ 문자열로 입력 받은 금액에 대한 검증 후 정수형으로 반환 기능</h4>
<ul>
<li><p>입력 금액의 맨 앞자리가 0이면 <code>IllegalArgumentException</code> 발생시키기</p>
</li>
<li><p>만약 1000원 단위의 금액이 아니면 <code>IllegalArgumentException</code> 을 발생시키기</p>
<p>  → [ERROR] 입력 금액은 천 원 단위어야 합니다.</p>
</li>
</ul>
<h4 id="✅-입력한-금액에-대하여-로또-개수-구하기-기능">✅ 입력한 금액에 대하여 로또 개수 구하기 기능</h4>
<h4 id="✅-로또-개수-출력-기능-→-8개를-구매했습니다">✅ 로또 개수 출력 기능 → “8개를 구매했습니다.”</h4>
<h4 id="✅-로또-개수-만큼-6개의-숫자를-랜덤으로-생성하는-기능">✅ 로또 개수 만큼 6개의 숫자를 랜덤으로 생성하는 기능</h4>
<ul>
<li><code>pickUniqueNumbersInRange(1, 45, 6)</code></li>
</ul>
<h4 id="✅-생성된-로또-번호-오름차순으로-정렬하기-기능">✅ 생성된 로또 번호 오름차순으로 정렬하기 기능</h4>
<h4 id="✅-입력-형식--구분해서-입력-검증-포함한-당첨-번호-입력-받기-기능">✅ 입력 형식 (, 구분해서 입력) 검증 포함한 당첨 번호 입력 받기 기능</h4>
<h4 id="✅-각각의-당첨-번호-유효성-검증">✅ 각각의 당첨 번호 유효성 검증</h4>
<ul>
<li>각각의 당첨 번호의 범위 검증 (1 ≤ 당첨 번호 ≤ 45)</li>
<li>각각의 당첨 번호 중복 여부 검증</li>
</ul>
<h4 id="✅-보너스-번호-입력-받기-기능">✅ 보너스 번호 입력 받기 기능</h4>
<h4 id="✅-보너스-번호-유효성-검증-기능">✅ 보너스 번호 유효성 검증 기능</h4>
<h4 id="✅-당첨-통계-출력-기능">✅ 당첨 통계 출력 기능</h4>
<h4 id="✅-모든-로또의-번호와-당첨번호를-비교해-각각의-일치-개수에-대하여-몇-개의-로또가-있는지-정보-출력-기능">✅ 모든 로또의 번호와 당첨번호를 비교해 각각의 일치 개수에 대하여 몇 개의 로또가 있는지 정보 출력 기능</h4>
<h4 id="✅-총-수익률-계산-기능소수점-둘째-자리에서-반올림">✅ 총 수익률 계산 기능(소수점 둘째 자리에서 반올림)</h4>
<hr>
<h2 id="3주차-진행-후-받은-공통-피드백">3주차 진행 후 받은 공통 피드백</h2>
<h3 id="🔔-함수메서드-라인에-대한-기준">🔔 함수(메서드) 라인에 대한 기준</h3>
<p>프로그래밍 요구사항을 보면 함수 15라인으로 제안하는 요구사항이 있다. 이 기준은 main() 함수에도 해당된다. 공백 라인도 한 라인에 해당한다. 15라인이 넘어간다면 함수 분리를 위한 고민을 한다.</p>
<h3 id="🔔-발생할-수-있는-예외-상황에-대해-고민한다">🔔 발생할 수 있는 예외 상황에 대해 고민한다</h3>
<p>정상적인 경우를 구현하는 것보다 예외 상황을 모두 고려해 프로그래밍하는 것이 더 어렵다. 예외 상황을 고려해 프로그래밍하는 습관을 들인다. 예를 들어 로또 미션의 경우 아래와 같은 예외 상황을 고민해 보고 해당 예외에 대해 처리를 할 수 있어야 한다.</p>
<ul>
<li>로또 구입 금액에 1000 이하의 숫자를 입력</li>
<li>당첨 번호에 중복된 숫자를 입력</li>
<li>당첨번호에 1~45 범위를 벗어나는 숫자를 입력</li>
<li>당첨 번호와 중복된 보너스 번호를 입력<h3 id="🔔-비즈니스-로직과-ui-로직을-분리한다">🔔 비즈니스 로직과 UI 로직을 분리한다</h3>
비즈니스 로직과 UI 로직을 한 클래스가 담당하지 않도록 한다. 단일 책임의 원칙에도 위배된다.
현재 객체의 상태를 보기 위한 로그 메시지 성격이 강하다면 toString()을 통해 구현한다. View에서 사용할 데이터라면 getter 메서드를 통해 데이터를 전달한다.</li>
</ul>
<h3 id="🔔-연관성이-있는-상수는-static-final-대신-enum을-활용한다">🔔 연관성이 있는 상수는 static final 대신 enum을 활용한다</h3>
<h3 id="🔔-final-키워드를-사용해-값의-변경을-막는다">🔔 final 키워드를 사용해 값의 변경을 막는다</h3>
<p>최근에 등장하는 프로그래밍 언어들은 기본이 불변 값이다. 자바는 final 키워드를 활용해 값의 변경을 막을 수 있다.</p>
<h3 id="🔔-객체의-상태-접근을-제한한다">🔔 객체의 상태 접근을 제한한다</h3>
<p>인스턴스 변수의 접근 제어자는 private으로 구현한다.</p>
<h3 id="🔔-객체는-객체스럽게-사용한다">🔔 객체는 객체스럽게 사용한다</h3>
<p>Lotto 클래스는 numbers를 상태 값으로 가지는 객체이다. 그런데 이 객체는 로직에 대한 구현은 하나도 없고, numbers에 대한 getter 메서드만을 가진다.
Lotto에서 데이터를 꺼내지(get) 말고 메시지를 던지도록 구조를 바꿔 데이터를 가지는 객체가 일하도록 한다.</p>
<h3 id="🔔-필드인스턴스-변수의-수를-줄이기-위해-노력한다">🔔 필드(인스턴스 변수)의 수를 줄이기 위해 노력한다</h3>
<p>필드(인스턴스 변수)의 수가 많은 것은 객체의 복잡도를 높이고, 버그 발생 가능성을 높일 수 있다. 필드에 중복이 있거나, 불필요한 필드가 없는지 확인해 필드의 수를 최소화한다.</p>
<h3 id="🔔-성공하는-케이스-뿐만-아니라-예외에-대한-케이스도-테스트한다">🔔 성공하는 케이스 뿐만 아니라 예외에 대한 케이스도 테스트한다</h3>
<p>테스트를 작성하면 성공하는 케이스에 대해서만 고민하는 경우가 있다. 하지만 예외에 대한 부분 또한 처리해야 한다. 특히 프로그램에서 결함이 자주 발생하는 부분 중 하나는 경계값이므로 이 부분을 꼼꼼하게 확인해야 한다.</p>
<h3 id="🔔-테스트-코드도-코드다">🔔 테스트 코드도 코드다</h3>
<p>테스트 코드도 코드이므로 리팩터링을 통해 개선해나가야 한다. 특히 반복적으로 하는 부분을 중복되지 않게 만들어야 한다. </p>
<h3 id="🔔-테스트를-위한-코드는-구현-코드에서-분리되어야-한다">🔔 테스트를 위한 코드는 구현 코드에서 분리되어야 한다</h3>
<p>테스트를 위한 편의 메서드를 구현 코드에 구현하지 마라. 아래의 예시처럼 테스트를 통과하기 위해 구현 코드를 변경하거나 테스트에서만 사용되는 로직을 만들지 않는다.</p>
<h3 id="🔔-테스트를-위한-코드는-구현-코드에서-분리되어야-한다-1">🔔 테스트를 위한 코드는 구현 코드에서 분리되어야 한다</h3>
<p>테스트를 위한 편의 메서드를 구현 코드에 구현하지 마라. 아래의 예시처럼 테스트를 통과하기 위해 구현 코드를 변경하거나 테스트에서만 사용되는 로직을 만들지 않는다.</p>
<ul>
<li>테스트를 위해 접근 제어자를 바꾸는 경우</li>
<li>테스트 코드에서만 사용되는 메서드</li>
</ul>
<h3 id="🔔-단위-테스트를-할-때-테스트하기-어려운-부분은-분리하고-테스트-가능한-부분을-단위-테스트한다">🔔 단위 테스트를 할 때 테스트하기 어려운 부분은 분리하고 테스트 가능한 부분을 단위 테스트한다.</h3>
<h3 id="🔔-private-함수를-테스트-하고-싶다면-클래스객체-분리를-고려한다">🔔 private 함수를 테스트 하고 싶다면 클래스(객체) 분리를 고려한다</h3>
<p>가독성의 이유만으로 분리한 private 함수의 경우 public으로도 검증 가능하다고 여겨질 수 있다. public 함수가 private 함수를 사용하고 있기 때문에 자연스럽게 테스트 범위에 포함된다. 하지만 가독성 이상의 역할을 하는 경우, 테스트하기 쉽게 구현하기 위해서는 해당 역할을 수행하는 다른 객체를 만들 타이밍이 아닐지 고민해 볼 수 있다. 다음 단계를 진행할 때에는 너무 많은 역할을 하고 있는 함수나 객체를 어떻게 의미 있는 단위로 분할할지에 초점을 맞춰 진행한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[우아한테크코스 5기 - 프리코스 2주차 미션[숫자 야구 게임]]]></title>
            <link>https://velog.io/@apple-juice/%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4-5%EA%B8%B0-%ED%94%84%EB%A6%AC%EC%BD%94%EC%8A%A4-2%EC%A3%BC%EC%B0%A8-%EB%AF%B8%EC%85%98%EC%88%AB%EC%9E%90-%EC%95%BC%EA%B5%AC-%EA%B2%8C%EC%9E%84</link>
            <guid>https://velog.io/@apple-juice/%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4-5%EA%B8%B0-%ED%94%84%EB%A6%AC%EC%BD%94%EC%8A%A4-2%EC%A3%BC%EC%B0%A8-%EB%AF%B8%EC%85%98%EC%88%AB%EC%9E%90-%EC%95%BC%EA%B5%AC-%EA%B2%8C%EC%9E%84</guid>
            <pubDate>Thu, 10 Nov 2022 03:41:40 GMT</pubDate>
            <description><![CDATA[<h1 id="서론">서론</h1>
<p>1주 차 미션에서 작성했던 준비 운동을 마무리하고 본격적인 미션이 시작되는 것 같다.</p>
<p>이번 2주 차 미션에서는 1주 차에서 학습한 것에 더해 <strong>함수를 분리</strong>하고, 각 <strong>함수별로 테스트를 작성하는 것</strong>에 익숙해지는 것을 목표로 하고 있다.</p>
<p>그리고 작성한 함수에 대한 테스트 코드를 작성하여 내가 생각한 기능대로 제대로 동작을 하는지 테스트도 진행을 해아 한다. 자발적으로 작성해 본 적이 없는 내 입장에서는 가치 있는 미션인 것 같다.</p>
<p>2주차 과제를 진행하면서 내가 과제를 진행했던 과정을 정리하겠다.</p>
<hr>
<h1 id="기능-구현-유의사항">기능 구현 유의사항</h1>
<p>문제 풀기에 앞서 다음과 같은 진행 방식을 유의하면서 기능을 구현해야 한다.</p>
<ul>
<li><p>미션은 <code>기능 요구 사항, 프로그래밍 요구 사항, 과제 진행 요구 사항</code> 세 가지로 구성되어 있다.</p>
</li>
<li><p>세 개의 요구 사항을 만족하기 위해 노력한다. 특히 <strong>기능을 구현하기 전에 기능 목록을 만들고, 기능 단위로 커밋 하는 방식으로 진행</strong>한다.</p>
</li>
<li><p>기능 요구 사항에 기재되지 않은 내용은 스스로 판단하여 구현한다.</p>
<h2 id="🚀-기능-요구-사항">🚀 기능 요구 사항</h2>
<p>1부터 9까지 서로 다른 수로 이루어진 3자리의 수를 맞추는 게임 기능을 구현해야 한다.</p>
</li>
<li><p>같은 수가 같은 자리에 있으면 스트라이크, 다른 자리에 있으면 볼, 같은 수가 전혀 없으면 낫싱이란 힌트를 얻고, 그 힌트를 이용해서 먼저 상대방(컴퓨터)의 수를 맞추면 승리한다.</p>
<ul>
<li>예를 들어 상대방(컴퓨터)의 수가 425일 때<ul>
<li>123을 제시한 경우: 2의 위치가 하나 맞았고, 1과 3은 425에서 존재하지도 않으므로 <code>1스트라이크</code></li>
<li>456을 제시한 경우: 5의 위치가 서로 다르고 4의 위치가 같으므로 <code>1볼 1스트라이크</code></li>
<li>789를 제시한 경우: 425에서 해당 숫자가 존재하지 않으므로 <code>낫싱</code></li>
</ul>
</li>
</ul>
</li>
<li><p>위 숫자 야구 게임에서 상대방의 역할을 컴퓨터가 한다. 컴퓨터는 1에서 9까지 서로 다른 임의의 수 3개를 선택한다. 게임 플레이어는 컴퓨터가 생각하고 있는 서로 다른 3개의 숫자를 입력하고, 컴퓨터는 입력한 숫자에 대한 결과를 출력한다.</p>
</li>
<li><p>이 같은 과정을 반복해 컴퓨터가 선택한 3개의 숫자를 모두 맞히면 게임이 종료된다.</p>
</li>
<li><p>게임을 종료한 후 게임을 다시 시작하거나 완전히 종료할 수 있다.</p>
</li>
<li><p>사용자가 잘못된 값을 입력할 경우 <code>IllegalArgumentException</code>을 발생시킨 후 애플리케이션은 종료되어야 한다.</p>
</li>
<li><p>프로그램이 실행될 때 다음과 같은 내용들이 출력되어야 한다.</p>
<pre><code class="language-TEXT">숫자 야구 게임을 시작합니다.
숫자를 입력해주세요 : 123
1볼 1스트라이크
숫자를 입력해주세요 : 145
1볼
숫자를 입력해주세요 : 671
2볼
숫자를 입력해주세요 : 216
1스트라이크
숫자를 입력해주세요 : 713
3스트라이크
3개의 숫자를 모두 맞히셨습니다! 게임 종료
게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.
1
숫자를 입력해주세요 : 123
1볼
...</code></pre>
</li>
</ul>
<h2 id="🎯-프로그램-요구-사항">🎯 프로그램 요구 사항</h2>
<ul>
<li>JDK 11 버전에서 실행 가능해야 한다. JDK 11에서 정상적으로 동작하지 않을 경우 0점 처리한다.</li>
<li>프로그램 실행의 시작점은 <code>Application</code>의 <code>main()</code>이다.</li>
<li><code>build.gradle</code> 파일을 변경할 수 없고, 외부 라이브러리를 사용하지 않는다.</li>
<li><a href="https://github.com/woowacourse/woowacourse-docs/tree/main/styleguide/java">Java 코드 컨벤션</a> 가이드를 준수하며 프로그래밍한다.</li>
<li>프로그램 종료 시 <code>System.exit()</code>를 호출하지 않는다.</li>
<li>프로그램 구현이 완료되면 <code>ApplicationTest</code>의 모든 테스트가 성공해야 한다. 테스트가 실패할 경우 0점 처리한다.</li>
<li>프로그래밍 요구 사항에서 달리 명시하지 않는 한 파일, 패키지 이름을 수정하거나 이동하지 않는다.</li>
</ul>
<h3 id="추가된-요구-사항">추가된 요구 사항</h3>
<ul>
<li><p>indent(인덴트, 들여쓰기) depth를 3이 넘지 않도록 구현한다. 2까지만 허용한다.</p>
<ul>
<li>예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다.</li>
</ul>
</li>
<li><p>3항 연산자를 쓰지 않는다.</p>
</li>
<li><p>함수(또는 메서드)가 한 가지 일만 하도록 최대한 작게 만들어야 한다.</p>
</li>
<li><p>JUnit 5와 AssertJ를 이용하여 본인이 정리한 기능 목록이 정상 동작함을 테스트 코드로 확인한다.</p>
<h3 id="라이브러리">라이브러리</h3>
</li>
<li><p><code>camp.nextstep.edu.missionutils</code>에서 제공하는 <code>Randoms</code> 및 <code>Console</code> API를 사용하여 구현해야 한다.</p>
</li>
</ul>
<pre><code>- Random 값 추출은 ```camp.nextstep.edu.missionutils.Randoms```의 ```pickNumberInRange()```를 활용한다.
- 사용자가 입력하는 값은 ```camp.nextstep.edu.missionutils.Console```의 ```readLine()```을 활용한다.</code></pre><h2 id="✏️-과제-진행-요구-사항">✏️ 과제 진행 요구 사항</h2>
<ul>
<li>기능을 구현하기 전 <code>docs/README.md</code>에 구현할 기능 목록을 정리해 추가한다.</li>
<li>Git의 커밋 단위는 앞 단계에서 <code>docs/README.md</code>에 정리한 기능 목록 단위로 추가한다.</li>
</ul>
<pre><code>- [커밋 메시지 컨벤션](https://gist.github.com/stephenparish/9941e89d80e2bc58a153) 가이드를 참고해 커밋 메시지를 작성한다.</code></pre><hr>
<h1 id="진행-과정의-순서">진행 과정의 순서</h1>
<h2 id="⭐-git-commit-convention에-대한-공부">⭐ git commit convention에 대한 공부</h2>
<p>프로그램 요구 사항에서 <a href="https://github.com/woowacourse/woowacourse-docs/tree/main/styleguide/java">Java 코드 컨벤션</a>의 링크를 들어가보았다. git commit을 할 때 어떤 형태로 작성을 해야 하는지 그에 대한 가이드가 들어있었다.</p>
<p>그 외에도 git comit에 대한 자세한 내용을 알고 싶어서 구글링을 통해 git commit convention에 대해 다양한 가이드를 참조했고, 내가 공부했던 내용들을 바탕으로 <a href="https://velog.io/@apple-juice/git-commit-convention%EC%97%90-%EA%B4%80%ED%95%98%EC%97%AC">벨로그</a>에 정리를 하였다.</p>
<h2 id="⚾-야구-게임을-위한-필요한-기능-목록들을-고찰">⚾ 야구 게임을 위한 필요한 기능 목록들을 고찰</h2>
<p>문제에서 이번 주차의 미션은 <strong>함수를 분리하고 이에 따른 테스트 코드를 작성하는 것을 목표</strong>로 한다. 그래서 나는 <strong>각 기능을 하나의 함수로 취급</strong>해서 각 가능들을 고찰하였다. 즉, 하나의 Application 파일 안에서 코드 작성을 진행했다. 내 코드의 내용이 정답이라는 보장은 없기에 어떤 함수를 만들었고, 무슨 기능인지 간단하게 설명만 하려고 한다.
최종적으로 내가 생각했던 기능들은 다음과 같다.
1️⃣ 게임 시작 공지 기능
2️⃣ 1부터 9까지 3개의 서로 다른 자연수의 컴퓨터 숫자 뽑기 기능
3️⃣ 사용자로부터 3개의 숫자 입력 받기 기능
4️⃣ 사용자로부터 입력된 3개의 숫자의 유효성 검증 기능
5️⃣ 컴퓨터 숫자와 사용자 숫자로부터 &#39;볼&#39;의 개수 뽑기 기능
6️⃣ 컴퓨터 숫자와 사용자 숫자로부터 &#39;스트라이크&#39;의 개수 뽑기 기능
7️⃣ &#39;스트라이크&#39; 및 &#39;볼&#39;의 개수 정보 출력 기능
8️⃣ 3스트라이크가 나올 때까지 3번과 7번을 반복 기능
9️⃣ 3스트라이크가 달성 후 게임 재시작 여부 기능</p>
<h2 id="🏀-각-기능-목록-하나씩-구현-후-commit-진행">🏀 각 기능 목록 하나씩 구현 후 commit 진행</h2>
<p>목록 당 기능을 구현 후 commit convention에 따라서 commit을 진행했다.</p>
<p>1️⃣ <code>숫자 야구 게임을 시작합니다.</code>문구 출력을 위한 기능이다. 이 기능에 대한 메서드를 따로 구현을 했고, 메서드 이름을 <code>noticeStartGame</code>으로 설정했다.
2️⃣ <code>createComputerNumbers</code> 메서드를 만들었고, <code>Randoms의 pickNumberInRange</code>메서드를 사용하였다.
3️⃣ <code>inputUserNumbers</code>메서드를 만들었다. 이 메서드에는 <code>숫자를 입력해주세요 :</code>도 출력이 된다. 처음에는 숫자 입력 출력 문구도 따로 기능으로 뺄 생각을 했지만, 입력 기능에 관련이 있으므로 빼지 않기로 결정했다.
4️⃣ <code>isValidUserNumbers</code> 메서드를 만들었다. 이 메서드는 다음과 같은 내용을 검증한다.</p>
<ul>
<li>입력한 숫자의 길이가 3인지 검증</li>
<li>각 자리당 숫자의 범위가 1이상 9이하인지 검증</li>
<li>각 자리마다 중복된 숫자가 있는지 검증</li>
</ul>
<p>5️⃣ <code>getBallNumber</code> 메서드를 만들었고, 3자리의 유효한 사용자 숫자와 컴퓨터 숫자를 비교하여 볼의 개수를 출력한다.
6️⃣ <code>getStrikeNumber</code>메서드를 만들었고, 3자리의 유효한 사용자 숫자와 컴퓨터 숫자를 비교하여 스트라이크의 개수를 출력한다.
7️⃣ <code>printBallStrikeResult</code>를 만들었다. 이 메서드는 들어온 볼의 개수와 스트라이크의 개수 정보를 바탕으로 알맞은 결과를 출력한다. 또한 boolean형의 메서드이므로 3스트라이크가 아니면 true를 반환한다.
8️⃣ 7️⃣번에서 3스트라이크가 나오지 않을 경우 true를 반환하는 것을 이용하여 <code>main</code>함수에서 반복문을 통해서 야구 게임 숫자 반복 입력을 설정했다.
9️⃣ <code>wantRestart</code>를 구현했고, 이 메서드는 boolean형이다. 즉, 사용자가 게임 재시작을 원하면 true를 반환, 게임 종료를 원하면 false를 반환하도록 설정해 <code>main</code>에서 반복문을 통해서 게임을 재시작 하도록 설정하였다.</p>
<h2 id="🔧-전반적인-코드-리펙토링-진행">🔧 전반적인 코드 리펙토링 진행</h2>
<p><a href="https://github.com/woowacourse/woowacourse-docs/tree/main/styleguide/java">Java 코드 컨벤션</a>에 따라서 전반적으로 가독성을 높이기 위한 코드 리펙토링을 진행했다.</p>
<ul>
<li>while, if 등의 내용 다음에 수직 빈 줄 쓰기</li>
<li>메서드와 메서드 사이에 수직 빈 줄 쓰기</li>
</ul>
<h2 id="🔍-기능별-테스트-코드-작성">🔍 기능별 테스트 코드 작성</h2>
<p>모든 기능 및 코드 리펙토링을 마치고 전반적으로 각 기능들이 이상이 없는지 그에 따른 테스트 코드를 작성하였다. 
테스트 코드에 대한 작성 경험은 별로 많지 않아서 테스트 코드를 쓸 때 주로 어떤 기능을 쓰는지, 또 어떤 방식으로 테스트를 진행하는지 공부하였다. 
테스트를 진행하는 방식에는 BDD(Behavior-driven development), TDD(Test-driven development)이 두 가지가 존재한다는 것을 알았다. 
TDD는 테스트를 먼저 작성하고 그 테스트를 통과시키는 코드를 작성하는 흐름을 기본으로 하지만, BDD는 시나이오를 기반으로 테스트를 작성한다. 그리고 <code>given</code>, <code>when</code>, <code>then</code>등의 구조로 테스트를 작성한다.
나는 BDD방식을 통해, 즉 <code>given</code>, <code>when</code>, <code>then</code>의 구조로 테스트 코드를 작성하려고 노력했다. 그래야 일반 사람들이 언뜻 봐서도 이해가 될 것 같았기에 가독성 면에서도 좋을 것 같다는 생각이 들었다.
테스트 코드를 작성을 해보면서 힘들었던 점을 꼽아서 얘기하자면 출력 관련 테스트에 대한 코드 작성과 private으로 설정된 메서드를 테스트 코드 파일로 불러오는 일이었다. 
나는 이것과 관련하여 구글링을 하는데 많은 시간을 투자했었다. 
하지만 결과적으로 테스트 코드를 완성했고, 꽤 유용한 기능들에 대한 노하우를 얻었다는 느낌을 받았다.</p>
<hr>
<h2 id="2주차-진행-후-받은-공통-피드백">2주차 진행 후 받은 공통 피드백</h2>
<h3 id="🔔-readmemd를-상세히-작성한다">🔔 README.md를 상세히 작성한다</h3>
<p>미션 저장소의 README.md는 소스코드에 앞서 해당 프로젝트가 어떠한 프로젝트인지 <strong>마크다운</strong>으로 작성하여 소개하는 문서이다. 해당 프로젝트가 어떠한 프로젝트이며, 어떤 기능을 담고 있는지 기술하기 위해서 마크다운문법을 검색해서 학습해보고 적용해 본다.</p>
<h3 id="🔔-기능-목록을-재검토한다">🔔 기능 목록을 재검토한다</h3>
<p>기능 목록을 클래스 설계와 구현, 함수(메서드) 설계와 구현과 같이 너무 상세하게 작성하지 않는다. 클래스 이름, 함수(메서드) 시그니처와 반환값은 언제든지 변경될 수 있기 때문이다. 너무 세세한 부분까지 정리하기보다 구현해야 할 기능 목록을 정리하는 데 집중한다. <strong>정상적인 경우도 중요하지만, 예외적인 상황도 기능 목록에 정리</strong>한다. 특히 예외 상황은 시작 단계에서 모두 찾기 힘들기 때문에 기능을 구현하면서 계속해서 추가해 나간다.</p>
<h3 id="🔔-기능-목록을-업데이트한다">🔔 기능 목록을 업데이트한다</h3>
<p>README.md 파일에 작성하는 기능 목록은 기능 구현을 하면서 변경될 수 있다. 시작할 때 모든 기능 목록을 완벽하게 정리해야 한다는 부담을 가지기보다 기능을 구현하면서 문서를 계속 업데이트한다. 죽은 문서가 아니라 살아있는 문서를 만들기 위해 노력한다.</p>
<h3 id="🔔-값을-하드-코딩하지-않는다">🔔 값을 하드 코딩하지 않는다</h3>
<p>문자열, 숫자 등의 값을 하드 코딩하지 마라. 상수(static final)를 만들고 이름을 부여해 이 변수의 역할이 무엇인지 의도를 드러내라. 구글에서 &quot;java 상수&quot;와 같은 키워드로 검색해 상수 구현 방법을 학습하고 적용해 본다.</p>
<h3 id="🔔-구현-순서도-코딩-컨벤션이다">🔔 구현 순서도 코딩 컨벤션이다</h3>
<p>클래스는 상수, 멤버 변수, 생성자, 메서드 순으로 작성한다.</p>
<pre><code class="language-JAVA">class A {
    상수(static final) 또는 클래스 변수

    인스턴스 변수

    생성자

    메서드
}</code></pre>
<h3 id="🔔-변수-이름에-자료형은-사용하지-않는다">🔔 변수 이름에 자료형은 사용하지 않는다</h3>
<p>변수 이름에 자료형, 자료 구조 등을 사용하지 마라.</p>
<pre><code class="language-JAVA">String carNameList = Console.readLine();
String[] arrayString = carNameList.split(&quot;,&quot;);</code></pre>
<h3 id="🔔-한-함수가-한-가지-기능만-담당하게-한다">🔔 한 함수가 한 가지 기능만 담당하게 한다</h3>
<p>함수 길이가 길어진다면 한 함수에서 여러 일을 하려고 하는 경우일 가능성이 높다. 아래와 같이 한 함수에서 안내 문구 출력, 사용자 입력, 유효값 검증 등 여러 일을 하고 있다면 이를 적절하게 분리한다.</p>
<h3 id="🔔-함수가-한-가지-기능을-하는지-확인하는-기준을-세운다">🔔 함수가 한 가지 기능을 하는지 확인하는 기준을 세운다</h3>
<p>만약 여러 함수에서 중복되어 사용되는 코드가 있다면 함수 분리를 고민해 본다. 또한, 함수의 길이를 15라인을 넘어가지 않도록 구현하며 함수를 분리하는 의식적인 연습을 할 수 있다.</p>
<h3 id="🔔-테스트를-작성하는-이유에-대해-본인의-경험을-토대로-정리해본다">🔔 테스트를 작성하는 이유에 대해 본인의 경험을 토대로 정리해본다</h3>
<p>단지 기능을 점검하기 위한 목적으로 테스트를 작성하는 것은 아니다. 테스트를 작성하는 과정을 통해서 나의 코드에 대해 빠르게 피드백을 받을 수 있을 뿐만 아니라 학습 도구로도 활용할 수 있다. 이런 경험을 통해 테스트에 대해 어떤 유용함을 느꼈는지 알아본다.</p>
<h3 id="🔔-처음부터-큰-단위의-테스트를-만들지-않는다">🔔 처음부터 큰 단위의 테스트를 만들지 않는다</h3>
<p>테스트의 중요한 목적 중 하나는 내가 작성하는 코드에 대해 빠르게 피드백을 받는 것이다. 시작부터 큰 단위의 테스트를 만들게 된다면 작성한 코드에 대한 피드백을 받기까지 많은 시간이 걸린다. 그래서 문제를 작게 나누고, 그 중 핵심 기능에 가까운 부분부터 작게 테스트를 만들어 나간다.</p>
<h4 id="큰-단위의-테스트">큰 단위의 테스트</h4>
<ul>
<li>숫자 야구 게임을 시작해서 사용자가 숫자를 입력하면, 컴퓨터 숫자와 비교하여 그 결과를 알려준다.<h4 id="작은-단위의-테스트">작은 단위의 테스트</h4>
</li>
<li>사용자의 숫자가 컴퓨터의 숫자와 하나도 일치하지 않으면 낫싱을 출력한다.</li>
<li>사용자의 숫자가 컴퓨터의 숫자와 1개는 일치하고, 위치가 다르면 1볼을 출력한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[git commit convention에 관하여]]></title>
            <link>https://velog.io/@apple-juice/git-commit-convention%EC%97%90-%EA%B4%80%ED%95%98%EC%97%AC</link>
            <guid>https://velog.io/@apple-juice/git-commit-convention%EC%97%90-%EA%B4%80%ED%95%98%EC%97%AC</guid>
            <pubDate>Thu, 03 Nov 2022 01:48:54 GMT</pubDate>
            <description><![CDATA[<h1 id="서론">서론</h1>
<p>우리가 작업을  하게 된다면 git을 이용한 commit 활동을 하게 된다. </p>
<p>개인 프로젝트 및 토이 프로젝트를 진행하는 경우에는 우리는 단순히 다음과 같은 명령어를 통해서 commit을 해봤을 것이다.</p>
<p><code>git commit -m “커밋할 메시지”</code></p>
<p>이 커밋할 메시지에서 자기가 원하는 방식대로 메시지를 작성했을 것이다. </p>
<p> 하지만 다른 사람과 같이 협업해야 하는 상황이라면 자기가 원하는대로 메시지를 작성하면 다른 협업 작업자 입장에서는 나의 메시지를 이해하기 힘들 수도 있고, 작업 하기가 수월하지 않을 수도 있는 상황이 발생할 수 있다. 또한 내가 그동안 작성한 commit의 log를 살펴보면 과거 내가 작성했던 commit의 내용을 이해하지 못하는 상황도 발생할 수 있다.</p>
<p>그래서 이러한 상황들을 방지하기 위해서 commit convention을 지키는 습관도 중요하다.</p>
<hr>
<h1 id="편집기를-통해서-commit-내용-작성하기">편집기를 통해서 commit 내용 작성하기</h1>
<p>1️⃣ <strong>git config —global core.editor (사용할 편집기)</strong> </p>
<p>어떤 환경에서 commit을 할 지 정하기 위해서 쓰이는 명령어이다. </p>
<p>나는 vim 편집기가 익숙해서 다음과 같은 명령어를 사용했다.</p>
<p><code>git config —global core.editor vim</code></p>
<p>그 밖에 <code>nano, emacs</code> 등이 있다.</p>
<p>2️⃣ <strong>git commit -a</strong></p>
<p>위의 명령어를 사용하면 자신이 설정한 편집기 환경에서 commit 내용을 작성할 수 있다.
<img src="https://velog.velcdn.com/images/apple-juice/post/cc8bab35-1099-408e-9293-fa03ed85b07f/image.png" alt=""></p>
<h1 id="좋은-commit-message를-작성하기-위한-형태">좋은 commit message를 작성하기 위한 형태</h1>
<pre><code class="language-text">&lt;type&gt;(&lt;scope&gt;): &lt;subject&gt;
&lt;BLANK LINE&gt;
&lt;body&gt;
&lt;BLANK LINE&gt;
&lt;footer&gt;</code></pre>
<p>⚠️ 한 라인에서 작성할 수 있는 글자 수는 100자를 넘어가면 안된다!</p>
<h2 id="type-의-종류">&lt;type&gt; 의 종류</h2>
<p>👉  <strong>feat(feature)</strong>: 새로운 기능을 추가할 시 작성한다.
👉  <strong>fix</strong>: 코드내에서 버그를 수정할 때 사용한다. 주로 기능상 오류를 수정할 때 사용한다.
👉 <strong>docs(documentation)</strong>:  문서 등의 내용을 수정할 때 쓰인다.
👉 <strong>style (formatting, missing semi colons, …)</strong>:  코드 포멧팅, 세미콜론 누락 등 코드 스타일링을 했을 때 사용한다.
👉  <strong>refactor</strong>: 코드 리펙토링시 사용한다. 코드를 수정하되 프로그램의 흐름은 변경이 없어야 한다! 예를 들어 어떤 입력값에 대한 결과값은 변경이 없어야 한다. 가독성, 복잡성 관련 작업을 진행할 때 사용한다.
👉  <strong>test</strong>: 누락된 테스트 코드를 작성했을 때 사용한다.
👉  <strong>chore(maintain)</strong>: 유지 보수 등의 내용일 때 사용한다.
👉  <strong>build</strong>: 빌드 관련 내용 변경이 있을 때 사용한다. (ex. npm 관련 내용, 외부 dependency 추가 등)
👉  <strong>perf</strong>: 성능 관련 코드 수정이 있을 때 사용한다.</p>
<h2 id="scope의-종류">&lt;scope&gt;의 종류</h2>
<p>   이 영역은 입력해도 되고 입력하지 않아도 된다. 사용자의 선택사항이다. 어떤 내용을 작성할지도 사용자의 선택사항이다. 예를 들어서 다음과 같이 사용할 수 있다.</p>
<p>  <code>$location, $browser, $compile, $rootScope, ngHref, ngClick, ngView, etc…</code></p>
<pre><code>&lt;subject\&gt;의 내용을 나타내기 위한 단어로 봐도 무방하다.</code></pre><h2 id="subject">&lt;subject&gt;</h2>
<p>commit message의 제목을 작성하는 영역으로 다른 작업자가 보기 좋게 최대한 간결하고 보기 좋게 어떤 내용 변경이 있었는지 작성한다. 해당 영역에서 마지막에는 마침표를 쓰면 안된다.
영어권의 경우 첫 글자는 대문자가 아닌 소문자로 시작해야하며 현재형을 사용해야 한다.</p>
<h2 id="body">&lt;body&gt;</h2>
<p>반드시 현재형으로 작성해야 한다. 
변경 내용에 대한 동기가 있어야 하고, 변경 전과 후에 대한 차이를 설명해야 한다. </p>
<h2 id="footer">&lt;footer&gt;</h2>
<p>여기에 모든 변경 사항들과 변경 내용의 정당성, 그리고 변경한 내용(변경 전과 변경 후)이 상세하게 작성이 되어야 한다.
특히 이슈 및 버그 관련 내용이라면 이슈 및 버그를 해결했을시 그동안 있었던 이슈 및 버그 번호들을 <code>closes</code>를 통해서 명시를 해주어야 한다. footer 초반에 명시를 해줘야 한다.
👉 <code>closes #이슈번호</code></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[우아한테크코스 5기 - 프리코스 1주차 미션 [온보딩]]]></title>
            <link>https://velog.io/@apple-juice/%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4-%ED%94%84%EB%A6%AC%EC%BD%94%EC%8A%A4-1%EC%A3%BC%EC%B0%A8-%EB%AF%B8%EC%85%98-%EC%98%A8%EB%B3%B4%EB%94%A9</link>
            <guid>https://velog.io/@apple-juice/%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4-%ED%94%84%EB%A6%AC%EC%BD%94%EC%8A%A4-1%EC%A3%BC%EC%B0%A8-%EB%AF%B8%EC%85%98-%EC%98%A8%EB%B3%B4%EB%94%A9</guid>
            <pubDate>Wed, 02 Nov 2022 05:03:58 GMT</pubDate>
            <description><![CDATA[<h1 id="서론">서론</h1>
<p>우아한테크코스 5기의 1주차 미션은 7개의 알고리즘 문제풀이였다.</p>
<p>본격적인 과제 들어가기에 앞서 준비운동을 위한 과제라고 생각이 되었다.
오리엔테이션 때 난이도는 쉬운 문제라고 하였으나 알고리즘 문제를 전혀 풀어본 경험이 없는 사람들에게는 만만치 않겠다는 생각이 들었다.</p>
<p>이번 과제를 통해서 각각의 문제마다 내가 생각했었던 문제풀이 설계 과정을 여기에 적어보려고 한다. 내 생각이 무조건 옳다라는 보장은 없다. 코드는 내용상 길어지므로 첨부는 하지 않았다.</p>
<h1 id="기능-구현-유의사항">기능 구현 유의사항</h1>
<p>문제 풀기에 앞서 다음과 같은 진행 방식을 유의하면서 기능을 구현해야 한다.</p>
<ul>
<li>미션은 <code>기능 요구 사항, 프로그래밍 요구 사항, 과제 진행 요구 사항 세 가지</code>로 구성되어 있다.</li>
<li>세 개의 요구 사항을 만족하기 위해 노력한다. 특히 <strong>기능을 구현하기 전에 기능 목록을 만들고, 기능 단위로 커밋 하는 방식으로 진행</strong>한다.</li>
<li>기능 요구 사항에 기재되지 않은 내용은 스스로 판단하여 구현한다.</li>
</ul>
<h2 id="🚀-기능-요구-사항">🚀 기능 요구 사항</h2>
<p>기능 요구 사항은 7가지의 알고리즘 문제를 말한다. 이 7문제에 대해서 요구 사항에 따라 적절한 기능을 구현하면 된다.</p>
<h2 id="🎯-프로그램-요구-사항">🎯 프로그램 요구 사항</h2>
<ul>
<li>JDK 11 버전에서 실행 가능해야 한다. <strong>JDK 11</strong>에서 정상적으로 동작하지 않을 경우 0점 처리한다.</li>
<li><code>build.gradle</code>을 변경할 수 없고, 외부 라이브러리를 사용하지 않는다.</li>
<li>프로그램 종료 시 <code>System.exit()</code>를 호출하지 않는다.</li>
<li>프로그램 구현이 완료되면 <code>ApplicationTest</code>의 모든 테스트가 성공해야 한다. 테스트가 실패할 경우 0점 처리한다.</li>
<li>프로그래밍 요구 사항에서 달리 명시하지 않는 한 파일, 패키지 이름을 수정하거나 이동하지 않는다.</li>
</ul>
<h2 id="✏️-과제-진행-요구-사항">✏️ 과제 진행 요구 사항</h2>
<ul>
<li>미션은 java-onboarding 저장소를 Fork &amp; Clone해 시작한다.</li>
<li>과제 진행 및 제출 방법은 프리코스 과제 제출 문서를 참고한다.</li>
</ul>
<hr>
<h1 id="🚀-problem-1">🚀 Problem 1</h1>
<p><img src="https://velog.velcdn.com/images/apple-juice/post/c5274489-cd0c-45e5-9392-b1a2901eb8bd/image.png" alt=""></p>
<h2 id="🔔-기능-목록-정리">🔔 기능 목록 정리</h2>
<ul>
<li>페이지 번호 게임을 하기 위해서 페이지 번호 검증 기능<ul>
<li>pobi와 crong에서 들어온 페이지가 1페이지 이상 400페이지 이하인지 확인</li>
<li>리스트 형태인 pobi와 crong에서 첫 요소의 값은 홀수이고, 두 번째 요소의 값은 짝수인지 확인</li>
<li>pobi, crong 둘 다 오른쪽 페이지가 왼쪽 페이지보다 값이 커야 하고, 둘의 차이가 1인지 확인</li>
</ul>
</li>
<li>페이지 번호 규칙에 따라 한 페이지에서의 페이지 번호 값을 추출기능</li>
<li>페이지 번호 검증, 게임 진행 후 pobi와 crong의 페이지 번호 게임의 결과값의 크기 비교에 따라 적당한 값 반환<h2 id="🤔-고찰의-단계-과정">🤔 고찰의 단계 과정</h2>
</li>
</ul>
<ol>
<li>페이지 번호 게임을 하기에 앞서서 pobi 또는 crong이 가진 페이지 번호들이 페이지 게임을 하기에 적절한지 검증하는 과정을 먼저 거쳐야 한다는 생각이 들었다. 내가 생각한 검증의 내용은 다음과 같다.<ul>
<li>pobi 또는 crong이 가지고 있는 페이지 정보들이 전부 1페이지 이상 400페이지 이하인지 검증</li>
<li>pobi 또는 crong이 가지고 있는 페이지 정보에서 왼쪽 페이지는 홀수, 오른쪽 페이지는 짝수이므로 pobi또는 crong이 가지고 있는 페이지 정보 중 첫 번째 인덱스는 홀수, 두 번째 인덱스는 짝수인지 검증</li>
<li>오른쪽 페이지와 왼쪽 페이지의 차이가 1인지 검증</li>
</ul>
</li>
<li>페이지 번호 게임이 가능하지 않은 경우라면 -1을 반환한다.</li>
<li>페이지 번호 게임이 가능한 경우라면 페이지 번호 게임에 따라서 pobi와 crong의 페이지 번호 게임 결과값을 추출한다.</li>
<li>만약 pobi의 페이지 번호 게임 결과가 crong의 페이지 번호 게임의 결과보다 크다면 1을 반환한다.</li>
<li>만약 pobi의 페이지 번호 게임 결과가 crong의 페이지 번호 게임의 결과보다 작다면 2을 반환한다.</li>
<li>만약 pobi의 페이지 번호 게임 결과가 crong의 페이지 번호 게임의 결과와 같다면 0을 반환한다.</li>
</ol>
<hr>
<h1 id="🚀-problem-2">🚀 Problem 2</h1>
<p><img src="https://velog.velcdn.com/images/apple-juice/post/4d50bf0f-4289-4278-a690-89a19dd8640e/image.png" alt=""></p>
<h2 id="🔔-기능-목록-정리-1">🔔 기능 목록 정리</h2>
<ul>
<li>연속된 문자가 나오는 문자열의 밤위 찾기</li>
<li>중복된 문자로 구성된 문자열을 제거<h2 id="🤔-고찰-단계-과정">🤔 고찰 단계 과정</h2>
</li>
</ul>
<ol>
<li>문자열의 시작점부터 살펴보면서 중복된 문자가 나오는 지점을 찾는다. 중복된 문자가 나오는 지점을 중복 시작점으로 잡아준다.</li>
<li>중복 문자열의 시작점부터 중복 문자가 어디까지 연속되었는지 그 끝지점을 잡아준다. 반복문을 통해서 중복 끝지점을 잡아주었다.</li>
<li>중복 시작점과 중복 끝지점을 잡아주었으므로 입력으로 들어온 기존 문자열에서 이 범위의 문자열을 제거한다.<ul>
<li>중복된 문자로 구성된 문자열이 기존 문자열의 중간 부분에 있으면 중간 부분의 문자열을 지운 후 나뉘어진 두 문자열을 서로 합쳐준다.</li>
</ul>
</li>
<li>1번 ~ 3번의 과정을 반복한다.</li>
<li>1번의 과정에서 중복 시작점을 잡지 못했다면 문자열에서 중복되는 문자가 없다는 의미이므로 현재 문자열을 반환한다.</li>
</ol>
<hr>
<h1 id="🚀-problem-3">🚀 Problem 3</h1>
<p><img src="https://velog.velcdn.com/images/apple-juice/post/bf6a32d8-54aa-4715-bffe-20b2fbbd9b3b/image.png" alt=""></p>
<h2 id="🔔-기능-목록-정리-2">🔔 기능 목록 정리</h2>
<ul>
<li>1부터 주어진 자연수까지 3, 6, 9의 출현 횟수 계산<h2 id="🤔-고찰-단계-과정-1">🤔 고찰 단계 과정</h2>
</li>
<li>단순 반복문을 활용하여 1부터 주어진 자연수까지 3, 6, 9의 출현 횟수를 계산해주었다.</li>
</ul>
<hr>
<h1 id="🚀-problem-4">🚀 Problem 4</h1>
<p><img src="https://velog.velcdn.com/images/apple-juice/post/7a3e3587-a8a9-432b-bf56-402766e401eb/image.png" alt=""></p>
<h2 id="🔔-기능-목록-정리-3">🔔 기능 목록 정리</h2>
<ul>
<li>주어진 문자열에서 특정 알파벳의 대소문자 구분 기능</li>
<li>대문자에 대응하는 청개구리 문자 추출 기능</li>
<li>소문자에 대응하는 청개구리 문자 추출 기능<h2 id="🤔-고찰-단계-과정-2">🤔 고찰 단계 과정</h2>
</li>
</ul>
<ol>
<li>문제 그림에서 사전순으로 정렬된 대문자의 배열에 대응하는 청개구리 문자의 정보를 관찰하였다.</li>
<li>이 정보를 보고 사전순 문자로 구성된 대문자의 문자열 &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;과 사전순 문자로 구성된 소문자의 문자열 &quot;abcdefghijklmnopqrstuvwxyz&quot;을 만들었다.</li>
<li>청개구리 결과 문자열을 담아주기 위해서 자바의 StringBuilder 객체를 사용하였다.<ul>
<li>StringBuilder 객체는 다음과 같이 선언이 가능하다.
  <code>StringBUilder sb = new StringBuilder();</code></li>
<li>StringBuilder의 append 메서드를 통해서 문자 또는 문자열을 추가할 수 있다.
  <code>sb.append(&#39;c&#39;)</code></li>
<li>StringBuilder 객체로 들어온 문자 또는 문자열은 배열의 형태로 문자를 저장하기 때문에 toString 메서드를 통해서 문자열로 변형을 해준다.
<code>sb.toString()</code></li>
</ul>
</li>
<li>주어진 word 문자열을 구성된 문자를 하나씩 살피면서 특정 문자가 소문자인데 대문자인지 구별하였다.</li>
<li>만약 대문자이면 대문자에 대응하는 청개구리 문자를 StringBuilder 객체에 담는다.<ul>
<li>대문자에 대응하는 청개구리 문자를 찾는 방법은 다음과 같다.<ul>
<li>예를 들어 어떤 문자 A를 살펴본다고 한다면 &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;에서 0번 인덱스를 말한다. </li>
<li>사전순 대문자열의 전체 크기는 26이므로 청개구리 문자는 25번 인덱스에 대응한다.</li>
<li>즉 청개구리 문자의 인덱스는 다음과 같이 뽑을 수가 있다.
  <code>25 - 대문자열에서 특정 문자의 인덱스 번호</code></li>
</ul>
</li>
</ul>
</li>
<li>만약 소문자이면 소문자에 대응하는 청개구리 문자를 StringBuilder 객체에 담는다.</li>
<li>소문자, 대문자도 아니면 그냥 StringBuilder 객체에 담는다.</li>
<li>StringBuilder에 담겨진 문자의 배열을 toString 메서드를 통해서 문자열로 변형해준다.</li>
</ol>
<hr>
<h1 id="🚀-problem-5">🚀 Problem 5</h1>
<p><img src="https://velog.velcdn.com/images/apple-juice/post/4b1b04e7-7645-4e2d-85a6-a50d1fb1d5a7/image.png" alt=""></p>
<h2 id="🔔-기능-목록-정리-4">🔔 기능 목록 정리</h2>
<ul>
<li>주어진 돈에 대하여 필요한 특정 돈(50000원 지폐, 10000원 지폐 등)의 개수 구하기<h2 id="🤔-고찰-단계-과정-3">🤔 고찰 단계 과정</h2>
</li>
</ul>
<ol>
<li>문제에서 필요한 돈의 개수를 최소로 해야 한다.</li>
<li>그래서 먼저 주어진 돈에 대해서 가장 큰 값을 가진 돈(50000)부터 필요한 개수를 구하는 방식을 고안하였다. </li>
<li>이를 위해서 내림차순으로 구성된 돈 정보의 배열을 만들었다.
<code>moneyList = [50000, 10000, 5000, 1000, 500, 100, 50, 10, 1]</code></li>
<li>moneyList의 첫 원소보터 주어진 돈을 나눈 몫의 정보를 담아준다. 이 정보가 곧 각 돈 당 필요한 개수이다.</li>
<li>나눈 몫을 구했으면 주어진 돈을 나눈 나머지 값으로 업데이트 한다.</li>
</ol>
<hr>
<h1 id="🚀-problem-6">🚀 Problem 6</h1>
<p><img src="https://velog.velcdn.com/images/apple-juice/post/8f8289c7-721e-409b-ac84-9c6e47cb7372/image.png" alt=""></p>
<h2 id="🔔-기능-목록-정리-5">🔔 기능 목록 정리</h2>
<ul>
<li>주어진 닉네임의 목록에서 특정 닉네임에 대한 연속으로 중복된 다른 닉네임 존재 여부 판단 기능</li>
<li>중복된 닉네임이 존재한 이메일들 사전순으로 정렬<h2 id="🤔-고찰-단계-과정-4">🤔 고찰 단계 과정</h2>
</li>
</ul>
<ol>
<li>주어진 닉네임들에 대해서 어떤 닉네임이 연속으로 중복된 다른 닉네임이 존재하는지 판단하는 기능을 먼저 고찰했다.<ul>
<li>연속 중복된 닉네임의 존재여부를 판단을 위해서 boolean형의 배열을 사용하였다. 배열 이름은 visited로 설정
<code>boolean[] visited = new boolean[forms.size()];</code></li>
<li>예를 들어서 닉네임 &quot;제이엠&quot;, &quot;제이슨&quot;, &quot;워니&quot;가 있다면 &quot;제이엠&quot;과 &quot;제이슨&quot;에서 <strong>제이</strong>가 중복이 되므로 visited는 정보는 다음과 같다.
<code>[true, true, false]</code></li>
</ul>
</li>
<li>닉네임 목록을 살피면서 연속 중복된 닉네임 검증을 위해서 내 입장에서 단순히 떠오르는 방식은 이중 반복문을 통한 확인 방법이었다.<ul>
<li>두 닉네임을 검사할 때 연속된 두 글자가 같기만 해도 두 닉네임은 중복된 글자가 있는 닉네임이라고 판단을 하였다.</li>
</ul>
</li>
<li>각 닉네임에 대하여 visited를 업데이트 한다. </li>
<li>visited의 정보를 바탕으로 중복된 닉네임끼리 이메일을 따로 리스트에 담아준다.</li>
<li>담겨진 이메일들에 대해 사전순 정렬한다.</li>
</ol>
<hr>
<h1 id="🚀-problem-7">🚀 Problem 7</h1>
<p><img src="https://velog.velcdn.com/images/apple-juice/post/ca238dbb-5bc2-4012-9d81-273d8303c18f/image.png" alt=""></p>
<h2 id="🔔-기능-목록-정리-6">🔔 기능 목록 정리</h2>
<ul>
<li>사용자의 친구 목록 담기 기능</li>
<li>사용자를 제외한 모든 사람들에 대한 점수 0점 부여 기능</li>
<li>함께 아는 친구에 대하여 점수 10점 부여 기능</li>
<li>방문자에 대하여 점수 1점 부여 기능</li>
<li>결과 정렬 기능<h2 id="🤔-고찰-단계-과정-5">🤔 고찰 단계 과정</h2>
</li>
</ul>
<ol>
<li>사용자와 함께 아는 친구의 의미가 무엇인지 처음에는 잘 이해가 가지 않았다.</li>
<li>거듭 고민을 해본 결과 나는 사용자와 함께 아는 친구에 대하여 다음과 같이 생각하였다.<ul>
<li>사용자의 직접적인 친구 관계는 아무 점수도 부여하지 않는다. (사용자 - 친구)</li>
<li>사용자의 친구의 친구 관계는 점수 10점을 부여한다. (사용자 - 친구 - 친구)</li>
</ul>
</li>
<li>사용자의 직접적인 친구는 0점을 부여해야하므로 사용자의 친구 목록 리스트에 사용자의 친구를 담았다.</li>
<li>사용자를 제외한 모든 사람들에 대하여 추천 점수를 먼저 0점으로 초기화를 진행했다. 이 때 사용한 객체는 자바의 HashMap을 사용하였다.<ul>
<li>선언 및 점수 부여 방식은 다음과 같이 진행했다.
선언: <code>Map&lt;String, Integer&gt; map = new HashMap&lt;&gt;();</code>
점수 부여: <code>map.put(&quot;name&quot;, 0);</code></li>
<li>여기서 사용자 자신은 점수를 부여할 필요가 없으므로 HashMap 목록에서 제외한다.</li>
</ul>
</li>
<li>friends에서 2번에서 고찰한 결과를 바탕으로 HashMap을 통해서 10점을 부여하였다.</li>
<li>visitors에서도 마찬가지로 HashMap을 통해서 2번에 따라 점수 1점을 부여한다.</li>
<li>HashMap에 있는 사람들마다 점수 부여를 완료했으므로 점수 기준으로 내림차순으로 HashMap을 정렬한다. <ul>
<li>HashMap의 내림차순 방식은 다음과 같다.<pre><code class="language-java">List&lt;Map.Entry&lt;String, Integer&gt;&gt; entryList = new LinkedList&lt;&gt;(map.entrySet());
entryList.sort(new Comparator&lt;Map.Entry&lt;String, Integer&gt;&gt;() {
   @Override
   public int compare(Map.Entry&lt;String, Integer&gt; o1, Map.Entry&lt;String, Integer&gt; o2) {
       return o2.getValue() - o1.getValue();
   }</code></pre>
</li>
<li>위의 방식의 코드를 줄이면 다음과 같다.<pre><code class="language-JAVA">List&lt;Map.Entry&lt;String, Integer&gt;&gt; entryList = new LinkedList&lt;&gt;(map.entrySet());
entryList.sort((o1, o2) -&gt; o2.getValue() - o1.getValue());</code></pre>
</li>
</ul>
</li>
<li>내림차순으로 정렬된 점수를 기준으로 HashMap에서 최대 5개의 이름들을 뽑아 따로 리스트로 모아준다. (단, 0점인 지점부터는 뽑지 않는다.)</li>
<li>중복된 점수 구간에 대해서 해당 구간에 속한 이름들을 사전순으로 정렬해준다.</li>
</ol>
<hr>
<h1 id="1주차-과제-후-받은-공통-피드백">1주차 과제 후 받은 공통 피드백</h1>
<h2 id="🔔-요구사항을-정확히-준수한다">🔔 요구사항을 정확히 준수한다</h2>
<p>과제 제출 전에 기능 요구 사항, 프로그래밍 요구 사항, 과제 진행 요구 사항의 항목을 모두 잘 지켰는지 다시 한 번 점검한다. </p>
<h2 id="🔔-커밋-메시지를-의미-있게-작성한다">🔔 커밋 메시지를 의미 있게 작성한다</h2>
<p>커밋 메시지에 해당 커밋에서 작업한 내용에 대한 이해가 가능하도록 작성한다.</p>
<h2 id="🔔-git을-통해-관리할-자원에-대해서도-고려한다">🔔 git을 통해 관리할 자원에 대해서도 고려한다</h2>
<p>.class 파일은 java 코드가 있으면 생성할 수 있다. 따라서 .class 파일은 굳이 git을 통해 관리하지 않아도 된다.
IntelliJ IDEA의 .idea  폴더, Eclipse의 .metadata 폴더 또한 개발 도구가 자동으로 생성하는 폴더이기 때문에 굳이 git으로 관리하지 않아도 된다.
앞으로 git에 코드를 추가할 때는 git을 통해 관리할 필요가 있는지를 고려해볼 것을 추천한다.</p>
<h2 id="🔔-pull-request를-보내기-전-브랜치를-확인한다">🔔 Pull Request를 보내기 전 브랜치를 확인한다</h2>
<p>기능 구현 작업을 fork된 Repository의 main branch가 아닌, 기능 구현을 위해 새로 만든 브랜치에서 작업한 후 PR을 보낸다. </p>
<h2 id="🔔-pr을-한-번-작성했다면-닫지-말고-추가-커밋을-한다">🔔 PR을 한 번 작성했다면 닫지 말고 추가 커밋을 한다</h2>
<p>PR을 이미 한 번 보냈다면, 새로운 PR을 생성할 필요가 없다. 수정이 필요하다면 추가 커밋을 하면 자동으로 반영된다. 단, 미션 제출 기간 이후에는 추가 커밋을 하지 않는다.</p>
<h2 id="🔔-이름을-통해-의도를-드러낸다">🔔 이름을 통해 의도를 드러낸다</h2>
<p>나 자신, 다른 개발자와의 소통을 위해 가장 중요한 활동 중의 하나가 좋은 이름 짓기이다. 변수 이름, 함수(메서드) 이름, 클래스 이름을 짓는데 시간을 투자하라. 이름을 통해 변수의 역할, 함수의 역할, 클래스의 역할에 대한 의도를 드러내기 위해 노력하라. 연속된 숫자를 덧붙이거나(a1, a2, ..., aN), 불용어(Info, Data, a, an, the)를 추가하는 방식은 적절하지 못하다.</p>
<h2 id="🔔-축약하지-않는다">🔔 축약하지 않는다</h2>
<p>의도를 드러낼 수 있다면 이름이 길어져도 괜찮다.</p>
<p>누구나 실은 클래스, 메서드, 또는 변수의 이름을 줄이려는 유혹에 곧잘 빠지곤 한다. 그런 유혹을 뿌리쳐라. 축약은 혼란을 야기하며, 더 큰 문제를 숨기는 경향이 있다. 클래스와 메서드 이름을 한 두 단어로 유지하려고 노력하고 문맥을 중복하는 이름을 자제하자. 클래스 이름이 Order라면 shipOrder라고 메서드 이름을 지을 필요가 없다. 짧게 ship()이라고 하면 클라이언트에서는 order.ship()라고 호출하며, 간결한 호출의 표현이 된다. </p>
<ul>
<li>객체 지향 생활 체조 원칙 5: 줄여쓰지 않는다 (축약 금지)<h2 id="🔔-공백도-코딩-컨벤션이다">🔔 공백도 코딩 컨벤션이다</h2>
if, for, while문 사이의 공백도 코딩 컨벤션이다.<h2 id="🔔-공백-라인을-의미-있게-사용한다">🔔 공백 라인을 의미 있게 사용한다</h2>
공백 라인을 의미 있게 사용하는 것이 좋아 보이며, 문맥을 분리하는 부분에 사용하는 것이 좋다. 과도한 공백은 다른 개발자에게 의문을 줄 수 있다.<h2 id="🔔-space와-tab을-혼용하지-않는다">🔔 space와 tab을 혼용하지 않는다</h2>
들여쓰기에 space와 tab을 혼용하지 않는다. 둘 중에 하나만 사용한다. 확신이 서지 않으면 pull request를 보낸 후 들여쓰기가 잘 되어 있는지 확인하는 습관을 들인다.<h2 id="🔔-의미-없는-주석을-달지-않는다">🔔 의미 없는 주석을 달지 않는다</h2>
변수 이름, 함수(메서드) 이름을 통해 어떤 의도인지가 드러난다면 굳이 주석을 달지 않는다. 모든 변수와 함수에 주석을 달기보다 가능하면 이름을 통해 의도를 드러내고, 의도를 드러내기 힘든 경우 주석을 다는 연습을 한다.<h2 id="🔔-ide의-코드-자동-정렬-기능을-활용한다">🔔 IDE의 코드 자동 정렬 기능을 활용한다</h2>
IDE의 코드 자동 정렬 기능을 사용하면 더 깔끔한 코드를 볼 수 있다.</li>
</ul>
<p>IntelliJ IDEA: ⌥⌘L, Ctrl+Alt+L
Eclipse: ⇧⌘F, Ctrl+Shift+F</p>
<h2 id="🔔-java에서-제공하는-api를-적극-활용한다">🔔 Java에서 제공하는 API를 적극 활용한다</h2>
<p>함수(메서드)를 직접 구현하기 전에 Java API에서 제공하는 기능인지 검색을 먼저 해본다.
Java API에서 제공하지 않을 경우 직접 구현한다.
예를 들어 사용자를 출력할 때 사용자가 2명 이상이면 쉼표(,) 기준으로 출력을 위한 문자열은 다음과 같이 구현 가능하다.</p>
<pre><code class="language-JAVA">List&lt;String&gt; members = Arrays.asList(&quot;pobi&quot;, &quot;jason&quot;);
String result = String.join(&quot;,&quot;, members); // &quot;pobi,jason&quot;</code></pre>
<h2 id="🔔-배열-대신-java-collection을-사용한다">🔔 배열 대신 Java Collection을 사용한다</h2>
<p>Java Collection 자료구조(List, Set, Map 등)를 사용하면 데이터를 조작할 때 다양한 API를 사용할 수 있다.
예를 들어 List<String>에 &quot;pobi&quot;라는 값이 포함되어 있는지는 다음과 같이 확인할 수 있다.</p>
<pre><code class="language-JAVA">List&lt;String&gt; members = Arrays.asList(&quot;pobi&quot;, &quot;jason&quot;);
boolean result = members.contains(&quot;pobi&quot;); // true</code></pre>
<h1 id="소감">소감</h1>
<p>문제를 설계하고 코드를 작성하면서 코드 리펙토링에 대한 필요성을 느껴 코드 리펙토링에 대한 습관과 가독성을 위해서 좋은 네이밍 습관을 들여야겠다는 생각도 들었다.</p>
<p>이것저것 시행착오를 겪으면서 내 자신의 코딩 습관에 대한 피드백을 스스로 가질 수 있는 의미 있는 주차였던 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[우아한테크코스 5기 도전기]]></title>
            <link>https://velog.io/@apple-juice/%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4-5%EA%B8%B0-%EB%8F%84%EC%A0%84%EA%B8%B0</link>
            <guid>https://velog.io/@apple-juice/%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4-5%EA%B8%B0-%EB%8F%84%EC%A0%84%EA%B8%B0</guid>
            <pubDate>Thu, 27 Oct 2022 06:33:02 GMT</pubDate>
            <description><![CDATA[<h1 id="오리엔테이션">오리엔테이션</h1>
<p><img src="https://velog.velcdn.com/images/apple-juice/post/92c8ebd3-a698-4ce5-be5a-dba1707d6a9c/image.png" alt=""></p>
<p> 우아한테크코스를 지원 후 2022년 10월 26일 우아한테크코스 5기 오리엔테이션을 들었다. 오리엔테이션에서는 우아한테크코스 과정에 대한 소개와 질의 응답 시간을 가졌는데 그런 시간들을 가지면서 내게는 정말 유익한 정보들을 얻을 수 있었던 것 같다.</p>
<h2 id="코딩테스트-없는-프리코스-과정">코딩테스트 없는 프리코스 과정</h2>
<p> 이번 우테코 5기에서는 <strong>프리코스에 들어가기 위한 별도의 코딩테스트 과정을 거치지 않는다.</strong> 그래서 지난 기수에 비해서 이번 프리코스의 참가자들 수가 꽤 많았다. 그만큼 본과정 진출도 많이 힘들어질 수도 있을 것 같다는 생각에 긴장 풀지 말고 항상 나태해지지 말고 더 열심히 해야겠다는 생각이 들었다.</p>
<h2 id="프리코스-교육의-목적">프리코스 교육의 목적</h2>
<p> 프리코스에서의 가장 큰 목적은 읽기 좋은 프로그래밍 코드를 만들고, 유지보수에 대한 역량을 기르는 것에 있다. 수많은 프로그래밍 교육기관이 있지만 그만큼 유지보수 등 효율적으로 가르치는 교육기관이 별로 없는 느낌을 받았는데 이번 우아한테크코스 프리코스를 통해서 나도 그런 역량들을 가질 수 있을 것 같다는 기대감이 든다.</p>
<h2 id="커뮤니케이션">커뮤니케이션</h2>
<p>  개발은 혼자만의 것이 아니다. 내가 쓴 프로그래밍 코드가 항상 옳은 코드는 아닐 수 있으므로 항상 피드백이 필요하다. 이번 프리코스에서 제공하는 미션을 통해서 동료들과의 소통 및 토론을 통해서 함께 과정을 해결하고, 더 나은 피드백을 받을 수 있도록 소통의 장을 이번 기수에서 더 많이 마련한 것 같다.</p>
<h2 id="앞으로의-다짐">앞으로의 다짐</h2>
<p>항상 정해진 계획을 지키려고 노력하고 개발을 게을리하지 않으며 미션을 잘 수행할 수 있도록 하고, 더 나은 나를 만들 수 있도록 해야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[aws] 아마존 웹서비스 mac으로 ssh를 통한 간단 접속하기]]></title>
            <link>https://velog.io/@apple-juice/aws-%EC%95%84%EB%A7%88%EC%A1%B4-%EC%9B%B9%EC%84%9C%EB%B9%84%EC%8A%A4-mac%EC%9C%BC%EB%A1%9C-ssh%EB%A5%BC-%ED%86%B5%ED%95%9C-%EA%B0%84%EB%8B%A8-%EC%A0%91%EC%86%8D%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@apple-juice/aws-%EC%95%84%EB%A7%88%EC%A1%B4-%EC%9B%B9%EC%84%9C%EB%B9%84%EC%8A%A4-mac%EC%9C%BC%EB%A1%9C-ssh%EB%A5%BC-%ED%86%B5%ED%95%9C-%EA%B0%84%EB%8B%A8-%EC%A0%91%EC%86%8D%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 25 Aug 2022 10:03:24 GMT</pubDate>
            <description><![CDATA[<p> 아마존 웹서비스에서 새로운 인스턴스를 만들고 mac 환경에서 터미널을 열고 인스턴스의 서버로 연결을 하는 단계이다. 이 글은 왜 이렇게 설정을 해야 하는지 원리 설명은 따로 안하고 서버를 접속할 수 있는 방법들 위주로 설명을 할 것이다. 추가적으로 궁금한 내용들은 구글링을 통해서 찾아보는 것을 추천한다. </p>
<hr>
<h2 id="mac을-통한-인스턴스-서버의-접속-방법">mac을 통한 인스턴스 서버의 접속 방법</h2>
<ol>
<li>만들어진 인스턴스의 아이디를 클릭해서 인스턴스 정보로 이동한다.그림에서 connect를 클릭 <img src="https://velog.velcdn.com/images/apple-juice/post/547c7563-a76b-404c-997c-f32c6c083606/image.png" alt=""></li>
<li>ssh client로 들어간다.
<img src="https://velog.velcdn.com/images/apple-juice/post/547c7563-a76b-404c-997c-f32c6c083606/image.png" alt=""></li>
<li>mac에서 터미널을 열고, <code>cd ~/.ssh</code>를 입력하여 .ssh 디렉토리로 이동. 필자의 경우는 iterm2를 사용한다. 그리고 <code>ls -al</code>명령어를 통해서 인스턴스에서 받은 pem 키가 있는지 확인한다. 만약 없다면 인스턴스를 만들었을 때 새로 키를 발급받았다면 Downloads 디렉토리로 가서 해당 키를 .ssh 디렉토리로 옮겨준다. 참고로 보통은 <code>mv (받은 키 경로) (.ssh 경로)</code>명령어로 키를 옮길 수가 있다.
<img src="https://velog.velcdn.com/images/apple-juice/post/2a9ff7a5-fbf2-4834-ab26-69388592cddf/image.png" alt=""></li>
<li>이제 2번의 그림에서 3번의 내용을 복사해서 터미널에 붙여넣기 해주고, Example에 있는 명령어를 복사 붙여넣기를 진행해서 서버가 잘 접속 되는지 확인한다.</li>
<li>접속이 되는 경우도 있지만 접속이 안되는 경우도 있다! 그럴 때는 Example이 적혀있는 명령어 앞에 <code>sudo</code>를 붙여서 실행을 해보면 실행이 될 것이다. </li>
<li>만약 이런 상황에도 실행이 안된다면 아쉽지만 인스턴스를 다시 만들어야 할 것 같다. 필자 같은 경우는 인스턴스를 다시 만들었다.</li>
</ol>
<hr>
<h2 id="mac-터미널로-좀-더-간단하게-서버에-접속하기">mac 터미널로 좀 더 간단하게 서버에 접속하기</h2>
<h3 id="기본-과정">기본 과정</h3>
<ol>
<li>&quot;.ssh&quot; 디렉토리로 이동한다. 이 디렉토리에서 config파일을 열어서 내용을 추가해준다. 만약에 config 파일이 존재하지 않다면 <code>vi config</code> 또는 <code>nano config</code>명령어를 통해서 config파일의 내용을 수정해준다. 필자는 전자의 명령어로 내용을 수정하였다. 아래 그림은 config의 내용이다. -&gt; <code>cat config</code>를 통해서 config의 내용을 출력했다. #은 주석 내용으로 신경 안 써도 된다.
<img src="https://velog.velcdn.com/images/apple-juice/post/cc7bea4e-11bf-45a8-a5f1-586db4696d0e/image.png" alt=""></li>
</ol>
<ul>
<li>Host부분에 자신이 변경하고 싶은 명령어를 입력하는 부분이다. 예를 들어서 <code>Host temp</code>라고 내용을 입력했으면 서버 접속 시 <code>ssh temp</code>를 입력하면 서버로 접속할 수가 있다.</li>
<li>Hostname 부분에는 자신이 만든 aws 서버의 ip 주소를 입력한다. 만약 탄력적 ip 주소를 등록했다면 탄력적 ip를 입력하도록 한다.</li>
<li>User부분에는 만든 인스턴스의 사용자 이름을 입력한다. 만약 인스턴스를 설정시 ubuntu로 만들어주었다면 ubuntu로 입력을 해주면 된다.</li>
<li>마지막으로 IdentityFile 부분에는 자신이 만든 pem 키의 위치를 지정하면 된다.</li>
</ul>
<ol start="2">
<li>이제 어느 디렉토리에서든 <code>ssh (자신이 만든 명령어 이름)</code>을 통해서 서버 접속을 할 수가 있다.</li>
<li>하지만 이 방법으로도 접속이 안되는 경우가 있다. 그 경우는 &quot;mac을 통한 인스턴스 서버의 접속 방법&quot;의 5번의 <code>sudo</code>를 통한 접속 경우이다.</li>
</ol>
<h3 id="sudo-권한-없이-서버-접속할-수-있도록-설정하기">sudo 권한 없이 서버 접속할 수 있도록 설정하기</h3>
<ol>
<li><p>먼저 sudo를 통한 서버 접속(&quot;mac을 통한 인스턴스 서버의 접속 방법&quot;의 5번)을 하고 <code>cd /etc/ssh</code>로 이동하고 <code>ls -al</code>을 통해서 파일들을 확인해준다. 다양한 파일들이 나오는데 여기서 이 파일의 내용을 봐야한다.<img src="https://velog.velcdn.com/images/apple-juice/post/1073a15a-ee8a-415e-afb3-320bc4b43810/image.png" alt="">
검은색으로 칠해져 있는 부분은 숫자이다.</p>
</li>
<li><p>맨 마지막에 &quot;root@ip주소&quot; 부분이 있는데 이 내용을 제외한 그 전의 내용들을 전부 복사해준다. </p>
</li>
<li><p><code>exit</code>명령어를 통해서 서버를 나와 로컬로 돌아온다. &quot;.ssh&quot;디렉토리에서 &quot;known_hosts&quot;파일을 찾는다.<img src="https://velog.velcdn.com/images/apple-juice/post/0616fac8-203f-4a78-aa57-91794c6f6121/image.png" alt=""></p>
</li>
<li><p><code>vi known_hosts</code>로 서버에서 복사한 내용들을 맨 밑에 추가해준다. (필자는 known_hosts의 적혀있는 내용들의 맨 마지막에 추가했다.) 그리고 추가한 내용의 앞에다 자신이 만들어준 자신이 만든 인스턴스의 ip 주소를 입력해준다!</p>
</li>
</ol>
<p>-&gt; <code>&quot;인스턴스 ip주소(탄력적 ip 주소가 존재하면 탄력적 ip입력)&quot; &quot;복사한 내용&quot;</code>
5. <code>:wq</code>를 통해서 저장을 하고 자신이 받은 pem 키의 권한 변경을 해야한다! 
-&gt; <code>chmod 600 (자신의 pem 키)</code>
6. 이제 <code>ssh (자신이 만든 명령어)</code>를 통해서 접속을 시도해보면 접속이 잘 되는 것을 확인할 수가 있다!<img src="https://velog.velcdn.com/images/apple-juice/post/d123ae50-b1cf-48b2-8578-c80c2cb55eeb/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring의 등장]]></title>
            <link>https://velog.io/@apple-juice/Spring-%EB%93%B1%EC%9E%A5</link>
            <guid>https://velog.io/@apple-juice/Spring-%EB%93%B1%EC%9E%A5</guid>
            <pubDate>Tue, 19 Jul 2022 14:29:44 GMT</pubDate>
            <description><![CDATA[<h2 id="spring의-등장-배경">spring의 등장 배경</h2>
<ul>
<li><p>2000년대 초반, 이 당시 개발자들은 java의 Enterprise Java Beans(EJB)를 사용했었음</p>
</li>
<li><p>EJB는 애플리케이션의 비즈니스 로직을 캡슐화하는 서버 측 소프트웨어 구성요소임</p>
</li>
<li><p>하지만 EJB의 복잡성(그리고 EJB로직에 의존하며 코드를 짜야 하는 경우가 많았음), 느린 속도 때문에 EJB의 단점이 부각.</p>
</li>
<li><p>그런 단점 때문에 다시 간단한 자바 오브젝트를 사용했던 시절로 돌아가고 싶은 개발자들이 많았다. </p>
</li>
<li><blockquote>
<p><strong>Plain Old Java Object(POJO)</strong></p>
</blockquote>
</li>
<li><p>이에 <strong>로드 존슨</strong>이 EJB의 문제점을 비판하고 이를 해결하기 위한 오픈소스를 담은 책을 발간 
-&gt; 이 때 많은 개발자들이 로드 존슨의 오픈소스를 많이 사용하였다고 한다. 
-&gt; 로드 존슨이 발간한 책에는 스프링 핵신 개념과 기반 코드가 들어 있다. </p>
</li>
<li><p>유겐 휠러, 얀 카로프가 로드 존슨에게 오픈소스 프로젝트를 제안.</p>
</li>
<li><p>얀 카로프는 <strong>J2EE(EJB) 겨울을 넘어 새롭게 시작하자는 의미</strong>로 프로젝트 이름을 <strong>spring으로 지었다.</strong> </p>
</li>
</ul>
<h2 id="문맥에-따른-spring의-의미">문맥에 따른 spring의 의미</h2>
<ul>
<li>스프링은 문맥에 따라 다음과 같은 의미를 가지고 있음
-&gt; 스프링 DI 컨테이너 기술(spring의 핵심이다)
-&gt; 스프링 프레임워크
-&gt; 스프링 부트, 스프링 프레임워크 등을 모두 포함한 스프링 생태계</li>
</ul>
<h2 id="spring-존재의-핵심">spring 존재의 핵심</h2>
<ul>
<li>당시 java에서 EJB를 사용하려면 <strong>EJB의 있는 기능들에 의존해서 코드를 짜야했음</strong></li>
<li><strong>의존</strong>해서 코드를 짜게 되면 <strong>객체 지향 언어가 가지는 의미가 사라지게 됨</strong></li>
<li><strong>spring</strong>은 <strong>객체 지향 언어가 가진 강력한 특징을 살려낸 프레임워크</strong>이다. 
-&gt; 객체 간의 종속이 없다. </li>
<li>그 때문에 <strong>좋은 객체 지향 애플리케이션을 개발할 수 있도록 도와줌</strong></li>
</ul>
<h2 id="spring-framework의-기술-소개">Spring Framework의 기술 소개</h2>
<h3 id="🔔-스프링의-핵심-기술-스프링-di-컨테이너-aop-이벤트">🔔 스프링의 핵심 기술: 스프링 DI 컨테이너, AOP, 이벤트</h3>
<h3 id="🔔-웹-기술-스프링-mvc-스프링-webflux">🔔 웹 기술: 스프링 MVC, 스프링 WebFlux</h3>
<h3 id="🔔-데이터-접근-기술-트랜잭션-jdbc-orm-지원-xml-지원">🔔 데이터 접근 기술: 트랜잭션, JDBC, ORM 지원, XML 지원</h3>
<h3 id="🔔-기술-통합-캐시-이메일-원격접근-스케줄링">🔔 기술 통합: 캐시, 이메일, 원격접근, 스케줄링</h3>
<h3 id="🔔-테스트-스프링-기반-테스트-지원">🔔 테스트: 스프링 기반 테스트 지원</h3>
<h3 id="🔔-언어-코틀린-그루비">🔔 언어: 코틀린, 그루비</h3>
<h2 id="spring-boot-소개">Spring Boot 소개</h2>
<h3 id="✅-스프링의-다양한-기능들을-편리하게-사용할-수-있도록-지원한다">✅ 스프링의 다양한 기능들을 편리하게 사용할 수 있도록 지원한다.</h3>
<h3 id="✅-tomcat과-같은-웹-서버를-내장하므로-별도로-tomcat을-설치할-필요가-없다">✅ Tomcat과 같은 웹 서버를 내장하므로 별도로 Tomcat을 설치할 필요가 없다.</h3>
<h3 id="✅-손쉬운-빌드-구성을-위해-starter-종속성을-제공한다">✅ 손쉬운 빌드 구성을 위해 starter 종속성을 제공한다.</h3>
<ul>
<li>스프링 프레임워크를 사용할 때 사용해야할 라이브러리들이 다양한데 starter를 통해서 필요한 라이브러리들을 전부 가져올 수가 있다.<h3 id="✅-스프링과-3rd-parth외부-라이브러리-자동-구성한다">✅ 스프링과 3rd parth(외부) 라이브러리 자동 구성한다.</h3>
</li>
<li>스프링 프레임워크 버젼마다 적용해야할 라이브러리들이 다를 수가 있는데 스프링부트는 스프링프레임워크의 버젼과 외부 라이브러리들과의 궁합을 직접 테스트해주고 적절한 버젼을 뽑아내주는 역할을 한다.<h3 id="✅-메트릭-상태-확인-외부-구성-같은-프로덕션-준비-기능-제공한다">✅ 메트릭, 상태 확인, 외부 구성 같은 프로덕션 준비 기능 제공한다.</h3>
<h3 id="✅-관례에-의한-간결한-설정을-해준다">✅ 관례에 의한 간결한 설정을 해준다.</h3>
</li>
<li>스프링프레임워크에 대한 사전 설정의 복잡성을 해소해준다.</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>