<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>c-hano.log</title>
        <link>https://velog.io/</link>
        <description>꼬질이</description>
        <lastBuildDate>Fri, 25 Apr 2025 09:53:40 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>c-hano.log</title>
            <url>https://velog.velcdn.com/images/c-hano/profile/da85a01d-9505-4201-a862-9215bf31dd02/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. c-hano.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/c-hano" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[백준] 1264. 모음의 개수]]></title>
            <link>https://velog.io/@c-hano/%EB%B0%B1%EC%A4%80-1264.-%EB%AA%A8%EC%9D%8C%EC%9D%98-%EA%B0%9C%EC%88%98</link>
            <guid>https://velog.io/@c-hano/%EB%B0%B1%EC%A4%80-1264.-%EB%AA%A8%EC%9D%8C%EC%9D%98-%EA%B0%9C%EC%88%98</guid>
            <pubDate>Fri, 25 Apr 2025 09:53:40 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/c-hano/post/d4148a4e-8b2a-40d5-b6bd-2ad968b4a759/image.png" alt=""></p>
<hr>
<ol>
<li>&quot;#&quot; 이 나오기전까진 while 반복문을 사용하여야한다.</li>
<li>입력된 string 중에서 모음 (a,e,i,o,u)의 개수를 세어야한다.</li>
<li>대문자 소문자 상관없이 모음의 개수를 세어야한다.</li>
</ol>
<br>

<p>1번을 만족하기 위해 while 반복문을 작성하고 &quot;#&quot;을 입력받으면 반복문이 종료 된다.</p>
<pre><code class="language-java">while(true) {
    Scanner sc = new Scanner(System.in);
    String str = sc.nextLine();

    if(str.equals(&quot;#&quot;))
    break;
}</code></pre>
<br>

<p>2번을 만족하기 위해 조건문을 추가해보자. 입력받은 String을 char단위로 점검해가며 모음일 경우 count가 올라간다.</p>
<pre><code class="language-java">while(true) {
    Scanner sc = new Scanner(System.in);
    String str = sc.nextLine();

    if(str.equals(&quot;#&quot;))
    break;

    int count = 0;
       for(int i = 0 ; i &lt; str.length(); i++) {
        if(
        str.charAt(i) == &#39;a&#39; || 
        str.charAt(i) == &#39;e&#39; ||
        str.charAt(i) == &#39;o&#39; ||
        str.charAt(i) == &#39;i&#39; ||
        str.charAt(i) == &#39;u&#39;)
        count ++;
    }
    System.out.println(count);
}</code></pre>
<br>

<p>3번을 만족하기 위해 입력받은 String을 소문자(대문자)로 바꾼다.</p>
<pre><code class="language-java">while(true) {
    Scanner sc = new Scanner(System.in);
    String str = sc.nextLine();
    str = str.toLowerCase();

    if(str.equals(&quot;#&quot;))
    break;

    int count = 0;
       for(int i = 0 ; i &lt; str.length(); i++) {
        if(
        str.charAt(i) == &#39;a&#39; || 
        str.charAt(i) == &#39;e&#39; ||
        str.charAt(i) == &#39;o&#39; ||
        str.charAt(i) == &#39;i&#39; ||
        str.charAt(i) == &#39;u&#39;) {
        count ++;
        }
    }
    System.out.println(count);
}</code></pre>
<br>

<h4 id="정답">정답</h4>
<pre><code class="language-java">import java.util.*;

public class Main {

    public static void main(String[] args) {

        while (true) {
            Scanner sc = new Scanner(System.in);

            String str = sc.nextLine();
            str = str.toLowerCase();

            int count = 0;
            if(str.equals(&quot;#&quot;))
                break;

            for (int i = 0; i &lt; str.length(); i++) {
                if(
                str.charAt(i)==&#39;a&#39; ||
                str.charAt(i)==&#39;i&#39; ||
                str.charAt(i)==&#39;o&#39; ||
                str.charAt(i)==&#39;u&#39; ||
                str.charAt(i)==&#39;e&#39;){
                    count++;
                }
            }
            System.out.println(count);
        }
    }
}</code></pre>
<h5 id="참고">&lt;참고&gt;</h5>
<ol>
<li>.toLowerCase() : 전부 소문자로 만들기</li>
<li>.toUpperCase() : 전부 대문자로 만들기</li>
<li>.charAt() : String 타입을 char형태로 바꿔주는 명령어 () 안의 숫자에 해당하는 글자를 반환한다. ex. String str = &quot;안녕하세요&quot; str.charAt(0) == &quot;안&quot;</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 2439. 별 찍기 - 2]]></title>
            <link>https://velog.io/@c-hano/%EB%B0%B1%EC%A4%80-2439.-%EB%B3%84-%EC%B0%8D%EA%B8%B0-2</link>
            <guid>https://velog.io/@c-hano/%EB%B0%B1%EC%A4%80-2439.-%EB%B3%84-%EC%B0%8D%EA%B8%B0-2</guid>
            <pubDate>Fri, 25 Apr 2025 01:33:32 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/c-hano/post/baae50f9-b91e-4f0b-bc68-793be63056e0/image.png" alt=""></p>
<hr>
<ol>
<li>입력된 값만큼의 줄이 있어야한다.</li>
<li>n번째 줄엔 입력된 값 -n 만큼의 공백을 입력해야한다.</li>
<li>n번째 줄엔 n개 만큼의 *을 입력해야한다.</li>
</ol>
<br>

<p>우선 1번을 만족하는 for 반복문을 작성해보자.</p>
<pre><code class="language-java">Scanner sc = new Scanner(System.in);
int a = sc.nextInt();

for(int i = 1; i &lt;= a; i++) {
    System.out.println();
}</code></pre>
<br>

<p>다음은 2번을 만족하는 for 반복문을 내부에 작성해보자.</p>
<pre><code class="language-java">Scanner sc = new Scanner(System.in);
int a = sc.nextInt();

for(int i = 1; i &lt;= a; i++) {
    for(int j = 1; j &lt;= a - i; j++){
        System.out.println(&quot; &quot;);
    }
    System.out.println();
}</code></pre>
<br>

<p>마지막으로 3번을 만족하는 for 반복문을 내부에 작성해보자.</p>
<pre><code class="language-java">Scanner sc = new Scanner(System.in);
int a = sc.nextInt();

for(int i = 1; i &lt;= a; i++) {
    for(int j = 1; j &lt;= a - i; j++){
        System.out.print(&quot; &quot;);
    }
    for(int k = 1; k &lt;= i; k++){
        System.out.print(&quot;*&quot;);
    }
    System.out.println();
}</code></pre>
<br>

<p>초반에 for문은 하나의 중첩만 가능한 줄 알고 for문을 안으로 안으로 넣었다...</p>
<pre><code class="language-java">Scanner sc = new Scanner(System.in);
int a = sc.nextInt();

for (int i = 1; i &lt;= a; i++) {
    for (int j = 1; j &lt;= i; j++) {
        for (int k = 1; k &lt;= a - i; k++) {
            if(j &gt; 1) {
                continue;
            }
            System.out.print(&quot; &quot;);
        }
        System.out.print(&quot;*&quot;);
        }
    System.out.println();
}</code></pre>
<p>이래도 통과되긴 했지만 코드가 한번에 보기 쉽지 않다. for문 안에 여러개의 for문을 사용할 수 있다는 것을 알아두자.</p>
<hr>
<h4 id="정답">정답</h4>
<pre><code class="language-java">import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int a = sc.nextInt();

        for(int i = 1; i &lt;= a; i++) {
            for(int j = 1; j &lt;= a - i; j++){
                System.out.print(&quot; &quot;);
            }
            for(int k = 1; k &lt;= i; k++){
                System.out.print(&quot;*&quot;);
            }
            System.out.println();
        }
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 2743. 단어 길이 재기]]></title>
            <link>https://velog.io/@c-hano/%EB%B0%B1%EC%A4%80-2743.-%EB%8B%A8%EC%96%B4-%EA%B8%B8%EC%9D%B4-%EC%9E%AC%EA%B8%B0</link>
            <guid>https://velog.io/@c-hano/%EB%B0%B1%EC%A4%80-2743.-%EB%8B%A8%EC%96%B4-%EA%B8%B8%EC%9D%B4-%EC%9E%AC%EA%B8%B0</guid>
            <pubDate>Thu, 24 Apr 2025 13:37:01 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/c-hano/post/bde4118a-db35-4e4a-b294-58c31ec9c797/image.png" alt=""></p>
<hr>
<h4 id="참고">참고</h4>
<p>String값을 입력 받을 경우 : .nextLine();
String의 문자열의 길이를 재는 명령어 : .length();</p>
<h4 id="정답">정답</h4>
<pre><code class="language-java">import java.util.* ;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();

        System.out.println(s.length());
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 2741. N 찍기]]></title>
            <link>https://velog.io/@c-hano/%EB%B0%B1%EC%A4%80-2741.-N-%EC%B0%8D%EA%B8%B0</link>
            <guid>https://velog.io/@c-hano/%EB%B0%B1%EC%A4%80-2741.-N-%EC%B0%8D%EA%B8%B0</guid>
            <pubDate>Thu, 24 Apr 2025 13:31:22 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/c-hano/post/21700e51-127e-4eb4-b237-af63f7ccb674/image.png" alt=""></p>
<hr>
<p>반복문 기초 문제.</p>
<h4 id="정답">정답</h4>
<pre><code class="language-java">import java.util.*;

public class Main {
    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        int a;

        a = sc.nextInt();
        for(int i = 1 ; i &lt;= a; i++) {
            System.out.println(i);
        }
    }
}</code></pre>
<p>간단!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 2739. 구구단]]></title>
            <link>https://velog.io/@c-hano/%EB%B0%B1%EC%A4%80-2739.-%EA%B5%AC%EA%B5%AC%EB%8B%A8</link>
            <guid>https://velog.io/@c-hano/%EB%B0%B1%EC%A4%80-2739.-%EA%B5%AC%EA%B5%AC%EB%8B%A8</guid>
            <pubDate>Thu, 24 Apr 2025 11:51:53 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/c-hano/post/c35ae69d-c73c-405b-aedb-6ac8fa622ec8/image.png" alt=""></p>
