<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>wjd_oou.log</title>
        <link>https://velog.io/</link>
        <description>반나서 만갑습니다</description>
        <lastBuildDate>Tue, 27 Aug 2024 12:53:55 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>wjd_oou.log</title>
            <url>https://velog.velcdn.com/images/wjd_oou/profile/c1301e60-844b-41ec-a8bc-fd585ab283e3/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. wjd_oou.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/wjd_oou" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[코드트리] 격자 안에서 완전탐색 / 양수 직사각형의 최대 크기]]></title>
            <link>https://velog.io/@wjd_oou/%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC-%EA%B2%A9%EC%9E%90-%EC%95%88%EC%97%90%EC%84%9C-%EC%99%84%EC%A0%84%ED%83%90%EC%83%89-%EC%96%91%EC%88%98-%EC%A7%81%EC%82%AC%EA%B0%81%ED%98%95%EC%9D%98-%EC%B5%9C%EB%8C%80-%ED%81%AC%EA%B8%B0</link>
            <guid>https://velog.io/@wjd_oou/%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC-%EA%B2%A9%EC%9E%90-%EC%95%88%EC%97%90%EC%84%9C-%EC%99%84%EC%A0%84%ED%83%90%EC%83%89-%EC%96%91%EC%88%98-%EC%A7%81%EC%82%AC%EA%B0%81%ED%98%95%EC%9D%98-%EC%B5%9C%EB%8C%80-%ED%81%AC%EA%B8%B0</guid>
            <pubDate>Tue, 27 Aug 2024 12:53:55 GMT</pubDate>
            <description><![CDATA[<h4 id="🌞-문제">🌞 문제</h4>
<p align="center"><img src="https://velog.velcdn.com/images/wjd_oou/post/b8e4408b-0bbd-4d48-a58c-19270cfd57a4/image.png" width=80%></p>

<p align="center"><img src="https://velog.velcdn.com/images/wjd_oou/post/4cdc60e8-31c2-4553-a981-eb20d2722d76/image.png" width=80%></p>


<hr>
<h4 id="🌞-풀이">🌞 풀이</h4>
<ol>
<li><p>한 점을 기준으로 직사각형을 그리는 함수 Rect 작성
1-1. 유효한 직사각형이라면, 가장 큰 크기의 직사각형이라면 maxSquare 변수에 값 저장 후 반환</p>
</li>
<li><p>그려진 Rect의 내부 점들이 모두 양수인지 판별하는 Counter 함수 작성</p>
</li>
<li><p>main 함수에서 모든 점을 대상으로 Rect 함수 실행 
3-1. arr를 입력받으면서 만약 음수가 있었다면 flag = false </p>
</li>
<li><p>최종 Rect을 실행하며 업데이트한 mS를 남겨둔 채로 flag를 검사
4-1. false일 경우 mS를 -1로 출력
4-2. true일 경우 mS 출력</p>
</li>
</ol>
<hr>
<h4 id="🌞-작성코드">🌞 작성코드</h4>
<pre><code>#include &lt;iostream&gt;
#include &lt;algorithm&gt;
using namespace std;

int n, m;
int arr[20][20];

bool Counter(int x1, int y1, int x2, int y2) {
    for(int i=x1; i&lt;=x2; i++) {
        for(int j=y1; j&lt;=y2; j++) {
            if(arr[i][j] &lt; 1) {
                return false;
            }
        }
    }
    return true;
}

int Rect(int x, int y) {
    int maxSquare;

    for(int i=x; i&lt;n; i++) {
        for(int j=y; j&lt;m; j++) {
            if(Counter(x, y, i, j)) {
                int square = (i-x+1) * (j-y+1);
                maxSquare = max(maxSquare, square);
            } else {
                break;
            }
        }
    }

    return maxSquare;
}

int main() {
    cin &gt;&gt; n &gt;&gt; m;

    bool flag=false;
    for(int i=0; i&lt;n; i++) {
        for(int j=0; j&lt;m; j++) {
            cin &gt;&gt; arr[i][j];

            if(arr[i][j] &gt; 0){
                flag=true;
            }
        }
    }

    int mS=-1;
    for(int i=0; i&lt;n; i++) {
        for(int j=0; j&lt;m; j++) {
            mS= max(mS, Rect(i, j));
        }
    }

    if (!flag) {
        mS = -1;
    }
    cout &lt;&lt; mS;
    return 0;
}</code></pre><hr>
<h4 id="🌞-제출결과">🌞 제출결과</h4>
<p align="center"><img src="https://velog.velcdn.com/images/wjd_oou/post/c192179d-706c-4902-bdbe-7c3b360c8ea4/image.png" width=80%></p>]]></description>
        </item>
        <item>
            <title><![CDATA[[코드트리] 격자 안에서 완전탐색 / 겹쳐지지 않는 두 직사각형]]></title>
            <link>https://velog.io/@wjd_oou/%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC-%EA%B2%A9%EC%9E%90-%EC%95%88%EC%97%90%EC%84%9C-%EC%99%84%EC%A0%84%ED%83%90%EC%83%89-%EA%B2%B9%EC%B3%90%EC%A7%80%EC%A7%80-%EC%95%8A%EB%8A%94-%EB%91%90-%EC%A7%81%EC%82%AC%EA%B0%81%ED%98%95</link>
            <guid>https://velog.io/@wjd_oou/%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC-%EA%B2%A9%EC%9E%90-%EC%95%88%EC%97%90%EC%84%9C-%EC%99%84%EC%A0%84%ED%83%90%EC%83%89-%EA%B2%B9%EC%B3%90%EC%A7%80%EC%A7%80-%EC%95%8A%EB%8A%94-%EB%91%90-%EC%A7%81%EC%82%AC%EA%B0%81%ED%98%95</guid>
            <pubDate>Tue, 27 Aug 2024 12:32:47 GMT</pubDate>
            <description><![CDATA[<h4 id="🌞-문제">🌞 문제</h4>
<p align="center"><img src="https://velog.velcdn.com/images/wjd_oou/post/a2832667-83eb-4ec6-8186-d9539f8c2680/image.png" width=80%></p>

<p align="center"><img src="https://velog.velcdn.com/images/wjd_oou/post/c4acc2c7-a567-4b1d-9609-4a252708f48a/image.png" width=80%></p>

<hr>
<h4 id="🌞-풀이">🌞 풀이</h4>
<ol>
<li><p>직사각형의 대각선 끝의 두 점이 주어지면 내부의 모든 숫자 합을 구하는 Counter 함수 작성</p>
</li>
<li><p>하나의 직사각형을 먼저 그리는 FirstRect 함수 작성</p>
</li>
<li><p>두 번째 직사각형을 그리는 SecondRect 함수 작성
3-1. SecondRect은 첫 번째 직사각형과 겹치면 안되기 때문에, 겹치는지 여부를 판단하기 위한 RectOverlap 함수 작성
3-2. 그린 직사각형들의 내부 숫자 합들 중 가장 큰 수를 max로 구하기</p>
</li>
<li><p>FirstRect 함수 내부에 첫 번째 사각형의 Counter + SeconRect에서 반환된 max Counter값을 더한 것과 기존의 값을 비교
4-1. 더 큰 값을 ans 변수를 통해 기존의 값으로 치환</p>
</li>
<li><p>max 함수로 비교할 때, 초기 값은 -25000으로 설정
5-1. 주어지는 table은 최대 25칸, 각 칸마다 최소 -1000까지 설정되기 때문</p>
</li>
<li><p>main 함수에서 주어진 table에 대해 FirstRect 함수를 돌려 최댓값 비교 (max)</p>
</li>
</ol>
<hr>
<h4 id="🌞-작성코드">🌞 작성코드</h4>
<pre><code>#include &lt;iostream&gt;
#include &lt;algorithm&gt;

using namespace std;

int n, m;
int arr[5][5];

bool RectOverlap(int x1, int y1, int x2, int y2, int nx1, int ny1, int nx2, int ny2) {
    return !(x2 &lt; nx1 || nx2 &lt; x1 || y2 &lt; ny1 || ny2 &lt; y1);
}

int Counter(int x1, int y1, int x2, int y2) {
    int cnt=0;
    for (int i=x1; i&lt;=x2; i++) {
        for (int j=y1; j&lt;=y2; j++) {
            cnt += arr[i][j];
        }
    }
    return cnt;
}

int SecondRect(int x1, int y1, int x2, int y2) {
    int cnt = -25000;

    for (int i = 0; i &lt; n; i++) {
        for (int j = 0; j &lt; m; j++) {
            for (int k = i; k &lt; n; k++) {
                for (int l = j; l &lt; m; l++) {
                    if (!RectOverlap(x1, y1, x2, y2, i, j, k, l)) {
                        cnt = max(cnt, Counter(i, j, k, l));
                    }
                }
            }
        }
    }

    return cnt;
}

int FirstRect(int x, int y){
    int cnt, ans = -25000;

    for(int i = x; i &lt; n; i++) {
        for(int j = y; j &lt; m; j++) {
            cnt = Counter(x, y, i, j) + SecondRect(x, y, i, j);
            ans = max(ans, cnt);
        }
    }

    return ans;
}

int main() {
    cin &gt;&gt; n &gt;&gt; m;

    int maxNum=-25000;

    for (int i=0; i&lt;n; i++) {
        for (int j=0; j&lt;m; j++) {
            cin &gt;&gt; arr[i][j];
        }
    }

    for (int i=0; i&lt;n; i++) {
        for(int j=0; j&lt;m; j++) {
            maxNum = max(maxNum, FirstRect(i, j));
        }
    }

    cout &lt;&lt; maxNum;

    return 0;
}</code></pre><hr>
<h4 id="🌞-제출결과">🌞 제출결과</h4>
<p align="center"><img src="https://velog.velcdn.com/images/wjd_oou/post/3b0bf765-eb3e-4fad-b114-406083687d7c/image.png" width=80%></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코드트리] dx dy technique / 거울에 레이저 쏘기 2]]></title>
            <link>https://velog.io/@wjd_oou/%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC-dx-dy-technique-%EA%B1%B0%EC%9A%B8%EC%97%90-%EB%A0%88%EC%9D%B4%EC%A0%80-%EC%8F%98%EA%B8%B0-2</link>
            <guid>https://velog.io/@wjd_oou/%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC-dx-dy-technique-%EA%B1%B0%EC%9A%B8%EC%97%90-%EB%A0%88%EC%9D%B4%EC%A0%80-%EC%8F%98%EA%B8%B0-2</guid>
            <pubDate>Tue, 20 Aug 2024 08:42:00 GMT</pubDate>
            <description><![CDATA[<h4 id="🌞-문제">🌞 문제</h4>
<p align="center"><img src="https://velog.velcdn.com/images/wjd_oou/post/4d9642f6-dee5-40d1-9f18-4bd0d3a74c2c/image.png" width=80%></p>


<p align="center"><img src="https://velog.velcdn.com/images/wjd_oou/post/3dfe709a-4bd6-420d-b44c-cdbb621093ee/image.png" width=80%></p>

<hr>
<h4 id="🌞-풀이">🌞 풀이</h4>
<ol>
<li><p>map의 정보를 저장
1-1. 이때 0으로 초기화된 arr[1001][1001]을 선언하여 (1,1) ~ (N,N) 까지 이용</p>
</li>
<li><p>레이저를 쏘는 위치 K를 결정하기 위해 K만큼 while 실행
2-1. (1,0) 부터 시작하여 R 방향으로 한 칸씩 증가
2-2. InRange 를 벗어나면 D 방향으로 한 칸씩 증가
2-3. 같은 방식으로 한바퀴를 돌기 전에 K가 실행되는 위치 (x, y)를 구함</p>
</li>
<li><p>K좌표에서 레이저 빛이 나가는 방향을 결정
3-1. 앞서 (x, y)를 구할 때의 방향을 오른쪽으로 돌리면 K에서 레이저 빛이 나가는 방향이 됨</p>
</li>
<li><p>최대 n<em>2 번 레이저 빛이 굴절될 수 있으므로, n</em>2 번 while 문 반복
4-1. arr[x][y]의 레이저 방향에 따라 방향 전환
4-2. 방향대로 한칸씩 이동하며 cnt ++ 하다가 범위를 벗어나면 return 0;</p>
</li>
</ol>
<hr>
<h4 id="🌞-작성코드">🌞 작성코드</h4>
<pre><code>#include &lt;iostream&gt;
using namespace std;

//U, R, D, L
int dx[4]={-1, 0, 1, 0};
int dy[4]={0, 1, 0, -1};

int N, K;
int x=1, y=0, dir=1, cnt=0;
char arr[1001][1001];

bool InRange(int x, int y) {
    return (1&lt;=x &amp;&amp; x&lt;=N &amp;&amp; 1&lt;=y &amp;&amp; y&lt;=N);
}

int main() {
    cin &gt;&gt; N;
    int max=2*N;

    for (int i=1; i&lt;=N; i++) {
        for (int j=1; j&lt;=N; j++) {
            cin &gt;&gt; arr[i][j];
        }
    }

    cin &gt;&gt; K;

    while(K&gt;0) {
        K--;
        int r = x + dx[dir]; int c = y + dy[dir];
        if(InRange(r, c)) {
            x=r; y=c;
        } else {
            dir = (dir+1)%4;
        }
    }

    dir = (dir+1)%4;

    while (max&gt;0) {
        max--;

        if(arr[x][y]==&#39;/&#39;) {
            if (dir == 0) {
                dir = 1;
            } else if (dir == 1) {
                dir = 0;
            } else if (dir == 2) {
                dir = 3;
            } else {
                dir = 2;
            }
        } else {
            if (dir == 0) {
                dir = 3;
            } else if (dir == 1) {
                dir = 2;
            } else if (dir == 2) {
                dir = 1;
            } else {
                dir = 0;
            }
        }

        if (InRange(x, y)) {
            cnt++;
            x += dx[dir]; y += dy[dir];
        } else {
            cout &lt;&lt; cnt;
            return 0;
        }
    }

    cout &lt;&lt; cnt;

    return 0;
}</code></pre><hr>
<h4 id="🌞-제출결과">🌞 제출결과</h4>
<p align="center"><img src="https://velog.velcdn.com/images/wjd_oou/post/abe451e2-9275-4f18-8724-be80558e56fe/image.png" width=80%></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코드트리] dx dy technique 작은 구슬의 이동]]></title>
            <link>https://velog.io/@wjd_oou/%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC-dx-dy-technique-%EC%9E%91%EC%9D%80-%EA%B5%AC%EC%8A%AC%EC%9D%98-%EC%9D%B4%EB%8F%99</link>
            <guid>https://velog.io/@wjd_oou/%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC-dx-dy-technique-%EC%9E%91%EC%9D%80-%EA%B5%AC%EC%8A%AC%EC%9D%98-%EC%9D%B4%EB%8F%99</guid>
            <pubDate>Sun, 18 Aug 2024 12:31:29 GMT</pubDate>
            <description><![CDATA[<h4 id="🌞-문제">🌞 문제</h4>
<p align="center"><img src="https://velog.velcdn.com/images/wjd_oou/post/8c7f5359-f7ea-4564-b265-6d095aad2212/image.png" width=80%></p>


<p align="center"><img src="https://velog.velcdn.com/images/wjd_oou/post/6b52cb4b-7592-43da-8e00-443c2ce2d13e/image.png" width=80%></p>

<hr>
<h4 id="🌞-풀이">🌞 풀이</h4>
<ol>
<li><p>while을 이용해 1초마다 구슬의 방향 결정 + 이동</p>
</li>
<li><p>구슬의 방향 결정을 위해서 InRange, Direction 함수 사용
2-1. 좌상단의 칸이 1행 1열이기 때문에 InRange 범위를 1부터 n까지로 설정
2-2. Direction 함수는 dr, dc의 배열 인덱스 중 어떤 방향을 사용할지 정해주는 dir 변수를 설정</p>
</li>
<li><p>while문 내에서 임시로 구슬을 옮긴 뒤(nr, nc) InRange 함수에 대입
3-1. True : 구슬을 실제로 옮긴다.
3-2. False : 구슬을 옮기지 않고 방향만 바꾼다.</p>
</li>
</ol>
<hr>
<h4 id="🌞-작성코드">🌞 작성코드</h4>
<pre><code>#include &lt;iostream&gt;
#define DIR 4
using namespace std;

int n, t, dir;

//U, R, D, L
int dr[DIR] = {-1, 0, 1, 0};
int dc[DIR] = {0, 1, 0, -1};

bool InRange(int r, int c) {
    return (1&lt;=r &amp;&amp; r&lt;=n &amp;&amp; 1&lt;=c &amp;&amp; c&lt;=n);
}

void Direction(char d) {
    if (d==&#39;U&#39;) {
        dir = 0;
    } else if (d==&#39;R&#39;) {
        dir = 1;
    } else if (d==&#39;D&#39;) {
        dir = 2;
    } else {
        dir = 3;
    }
}

int main() {
    cin &gt;&gt; n &gt;&gt; t;
    int a[n][n];

    int r, c; char d;
    cin &gt;&gt; r &gt;&gt; c &gt;&gt; d;

    Direction(d);
    while (t&gt;0) {
        int nr = r, nc = c;
        nr += dr[dir];
        nc += dc[dir];

        if (InRange(nr, nc)) {
            r = nr; c = nc;
        } else {
            if (d==&#39;U&#39;) { d=&#39;D&#39;; }
            else if (d==&#39;D&#39;) { d=&#39;U&#39;; }
            else if (d==&#39;R&#39;) { d=&#39;L&#39;; }
            else if (d==&#39;L&#39;) { d=&#39;R&#39;; }

            Direction(d);
        }

        t--;
    }

    cout &lt;&lt; r &lt;&lt; &quot; &quot; &lt;&lt; c;
    return 0;
}</code></pre><hr>
<h4 id="🌞-제출결과">🌞 제출결과</h4>
<p align="center"><img src="https://velog.velcdn.com/images/wjd_oou/post/18cc2792-aba7-46a1-8cd2-1ec90ff35148/image.png" width=80%></p>]]></description>
        </item>
        <item>
            <title><![CDATA[[Colab] 번역 API 비교]]></title>
            <link>https://velog.io/@wjd_oou/Colab-Google-Colab%EC%97%90-%EB%B2%88%EC%97%AD-%EC%98%AC%EB%A6%AC%EA%B8%B0</link>
            <guid>https://velog.io/@wjd_oou/Colab-Google-Colab%EC%97%90-%EB%B2%88%EC%97%AD-%EC%98%AC%EB%A6%AC%EA%B8%B0</guid>
            <pubDate>Mon, 27 May 2024 19:30:23 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="💻졸업프로젝트-보성말차">💻졸업프로젝트 &lt;보성말차&gt;</h2>
<hr>
<p>교내 분실물 센터에서는 하나의 사진 안에 모든 분실물을 때려박아 (?) 업로드 하고 있다. 우리가 원하는 건 쉽게 말해 사진에 있는 물체를 자동으로 분류하는 것인데, 그러려면 먼저 생성형 LLM 모델이 물체를 인식해 특징을 출력해야겠다.</p>
<br>

<p>👩🏻👧🏻🧒🏻 멘토님 도와주세요@!!</p>
<blockquote>
<p>👦🏻 LLaVA, MiniGPT-4, deepseek</p>
</blockquote>
<br>

<h3 id="💻model">💻Model</h3>
<p>멘토님께서 추천해주신 여러가지 기술들은 &lt;영어&gt; 기준이다. 
한글로 prompt를 입력했을 경우 영어보다 성능이 좋지않게 나올 수 있으니 멘토님께서 추천해주신 방법은 </p>
<ol>
<li>한글로 질문</li>
<li>질문을 영어로 번역</li>
<li>영어로 출력된 결과를 한글로 다시 번역</li>
<li>한글로 번역된 결과를 출력</li>
</ol>
<p>번역을 돕는 API는 여러가지가 있기 때문에 어떤 API를 올리는 것이 가장 좋은 성능을 보일지 직접 부딪혀보는 수 밖에는 없겠다.</p>
<blockquote>
<p><a href="https://jehyunlee.github.io/2023/02/20/Python-DS-128-transqual/">https://jehyunlee.github.io/2023/02/20/Python-DS-128-transqual/</a></p>
</blockquote>
<p>번역 모델을 비교해주신 좋은 글이 있길래 참고하였다.
직접 소요시간을 확인해보고 싶은데, 아쉽게 파파고는 서비스를 종료하였다.</p>
<p align="center"><img src="https://velog.velcdn.com/images/wjd_oou/post/fd83cead-4e4f-42d5-ba6d-f8f11f7fd6fb/image.png" width=80%></p>

<p>그래서 위 글을 참고하여 아래 세 개 모델에 대해서 성능을 비교해보기로 한다.</p>
<ol>
<li>Google Translation API<ul>
<li>무료 (체험판)</li>
<li>안정적인 성능</li>
</ul>
</li>
<li>Huggingface<ul>
<li>무료</li>
<li>최신, 완성도 높은 모델</li>
</ul>
</li>
<li>OpenAI GPT3<ul>
<li>유료</li>
<li>수행할 때마다 다른 결과</li>
</ul>
</li>
</ol>
<br>

<h2 id="💻google-colab">💻Google Colab</h2>
<p align="center"><img src="https://colab.research.google.com/img/colab_favicon_256px.png" ></p>

<p>협업에 용이한 Google Colab에서 코드를 작성하기로.</p>
<br>

<h3 id="💻colab에-llava를-올려보자">💻Colab에 LLaVA를 올려보자</h3>
<p>번역 성능을 비교하려면 번역할 문장이 필요하다. (당연함)
번역할 문장을 유명한 책이나 논문 초록에서 뽑아올까 생각했으나
이왕이면 우리가 사용할 분실물 사진을 이용하는게 좋을 듯.</p>
<p>Segmentation 과정을 거치지 않은 원본 분실물 사진 데이터를 설명해줄 LLaVA를 Colab에 먼저 올려보자.</p>
<blockquote>
<p><a href="https://github.com/camenduru/LLaVA-colab/blob/main/LLaVA_7b_colab.ipynb">https://github.com/camenduru/LLaVA-colab/blob/main/LLaVA_7b_colab.ipynb</a></p>
</blockquote>
<blockquote>
<p><a href="https://hypro2.github.io/llava-colab/">https://hypro2.github.io/llava-colab/</a></p>
</blockquote>
<p>위의 두 링크를 참고해서 코드를 완성했다. 
특히 아래 포스팅의 <code>def caption_image(image_file, prompt)</code> 함수를 눈여겨보았다. </p>
<p>Colab에 LLaVA를 올리는 것, 쉽지않은 일이다.
생각보다 LLaVA가 무거워서 설치하는 데에만 몇십 분 이상 걸린다.</p>
<p>Colab 내 &#39;/content&#39; 하위 폴더로 &#39;/image&#39;를 생성한다. 
image 폴더에 분실물 사진을 저장한다.</p>
<p align="center"><img src="https://velog.velcdn.com/images/wjd_oou/post/a419f544-0616-4bac-8511-708f7c47b5db/image.jpg" width=60%>
  (저장한 분실물 예시)</p>

<pre><code>image_path = &quot;/content/image&quot;
file_list = [file_name for file_name in os.listdir(image_path) if os.path.isfile(os.path.join(image_path, file_name))]

prompt = &quot;Please describe this image. Which objects are in this image?&quot;

# 이미지 파일 읽어서 번역 후 출력
for file_name in file_list:
  images =(os.path.join(image_path, file_name))
  image, output = caption_image(images, prompt)

  print(&quot;파일명:&quot;+file_name+&quot;\n&quot;)
  print(&quot;본문: &quot;+output+&quot;\n&quot;)</code></pre><p align="center"><img src="https://velog.velcdn.com/images/wjd_oou/post/9a7b2d40-3058-418b-8951-b60b2d31436a/image.png" ></p>

<p>LLaVA에게 의뢰한 (?) 결과가 잘 나온다. 
해당 결과를 먼저 Google Translation으로 번역해보자. </p>
<br>

<h3 id="💻실행-오류-발생-시">💻실행 오류 발생 시</h3>
<blockquote>
<p>본격적인 설치에 앞서</p>
</blockquote>
<p>만약 실행이 되지 않는다면 오류 로그를 확인해보고, 각 API 실행에 필요한 python 패키지를 맞는 버전으로 모두 설치했는지 확인해보자.</p>
<p>패키지 업그레이드 <code>!pip install --upgrade 패키지명==버전</code></p>
<p>패키지 삭제 <code>!pip uninstall 패키지명</code></p>
<p>패키지 설치 여부 확인 <code>!pip list</code></p>
<br>

<h2 id="💻google-translation">💻Google Translation</h2>
<pre><code>!pip install --upgrade httpcore==0.15.* httpx==0.24.*
!pip install --upgrade googletrans==4.0.0-rc1</code></pre><p>컴퓨터에 httpcore와 httpx, googletrans가 설치되어있지 않다면 --upgrade를 제외하고 실행하면 된다. </p>
<blockquote>
<p>실행 코드</p>
</blockquote>
<pre><code>import os
from googletrans import Translator
from time import time

google = Translator()

image_path = &quot;/content/image&quot;
file_list = [file_name for file_name in os.listdir(image_path) if os.path.isfile(os.path.join(image_path, file_name))]

prompt = &quot;Please describe this image. Which objects are in this image?&quot;

# 이미지 파일 읽어서 번역 후 출력
for file_name in file_list:
  images =(os.path.join(image_path, file_name))
  image, output = caption_image(images, prompt)

  time_start = time()
  translation = google.translate(output, dest=&quot;ko&quot;)
  time_end = time()

  print(&quot;파일명:&quot;+file_name+&quot;\n&quot;)
  print(&quot;본문: &quot;+output+&quot;\n&quot;)
  print(&quot;번역문: &quot;+translation.text+&quot;\n&quot;)
  print(f&quot;소요시간: {time_end-time_start:.2f}s&quot;)</code></pre><blockquote>
<p>결과</p>
</blockquote>
<pre><code>파일명:1.jpg

본문: The image features a spacious room with a variety of objects scattered across the floor. There is a spiral notebook, a Starbucks coffee cup, a cell phone, a laptop, and a power cord. Additionally, there are some stickers on the floor, adding to the cluttered appearance of the scene.

번역문: 이미지에는 바닥에 다양한 물체가 흩어져있는 넓은 방이 있습니다.나선형 노트북, 스타 벅스 커피 컵, 휴대폰, 노트북 및 전원 코드가 있습니다.또한 바닥에 스티커가 있으며 장면의 혼란스러운 모양이 추가됩니다.

소요시간: 0.87s
파일명:12.jpg

본문: The image features a variety of items laid out on a table or floor. These items include a package of noodles, a pair of scissors, a pen, a watch, and a cell phone. The objects are spread out, with some items placed closer to the front and others near the back. The scene appears to be a collection of everyday items, possibly for a craft project or a display of personal belongings.

번역문: 이미지에는 테이블이나 바닥에 배치 된 다양한 항목이 있습니다.이 항목에는 국수 패키지, 가위, 펜, 시계 및 휴대폰이 포함됩니다.물체는 펼쳐져 있으며 일부 품목은 전면에 가까워지고 다른 항목은 뒤쪽 근처에 있습니다.이 장면은 공예 프로젝트 또는 개인 소지품 전시를위한 일상적인 아이템 모음으로 보입니다.

소요시간: 0.53s
파일명:4.jpg

본문: The image features a white keyboard, a hat, and a sweater. The keyboard is placed next to the hat, and the sweater is positioned nearby. The objects are arranged on a surface, possibly a table or a floor.

번역문: 이미지에는 흰색 키보드, 모자 및 스웨터가 있습니다.키보드는 모자 옆에 배치되며 스웨터는 근처에 위치합니다.물체는 표면, 아마도 테이블 또는 바닥에 배치됩니다.

소요시간: 0.98s
파일명:13.jpg

본문: The image features a variety of objects laid out on a table, including a laptop, a keyboard, a mouse, a book, a cell phone, and a stuffed animal. The objects are arranged in a way that suggests they are being prepared for packing or organizing.

번역문: 이미지에는 랩톱, 키보드, 마우스, 책, 휴대폰 및 박제 동물을 포함하여 다양한 물체가 테이블에 배치되어 있습니다.물체는 포장 또는 구성을 준비하고 있음을 시사하는 방식으로 배열됩니다.

소요시간: 0.99s
파일명:2.jpg

본문: The image features a notebook and a pair of earbuds placed on a table. The notebook is open, and the earbuds are sitting next to it. The table appears to be a desk, and the objects are arranged neatly on its surface.

번역문: 이미지에는 노트북과 한 쌍의 이어 버드가 테이블 위에 놓여 있습니다.노트북이 열려 있고 이어 버드는 그 옆에 앉아 있습니다.테이블은 책상 인 것처럼 보이며 물체는 표면에 깔끔하게 배열됩니다.

소요시간: 0.50s</code></pre><br>

<p>몇 가지 아쉬운 점이 눈에 띈다. </p>
<p><span style='background-color: #F7DDBE'>spiral notebook </span></p>
<ul>
<li>예상 결과 : 스프링노트</li>
<li>실제 결과 : 나선형 노트북</li>
</ul>
<p><span style='background-color: #F7DDBE'>earbuds</span></p>
<ul>
<li>예상 결과 : 이어폰</li>
<li>실제 결과 : 이어 버드</li>
</ul>
<br>

<p>전체적인 번역 퀄리티는 나쁘지 않으나, 평소 사용하지 않는 용어로 번역된 단어가 많아 &#39;용어집&#39; 사용 등을 고려해보는 것이 좋을 것 같다. </p>
<br>

<h2 id="💻huggingface">💻Huggingface</h2>
<p>별도로 프로그램을 설치하거나 API를 받을 필요 없이 파이썬 패키지 설치로 사용할 수 있기 때문에 간단하다.</p>
<pre><code>!pip install transformers sentencepiece -q</code></pre><p>다만 아래와 같은 오류가 발생할 수 있는데, 
<code>A UTF-8 locale is required. Got ANSI_X3.4-1968</code>
이런 경우에는 &#39;!&#39; 명령어 대신 파이썬에서 제공하는 &#39;subprocess&#39; 모듈을 통해 UTF-8 export, pip install을 진행해준다.</p>
<pre><code>import subprocess

subprocess.run([&#39;export&#39;, &#39;LC_ALL=C.UTF-8&#39;], shell=True)
subprocess.run([&#39;export&#39;, &#39;LANG=C.UTF-8&#39;], shell=True)

subprocess.run([&#39;pip&#39;, &#39;install&#39;, &#39;transformers&#39;, &#39;sentencepiece&#39;, &#39;-q&#39;])</code></pre><blockquote>
<p>실행</p>
</blockquote>
<pre><code>from transformers import pipeline

pipe = pipeline(task=&#39;text2text-generation&#39;, model=&#39;facebook/m2m100_418M&#39;)

image_path = &quot;/content/image&quot;
file_list = [file_name for file_name in os.listdir(image_path) if os.path.isfile(os.path.join(image_path, file_name))]

prompt = &quot;Please describe this image. Which objects are in this image?&quot;

# 이미지 파일 읽어서 번역 후 출력
for file_name in file_list:
  images =(os.path.join(image_path, file_name))
  image, output = caption_image(images, prompt)

  time_start = time()
  translation = pipe(output, forced_bos_token_id=pipe.tokenizer.get_lang_id(lang=&#39;ko&#39;))
  time_end = time()

  print(&quot;파일명:&quot;+file_name+&quot;\n&quot;)
  print(&quot;본문: &quot;+output+&quot;\n&quot;)
  print(f&quot;번역문: {translation[0][&#39;generated_text&#39;]}&quot;+&quot;\n&quot;)
  print(f&quot;소요시간: {time_end-time_start:.2f}s&quot;)</code></pre><blockquote>
<p>결과</p>
</blockquote>
<pre><code>파일명:1.jpg

본문: The image features a spacious room with a variety of objects on the floor. There is a notebook, a Starbucks coffee cup, a cell phone, and a book. Additionally, there are two cords and a small container on the floor. The objects are scattered around the room, creating a casual and relaxed atmosphere.

번역문: 그림은 바닥에 다양한 개체가있는 넓은 방을 갖추고 있습니다. 노트북, 스타벅스 커피 컵, 휴대 전화 및 책이 있습니다. 또한 바닥에 두 개의 코드와 작은 컨테이너가 있습니다.

소요시간: 19.87s
파일명:12.jpg

본문: The image features a variety of objects laid out on a table or counter. Among these objects, there is a package of noodles, a package of chocolate, a pair of scissors, a pen, a watch, and a cell phone. The items are spread out, and some are placed closer to the edges of the table. The scene gives the impression of a collection of everyday items, possibly for a craft project or a display of personal belongings.

번역문: 이 이미지에는 테이블이나 컨테이너에 놓인 다양한 개체가 있습니다.이 개체 중에는 노드 패키지, 초콜릿 패키지, 쌍의 분쇄기, 펜, 시계 및 휴대 전화가 있습니다. 항목이 퍼져 있으며 일부는 테이블의 가장자리에 더 가까이 배치됩니다.

소요시간: 25.18s
파일명:4.jpg

본문: The image features a variety of objects, including a white keyboard, a hat, a sweater, and a pair of glasses. The objects are placed on a table, creating an assortment of items.

번역문: 그림에는 화이트 키보드, 모자, 스위터, 그리고 안경 쌍을 포함한 다양한 개체가 있습니다.

소요시간: 9.29s
파일명:13.jpg

본문: The image features a variety of objects laid out on a table or a counter. There is a laptop computer, a keyboard, a mouse, a cell phone, and a book. Additionally, there is a stuffed animal, possibly a teddy bear, and a jacket. The objects are arranged in a way that suggests they are being prepared for a trip or a journey.

번역문: 그림은 테이블이나 카운터에 놓인 다양한 개체를 보여줍니다. 노트북 컴퓨터, 키보드, 마우스, 휴대 전화, 그리고 책이 있습니다. 또한, 포장 된 동물, 어쩌면 꼬마 곰, 그리고 재킷이 있습니다.

소요시간: 20.98s
파일명:2.jpg

본문: The image features a notebook and a pair of earbuds placed on a table. The notebook is open, and the earbuds are lying next to it.

번역문: 그림에는 노트북과 테이블에 놓인 쌍의 벽돌이 있습니다. 노트북은 열려 있으며 벽돌은 그 옆에 있습니다.

소요시간: 12.02s</code></pre><br>


<p>굉장히 느리다. 
앞서 Google Translation이 채 10초가 되지 않는 시간에 결과를 뽑았던 것과는 다르게 Huggingface는 <del>최소10초?</del></p>
<p>번역해야할 문장이 많은 우리 프로젝트에는 적합하지 않아 보인다.</p>
<p>번역의 성능은 어떨지 질적 평가를 해보자. </p>
<p>LLaVA 모델을 계속 새로 돌리다보니 Google Translation과 번역한 본문이 달라졌다는 것이 아쉬운데, 마지막에 같은 문장으로 성능을 한번 비교해보도록 하자. </p>
<blockquote>
<p>본문
The image features a variety of objects laid out on a table or a counter. There is a laptop computer, a keyboard, a mouse, a cell phone, and a book. Additionally, there is a stuffed animal, possibly a teddy bear, and a jacket. The objects are arranged in a way that suggests they are being prepared for a trip or a journey.</p>
</blockquote>
<h5 id="본문의-마지막-문장을-주목하자">본문의 마지막 문장을 주목하자</h5>
<blockquote>
<p>번역문
그림은 테이블이나 카운터에 놓인 다양한 개체를 보여줍니다. 노트북 컴퓨터, 키보드, 마우스, 휴대 전화, 그리고 책이 있습니다. 또한, 포장 된 동물, 어쩌면 꼬마 곰, 그리고 재킷이 있습니다.</p>
</blockquote>
<p>본문의 마지막 문장은 <span style="color: red">아예 번역하지 않았다.</span></p>
<p>번역의 퀄리티를 떠나 아예 문장을 번역하지 않는다는 것은 우리 프로젝트 결과에도 영향을 줄 수 있는 부분이다. </p>
<br>

<h2 id="💻gpt">💻GPT</h2>
<p>GPT에서 주목할 점은 앞선 번역 모델들과 달리, 실행할때마다 결과가 다르게 나온다는 점이다. </p>
<blockquote>
<p>사전 준비</p>
</blockquote>
<p><code>!pip install openai==0.28</code>
<code>!pip install httpx==0.23.0</code></p>
<p>또는</p>
<pre><code>import subprocess

subprocess.run([&#39;export&#39;, &#39;LC_ALL=C.UTF-8&#39;], shell=True)
subprocess.run([&#39;export&#39;, &#39;LANG=C.UTF-8&#39;], shell=True)

subprocess.run([&#39;pip&#39;, &#39;install&#39;, &#39;openai==0.28&#39;])
subprocess.run([&#39;pip&#39;, &#39;install&#39;, &#39;httpx==0.23.0&#39;])</code></pre><blockquote>
<p>실행</p>
</blockquote>
<pre><code>import openai
openai.api_key = &quot;본인의 API 키&quot;

from functools import wraps

image_path = &quot;/content/image&quot;
file_list = [file_name for file_name in os.listdir(image_path) if os.path.isfile(os.path.join(image_path, file_name))]

prompt = &quot;Please describe this image. Which objects are in this image?&quot;

def timed(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        time_start = time()
        result = func(*args, **kwargs)
        time_end = time()
        print(f&#39;- 소요시간: {time_end-time_start:.2f}s&#39;)
        return result
    return wrapper

@timed
def translateGPT(text, model=&quot;gpt-3.5-turbo-0613&quot;, max_tokens=1000, top_p=1.0):
    response = openai.Completion.create(
      model=model,
      prompt=f&quot;Translate this in Korean:{text}&quot;,
      temperature=0.3,
      max_tokens=max_tokens,
      top_p=top_p,
      frequency_penalty=0.0,
      presence_penalty=0.0
    )
    return response.to_dict()[&#39;choices&#39;][0][&quot;text&quot;].lstrip(&quot;\n&quot;)

for file_name in file_list:
  images =(os.path.join(image_path, file_name))
  image, output = caption_image(images, prompt)

  print(&quot;파일명:&quot;+file_name+&quot;\n&quot;)
  print(&quot;본문: &quot;+output+&quot;\n&quot;)
  print(f&quot;번역문: {translateGPT(output)}&quot;)</code></pre><blockquote>
<p>결과</p>
</blockquote>
<pre><code>RateLimitError: You exceeded your current quota, please check your plan and billing details. 
For more information on this error, read the docs:
https://platform.openai.com/docs/guides/error-codes/api-errors.</code></pre><p>Chat GPT는 과금 이슈를 해결하지 못해서 아쉽게 번역해보지 못했다.</p>
<p>다만 저예산으로 최고의 효율을 뽑아내야하는 대학수준 졸업프로젝트에서 &lt;과금&gt; 요소는 부담이다. </p>
<br>

<h2 id="💻api-선택">💻API 선택</h2>
<p>결국 나의 선택은 Google Translation API! </p>
<p>무료이면서 빠른 속도, 괜찮은 성능이 선택 이유이다.</p>
<p>단어 번역이 아쉬웠으나, 대학교 내에서 자주 잃어버리는 물건 등은 용어집을 적극적으로 활용해 번역 정확도를 높이도록 하겠다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[스프링 부트와 AWS로 혼자 구현하는 웹 서비스] 오류Log (3)]]></title>
            <link>https://velog.io/@wjd_oou/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8%EC%99%80-AWS%EB%A1%9C-%ED%98%BC%EC%9E%90-%EA%B5%AC%ED%98%84%ED%95%98%EB%8A%94-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%98%A4%EB%A5%98Log-3</link>
            <guid>https://velog.io/@wjd_oou/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8%EC%99%80-AWS%EB%A1%9C-%ED%98%BC%EC%9E%90-%EA%B5%AC%ED%98%84%ED%95%98%EB%8A%94-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%98%A4%EB%A5%98Log-3</guid>
            <pubDate>Fri, 01 Mar 2024 17:13:59 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>📚 <a href="https://product.kyobobook.co.kr/detail/S000001019679">스프링 부트와 AWS로 혼자 구현하는 웹 서비스</a></p>
</blockquote>
<hr>
<h3 id="p181---antmatchers-오류">p.181   .antMatchers 오류</h3>
<p>버전이 바뀌면서 더이상 <span style="color: red"><code>.antMatchers</code></span> 를 지원하지 않는다고 한다. </p>
<p><a href="https://mingeonho1.tistory.com/entry/Spring-Security-%EB%B2%84%EC%A0%84-%EC%9D%B4%EC%8A%88%EB%A1%9C-%EC%9D%B8%ED%95%9C-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0">(참고) 블로그</a></p>
<p>다음과 같이 코드를 바꿔주었다. </p>
<br>

<p><span style="background-color: #F7DDBE">기존 코드</span></p>
<pre><code>package com.jojoldu.book.springboot.config.auth;

import com.jojoldu.book.springboot.domain.user.Role;
import lombok.RequiredArgsConstructor;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@RequiredArgsConstructor
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final CustomOAuth2UserService customOAuth2UserService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .headers().frameOptions().disable()
                .and()
                    .authorizeRequests()
                    .antMatchers(&quot;/&quot;, &quot;/css/**&quot;, &quot;/images/**&quot;, &quot;/js/**&quot;, &quot;/h2-console/**&quot;, &quot;/profile&quot;).permitAll()
                    .antMatchers(&quot;/api/v1/**&quot;).hasRole(Role.USER.name())
                    .anyRequest().authenticated()
                .and()
                    .logout()
                        .logoutSuccessUrl(&quot;/&quot;)
                .and()
                    .oauth2Login()
                        .userInfoEndpoint()
                            .userService(customOAuth2UserService);
    }
}</code></pre><br>

<p><span style="background-color: #F7DDBE">바꾼 코드</span></p>
<pre><code>package com.jojoldu.book.springboot.config.auth;

import com.jojoldu.book.springboot.domain.user.Role;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@RequiredArgsConstructor
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final CustomOAuth2UserService customOAuth2UserService;

    @Bean
    protected SecurityFilterChain configure(HttpSecurity http) throws Exception {
        http
                .csrf(AbstractHttpConfigurer::disable)
                .headers((headers) -&gt; headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
                .authorizeHttpRequests(auth -&gt; auth
                        .requestMatchers(
                                new AntPathRequestMatcher(&quot;/&quot;),
                                new AntPathRequestMatcher(&quot;/css/**&quot;),
                                new AntPathRequestMatcher(&quot;/images/**&quot;),
                                new AntPathRequestMatcher(&quot;/js/**&quot;),
                                new AntPathRequestMatcher(&quot;/h2-console/**&quot;),
                                new AntPathRequestMatcher(&quot;/profile&quot;)
                        ).permitAll()
                        .requestMatchers(new AntPathRequestMatcher(&quot;/api/v1/**&quot;)).hasRole(Role.USER.name())
                        .anyRequest().authenticated())
                .logout((logout) -&gt; logout
                        .logoutSuccessUrl(&quot;/&quot;))
                .oauth2Login((oauth2) -&gt; oauth2
                        .userInfoEndpoint(userInfoEndpoint -&gt; userInfoEndpoint
                                .userService(customOAuth2UserService))
                        .defaultSuccessUrl(&quot;/&quot;, true));

        return http.build();
    }
}</code></pre><br>

<pre><code>.csrf(AbstractHttpConfigurer::disable)</code></pre><p>이 코드에서 <code>AbstractHttpConfigurer</code> 에 오류가 나던데
아예 지우고 다시 작성하니 제대로 돌아간다.</p>
<br>

<hr>
<h3 id="p190---테이블-생성-오류">p.190   테이블 생성 오류</h3>
<br>

<p>Google Login 화면에서 로그인하려해도 다음 화면으로 넘어가지지를 않는 문제가 생겼다. (화면이 멈춰서 클릭이 안먹히는)</p>
<p>오류로그 전문 중 첫번째 줄</p>
<pre><code>org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL &quot;drop table if exists user&quot; via JDBC [Syntax error in SQL statement &quot;drop table if exists [*]user&quot;; expected &quot;identifier&quot;;]</code></pre><p><span style="background-color: #F7DDBE">expected “identifier”</span> 가 의심스러워서 좀 찾아보니</p>
<p>h2에서 user 라는 예약어가 이미 존재하기 때문에 책처럼 user 라는 이름으로 테이블을 생성하면 오류가 난다.</p>
<p><a href="https://github.com/jojoldu/freelec-springboot2-webservice/issues/875">(참고) Github💻 Q&amp;A</a></p>
<p>나랑 비슷한 문제가 생겼던 사람이 github에 질문을 남긴 것을 확인했다. </p>
<br>

<h5 id="before--span-stylebackground-color-lightgrey📁-domainuser-span">before : <span style="background-color: lightGrey">📁 /domain/user </span></h5>
<h5 id="after--span-stylebackground-color-lightgrey📁-domainusers-span">after : <span style="background-color: lightGrey">📁 /domain/users </span></h5>
<p>user 아래에 Role, User, UserRepository 세 파일을 만들어두었는데, 이걸 모두 Users 로 변경해주었다. </p>
<br>
<br>

<h4 id="role-enum-클래스">Role Enum 클래스</h4>
<pre><code>package com.jojoldu.book.springboot.domain.users;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum Role {

    GUEST(&quot;ROLE_GUEST&quot;, &quot;손님&quot;),
    USER(&quot;ROLE_USER&quot;, &quot;일반 사용자&quot;);

    private final String key;
    private final String title;

}</code></pre><br>

<h4 id="users-클래스">Users 클래스</h4>
<pre><code>package com.jojoldu.book.springboot.domain.users;

import com.jojoldu.book.springboot.domain.BaseTimeEntity;
import com.jojoldu.book.springboot.domain.users.Role;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import jakarta.persistence.*;

@Getter
@NoArgsConstructor
@Entity
public class Users extends BaseTimeEntity {

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

    @Column(nullable = false)
    private String name;

    @Column(nullable = false)
    private String email;

    @Column
    private String picture;

    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private com.jojoldu.book.springboot.domain.users.Role role;

    @Builder
    public Users(String name, String email, String picture, Role role) {
        this.name = name;
        this.email = email;
        this.picture = picture;
        this.role = role;
    }

    public com.jojoldu.book.springboot.domain.users.Users update(String name, String picture) {
        this.name = name;
        this.picture = picture;

        return this;
    }

    public String getRoleKey() {
        return this.role.getKey();
    }
}</code></pre><br>

<h4 id="usersrepository-인터페이스">UsersRepository 인터페이스</h4>
<pre><code>package com.jojoldu.book.springboot.domain.users;

import com.jojoldu.book.springboot.domain.users.Users;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface UsersRepository extends JpaRepository&lt;Users, Long&gt; {

    Optional&lt;Users&gt; findByEmail(String email);
}</code></pre><br>

<p>변경 완료!</p>
<p>이외에 다른 파일들도 작성하면서 domain.user 경로로 import 했던 것들을 모두 domain.users 로 변경해주었다. </p>
<p align="center">
  <img src="https://velog.velcdn.com/images/wjd_oou/post/b9e9b485-541c-4b89-9c2b-43832a65a307/image.png" alt="설명글" width="100%" />
</p>

<p>로그인이 잘 되는 것을 확인하였다. </p>
<p align="center">
  <img src="https://velog.velcdn.com/images/wjd_oou/post/0dbafe1e-464f-49e4-8eaf-7c344ee86193/image.png" alt="설명글" width="100%" />
</p>

<p>USERS 테이블도 잘 생성된 것을 확인할 수 있었다.</p>
<br>

<hr>
<h3 id="p194---권한-변경">p.194   권한 변경</h3>
<br>

<p>기존과 테이블 이름을 다르게 설정해주었으므로 쿼리문도 다르게 작성해주어야한다. 
이걸 깜빡해서 쿼리문은 죄다 -- USER -- 로 RUN 하는 바람에 오류가 나서 당황했다. 항상 내가 쓴 변수명이 무엇인지 잘 기억하도록 하자!</p>
<pre><code>///변경 전
update user set role = &#39;USER&#39;;</code></pre><pre><code>///변경 후
update users set role = &#39;USER&#39;;</code></pre><br>

<hr>
<h3 id="p222---hellocontrollertest-오류">p.222   HelloControllerTest 오류</h3>
<br>

<p>HelloControllerTest 코드를 수정하고 github 예제코드와 분명 비교까지 했는데도 오류가 발생
(코드에 오타 없음... 도대체 왜?)</p>
<pre><code>org.springframework.beans.factory.BeanCreationException: Error creating bean with name &#39;jpaAuditingHandler&#39;: Cannot resolve reference to bean &#39;jpaMappingContext&#39; while setting constructor argument</code></pre><p>아직 오류코드에 익숙하지 않아 봤는데도 솔직히 잘 모르겠어서 구글에 검색 </p>
<br>

<p><a href="https://velog.io/@junsj119/errorMock%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-test%ED%95%98%EB%8D%98-%EC%A4%91-%EB%A7%88%EC%A3%BC%EC%B9%9C-%EC%97%90%EB%9F%AC">(참고) 블로그</a></p>
<p>간단 요약 : <span style="color: green">test 중에 데이터베이스를 사용하지 않아서 스프링이 발생시키는 에러</span></p>
<pre><code>@RunWith(SpringRunner.class)
@WebMvcTest(controllers = HelloController.class,
        excludeFilters = {
                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class)
        }
)
@MockBean(JpaMetamodelMappingContext.class)
public class HelloControllerTest { 
    ...
}</code></pre><p>HelloControllerTest 클래스 위에 <code>@MockBean(JpaMetamodelMappingContext.class)</code> 어노테이션 추가</p>
<pre><code>@MockBean(JpaMetamodelMappingContext.class)</code></pre><p align="center">
  <img src="https://velog.velcdn.com/images/wjd_oou/post/76d80ad5-d4ac-440a-8455-161e200788ae/image.png" alt="설명글" width="100%" />
</p> 

<p>잘 돌아간다</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[스프링 부트와 AWS로 혼자 구현하는 웹 서비스] 오류Log (2)]]></title>
            <link>https://velog.io/@wjd_oou/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8%EC%99%80-AWS%EB%A1%9C-%ED%98%BC%EC%9E%90-%EA%B5%AC%ED%98%84%ED%95%98%EB%8A%94-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%98%A4%EB%A5%98Log-2</link>
            <guid>https://velog.io/@wjd_oou/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8%EC%99%80-AWS%EB%A1%9C-%ED%98%BC%EC%9E%90-%EA%B5%AC%ED%98%84%ED%95%98%EB%8A%94-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%98%A4%EB%A5%98Log-2</guid>
            <pubDate>Thu, 29 Feb 2024 13:34:53 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>📚 <a href="https://product.kyobobook.co.kr/detail/S000001019679">스프링 부트와 AWS로 혼자 구현하는 웹 서비스</a></p>
</blockquote>
<hr>
<h3 id="p88---import-javapersistence-오류-발생">p.88   import java.persistence 오류 발생</h3>
<br>

<p>Spring Boot3 부터는 <span style="color: orange">jakarta</span>로 import 해주는 것이 정석이다.
(javax 패키지명이 jakarta 로 변경되었음)</p>
<p><a href="https://www.inflearn.com/questions/822610/javax-persistence%EA%B0%80-import%EB%90%98%EC%A7%80-%EC%95%8A%EC%8A%B5%EB%8B%88%EB%8B%A4">참고) inflearn🌿 Q&amp;A</a></p>
<pre><code>import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;</code></pre><p>위와같이 변경하여 import 성공!</p>
<br>

<hr>
<h3 id="p100---mysql-쿼리-로그-오류">p.100   MySQL 쿼리 로그 오류</h3>
<br>

<p>출력되는 쿼리 로그를 MySQL 버전으로 변경하는 예제 </p>
<blockquote>
<p>📁 /main/resources/application.properties</p>
</blockquote>
<pre><code>spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect</code></pre><p>책과 똑같이 작성하였는데 테스트 실패</p>
<br>

<p><span style='background-color: #F7DDBE'>저자의 깃허브를 참고</span>하여 다음과 같은 코드로 수정하여 시도</p>
<pre><code>spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
spring.jpa.properties.hibernate.dialect.storage_engine=innodb
spring.datasource.hikari.jdbc-url=jdbc:h2:mem://localhost/~/testdb;MODE=MYSQL</code></pre><p>실패...</p>
<br>

<p>오류 로그를 확인해보니 계속 org.hibernate.dialect 여기서 뭘 가져올 수가 없다고 하는데...</p>
<p>살펴보니 MySQL5 &lt;&lt; 버전이 문제인 것 같아서 다음과 같이 수정하여 시도</p>
<pre><code>spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.jpa.properties.hibernate.dialect.storage_engine=innodb
spring.datasource.hikari.jdbc-url=jdbc:h2:mem://localhost/~/testdb;MODE=MYSQL</code></pre><p align="center">
  <img src="https://velog.velcdn.com/images/wjd_oou/post/a32339ce-e833-4bdf-9244-2db773f58706/image.png" alt="옵션 적용" width="100%" />

<p>옵션이 잘 적용 되었다. </p>
<br>

<hr>
<h3 id="p114---postapicontrollertest-오류">p.114   PostApiControllerTest 오류</h3>
<br>


<pre><code>java.lang.IllegalArgumentException: Name for argument of type [java.lang.Long] not specified, and parameter name information not available via reflection. Ensure that the compiler uses the &#39;-parameters&#39; flag.</code></pre><p>  (오류 로그 전문 중 첫번째 줄)</p>
  <br>

<p>  <span style='background-color: #F7DDBE'>‘-parameters’ flag를 컴파일러가 사용하도록 해라 (?)</span></p>
<p>그거 어떻게 하는건데…</p>
<p align="center">
<img src="https://velog.velcdn.com/images/wjd_oou/post/cc2bf072-ceb6-453f-9301-04e3b6f28ff3/image.png" alt="설명글" width="100%" /></p>


<p>해결방안 2를 따라서 </p>
<p>  <span style='background-color: #F7DDBE'>-parameters 추가 후 out 폴더까지 삭제하는 것</span> 잊지 않고 다시 실행</p>
<p align="center">
<img src="https://velog.velcdn.com/images/wjd_oou/post/c44eb1a8-fe26-4096-8a37-19f44b224220/image.png"alt="설명글" width="100%" /></p>

<p>테스트를 잘 통과하였다!</p>
<p><br></br></p>
<hr>
<h3 id="p116---h2-console-오류">p.116   h2-console 오류</h3>
<br>

<p>책에서와 같이 JDBC URL : jdbc:h2:mem:testdb 로 작성할 경우 Connect 시 오류 발생</p>
<p align="center">
<img src="https://velog.velcdn.com/images/wjd_oou/post/2e7deab3-b8de-409c-aa8f-a6775b42f7bb/image.png" alt="설명글" width="100%" /></p>

<blockquote>
<p>🚨 <span style='color: #D1180B'>Database &quot;mem:testdb&quot; not found, either pre-create it or allow remote database creation (not recommended in secure environments) [90149-224] 90149/90149 (Help)</span></p>
</blockquote>
<p>오류메세지 전문 </p>
<p>mem:testdb 이름의 데이터베이스를 찾을 수 없다고 하는데, 뭔가 문제가 있는 것 같아 <code>application.properties</code> 에 추가한 코드 점검</p>
<pre><code>spring.jpa.show_sql=true

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.jpa.properties.hibernate.dialect.storage_engine=innodb
spring.datasource.hikari.jdbc-url=jdbc:h2:mem://localhost/~/testdb;MODE=MYSQL

spring.h2.console.enabled=true</code></pre><p>세번째 줄 <code>jdbc:h2:mem://localhost/~/testdb;MODE=MYSQL</code> 에 주의
잘보면... datasource url을 jdbc:h2:mem:testdb로 연결하고 있지 않다!</p>
<p align="center">
<img src="https://velog.velcdn.com/images/wjd_oou/post/6ba34898-4201-454a-8556-c99dae6796c2/image.png" alt="설명글" width="100%" /></p>

<p>JDBC URL 을 바꿔주면</p>
<p align="center">
<img src="https://velog.velcdn.com/images/wjd_oou/post/2919f76f-da08-4997-9014-eabdc992ea07/image.png" alt="설명글" width="100%" /></p>


<p>제대로 연결되었다. </p>
<p>왼쪽의 POSTS 테이블도 정상적으로 노출된다.</p>
<p><br></br></p>
<hr>
<h3 id="p134---mustache-한글-깨짐-오류">p.134   mustache 한글 깨짐 오류</h3>
<br>

<p>test 코드를 돌려보니 <span style='color: #D1180B'><code>index.mustache</code></span> 에 작성한 한글 문자가 ???? 로 처리되는 오류가 발생했다. </p>
<p>test 파일에 적어둔 한글 문자와 당연히 똑같지 않아 오류가 발생</p>
<pre><code>java.lang.AssertionError: 
Expecting actual:
  &quot;&lt;!DOCTYPE HTML&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;??? ?? ????&lt;/title&gt;
    &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot; /&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;??? ??? ???? ? ???&lt;/h1&gt;
&lt;/body&gt;
&lt;/html&gt;&quot;
to contain:
  &quot;스트링 부트로 시작하는 웹 서비스&quot;</code></pre><p>와중에 띄어쓰기 맞춰서 문자 하나당 정확히 ? 로 치환된게 웃겨서 열받는다</p>
<p>한시간 정도 오류 해결을 위해 구글링 서치</p>
<p>여러가지 설정도 변경해보고 build도 다시해보고 별방법을 다해봤는데!
결국엔 아래 코드 한 줄로 해결</p>
<blockquote>
<p>📁 …/application.properties</p>
</blockquote>
<pre><code>server.servlet.encoding.force-response= true</code></pre><p align="center">
<img src="https://velog.velcdn.com/images/wjd_oou/post/4388dd9a-e0fc-4def-8fce-b04456e28ad7/image.png" alt="설명글" width="100%" /></p>

<p><br></br></p>
<hr>
<h3 id="p144---파일이-등록되었습니다-오류">p.144   “파일이 등록되었습니다” 오류</h3>
<br>

<p>아무리 새로고침하고 서버를 껐다 켜도 <span style='color: #D1180B'><code>파일이 등록되었습니다</code></span>알람이 뜨지 않는다. </p>
<p>뒤에 나오는 파일들까지 입력하니 돌아간다</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[스프링 부트와 AWS로 혼자 구현하는 웹 서비스] 오류Log (1)]]></title>
            <link>https://velog.io/@wjd_oou/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8%EC%99%80-AWS%EB%A1%9C-%ED%98%BC%EC%9E%90-%EA%B5%AC%ED%98%84%ED%95%98%EB%8A%94-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%98%A4%EB%A5%98Log-1</link>
            <guid>https://velog.io/@wjd_oou/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8%EC%99%80-AWS%EB%A1%9C-%ED%98%BC%EC%9E%90-%EA%B5%AC%ED%98%84%ED%95%98%EB%8A%94-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%98%A4%EB%A5%98Log-1</guid>
            <pubDate>Tue, 27 Feb 2024 07:25:32 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>📚 <a href="https://product.kyobobook.co.kr/detail/S000001019679">스프링 부트와 AWS로 혼자 구현하는 웹 서비스</a></p>
</blockquote>
<hr>
<h3 id="hellodto가_리턴된다-오류">helloDto가_리턴된다() 오류</h3>
<p>2장 마지막 Test code인 <strong>helloDto가_리턴된다()</strong> 가 
test 오류를 보이며 실행되지 않았다. </p>
<p>해결하느라 진짜 애먹었다!</p>
<pre><code>@Test
    public void helloDto가_리턴된다() throws Exception {
        String name = &quot;hello&quot;;
        int amount = 1000;
        mvc.perform(get(&quot;/hello/dto&quot;)
                        .param(&quot;name&quot;, name)
                        .param(&quot;amount&quot;, String.valueOf(amount)))
                .andExpect(status().isOk())
                .andExpect(jsonPath(&quot;$.name&quot;, is(name)))
                .andExpect(jsonPath(&quot;$.amount&quot;, is(amount)));
    }</code></pre><p>혹시 이것도 업데이트 하면서 달라진 명령어가 오류를 일으킨건 아닌지, 타이포가 있는 건지 하루종일 시간을 들여 고민했는데,</p>
<p><span style='background-color: #F7DDBE'>결국 이유를 찾았다</span></p>
<blockquote>
<p>📁 /web/HelloController.java</p>
</blockquote>
<pre><code>@GetMapping(&quot;/hello/dto&quot;)
    public HelloResponseDto helloDto(@RequestParam(&quot;name&quot;) String name,
                                     @RequestParam(&quot;amount&quot;) int amount) {
        return new HelloResponseDto(name, amount);
    }</code></pre><p>테스트 코드가 테스트하는 <strong>HelloResponseDto</strong>를 잘못된 파일에 작성해두고 테스트를 시도했던 것</p>
<p>제대로 된 파일에 붙여넣어두니 Test 코드가 제대로 돌아갔다</p>
<p>(허무)</p>
<br>

<p>오류가 나면 log를 제대로 분석하는 것의 중요성을 깨닫게 된 순간이었다. 로그를 한번만 읽어봤으면 하루종일 고생하는 일은 없었을 텐데</p>
<hr>
<p>이 과정에서 알게된 몇가지</p>
<ol>
<li><p>코드에 오타가 없는지, 잘못 작성하진 않았는지 제대로 확인하기</p>
</li>
<li><p>저자가 티스토리에 여러 명령어를 최신버전으로 업데이트 해두었다.</p>
<p> 🌐 <a href="https://jojoldu.tistory.com/539">jojoldu.tistory.com</a>
 2020.12.16 기준</p>
</li>
</ol>
<hr>
<h4 id="주요-변경사항">주요 변경사항</h4>
<p>@RunWith → @ExtendWith
@SpringRunner → @SpringExtenstion</p>
<hr>
<h3 id="gradle-버전이-맞지-않아-생기는-오류">Gradle 버전이 맞지 않아 생기는 오류</h3>
<pre><code>PermittedSubclasses requires ASM9</code></pre><p>build.gradle 파일에 새로운 dependencies 들을 implementation 했더니 위와같은 오류 발생</p>
<blockquote>
<p>📁 /gradle/wrapper/gradle-wrapper.properties </p>
</blockquote>
<pre><code>distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip</code></pre><p>기존 7.2-bin &gt; 7.6-bin 으로 변경 후 gradle 새로고침</p>
<p><span style='background-color: #F7DDBE'>dependencies 부분만 새로고침 해주었더니 잘 돌아간다.</span></p>
<p><img src="https://velog.velcdn.com/images/wjd_oou/post/9717830a-65fd-4d92-b225-9eb997d1b16d/image.png" alt=""></p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[스프링 부트와 AWS로 혼자 구현하는 웹 서비스] 오류Log (0)]]></title>
            <link>https://velog.io/@wjd_oou/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8%EC%99%80-AWS%EB%A1%9C-%ED%98%BC%EC%9E%90-%EA%B5%AC%ED%98%84%ED%95%98%EB%8A%94-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%98%A4%EB%A5%98Log-0</link>
            <guid>https://velog.io/@wjd_oou/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8%EC%99%80-AWS%EB%A1%9C-%ED%98%BC%EC%9E%90-%EA%B5%AC%ED%98%84%ED%95%98%EB%8A%94-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%98%A4%EB%A5%98Log-0</guid>
            <pubDate>Tue, 27 Feb 2024 07:07:34 GMT</pubDate>
            <description><![CDATA[<p>방학 기간 동안 혼자 해볼만한 토이 프로젝트를 찾던 도중, 좋은 책을 추천 받아 공부하기 시작했다. </p>
<p>아직 모든 걸 혼자 구현하기는 어려움이 있을 거라고 생각했기 때문에, 
책에서 설명해주는 대로 차근차근 웹서비스를 구현해본 뒤 나만의 프로젝트를 시작해보기로 계획을 세웠다. </p>
<hr>
<br>

<h3 id="📚-스프링-부트와-aws로-혼자-구현하는-웹-서비스"><a href="https://product.kyobobook.co.kr/detail/S000001019679">📚 스프링 부트와 AWS로 혼자 구현하는 웹 서비스</a></h3>
<p><img src="https://velog.velcdn.com/images/wjd_oou/post/2082ee03-2705-4092-823f-18224627cd7d/image.png" alt=""></p>
<p>물론 광고 아님... 
<del>나 광고 붙을 만큼 대단한 개발자는 아닌 것 같음</del></p>
<hr>
<br>
결론적으로 이야기하자면, 책에서 설명한 대로 <span style='background-color: #F7DDBE'>구현을 완성하지는 못했다. </span> 

<p>책을 따라 구현하면서 생긴 여러가지 실패의 원인을 나름대로 스스로 분석해보았다. </p>
<br>

<h3 id="구현-실패-원인">구현 실패 원인</h3>
<h4 id="1-버전이-업데이트-되면서-달라진-명령어">1. 버전이 업데이트 되면서 달라진 명령어</h4>
<p>책이 쓰여진 당시와 지금까지 시간 간격이 있다보니, 그동안 <span style="color: orange">Springboot와 java 버전이 업데이트</span> 되며 바뀐 명령어가 꽤 있었다. </p>
<p>저자의 깃허브 계정으로 가보면 현재까지도 많은 학생들이 질문과 답변을 공유하고 있어 도움을 받을 수 있었다.</p>
<p>하지만 여기에도 어느정도의 한계가 있어서 추가로 발생한 오류들은 구글링을 통해 해결해야했다. </p>
<h4 id="2-방대한-코드를-제대로-다루지-못했음">2. 방대한 코드를 제대로 다루지 못했음</h4>
<p>책에서는 간단한 로그인/게시판 기능만을 다루는 웹 페이지를 구현하였다. 이런 간단한 페이지에도 굉장히 많은 파일이 엮여있다는 것에 놀랐다! </p>
<p>각 파일마다 포함하고 있는 코드 줄 수도 굉장히 많았는데, 이걸 하나하나 타이핑하며 따라하다보니 중간중간 오류가 발생하는 경우가 굉장히 많았다. </p>
<p><span style="color: orange">타이포</span> 때문에 스트레스를 너무 받아서 저자의 깃허브 계정에서 풀코드를 복사/붙여넣기 하려고 여러번 시도하였으나, 이건 의미가 없다고 생각했을 뿐더러 업데이트된 명령어가 포함되어있지 않아 마찬가지로 오류가 자주 발생하였다. </p>
<p><span style="color: orange">많은 양의 파일</span>을 혼자서는 처음 다뤄보는 만큼 더 세심한 주의가 필요했는데, 그러지 못해 구현에 실패한 것 같아 아쉽다. </p>
<h4 id="3-버전-관리를-제대로-하지-못했음">3. 버전 관리를 제대로 하지 못했음</h4>
<p>책에서 추천하는 스프링, 자바 버전과 다른 버전으로 파일을 작성하다보니 여러가지 문제가 많았다. 앞서 언급했던 버전 별로 업데이트 된 명령어의 문제도 있었지만, 프로그램 자체의 버전이 책과 맞지 않아 생긴 문제도 있었다. </p>
<p>gradle 버전이 맞지 않아 책을 보고 build.gradle 파일에 똑같이 작성해두었던 버전을 업데이트 해주어야 한다는 사소한 것부터 자바 버전이 맞지 않아 초기화 후 책 전체를 처음부터 다시 따라했던 일까지... </p>
<h4 id="4-절대적인-시간-투자가-부족했음">4. 절대적인 시간 투자가 부족했음</h4>
<p>겨울 방학 동안 열심히 공부하기로 다짐했다. </p>
<p>그런데 1월 초까지는 어떤 프레임워크를 공부하면 좋을지 고민하며 이것 저것 공부하느라 시간을 쏟아부었다. 
<span style="color: lightgrey">(사실상 핑계... 이지만 javascript, react, spring 등 여러가지 프레임 워크의 기초적인 개념을 배운 뒤 1월 중순부터 본격적으로 공부하려했다)<span></p>
<p>정보처리기사 필기 시험과 sqld 시험 준비, 오픽, 토익 등 스스로 준비해보고 싶은 것들이 많아 이들과 공부를 병행하며 책을 함께 보다보니, 두번의 실패를 겪고 나서부터는 의지가 많이 꺾였던 것 같다. </p>
<p>함께 공부하고 화이팅 할 동료를 구해볼 걸 하는 아쉬움이 든다. 
<span style="color: lightgrey">(포기하지 말고 2월 중순에도 틈틈히 구현을 시도해볼걸!)<span></p>
<hr>
<br>
어쨋든, 책에서 구현에 성공한 부분까지 생겼던 오류들과 해결한 방법들을 정리하여 두겠다. 

<p>어떻게 해결이 된건지 제대로 이해하지 못하고 넘어간 오류들도 있으나, 후에 이 책을 다시 공부하게 될 때 이 기록들을 참고하여 확실하게 해두고 넘어가기로 다짐한다.</p>
<br>


<hr>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[SSAFY 앰버서더] SSAFY 11기 모집마감!]]></title>
            <link>https://velog.io/@wjd_oou/SSAFY-11%EA%B8%B0-%EB%AA%A8%EC%A7%91%EB%A7%88%EA%B0%90</link>
            <guid>https://velog.io/@wjd_oou/SSAFY-11%EA%B8%B0-%EB%AA%A8%EC%A7%91%EB%A7%88%EA%B0%90</guid>
            <pubDate>Sun, 05 Nov 2023 13:03:53 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>🌲 <a href="https://ssafy.com/">SSAFY 홈페이지</a> 🌲</p>
</blockquote>
<p>아래 설명할 내용들은 SSAFY 홈페이지에서 더욱 자세하게 확인해보실 수 있습니다!</p>
<hr>
<p>돌아오는 월요일(11월 6일) SSAFY 11기 모집이 마감됩니다. </p>
<p>SSAFY에 관심을 두고있지만 아직까지 지원을 망설이시는 분들이 많을 것으로 예상합니다! </p>
<hr>
<p>🙋‍♀️
&quot;SSAFY에 관심이 있는데, 정보를 어디서 얻어야할지 모르겠어요!&quot;
🙋‍♂️
&quot;지난 대면 설명회에는 개인사정으로 참여하지 못했어요.&quot;</p>
<p align="center">
  <img src="https://velog.velcdn.com/images/wjd_oou/post/d137e03f-c9b9-4ee0-bede-81926ea311f3/image.png" alt="text" width="80%" />
</p>

<p>아쉬웠던 분들을 위해, 지난 10월 31일 (화) 진행된 11기 온라인 설명회의 영상을 공유드립니다!</p>
<p><a href="https://youtube.com/@hellossafy">🌲 SSAFY 11기 온라인 설명회</a></p>
<p align="center">
  <img src="https://velog.velcdn.com/images/wjd_oou/post/f137b5a0-fcd8-4b65-872d-3cd71bf15b2f/image.png" alt="text" width="80%" />
</p>


<p>💬 국내외 4년제 대학 졸업예정자 
💬 2024년 1월부터 12월까지 1년동안 열심히 공부해보고 싶은 모두
💬 서울, 대전, 광주, 구미, 부울경 캠퍼스에서</p>
<br>

<hr>
<p><a href="https://bit.ly/3ZKO74z">🌲 SSAFY에 대해 더 자세히!</a></p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[SSAFY 앰배서더] SSAFY 11기 모집설명회 안내]]></title>
            <link>https://velog.io/@wjd_oou/SSAFY-%EC%95%B0%EB%B0%B0%EC%84%9C%EB%8D%94-SSAFY-11%EA%B8%B0-%EB%AA%A8%EC%A7%91%EC%84%A4%EB%AA%85%ED%9A%8C-%EC%95%88%EB%82%B4</link>
            <guid>https://velog.io/@wjd_oou/SSAFY-%EC%95%B0%EB%B0%B0%EC%84%9C%EB%8D%94-SSAFY-11%EA%B8%B0-%EB%AA%A8%EC%A7%91%EC%84%A4%EB%AA%85%ED%9A%8C-%EC%95%88%EB%82%B4</guid>
            <pubDate>Sun, 15 Oct 2023 11:31:54 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>🌲 <a href="https://ssafy.com/">SSAFY 홈페이지</a> 🌲</p>
</blockquote>
<p>아래 설명할 내용들은 SSAFY 홈페이지에서 더욱 자세하게 확인해보실 수 있습니다!</p>
<hr>
<p align="center">
  <img src="https://velog.velcdn.com/images/wjd_oou/post/76f001f3-10dc-4328-af05-61ff37a0eff1/image.png" alt="text" width="80%" />
</p>

<p align="center">
  <img src="https://velog.velcdn.com/images/wjd_oou/post/635fae71-6dd1-4d91-b796-7de85c9dd9dc/image.png" alt="text" width="80%" />
</p>

<p>🙄 SSAFY 11기 모집에 관심이 있지만, 더 자세한 정보를 얻고 싶다!</p>
<p>🙄 왜 꼭 SSAFY여야 하는지, SSAFY人이 되면 어떤 혜택이 있는지 궁금하다!</p>
<p>🙄 SSAFY의 자세한 교육과정이 궁금하다!</p>
<br>
SSAFY에 대한 더 자세한 정보가 필요하셨던 여러분을 위해 캠퍼스로 찾아가는 SSAFY 모집 설명회가 열립니다!

<hr>
<h3 id="🎊-ssafy-모집-설명회-안내-🎊">🎊 SSAFY 모집 설명회 안내 🎊</h3>
<br>
SSAFY 모집 설명회는 다음과 같은 순서로 진행됩니다. 

<p>🚩 SSAFY 서울캠 : 10/16(월) 1차 14시 / 2차 16시
🚩 계명대학교 : 10/17(화) 14시
🚩 경성대학교 : 10/18(수) 14시
🚩 전북대학교 : 10/24(화) 14시
🚩 전남대학교 : 10/25(수) 14시
🚩 충남대학교/조선대학교 : 10/26(목) 14시
🚩 충북대학교 : 10/27(금) 14시</p>
<hr>
<h3 id="🎊-ssafy-모집-설명회-신청-🎊">🎊 SSAFY 모집 설명회 신청 🎊</h3>
<blockquote>
<p>🌼 <a href="https://docs.google.com/forms/d/e/1FAIpQLScoN9-HLGjJR2WGEuI9491oLdI7-9d_7vtHhC9N_x4smeF_IQ/viewform">신청 바로가기</a> 🌼</p>
</blockquote>
<p>예비 SSAFY인 여러분의 많은 관심과 신청 부탁드립니다! </p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[SSAFY 앰배서더] SSAFY 11기 모집 안내]]></title>
            <link>https://velog.io/@wjd_oou/SSAFY-%EC%95%B0%EB%B0%B0%EC%84%9C%EB%8D%94-SSAFY-11%EA%B8%B0-%EB%AA%A8%EC%A7%91-%EC%95%88%EB%82%B4</link>
            <guid>https://velog.io/@wjd_oou/SSAFY-%EC%95%B0%EB%B0%B0%EC%84%9C%EB%8D%94-SSAFY-11%EA%B8%B0-%EB%AA%A8%EC%A7%91-%EC%95%88%EB%82%B4</guid>
            <pubDate>Sun, 15 Oct 2023 11:10:57 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>🌲<a href="https://www.ssafy.com/">SSAFY 홈페이지</a>🌲</p>
</blockquote>
<p>아래 설명할 내용들은 SSAFY 홈페이지에서 더욱 자세하게 확인해보실 수 있습니다!
<br></p>
<hr>
<h2 id="🎉-ssafy-11기-모집-🎉">🎉 SSAFY 11기 모집 🎉</h2>
<p>SSAFY는 삼성의 SW 교육 경험과 고용노동부의 취업 지원 노하우를 바탕으로, 취업 준비생에게 SW 역량 향상 교육 및 다양한 취업 지원 서비스를 제공하여 취업에 성공하도록 돕는 프로그램입니다.</p>
<p align="center">
  <img src="https://velog.velcdn.com/images/wjd_oou/post/f0f00c31-7626-463b-a2bf-e2c0d5131c7e/image.png" alt="text" width="number" />
</p>

<p align="center">
  <img src="https://velog.velcdn.com/images/wjd_oou/post/5548a773-99a6-46db-a79f-14830721889c/image.png" alt="text" width="number" />
</p>



<h3 id="ssafy-11기-모집-일정">SSAFY 11기 모집 일정</h3>
<p>드디어 SSAFY 11기의 모집 일정이 공고되었습니다!</p>
<p>평소 SSAFY를 관심있게 지켜보고 계셨다면 이번 모집 일정을 자세하게 확인해보시는 것을 추천드립니다. </p>
<blockquote>
<p>📢지원자격 : 29세 이하의 국내외 4년제 대학 졸업자(졸업예정자) 
(94년 1월 1일 이후 출생자)</p>
</blockquote>
<blockquote>
<p>📢지원방법 : SSAFY 홈페이지 접속 후 지원서 작성</p>
</blockquote>
<blockquote>
<p>📢모집기간 : 23년 10월 23일(월) ~ 11월 6일(월)</p>
</blockquote>
<blockquote>
<p>📢교육기간 : 2024년 1월~ 2024년 12월</p>
</blockquote>
<blockquote>
<p>📢교육시간 : 09:00~ 18:00📢교육기관 : 서울, 대전, 광주, 구미, 부울경(부산) 캠퍼스</p>
</blockquote>
<hr>
<h3 id="ssafy-교육생-지원혜택">SSAFY 교육생 지원혜택</h3>
<p>SSAFY의 또다른 장점, SSAFY 교육생들만이 누릴 수 있는 혜택이 풍부하다는 점인데요!</p>
<blockquote>
<p>💰 월 100만원의 교육지원금</p>
</blockquote>
<blockquote>
<p>💻 실전형 SW교육 및 개인별 맞춤형 취업컨설팅 제공</p>
</blockquote>
<blockquote>
<p>🏢 150여개 기업에서 SSAFY 교육생 채용 우대</p>
</blockquote>
<blockquote>
<p>📃 교육 중 삼성SW역량테스트 응시 기회 제공</p>
</blockquote>
<blockquote>
<p>🏆 우수 교육생 삼성전자 실습 및 다양한 시상 제도 실시</p>
</blockquote>
<blockquote>
<p>🎊 매학기 교육 종료 후 Job Fair 운영</p>
</blockquote>
<p>이렇게 다양한 혜택이 예비 SSAFY인 여러분을 위해 기다리고 있습니다!</p>
<br>

<hr>
<h3 id="ssafy-지원-더보기">SSAFY 지원 더보기</h3>
<blockquote>
<p>🌼 <a href="https://bit.ly/3ZKO74z">SSAFY 11기 관련 더보기</a></p>
</blockquote>
<p>꿈을 현실로 만드는 시작, 삼성 청년 SW 아카데미 11기에 지금 바로 지원하세요! </p>
<p align="center">
  <img src="https://velog.velcdn.com/images/wjd_oou/post/b080ad81-bf71-4476-a97d-c6420cc28961/image.jpg" alt="text" width="number" />
</p>



]]></description>
        </item>
        <item>
            <title><![CDATA[[SSAFY 앰배서더] SSAFY와 가까워지기, SSAFY란?]]></title>
            <link>https://velog.io/@wjd_oou/SSAFY-%EC%95%B0%EB%B0%B0%EC%84%9C%EB%8D%94-SSAFY%EC%99%80-%EA%B0%80%EA%B9%8C%EC%9B%8C%EC%A7%80%EA%B8%B0-SSAFY%EB%9E%80</link>
            <guid>https://velog.io/@wjd_oou/SSAFY-%EC%95%B0%EB%B0%B0%EC%84%9C%EB%8D%94-SSAFY%EC%99%80-%EA%B0%80%EA%B9%8C%EC%9B%8C%EC%A7%80%EA%B8%B0-SSAFY%EB%9E%80</guid>
            <pubDate>Wed, 04 Oct 2023 14:22:22 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>🌲 <a href="https://www.ssafy.com/">SSAFY 홈페이지</a> 🌲</p>
</blockquote>
<p>아래 설명할 내용들은 SSAFY 홈페이지에서 더욱 자세하게 확인해보실 수 있습니다!</p>
<br>

<hr>
<h3 id="🤔-ssafy란">🤔 SSAFY란?</h3>
<p>SSAFY는 <span style='background-color: #F7DDBE'>삼성 SW 청년 아카데미 (Samsung SW Academy For Youth)</span> 의 줄임말입니다!</p>
<p>SSAFY는 삼성과 고용노동부가 함께 청년들에게 SW 역량을 향상할 수 있는 양질의 교육을 제공하는 프로그램입니다. SW 교육 뿐만 아니라 <span style="color: orange">다양한 취업 지원 서비스</span>를 통해 청년들이 취업 경쟁력을 갖출 수 있도록 도움을 주고 있습니다.</p>
<p>지난 23년 6월 <span style="color: orange">4대 은행(신한, 국민, 하나, 우리)</span>과 협약식을 맺은 SSAFY는 9월 <span style="color: orange">NH농협은행</span>과도 추가로 협약을 맺으며 다섯 군데의 은행으로부터 후원을 받고 있습니다!</p>
<p>뿐만 아니라, 삼성 계열사로부터의 지원과 삼성 임직원의 후원, SSAFY 동문회인 SSAFYnity 에서도 후원을 받고 있습니다.</p>
<hr>
<h3 id="🤨-ssafy의-교육과정">🤨 SSAFY의 교육과정?</h3>
<h4 id="ssafy의-교육기간">SSAFY의 교육기간</h4>
<p>SSAFY인(SSAFY+人)들은 <span style='background-color: #F7DDBE'>총 12개월의 교육기간</span>을 거쳐 <span style="color: orange"><u>문제해결능력을 갖춘 차세대 SW 인력</u></span>으로 거듭나게 됩니다.  </p>
<p align="center">
  <img src="https://velog.velcdn.com/images/wjd_oou/post/524274ac-cdf3-4a33-a4cc-9d1ae76f61b5/image.png" alt="SSAFY 교육 기간" width="100%" />
</p> 

<h4 id="💻-ssafy의-기본과정-커리큘럼">💻 SSAFY의 기본과정 커리큘럼</h4>
<p>SSAFY에서는 세 가지의 트랙을 제공하고 있습니다. </p>
<p>(1) Coding Track
(2) Embedded Track
(3) Mobile Track</p>
<p>각 트랙에서 배우게될 자세한 커리큘럼 (개발언어, 프레임워크) 은 홈페이지에서 확인해보실 수 있습니다. </p>
<br>

<h4 id="💻-ssafy의-심화과정-커리큘럼">💻 SSAFY의 심화과정 커리큘럼</h4>
<p>SSAFY의 심화과정에서는 팀 프로젝트 경험을 쌓아볼 수 있는 기회를 제공하고 있습니다. </p>
<p>크게 프로젝트 과제 선정과 프로젝트 수행 단계로 나눠 진행하게 되는데, 5개월(21주) 간 여러가지 프로젝트를 경험하며 포트폴리오를 완성할 수 있게 됩니다. </p>
<p align="center">
  <img src="https://velog.velcdn.com/images/wjd_oou/post/0d48cddf-308f-4b87-9a03-e09f77940c65/image.png" alt="text" width="number" />
</p>
<p align="center">
  <img src="blob:https://velog.io/b6b3fc94-ccd5-41a3-b2bc-3c0ae079ae3d" alt="text" width="number" />
</p>

<hr>
<h3 id="😮-ssafy의-교육생-지원">😮 SSAFY의 교육생 지원?</h3>
<p>SSAFY에서는 교육생들을 위한 다양한 지원을 아끼지 않고 있습니다. </p>
<h4 id="전문화된-sw-교육-제공">전문화된 SW 교육 제공</h4>
<ul>
<li>SSAFY는 우수한 대학 교수진으로 구성된 자문위원단을 두고 있습니다.  </li>
<li>취업에 도움이 될 수 있도록 다양한 실전 학습 기회를 제공합니다. 
(삼성 SW역량 테스트 응시기회, SSAFY 교육생 대상 해커톤 개최 등)</li>
</ul>
<h4 id="교육지원금-지급">교육지원금 지급</h4>
<ul>
<li>12개월 동안 SSAFY에 집중하여 SW 교육을 받게 될 SSAFY 교육생들을 위해 매달 100만원 가량의 교육지원금을 지급합니다. </li>
</ul>
<h4 id="연수-기회-제공">연수 기회 제공</h4>
<ul>
<li>우수 활동 SSAFY인들을 위해 해외 연수 기회, 국내외 연구소의 실습 기회를 제공합니다. (삼성전자 해외연구소 등)</li>
</ul>
<h4 id="우수교육생-시상">우수교육생 시상</h4>
<ul>
<li>교육 성적 우수자 등 우수 교육생을 위해 다양한 시상 제도를 실시합니다.</li>
</ul>
<h4 id="진로상담-및-취업서비스-제공">진로상담 및 취업서비스 제공</h4>
<ul>
<li>맞춤형 일자리 정보, 취업 실전 역량 교육, 컨설팅 서비스 등 교육생들이 취업에 성공할 수 있도록 여러가지 서비스를 지원합니다. </li>
</ul>
<br>

<hr>
<h3 id="😀-ssafy에-지원하려면">😀 SSAFY에 지원하려면?</h3>
<p>(아래 내용은 SSAFY 내부사정에 따라 변동될 수 있습니다.)
(지원 당시의 자세한 지원자격 및 안내사항은 필히 당시의 모집 안내를 확인하시기를 권장드립니다.)</p>
<br>

<p><span style='background-color: #F7DDBE'>SSAFY에서는 매년 상반기/하반기에 걸쳐 교육생을 모집</span>하고 있습니다. 매년 상반기에 모집하는 기수는 당해 하반기부터 이듬해 상반기까지 교육을 받게 되며, 매년 하반기에 모집하는 기수는 이듬해 상반기부터 하반기까지 교육을 받게 됩니다. </p>
<p>가장 최근에 모집된 SSAFY 10기의 경우 2023년 하반기부터 2024년 상반기까지 교육을 받게 됩니다. </p>
<p>SSAFY에 지원하려면 몇가지 <span style='background-color: #F7DDBE'>지원 자격</span>을 충족해야 합니다. </p>
<p>🏆 연령 : 만 29세 이하
🏆 학력 : 국내외 4년제 대학 졸업(예정)자 (전공무관)
🏆 재직여부 : 미취업자
🏆 기타 : 교육기간 중 통학 가능한 자 등등 </p>
<br>
<br>

<h4 id="span-stylebackground-color-f7ddbe지방에-거주span하고-있는-청년은-어떻게-하나요"><span style='background-color: #F7DDBE'>지방에 거주</span>하고 있는 청년은 어떻게 하나요?</h4>
<p>SSAFY 캠퍼스는 <span style="color: orange">서울, 구미, 대전, 광주, 부울경(부산)</span> 5개 지역에 위치하고 있습니다. </p>
<p>SSAFY 교육생들은 교육기간 내 <span style="color: orange">오전 9:00 ~ 오후 6:00</span> 까지 캠퍼스에서 교육을 받게 되므로 캠퍼스로 통학할 수 있어야합니다. </p>
<p>만약 지방에 거주하여 서울 캠퍼스로의 통학이 불가능하더라도 교육기간 중 <span style="color: orange">각 지역의 캠퍼스로 통학이 가능하다면</span> 지원할 수 있습니다. </p>
<p align="center">
  <img src="blob:https://velog.io/2ffd8e17-557e-4ffb-9b61-f2327fa43a34" alt="text" width="100%" />
</p>

<hr>
<h3 id="ssafy와-관련된-소식을-알림받고-싶을-때">SSAFY와 관련된 소식을 알림받고 싶을 때?</h3>
<p>SSAFY에서는 다양한 플랫폼을 통해 SSAFY의 소식과 SSAFY인들의 재미있는 이야기들을 공유하고 있습니다. </p>
<blockquote>
<p>🌼 <a href="https://www.ssafy.com/ksp/jsp/swp/swpMain.jsp">SSAFY 홈페이지</a></p>
</blockquote>
<blockquote>
<p>🌼 <a href="https://pf.kakao.com/_Vhxoxnxb">SSAFY 카카오톡 채널</a></p>
</blockquote>
<blockquote>
<p>🌼 <a href="https://www.instagram.com/hellossafy/">SSAFY 인스타그램</a></p>
</blockquote>
<blockquote>
<p>🌼 <a href="https://www.facebook.com/hellossafy">SSAFY 페이스북</a></p>
</blockquote>
<blockquote>
<p>🌼 <a href="https://www.youtube.com/@hellossafy">SSAFY 유튜브</a></p>
</blockquote>
<p>SSAFY에 관심이 생기셨다면!
위의 SNS를 구독하여 SSAFY에 관한 정보를 알림받으실 수 있습니다. </p>
<p>SSAFY를 구독하시고, 곧 모집을 시작하게 될 <span style='background-color: #F7DDBE'>SSAFY 11기</span>에 관한 정보를 누구보다 빨리 알림받으시길 바랍니다!</p>
<hr>
<h3 id="😍-온라인에서-ssafy를-경험할-수-있는-방법">😍 온라인에서 SSAFY를 경험할 수 있는 방법?</h3>
<p>SSAFY에 너무나도 관심이 있지만 아직은 SSAFY와 더 친해질 시간이 필요하다면? 아래 SSAFY 트윈캠퍼스에서 각 지역의 캠퍼스를 투어해보실 수 있습니다. </p>
<blockquote>
<p>🌼 <a href="https://zep.us/play/8r9VmO">SSAFY 트윈캠퍼스</a></p>
</blockquote>
<br>

<hr>
<p><strong>SSAFY 앰배서더 11기 이정은</strong></p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[SSAFY 앰배서더] 지원과정과 SSAFY 트윈캠퍼스 소개]]></title>
            <link>https://velog.io/@wjd_oou/SSAFY-%EC%95%B0%EB%B0%B0%EC%84%9C%EB%8D%94-11%EA%B8%B0-%EC%A7%80%EC%9B%90%EA%B3%BC%EC%A0%95%EA%B3%BC-SSAFY-%ED%8A%B8%EC%9C%88%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EC%86%8C%EA%B0%9C</link>
            <guid>https://velog.io/@wjd_oou/SSAFY-%EC%95%B0%EB%B0%B0%EC%84%9C%EB%8D%94-11%EA%B8%B0-%EC%A7%80%EC%9B%90%EA%B3%BC%EC%A0%95%EA%B3%BC-SSAFY-%ED%8A%B8%EC%9C%88%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EC%86%8C%EA%B0%9C</guid>
            <pubDate>Sat, 30 Sep 2023 11:31:00 GMT</pubDate>
            <description><![CDATA[<hr>
<p>평소 SSAFY에 많은 관심을 두고있던 나!
Instagram, Youtube 등등 SSAFY의 소식을 접할 수 있는 플랫폼이란 플랫폼은 전부 구독해두면서 시간 날때마다 틈틈이 들여다보고는 했었는데...
<br>
그러던 중
<br>
<img src="https://velog.velcdn.com/images/wjd_oou/post/a7280145-3ad3-443f-8d76-ddcb6ea90b43/image.jpg" width=50%></p>
<h3 id="⭐ssafy-앰배서더⭐-모집소식에-바로-지원서-작성-시작">⭐SSAFY 앰배서더⭐ 모집소식에 <strong>바로</strong> 지원서 작성 시작</h3>
<p>모집마감일이 학과 개강파티 날이어서 잠깐 화장실 갔다 온다고하고 구석에 쭈그려 앉아서 마지막까지 지원서를 열심히 수정했다.</p>
<p>지난 학기 막 컴퓨터공학과 복수전공을 승인받아 이렇다할 스펙도 없었고, 남들 다한다는 토이 프로젝트도 없었기 때문에 <strong>성실함</strong>, <strong>열정</strong>만 가득 담긴 지원서를 제출하고 큰 기대없이 주말을 보냈다.</p>
<hr>
<h3 id="그런데-최종-span-stylecolor-orange앰배서더-선정span">그런데 최종 <span style="color: orange"><strong>앰배서더 선정!</strong></span></h3>
<p>내가 <span style='background-color: #F7DDBE'>SSAFY 앰배서더</span> 라니
<br>
<img src="https://velog.velcdn.com/images/wjd_oou/post/67060e26-ac35-4177-9e43-50922e201cab/image.png" width=50%></p>
<br>
나는 1조에 배정되었다!
<br>

<p>개인사정으로 초청행사가 열리는 9월 23일(토)에 대면으로 행사에 참여하지 못하게 되었는데, 걱정하던 와중 SSAFY 사무국에서 혹시 비대면으로라도 행사에 참여할 수 있을지 물어봐주셨다. 
<del>정말가능합니다정말감사합니다</del></p>
<p>혹시 이 글을 읽으시는 1조 팀원 분들이 있으시다면, 대면행사에서 만나뵙지 못해 미안하다는 말씀을 드리고 싶다,,, 그리고 꼭 연락 주셨으면 좋겠다!⭐ 
(같이 앰배서더 활동해요!)</p>
<br>
<br>

<hr>
<p>그래서 우여곡절 끝에 돌아오는 월요일에 비대면으로 초청행사에 참여하게 되었다!</p>
<p>대면행사에서는 실제 SSAFY인들이 공부하는 서울캠퍼스를 탐방했지만, 비대면으로는 그럴 수 없으니 아쉬운대로 SSAFY 트윈캠퍼스에서 이곳 저곳을 둘러볼 수 있었다.</p>
<hr>
<br>

<h3 id="ssafy-트윈캠퍼스"><a href="https://zep.us/play/8r9VmO">SSAFY 트윈캠퍼스</a></h3>
<br>

<blockquote>
<p>SSAFY 트윈캠퍼스 맵투어</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/wjd_oou/post/fba86df4-be7c-4deb-b579-153761e19d6a/image.png" alt=""></p>
<p>트윈캠퍼스에 들어오면 먼저 <span style='background-color: yellow'>서울캠퍼스 광장</span>으로 오게 된다!
SSAFY 앞에서 사진 한장
<del>그런데 왜 아무도없지</del></p>
<p><img src="https://velog.velcdn.com/images/wjd_oou/post/19eb98ea-2a0f-4231-8044-7a572cbefad6/image.png" alt=""></p>
<p>광장 왼쪽 위의 미니맵은 <code>F</code> 를 눌러 확인할 수 있다.
건물 배치도를 한 눈에 확인할 수 있으니, 가보고 싶은 곳이 있다면 미니맵으로 위치를 확인하고 가면 좋겠다! (생각보다 맵이 넓어서 진짜 길 잃을 수도 있음)</p>
<p><img src="https://velog.velcdn.com/images/wjd_oou/post/eb3bb199-c82c-4dd7-afa8-9ded8df86fdd/image.png" alt=""></p>
<p>키보드 방향키를 이용하면 생각보다 빠른(?) 속도로 캐릭터를 움직일 수 있지만 그것도 답답하다! 순간이동하고싶다! 한다면
화면 왼쪽에 <code>이동</code> 에서 가고싶은 장소를 누르면 한번에 이동이 가능하다.
<del>비현실에서만 가능한 꿀팁</del>
<br>
<img src="https://velog.velcdn.com/images/wjd_oou/post/ccb9ef82-55db-4825-ac98-ce0286ab634e/image.png" width=60%></p>
<p>내 캐릭터를 누르면 이렇게 아바타 꾸미기도 가능하다.</p>
<p><img src="https://velog.velcdn.com/images/wjd_oou/post/2ce552e9-b640-4f74-b1ef-c8771795d76e/image.png" alt=""></p>
<p>먼저 서울캠퍼스로 와보았다.
여기저기 구역을 나눠서 즐길거리/볼거리 들을 많이 만들어두었다.</p>
<p><img src="https://velog.velcdn.com/images/wjd_oou/post/0451632c-4118-40d0-a26a-cd9d8b14de18/image.png" alt=""></p>
<p>서울캠퍼스 2층 모습
왼쪽/오른쪽 두개의 강의장이 있는데, 1학기 강의장은 한 방향을 향해 강의를 들을 수 있도록 배치되어있다. 나도 왠지 첫 번째 줄에서 강의를 듣는 것 마냥 앉아서 인증사진을 찍어보았다.</p>
<p>오른쪽에 있는 2학기 강의장은 팀프로젝트를 하기에 용이하도록 테이블이 조별로 모여있었다. </p>
<p><img src="https://velog.velcdn.com/images/wjd_oou/post/68e012fb-753e-4a4d-8b74-401370f2a758/image.png" alt=""></p>
<p>서울 캠퍼스 구경을 마치고 대전 캠퍼스로 이동해보았다.
<code>이동</code> 탭을 이용해서 순간이동 했는데, 도착하니까 귀여운 셔틀버스에서 내렸다. </p>
<p><img src="https://velog.velcdn.com/images/wjd_oou/post/4b7f397d-fbf9-4100-af3b-dbe95531ae47/image.png" alt=""></p>
<p>실제 대전캠퍼스와 아주 유사하게 구현되었다는데, 가운데 분수가 크게 있는게 마음에 들었다. 뽈뽈 돌아다니면서 실컷 구경했다.</p>
<br>


<hr>
<p>SSAFY 앰배서더에 선정된 것은 엄청난 행운이라고 생각한다!
비록 초청행사에는 참여하지 못하였지만, 좋은 활동에 함께할 수 있게 되어서 행복하다. </p>
<hr>
<blockquote>
<p>활동 기간 동안 최선을 다해 활동하겠습니다~!!</p>
</blockquote>
]]></description>
        </item>
    </channel>
</rss>