<hr>
<ol>
<li>N을 입력 받는다.</li>
<li>입력받은 N의 수를 구구단의 형태로 출력한다.</li>
</ol>
<pre><code class="language-java">import java.util.*;

public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int a;
        a = sc.nextInt();
        for (int i = 1; i &lt; 10; i ++) {
            System.out.println(a + &quot; * &quot; + i + &quot; = &quot; + (a*i));
        }
    }
}</code></pre>
<p>문제가 요구하는 공백을 신경쓰자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 2475. 검증수]]></title>
            <link>https://velog.io/@c-hano/%EB%B0%B1%EC%A4%80-2475.-%EA%B2%80%EC%A6%9D%EC%88%98</link>
            <guid>https://velog.io/@c-hano/%EB%B0%B1%EC%A4%80-2475.-%EA%B2%80%EC%A6%9D%EC%88%98</guid>
            <pubDate>Thu, 24 Apr 2025 09:52:41 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/c-hano/post/0f7946b0-7305-461f-a387-639f23a014f3/image.png" alt=""></p>
<hr>
<ol>
<li>5개의 숫자를 입력 받아야함</li>
<li>각각의 숫자의 제곱을 하고 합을 구해야함</li>
<li>합을 10으로 나눈 나머지를 구해야함</li>
</ol>
<p>5개의 숫자를 입력 받기.</p>
<pre><code class="language-java">Scanner sc = new Scanner(System.in);
int[] numbers = new int[5];
for(int i = 0; i &lt; 5; i++) {
  numbers[i] = sc.nextInt();
}</code></pre>
<p>각각의 숫자의 제곱을 하고 합을 구하기.</p>
<pre><code class="language-java">int sum = 0;

Scanner sc = new Scanner(System.in);
int[] numbers = new int[5];
for(int i = 0; i &lt; 5; i++) {
  numbers[i] = sc.nextInt();
  sum += numbers[i] * numbers[i]
}</code></pre>
<p>합을 10으로 나눈 나머지를 구하기.</p>
<pre><code class="language-java">int sum = 0;

Scanner sc = new Scanner(System.in);
int[] numbers = new int[5];
for(int i = 0; i &lt; 5; i++) {
  numbers[i] = sc.nextInt();
  sum += numbers[i] * numbers[i]
}

int answer = sum % 10;</code></pre>
<hr>
<h4 id="정답">정답</h4>
<pre><code class="language-java">import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int[] numbers = new int[5];
        int sum = 0;

        for(int i = 0; i &lt; 5; i++) {
            numbers[i] = sc.nextInt();
            sum += numbers[i] * numbers[i];
        }

        int answer = sum % 10;
        System.out.println(answer); 
   }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 2438. 별 찍기 - 1]]></title>
            <link>https://velog.io/@c-hano/%EB%B0%B1%EC%A4%80-2438.-%EB%B3%84-%EC%B0%8D%EA%B8%B0-1</link>
            <guid>https://velog.io/@c-hano/%EB%B0%B1%EC%A4%80-2438.-%EB%B3%84-%EC%B0%8D%EA%B8%B0-1</guid>
            <pubDate>Thu, 24 Apr 2025 03:00:17 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/c-hano/post/8e109a19-5096-44f5-8e1a-5444bdddd2eb/image.png" alt=""></p>
<hr>
<p>중복 for 문을 사용하여 문제를 해결해보자.</p>
<p>첫번째 줄에는 <code>*</code> 이 하나
두번째 줄에는 <code>*</code> 이 두개
(입력받은) N번째 줄에는 <code>*</code> 이 N개 ...</p>
<p>우선 N번째 줄을 설정하는 식을 입력해보자.</p>
<pre><code class="language-java">Scanner sc = new Scanner(System.in);
int N = sc.nextInt();

for(int a = 1; a &lt;= N; a++) {}</code></pre>
<p>입력받은 N만큼 for문이 반복된다.</p>
<p>그럼 그 안에 N번째 줄에 <code>*</code>을 출력하는 식을 설정해보자.</p>
<pre><code class="language-java">Scanner sc = new Scanner(System.in);
int N = sc.nextInt();

for(int a = 1; a &lt;= N; a++) {
    for(int j = 1; j &lt;= a; j++) {
        System.out.print(&quot;*&quot;);
    }
    System.out.println();
}</code></pre>
<p>N번째 줄에서 N만큼의 <code>*</code>이 출력되고 줄바꿈이 되는 것을 알 수 있다</p>
<hr>
<h4 id="정답">정답</h4>
<pre><code class="language-java">import java.util.*;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int N = sc.nextInt();

        for (int i = 1; i &lt;= N; i++) {
            for (int j = 1; j &lt;= i; j++) {
                System.out.print(&quot;*&quot;);
            }
            System.out.println();
        }
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 2420. 사파리월드]]></title>
            <link>https://velog.io/@c-hano/%EB%B0%B1%EC%A4%80-2420.-%EC%82%AC%ED%8C%8C%EB%A6%AC%EC%9B%94%EB%93%9C</link>
            <guid>https://velog.io/@c-hano/%EB%B0%B1%EC%A4%80-2420.-%EC%82%AC%ED%8C%8C%EB%A6%AC%EC%9B%94%EB%93%9C</guid>
            <pubDate>Thu, 24 Apr 2025 02:29:19 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/c-hano/post/5ca3e1bf-888f-4e7e-9b4b-d083f49824b2/image.png" alt=""></p>
<p>_ Int 범위 : -2,147,483,648 ~ 2,147,483,647 _</p>
<p><em>ㅣN-Mㅣ의 최대값이 Int 의 범위에 벗어나므로 변수에 long을 써야한다.</em></p>
<p><em>절대값을 구하는 Math.abs() 를 사용하였다.</em></p>
<h4 id="정답">정답</h4>
<pre><code>package org.example;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        long a = scanner.nextLong();
        long b = scanner.nextLong();

        System.out.println(Math.abs(a-b));
    }
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 레포지토리 테스트.]]></title>
            <link>https://velog.io/@c-hano/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%A0%88%ED%8F%AC%EC%A7%80%ED%86%A0%EB%A6%AC-%ED%85%8C%EC%8A%A4%ED%8A%B8</link>
            <guid>https://velog.io/@c-hano/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%A0%88%ED%8F%AC%EC%A7%80%ED%86%A0%EB%A6%AC-%ED%85%8C%EC%8A%A4%ED%8A%B8</guid>
            <pubDate>Thu, 27 Feb 2025 02:44:41 GMT</pubDate>
            <description><![CDATA[<p>개발용, 테스트용 yml파일을 설정하였다. </p>
<p><img src="https://velog.velcdn.com/images/c-hano/post/4d90a9b8-8380-4c3c-9ac7-b9bbd423210c/image.png" alt=""></p>
<p>해당 레포지터리가 엔티티와 연결되어 잘 작동하는지 확인해보자.</p>
<p>테스트 파일에 직접 파일을 작성해도 되지만 인텔리J에서 제공하는 단축키인 커멘드+shift+T 를 사용하여 테스트 파일을 생성하였다.
<br>
테스트해볼 기능은 다음과 같다.
<br>
<em>1. 엔티티에 데이터를 넣었을 때 값이 저장이 되는지.
2. findByName 메서드가 작동을 하는지.</em></p>
<pre><code class="language-java">package reproject.calendars.repository;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.transaction.annotation.Transactional;
import reproject.calendars.entity.Calendar;

import java.util.Optional;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest 
-&gt; 해당 에너테이션이 있을 시 테스트 실행 시 스프링에 모든 bean이 실행된다.

@ActiveProfiles(&quot;test&quot;) 
-&gt; application-{profiles}.yml 에서 &quot;&quot; 안의 값을 profiles로 읽는다.
    application-test.yml을 실행하도록 설정한다.

@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
-&gt; 스프링은 기본 실행시 데이터베이스를 embedded모드로 실행시키려한다. 해당 기능을 NONE을 통해 방지하여 
    application-test.yml에 있는 mem모드로 강제로 실행시킨다.

@Transactional
-&gt; 테스트 메서드 하나 실행 시 데이터를 초기화시켜준다.

class CalendarRepositoryTest {

    @Autowired
    private CalendarRepository calendarRepository;

    @Test
    void 캘린더_엔티티_생성() {
        //GIVEN
        Calendar calendar = new Calendar(&quot;test&quot;, &quot;test&quot;);

        //WHEN
        Calendar saveCalendar = calendarRepository.save(calendar);

        //THEN
        assertNotNull(saveCalendar.getId());
        assertEquals(&quot;test&quot;, saveCalendar.getName());
    }

    @Test
    void findByName_테스트() {
        //GIVEN
        Calendar calendar = new Calendar(&quot;test1&quot;, &quot;test1&quot;);
        calendarRepository.save(calendar);

        //WHEN
        Optional&lt;Calendar&gt; saveCalendar = calendarRepository.findByName(&quot;test1&quot;);

        //THEN
        assertThat(saveCalendar.isPresent());
        assertThat(saveCalendar.get().getName()).isEqualTo(&quot;test1&quot;);
        -&gt; Optional로 감싸져 있는 객체는 null값일 수도 있으므로 바로 .getName()을 사용하지 못한다.
            .get()으로 Optional을 한번 벗겨주고 .getName()을 사용해야한다.
    }
}</code></pre>
<p>실제로 test파일이 application-test.yml에서 mem 모드의 데이터베이스를 사용하고 있는지 확인하고 싶다면 application-test.yml에 해당 코드를 추가하자.</p>
<pre><code class="language-java">logging:
  level:
    org.springframework: DEBUG  # 스프링 관련 로그를 DEBUG 수준으로 출력
    org.hibernate.SQL: DEBUG  # Hibernate가 실행하는 SQL 쿼리 로그 출력</code></pre>
<br>

<p>test파일을 실행 후 터미널 로그에서 test를 확인해보자. 검색이 된다면 잘 연결이 된 것이다.</p>
<p><img src="https://velog.velcdn.com/images/c-hano/post/7f4f68d4-43e7-4362-92b4-270b58bb86a1/image.png" alt=""></p>
<p>테스트도 무사 통과하였다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 데이터베이스 설정 - yml]]></title>
            <link>https://velog.io/@c-hano/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%84%A4%EC%A0%95-yml</link>
            <guid>https://velog.io/@c-hano/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%84%A4%EC%A0%95-yml</guid>
            <pubDate>Thu, 27 Feb 2025 02:32:01 GMT</pubDate>
            <description><![CDATA[<p>개발환경 -&gt; application-dev.yml / embedded 모드로 데이터베이스 설정</p>
<p>테스트환경 -&gt; application-test.yml / mem 모드로 데이터베이스 설정.</p>
<p>통합 -&gt; application.yml / 두 파일의 공통 코드를 해당 파일에서 설정.</p>
<br>

<p><strong>1. application.yml 설정.</strong></p>
<pre><code class="language-java">spring:
    profiles:
    active: dev -&gt; 따로 에너테이션으로 설정하지 않을시 기본적으로 application-{profiles}.yml 을 불러옴.
                    여기선 profiles를 dev로 설정하였다.

    jpa:
        show-sql: true -&gt; sql을 보여준다.
        database-platform: org.hibernate,dialect.H2Dialect -&gt; h2데이터베이스의 플랫폼 설정.
        hibernate:
            ddl-auto: update -&gt; 어플리케이션 실행 시 자동으로 테이블을 업데이트 해주는 기능.

    h2:
        console:
            enabled: true -&gt; 콘솔(브라우저)에서 h2데이터베이스에 접근할 수 있도록 하는 기능.
            path: /h2-console -&gt; 콘솔(브라우저)에서 localhost:8080/h2-console 으로 h2 접근 가능.</code></pre>
<br>

<p><strong>2. application-dev.yml 설정.</strong></p>
<pre><code class="language-java">spring:
    datasource:
        url: jdbc:h2:~/reproject
        driver-class-name: org.h2.driver
        username: sa
        password: 1</code></pre>
<br>

<p><strong>3. application-test.yml 설정.</strong></p>
<pre><code class="language-java">spring:
    datasource:
        url: jdbc:h2:mem:testdb -&gt; mem방식의 데이터베이스 사용
        driver-class-name: org.h2.driver
        username: sa
        password:

    jpa:
        hibernate:
            ddl-auto: create-drop -&gt; 어플리케이션 종료 시 데이터값 삭제.</code></pre>
<br>

<ul>
<li><p>스프링은 작동 시 기본적으로 application.yml 파일을 확인 후 해당 설정을 적용하고 클래스에서 에너테이션을 확인 후 application-{profiles}.yml 에서 profiles에 따른 yml 파일을 덮어쓴다. </p>
</li>
<li><p>-test.yml 파일을 사용하려면 클래스에서 @ActiveProfiles(&quot;test&quot;)를 선언해야한다.</p>
</li>
</ul>
<p>이제 작성한 엔티티와 레포지토리가 실제로 작동하는지 test파일을 만들어볼 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[데이터베이스 타입 - tcp, embeded, mem]]></title>
            <link>https://velog.io/@c-hano/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%ED%83%80%EC%9E%85-tcp-embeded-mem</link>
            <guid>https://velog.io/@c-hano/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%ED%83%80%EC%9E%85-tcp-embeded-mem</guid>
            <pubDate>Thu, 27 Feb 2025 02:18:29 GMT</pubDate>
            <description><![CDATA[<p>** 1. TCP(server) 모드 - jdbc:h2:tcp://localhost... **</p>
<p>터미널에서 ./h2.sh 을 실행하여 직접 데이터베이스 어플을 실행시킨다.
<img src="https://velog.velcdn.com/images/c-hano/post/0a689891-28aa-448d-bf43-afbe59b9c518/image.png" alt=""></p>
<ul>
<li>여러 외부 어플리케이션에서 동일한 db를 공유할 수 있다.</li>
<li>서버(h2  어플리케이션)이 꺼지지 않는 한 계속해서 접근할 수 있다. (h2 어플리케이션을 누르면 된다.)</li>
</ul>
<p>-&gt; yml의 url에서 jdbc:h2:tcp://localhost.. 를 입력해야한다.</p>
<br>

<p>** 2. Embedded 모드 - jdbc:h2:~/...**</p>
<ul>
<li>H2 데이터베이스가 애플리케이션 내부에서 실행된다.</li>
<li>어플리케이션이 종료되면 DB도 같이 종료된다.</li>
<li>파일로 저장하여 (tcp도 동일) 어플리케이션 종료 후에도 데이터가 유지 된다.</li>
<li>tcp보다 처리속도가 빠르다 (네트워크 소켓을 거치지 않기 때문)</li>
<li>한 어플리케이션에서만 접근이 가능하다.</li>
</ul>
<br>

<p><strong>3. MEM 모드 - jdbc:h2:mem:...</strong></p>
<ul>
<li>H2 데이터베이스를 메모리에서 실행하는 방식.</li>
<li>어플리케이션이 종료되면 데이터도 삭제된다.</li>
<li>주로 테스트 환경에서 사용한다.</li>
<li>어플리케이션 실행 중에만 데이터가 유지된다.</li>
</ul>
<br>

<p><strong>📌 최종 비교표</strong></p>
<table>
<thead>
<tr>
<th>모드</th>
<th>데이터 저장 방식</th>
<th>애플리케이션 종료 후 데이터 유지</th>
<th>멀티 프로세스 접근</th>
<th>속도</th>
</tr>
</thead>
<tbody><tr>
<td>TCP(Server) 모드</td>
<td>파일(.mv.db)</td>
<td>✅ 유지됨</td>
<td>✅ 여러 애플리케이션 가능</td>
<td>⬇ 느림 (네트워크 필요)</td>
</tr>
<tr>
<td>Embedded(임베디드) 모드</td>
<td>파일(.mv.db)</td>
<td>✅ 유지됨</td>
<td>❌ 단일 애플리케이션만 사용 가능</td>
<td>⬆ 빠름 (로컬 접근)</td>
</tr>
<tr>
<td>MEM(메모리) 모드</td>
<td>메모리(RAM)</td>
<td>❌ 유지 안됨</td>
<td>❌ 단일 애플리케이션만 사용 가능</td>
<td>🚀 가장 빠름</td>
</tr>
<tr>
<td><strong>📌 언제 어떤 모드를 사용해야 할까?</strong></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>상황</th>
<th>추천 모드</th>
<th>이유</th>
</tr>
</thead>
<tbody><tr>
<td>운영 환경 (실제 서비스 배포)</td>
<td>TCP(Server) 모드</td>
<td>여러 애플리케이션에서 같은 DB 접근 가능, 데이터 유지됨</td>
</tr>
<tr>
<td>로컬 개발 환경 (파일 기반 데이터 저장)</td>
<td>Embedded 모드</td>
<td>단일 애플리케이션에서 사용, 데이터 유지됨</td>
</tr>
<tr>
<td>테스트 환경 (테스트 실행 시마다 초기화됨)</td>
<td>MEM(메모리) 모드</td>
<td>빠르고 테스트 종료 후 자동 삭제됨</td>
</tr>
</tbody></table>
<p><strong>🚀 결론</strong></p>
<p>운영 환경에서는 TCP(Server) 모드를 사용하여 여러 애플리케이션이 동일한 DB를 공유하도록 설정.
로컬 개발 환경에서는 Embedded 모드를 사용하여 쉽게 데이터베이스를 유지하면서 개발 가능.
테스트 환경에서는 MEM 모드를 사용하여 빠른 테스트 실행과 자동 초기화가 가능.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 복기 - 엔티티]]></title>
            <link>https://velog.io/@c-hano/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%B3%B5%EA%B8%B0-%EC%97%94%ED%8B%B0%ED%8B%B0</link>
            <guid>https://velog.io/@c-hano/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%B3%B5%EA%B8%B0-%EC%97%94%ED%8B%B0%ED%8B%B0</guid>
            <pubDate>Fri, 21 Feb 2025 02:11:47 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/c-hano/post/c0200a44-665e-49cf-a426-b4d6fe73a556/image.png" alt=""></p>
<p>해당 테이블을 기준으로 calendar 엔티티를 작성하였다.</p>
<pre><code class="language-java">
package reproject.calendars.entity;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.time.LocalDateTime;

@Entity
@Getter
@NoArgsConstructor
public class Calendar {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private String description;

    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;

    public Calendar(String name, String description) {
        this.name = name;
        this.description = description;
        this.createdAt = LocalDateTime.now();
    }

    public void update(String name, String description) {
        this.name = name;
        this.description = description;
        this.updatedAt = LocalDateTime.now();
    }
}</code></pre>
<p>** @Entity , @Id, @GeneratedValue(strategy = GenerationType.IDENTITY) **</p>
<ul>
<li>@Entity 에너테이션이 있을 경우 Pr키를 설정하는 @Id 에너테이션이 필수이다.</li>
<li>@GeneratedValue(strategy = GenerationType.IDENTITY)<ul>
<li>다른 데이터 값이 들어올때 해당 에너테이션이 붙은 값을 자동으로 1씩 올려준다.</li>
</ul>
</li>
</ul>
<p>** @NoArgsConstructor **</p>
<ul>
<li>자바에선 생성자 생성이 필수이다. 매개변수를 받지 않는 기본 생성자가 있을 시 자동으로 생성자를 만들어준다. 하지만 매개변수를 받는 생성자가 하나라도 있을 시 기본 생성자를 입력을 해주어야 한다.</li>
<li>하지만 @NoArgsConstructor 에너테이션이 있을 시 기본 생성자 입력을 하지 않아도 자동으로 스프링에서 해당 에너테이션을 보고 기본 에너테이션을 생성해준다.</li>
</ul>
<ul>
<li>calendar 생성 시 매개변수로 이름과 설명을 받아야하고 메서드를 호출한 시점의 시간을 createdAt에  담는다.</li>
<li>update 매서드 실행시 이름과 설명을 받고, 메서드를 호출한 시점의 시간을 updatedAt에 담는다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[새로운 mv.db 파일 만들기. - tcp 서버]]></title>
            <link>https://velog.io/@c-hano/%EC%83%88%EB%A1%9C%EC%9A%B4-mv.db-%ED%8C%8C%EC%9D%BC-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@c-hano/%EC%83%88%EB%A1%9C%EC%9A%B4-mv.db-%ED%8C%8C%EC%9D%BC-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Thu, 20 Feb 2025 07:21:16 GMT</pubDate>
            <description><![CDATA[<p>기존에 맥 터미널로 ./h2.sh로 h2어플리케이션을 실행시켰을 것이다.</p>
<p>해당 어플리케이션을 실행하면서 하나의 mv.db파일을 생성하였다.</p>
<p>다른 프로젝트에서 다른 mv.db파일을 사용해야할 경우 새로운 mv.db파일을 만들어야 한다.</p>
<p><img src="https://velog.velcdn.com/images/c-hano/post/e070aa87-09af-4625-b92d-dd1f3dc07221/image.png" alt=""></p>
<p>맥의 경우 h2 콘솔을 누른 후 Create a new database를 누른다.</p>
<p><img src="https://velog.velcdn.com/images/c-hano/post/59722829-2d99-477f-ad05-d35b4c9ddc88/image.png" alt=""></p>
<p>다음과 같은 화면이 뜬다.</p>
<p>path에서 ./ 을 입력하면 h2폴더 안에 mv.db파일이 생성된다.
~/ 을 입력하면 user 폴더 안에 mv.db파일이 생성된다.</p>
<p>이렇게 새로운 mv.db파일을 생성하고 관리할 수 있다.</p>
<br>

<p><strong>추가</strong></p>
<p>해당 방식으로 데이터베이스를 생성하는 것이 tcp서버 방식인듯 하다.</p>
<p>tcp방식은 h2어플리케이션이 실행되는 동안에는 인텔리J에서 어플을 실행시키지 않아도 데이터베이스를 브라우저에서 h2콘솔에 접근이 가능하다.</p>
<p><del><em>기존 embedded 방식은 인텔리J 어플리케이션이 실행될 때에만 h2콘솔에 접근이 가능하다.</em></del></p>
<p>yml에서 url에 jdbc:h2:tcp://localhost/~/... 로 명시해주어야 하고,</p>
<p>인텔리J 데이터 베이스 설정에서도 connection type -&gt; remote로 해주어야한다.</p>
<p><img src="https://velog.velcdn.com/images/c-hano/post/e500021b-2629-4806-a56a-d6a9e25b37ca/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/c-hano/post/7c009e01-1284-41d9-a769-32d203f3cdce/image.png" alt=""></p>
<p>기존 embedded 방식에서 url만 바꾸어서 tcp 방식으로 데이터베이스에 접근하도록 변경하였다.</p>
<p>@Entity가 붙은 calendar가 테이블로 등록되어있음을 볼 수 있다.
<img src="https://velog.velcdn.com/images/c-hano/post/e4f74517-676e-499b-9c6e-db16ace984a3/image.png" alt="">
인텔리J 어플이 꺼져있고 h2 콘솔에 접근하려면 해당 h2어플리케이션을 누르고 H2 Console을 누르면 된다.</p>
<p><img src="https://velog.velcdn.com/images/c-hano/post/d6afabc8-c738-40f1-87d2-5e14489889a4/image.png" alt=""></p>
<p>인텔리J 어플리케이션이 실행되지 않아도 콘솔에 접근이 가능한 것을 볼 수 있다.</p>
<br>

]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 복기 - 초기설정 yml]]></title>
            <link>https://velog.io/@c-hano/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%B3%B5%EA%B8%B0-%EC%B4%88%EA%B8%B0%EC%84%A4%EC%A0%95-yml</link>
            <guid>https://velog.io/@c-hano/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%B3%B5%EA%B8%B0-%EC%B4%88%EA%B8%B0%EC%84%A4%EC%A0%95-yml</guid>
            <pubDate>Thu, 20 Feb 2025 07:17:42 GMT</pubDate>
            <description><![CDATA[<p>데이터베이스는 프로젝트 때 사용했던 것 과 동일하게 h2를 사용할 것이다.</p>
<p>생성된 mv.db파일을 사용할 것인가, 어플리케이션이 작동될 때마다 h2데이터베이스를 생성할 것인가. 고려해봤을 때,</p>
<p>각각의 장단점이 있다.
  <br></p>
<ul>
<li><p><em>매번 새 데이터를 테스트하고 싶을때</em>
  <em>프로젝트를 빠르게 실행하고 초기 데이터를 넣어 테스트할 때</em>
  <em>운영 환경이 아닌 개발환경에서만 사용할때 -&gt; 스프링 시작 시 h2 데이터베이스가 생성되도록 설정.</em></p>
</li>
<li><p><em>기존 데이터(mv.db)를 유지하면서 개발을 이어가야 할 때</em>
  <em>프로젝트 재시작 후에도 데이터가 유지되어야 할 때</em>
  <em>운영환경과 비슷한 방식으로 개발하고 싶을 때 -&gt; 기존 데이터베이스를 사용. mv.db.</em></p>
  <br>

</li>
</ul>
<p>프로젝트 때에도 어플리케이션 생성 시 db파일이 생성되었던 것 같다. <del>첫번째 방법으로 진행하자.</del></p>
<p>개발시엔 어플리케이션 실행시에만 접근이 가능한 embedded 타입으로</p>
<p>첫번째 방법으로 진행하려면 application.yml 파일에 설정값을 입력하여야 한다.</p>
<pre><code class="language-java">src/main/resources/application.yml

spring:
  datasource:
    url: jdbc:h2:mem:testdb
    driver-class-name: org.h2.Driver
    username: sa
    password:

  jpa:
    show-sql: true
    database-platform: org.hibernate.dialect.H2Dialect
    hibernate:
      ddl-auto: update # 애플리케이션 실행 시 자동으로 테이블 업데이트

  h2:
    console:
      enabled: true
      path: /h2-console</code></pre>
<ul>
<li><p>url : jdbc:h2:mem:testdb</p>
<ul>
<li>mem은 메모리 버전의 테스트 db파일을 사용한다. (어플 중지 시 db가 사라짐)</li>
<li>file이나 기존에 있는 db를 tcp방식으로 사용하려면,<ul>
<li>url : jdbc:h2:file:~/h2-database/testdb</li>
<li>url : jdbc:h2:tcp://localhost/~/h2-database/testdb 를 입력하여야 한다.</li>
</ul>
</li>
<li>driver-class-name : org.h2.Driver<ul>
<li>h2드라이버를 사용하겠다는 의미. sql이나 다른 툴을 사용시 해당 코드가 변경되어야 한다.<br>
</li>
</ul>
</li>
</ul>
</li>
<li><p>jpa : database-platforn: org.hibernate.dialect.H2Dialect</p>
<ul>
<li>h2드라이버를 사용하겠다는 의미. sql이나 다른 툴을 사용시 해당 코드가 변경되어야 한다.</li>
<li>hibernate: ddl-auto: update<ul>
<li>어플리케이션 실행 시 자동으로 테이블이 업데이트가 된다. true, none, 등등 다른 값들이 있지만 나중에 필요하면 알아보자.<br>  </li>
</ul>
</li>
</ul>
</li>
<li><p>h2:</p>
<ul>
<li>console : enable: true<ul>
<li>기존 값은 false이다. 브라우저에서 h2 콘솔에 접속하게 해주었다.</li>
</ul>
</li>
<li>path: /h2-console<ul>
<li>localhost:8080/h2-console에 접속 시 h2 콘솔에 접근이 가능하다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>이제 서버 실행 후 브라우저 url에 localhost:8080/h2-console 에 접속 후 url 복붙하면 정상적으로 데이터베이스를 볼 수 있다.</p>
<br>
-----------

<p><em>테스트시엔 테스트 실행시 db가 생성되고 테스트가 끝나면 db가 사라지는 mem 방식으로 데이터베이스를 구분하였다.</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 복기 - 기획서]]></title>
            <link>https://velog.io/@c-hano/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%B3%B5%EA%B8%B0-%EA%B8%B0%ED%9A%8D%EC%84%9C</link>
            <guid>https://velog.io/@c-hano/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%B3%B5%EA%B8%B0-%EA%B8%B0%ED%9A%8D%EC%84%9C</guid>
            <pubDate>Thu, 20 Feb 2025 02:39:29 GMT</pubDate>
            <description><![CDATA[<p>마감 기한에 맞춰 후닥닥 프로젝트를 완성하다 보니 지피티 범벅인 프로젝트가 되어버렸다.</p>
<p>팀원분이 코드를 설명해달라고 했는데 내가 짠 코드를 설명하지 못하는 상황에 직면..</p>
<p>프로젝트가 끝난 지금 조금 여유가 생겨 적어도 내가 짠 부분의 코드는 알아두고자 하여 처음부터 다시 해보기로 했다.</p>
<br>
그럼 고고


<hr>
<br>

<h3 id="프로젝트-기획서">프로젝트 기획서</h3>
<br>

<h4 id="1-프로젝트-개요">1. 프로젝트 개요</h4>
<ul>
<li>프로젝트명 : CANBEJ</li>
<li>설명: 사용자가 개인 또는 그룹 캘린더를 생성하여 일정을 효율적으로 관리할 수 있는 웹 애플리케이션</li>
<li>목표: 사용자가 손쉽게 일정을 추가하고, 수정 및 삭제하며, 다른 사용자와 공유할 수 있는 기능을 제공<br>

</li>
</ul>
<h4 id="2-주요-기능-정리">2. 주요 기능 정리</h4>
<ul>
<li><p><strong>사용자 관리</strong></p>
<ul>
<li><p>회원가입 및 로그인 (JWT 인증 적용)</p>
</li>
<li><p>사용자 정보 수정 (닉네임 변경)</p>
</li>
<li><p>비밀번호 변경 및 비밀번호 찾기 기능</p>
</li>
</ul>
</li>
</ul>
<ul>
<li><p><strong>캘린더 관리 (핵심 기능)</strong></p>
<ul>
<li><p>캘린더 생성: 사용자가 새로운 캘린더를 생성할 수 있음</p>
</li>
<li><p>캘린더 조회: 사용자가 소유한 캘린더 목록을 확인할 수 있음</p>
</li>
<li><p>캘린더 수정: 캘린더 이름 및 설명을 수정할 수 있음</p>
</li>
<li><p>캘린더 삭제: 불필요한 캘린더를 삭제할 수 있음</p>
</li>
<li><p>캘린더 공유: 다른 사용자와 캘린더를 공유하고 권한을 설정할 수 있음</p>
</li>
</ul>
</li>
<li><p><strong>일정(Schedule) 관리</strong></p>
<ul>
<li><p>일정 추가 (제목, 설명, 날짜/시간, 장소 포함)</p>
</li>
<li><p>일정 수정 및 삭제 (캘린더 소유자 및 일정 작성자만 가능)</p>
</li>
<li><p>특정 캘린더의 일정 목록 조회</p>
</li>
<li><p>일정 상세 조회 및 참가자 관리</p>
</li>
</ul>
</li>
<li><p><strong>보안 및 인증</strong></p>
<ul>
<li><p>JWT 기반 로그인/회원가입 구현</p>
</li>
<li><p>Spring Security 적용 (API 보안 강화)</p>
</li>
<li><p>비밀번호 암호화 (BCrypt 사용)</p>
</li>
</ul>
</li>
</ul>
<br>

<pre><code>우선은 프로젝트 내에서 맡은 파트가 캘린더 파트여서 캘린더 부분을 복기를 해보고 시간이 남으면 나머지도 해보겠슴.</code></pre><br>

<h4 id="3-1-캘린더-관리-기능-상세-요구사항-">3-1. 캘린더 관리 기능 상세 요구사항 **</h4>
<ul>
<li><p><strong>캘린더 생성</strong></p>
<ul>
<li>사용자는 캘린더의 이름(name)과 설명(description)을 입력해야 함</li>
<li>생성된 캘린더는 사용자 ID(user_id)와 연결됨</li>
<li>캘린더는 자동으로 생성된 ID(id)를 가짐</li>
<li>생성 시간(created_at)을 자동 저장해야 함</li>
<li>캘린더는 기본적으로 개인 전용(private) 상태이며, 공유 설정을 변경할 수 있음</li>
</ul>
</li>
<li><p><strong>캘린더 조회</strong></p>
<ul>
<li>사용자는 본인이 소유한 캘린더 목록을 확인할 수 있음</li>
<li>특정 캘린더의 상세 정보를 조회할 수 있음</li>
<li>공유된 캘린더도 함께 조회할 수 있음</li>
</ul>
</li>
<li><p><strong>캘린더 수정</strong></p>
<ul>
<li>사용자는 이름(name)과 설명(description)을 수정할 수 있음</li>
<li>캘린더 수정 시 수정 시간(updated_at)을 자동 저장해야 함</li>
<li>캘린더 소유자만 수정할 수 있음</li>
</ul>
</li>
<li><p>*<em>캘린더 삭제 *</em></p>
<ul>
<li>사용자는 자신의 캘린더만 삭제할 수 있음</li>
<li>캘린더 삭제 시, 해당 캘린더에 포함된 일정도 함께 삭제됨</li>
<li>공유된 캘린더를 삭제할 경우, 공유된 사용자에게 알림을 보낼 수 있도록 해야 함</li>
</ul>
</li>
<li><p><strong>캘린더 공유 기능</strong></p>
<ul>
<li>캘린더 소유자는 다른 사용자를 초대하여 캘린더를 공유할 수 있음</li>
<li>공유된 사용자는 캘린더에 대한 읽기(read) 또는 쓰기(write) 권한을 가질 수 있음</li>
<li>공유된 사용자는 자신의 캘린더 목록에서 확인 가능함</li>
<li>소유자가 공유를 해제하면 해당 사용자 목록에서 캘린더가 사라짐</li>
</ul>
</li>
<li><p>생성된 캘린더가 없을 시 캘린더를 생성하라고 알려줌.</p>
</li>
</ul>
<br>

<h4 id="4-1-캘린더-관리-기능-api-상세-설계">4-1. 캘린더 관리 기능 API 상세 설계</h4>
<p><strong>캘린더 생성</strong>
HTTP 메서드 : POST
URL : /api/calendars</p>
<p>요청</p>
<pre><code class="language-java">{
 &quot;name&quot;: &quot;개인 일정&quot;,
  &quot;description&quot;: &quot;2024년 개인 일정 관리&quot;
}</code></pre>
<p>반환
성공(201 Created)</p>
<pre><code class="language-java">{
  &quot;id&quot;: 1,
  &quot;name&quot;: &quot;개인 일정&quot;,
  &quot;description&quot;: &quot;2024년 개인 일정 관리&quot;,
  &quot;created_at&quot;: &quot;2024-02-01T10:00:00&quot;
}</code></pre>
<br>

<p><strong>캘린더 조회</strong>
HTTP 메서드 : GET
URL : /api/calendars</p>
<p>반환
성공(200 OK)</p>
<pre><code class="language-java">[
  {
    &quot;id&quot;: 1,
    &quot;name&quot;: &quot;개인 일정&quot;,
    &quot;description&quot;: &quot;2024년 개인 일정 관리&quot;
  },
  {
    &quot;id&quot;: 2,
    &quot;name&quot;: &quot;업무 일정&quot;,
    &quot;description&quot;: &quot;회사 일정 관리&quot;
  }
]</code></pre>
<br>

<p><strong>특정 캘린더 조회</strong>
HTTP 메서드 : GET
URL : /api/calendars/{id}</p>
<p>반환
성공(200 OK)</p>
<pre><code class="language-java">{
  &quot;id&quot;: 1,
  &quot;name&quot;: &quot;개인 일정&quot;,
  &quot;description&quot;: &quot;2024년 개인 일정 관리&quot;,
  &quot;created_at&quot;: &quot;2024-02-01T10:00:00&quot;
}</code></pre>
<br>

<p><strong>캘린더 수정</strong>
HTTP 메서드 : POST
URL : /api/calendars/{id}</p>
<p>요청</p>
<pre><code class="language-java">{
  &quot;name&quot;: &quot;수정된 일정&quot;,
  &quot;description&quot;: &quot;업데이트된 일정 정보&quot;
}</code></pre>
<p>반환
성공(200 OK)</p>
<pre><code class="language-java">{
  &quot;id&quot;: 1,
  &quot;name&quot;: &quot;수정된 일정&quot;,
  &quot;description&quot;: &quot;업데이트된 일정 정보&quot;,
  &quot;updated_at&quot;: &quot;2024-02-01T12:00:00&quot;
}</code></pre>
<br>

<p><strong>캘린더 삭제</strong>
HTTP 메서드 : DELETE
URL : /api/calendars/{id}</p>
<p>반환
성공(200 OK)</p>
<pre><code class="language-java">{
  &quot;message&quot;: &quot;캘린더가 삭제되었습니다.&quot;
}</code></pre>
<br>

<p><strong>캘린더 공유</strong>
HTTP 메서드 : POST
URL : /api/calendars/{id}/share</p>
<p>요청</p>
<pre><code class="language-java">{
  &quot;user_id&quot;: 2,
  &quot;permission&quot;: &quot;read&quot;
}</code></pre>
<p>반환
성공(200 OK)</p>
<pre><code class="language-java">{
  &quot;message&quot;: &quot;캘린더가 사용자에게 공유되었습니다.&quot;
}</code></pre>
<br>

<h4 id="5-1-엔티티-설계">5-1. 엔티티 설계</h4>
<p><img src="https://velog.velcdn.com/images/c-hano/post/333315a9-b4d4-48b1-bdf3-41155185f21f/image.png" alt="">
<img src="https://velog.velcdn.com/images/c-hano/post/b49b701b-607f-4bcd-a092-d53d7a2788c7/image.png" alt=""></p>
<hr>
<p>다음은 calendar 클래스를 만들어 보자. 코드를 짜며 개념 정리도 같이 기입하여보자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[MySQL실습] 흉부외과 또는 일반외과 의사 목록 출력하기]]></title>
            <link>https://velog.io/@c-hano/MySQL%EC%8B%A4%EC%8A%B5-%ED%9D%89%EB%B6%80%EC%99%B8%EA%B3%BC-%EB%98%90%EB%8A%94-%EC%9D%BC%EB%B0%98%EC%99%B8%EA%B3%BC-%EC%9D%98%EC%82%AC-%EB%AA%A9%EB%A1%9D-%EC%B6%9C%EB%A0%A5%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@c-hano/MySQL%EC%8B%A4%EC%8A%B5-%ED%9D%89%EB%B6%80%EC%99%B8%EA%B3%BC-%EB%98%90%EB%8A%94-%EC%9D%BC%EB%B0%98%EC%99%B8%EA%B3%BC-%EC%9D%98%EC%82%AC-%EB%AA%A9%EB%A1%9D-%EC%B6%9C%EB%A0%A5%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 12 Dec 2024 07:49:32 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/c-hano/post/c2a1462d-2e87-47cc-8d9e-6125d08a002c/image.png" alt=""></p>
<h4 id="정답">정답</h4>
<pre><code>SELECT DR_NAME, DR_ID, MCDP_CD, date_format(HIRE_YMD, &#39;%Y-%m-%d&#39;) AS HIRE_YMD
FROM DOCTOR
WHERE MCDP_CD = &#39;CS&#39; OR MCDP_CD = &#39;GS&#39;
ORDER BY HIRE_YMD DESC, DR_NAME</code></pre><ul>
<li>DATE_값 처리하기. date_format(칼럼이름, &#39;sql 연,월,일.. 표기방법&#39;)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[MySQL실습] 3월에 태어난 여성 회원 목록 출력하기]]></title>
            <link>https://velog.io/@c-hano/MySQL%EC%8B%A4%EC%8A%B5.-3%EC%9B%94%EC%97%90-%ED%83%9C%EC%96%B4%EB%82%9C-%EC%97%AC%EC%84%B1-%ED%9A%8C%EC%9B%90-%EB%AA%A9%EB%A1%9D-%EC%B6%9C%EB%A0%A5%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@c-hano/MySQL%EC%8B%A4%EC%8A%B5.-3%EC%9B%94%EC%97%90-%ED%83%9C%EC%96%B4%EB%82%9C-%EC%97%AC%EC%84%B1-%ED%9A%8C%EC%9B%90-%EB%AA%A9%EB%A1%9D-%EC%B6%9C%EB%A0%A5%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 12 Dec 2024 07:43:58 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/c-hano/post/d8b81c6b-ba47-4b4d-b648-7f6e3a7ebbe0/image.png" alt=""></p>
<h4 id="정답">정답</h4>
<pre><code>SELECT MEMBER_ID, MEMBER_NAME, GENDER, date_format(DATE_OF_BIRTH, &#39;%Y-%m-%d&#39;) AS DATE_OF_BIRTH
FROM MEMBER_PROFILE
WHERE MONTH(DATE_OF_BIRTH) = &#39;3&#39; AND TLNO IS NOT NULL AND GENDER = &#39;W&#39;
ORDER BY MEMBER_ID</code></pre><ul>
<li><p>DATE_값들 처리하는 방법. </p>
<p>  date_format(칼럼 이름, &#39;연,월,일,,,표기 형식에 따름&#39;)</p>
<table>
<thead>
<tr>
<th>표기 형식</th>
<th>의미</th>
</tr>
</thead>
<tbody><tr>
<td>%Y</td>
<td>연도(year): 4자리 표현</td>
</tr>
<tr>
<td>%y</td>
<td>연도(year): 뒤에서 2자리 표현</td>
</tr>
<tr>
<td>%a</td>
<td>요일(weekday): 이름 줄임표현</td>
</tr>
<tr>
<td>%W</td>
<td>요일(weekday): 이름</td>
</tr>
<tr>
<td>%w</td>
<td>요일(weekday): 숫자 활용</td>
</tr>
<tr>
<td>%b</td>
<td>월(month): 이름 줄임표현</td>
</tr>
<tr>
<td>%M</td>
<td>월(month): 이름</td>
</tr>
<tr>
<td>%c</td>
<td>월(month): 숫자 표기(자릿수 고정 X)</td>
</tr>
<tr>
<td>%m</td>
<td>월(month): 숫자 표기(자릿수 2개로 고정)</td>
</tr>
<tr>
<td>%D</td>
<td>일(day): 접미사 활용</td>
</tr>
<tr>
<td>%d</td>
<td>일(day): 숫자 활용(1개월 단위)</td>
</tr>
<tr>
<td>%j</td>
<td>일(day): 숫자 활용(1년 단위)</td>
</tr>
<tr>
<td>%p</td>
<td>오전/오후 구분</td>
</tr>
<tr>
<td>... 등등</td>
<td></td>
</tr>
</tbody></table>
</li>
<li><p>해당 문제에선 연,월,일 의 정보값만 나타내야하니</p>
</li>
<li><p>date_format(DATE_OF_BIRTH, &#39;%Y-%m-%d&#39;) 를 사용하였다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[MySQL실습] 과일로 만든 아이스크림 고르기]]></title>
            <link>https://velog.io/@c-hano/MySQL%EC%8B%A4%EC%8A%B5.-%EA%B3%BC%EC%9D%BC%EB%A1%9C-%EB%A7%8C%EB%93%A0-%EC%95%84%EC%9D%B4%EC%8A%A4%ED%81%AC%EB%A6%BC-%EA%B3%A0%EB%A5%B4%EA%B8%B0</link>
            <guid>https://velog.io/@c-hano/MySQL%EC%8B%A4%EC%8A%B5.-%EA%B3%BC%EC%9D%BC%EB%A1%9C-%EB%A7%8C%EB%93%A0-%EC%95%84%EC%9D%B4%EC%8A%A4%ED%81%AC%EB%A6%BC-%EA%B3%A0%EB%A5%B4%EA%B8%B0</guid>
            <pubDate>Thu, 12 Dec 2024 07:30:03 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/c-hano/post/2c53a1b2-a641-4b29-93bf-e060cc5325eb/image.png" alt="">
<img src="https://velog.velcdn.com/images/c-hano/post/f74cd803-8985-457e-a280-36e8af9400c9/image.png" alt="">
<img src="https://velog.velcdn.com/images/c-hano/post/390bcad2-35dc-4eff-a38b-a04d718789b0/image.png" alt=""></p>
<h4 id="정답">정답</h4>
<pre><code>SELECT a.FLAVOR 
FROM FIRST_HALF AS a 
LEFT JOIN ICECREAM_INFO AS b 
ON a.FLAVOR = b.FLAVOR
WHERE a.TOTAL_ORDER &gt; 3000 AND b.INGREDIENT_TYPE LIKE &#39;fruit_based&#39;
ORDER BY a.TOTAL_ORDER DESC;</code></pre><ul>
<li>LEFT JOIN 이던 INNER JOIN 이던 둘다 정답이다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[MySQL실습] 재구매가 일어난 상품과 회원 리스트 구하기]]></title>
            <link>https://velog.io/@c-hano/MySQL%EC%8B%A4%EC%8A%B5.-%EC%9E%AC%EA%B5%AC%EB%A7%A4%EA%B0%80-%EC%9D%BC%EC%96%B4%EB%82%9C-%EC%83%81%ED%92%88%EA%B3%BC-%ED%9A%8C%EC%9B%90-%EB%A6%AC%EC%8A%A4%ED%8A%B8-%EA%B5%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@c-hano/MySQL%EC%8B%A4%EC%8A%B5.-%EC%9E%AC%EA%B5%AC%EB%A7%A4%EA%B0%80-%EC%9D%BC%EC%96%B4%EB%82%9C-%EC%83%81%ED%92%88%EA%B3%BC-%ED%9A%8C%EC%9B%90-%EB%A6%AC%EC%8A%A4%ED%8A%B8-%EA%B5%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 11 Dec 2024 03:49:02 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/c-hano/post/c66b2069-c806-4c33-b949-5cd78af61225/image.png" alt=""></p>
<h4 id="정답">정답</h4>
<pre><code>SELECT USER_ID, PRODUCT_ID
FROM ONLINE_SALE
GROUP BY USER_ID, PRODUCT_ID
HAVING COUNT(*) &gt;= 2
ORDER BY USER_ID, PRODUCT_ID DESC</code></pre><ul>
<li>GROUP BY로 USER_ID와 PRODUCT_ID를 하나로 묶었다.</li>
<li>묶은 데이터 값이 두번 이상 나올 경우 (COUNT(*)&gt;=2) 의 데이터 값들을 걸러준다.</li>
<li>USER_ID를 오름차순으로 정렬하였고(ORDER BY), &#39;,&#39;를 통해 USER_ID가 같을 경우 PRODUCT_ID는 내림차순으로 정렬하였다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[MySQL실습] 평균 일일 대여 요금 구하기
]]></title>
            <link>https://velog.io/@c-hano/MySQL%EC%8B%A4%EC%8A%B5.-%ED%8F%89%EA%B7%A0-%EC%9D%BC%EC%9D%BC-%EB%8C%80%EC%97%AC-%EC%9A%94%EA%B8%88-%EA%B5%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@c-hano/MySQL%EC%8B%A4%EC%8A%B5.-%ED%8F%89%EA%B7%A0-%EC%9D%BC%EC%9D%BC-%EB%8C%80%EC%97%AC-%EC%9A%94%EA%B8%88-%EA%B5%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 11 Dec 2024 03:40:21 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/c-hano/post/38ae114d-dad3-4b7e-a7a5-fffa9e9afb20/image.png" alt=""></p>
<h4 id="정답">정답</h4>
<pre><code>SELECT ROUND(AVG(DAILY_FEE), 0) AS AVERRAGE_FEE
FROM CAR_RENTAL_COMPANY_CAR
WHERE CAR_TYPE = &#39;SUV&#39;</code></pre><ul>
<li>ROUND( a ,int x ) : a의 값을 x번째 소수점자리까지 반올림한다.</li>
<li>AVG(a) : a의 평균값을 구한다.</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>