<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Whaeun Story</title>
    <link>https://whaeun.tistory.com/</link>
    <description>Github : https://github.com/whaeundo25
E -mail : doeun536@gmail.com </description>
    <language>ko</language>
    <pubDate>Sat, 20 Jun 2026 17:08:46 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>whaeun</managingEditor>
    <image>
      <title>Whaeun Story</title>
      <url>https://tistory1.daumcdn.net/tistory/4756093/attach/b9e4ef15211940ca903fdde6f3754ef9</url>
      <link>https://whaeun.tistory.com</link>
    </image>
    <item>
      <title>[ BOJ 1260 ] DFS와 BFS 풀이</title>
      <link>https://whaeun.tistory.com/44</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1842&quot; data-origin-height=&quot;986&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/erTIy7/btr8XzFJ1hh/XhkPPgHKwpyIazcoKkjpR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/erTIy7/btr8XzFJ1hh/XhkPPgHKwpyIazcoKkjpR1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/erTIy7/btr8XzFJ1hh/XhkPPgHKwpyIazcoKkjpR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FerTIy7%2Fbtr8XzFJ1hh%2FXhkPPgHKwpyIazcoKkjpR1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1842&quot; height=&quot;986&quot; data-origin-width=&quot;1842&quot; data-origin-height=&quot;986&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 링크: &lt;a href=&quot;https://www.acmicpc.net/problem/1260&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.acmicpc.net/problem/1260&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1680940446131&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;1260번: DFS와 BFS&quot; data-og-description=&quot;첫째 줄에 정점의 개수 N(1 &amp;le; N &amp;le; 1,000), 간선의 개수 M(1 &amp;le; M &amp;le; 10,000), 탐색을 시작할 정점의 번호 V가 주어진다. 다음 M개의 줄에는 간선이 연결하는 두 정점의 번호가 주어진다. 어떤 두 정점 사&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/1260&quot; data-og-url=&quot;https://www.acmicpc.net/problem/1260&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/R09aq/hyScCsG8rn/p6GkmUmRI2sjVQGbKuLefk/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1260&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/1260&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/R09aq/hyScCsG8rn/p6GkmUmRI2sjVQGbKuLefk/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;1260번: DFS와 BFS&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;첫째 줄에 정점의 개수 N(1 &amp;le; N &amp;le; 1,000), 간선의 개수 M(1 &amp;le; M &amp;le; 10,000), 탐색을 시작할 정점의 번호 V가 주어진다. 다음 M개의 줄에는 간선이 연결하는 두 정점의 번호가 주어진다. 어떤 두 정점 사&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 문제는 DFS와 BFS의 기본 문제로 DFS와 BFS를 코드로 어떻게 구현해야 할지 생각해 볼 수 있는 문제이다. 아래 풀이 코드에서 각 변수는 다음과 같은 용도로 사용했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;edge: 그래프 연결 정보 저장&lt;/li&gt;
&lt;li&gt;visited: 그래프 탐색 시 방문 여부 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;❗️풀이 코드&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1680940371185&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;algorithm&amp;gt;
#include &amp;lt;queue&amp;gt;
#include &amp;lt;stack&amp;gt;

using namespace std;

vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; edge;
vector&amp;lt;int&amp;gt; num;
vector&amp;lt;int&amp;gt; visited;

void dfs(int node){
    cout &amp;lt;&amp;lt; node &amp;lt;&amp;lt; &quot; &quot;;
    visited[node] = true;
    
    for(int i = 0; i &amp;lt; edge[node].size(); i++){
        int next = edge[node][i];
        
        if(!visited[next]){
            visited[next] = true;
            dfs(next);
        }
    }
}

void bfs(int node){
    queue&amp;lt;int&amp;gt; q;
    
    q.push(node);
    visited[node] = true;
    
    while(!q.empty()){
        int now = q.front();
        cout &amp;lt;&amp;lt; now &amp;lt;&amp;lt; &quot; &quot;;

        q.pop();
        
        for(int i = 0;  i &amp;lt; edge[now].size(); i++){
            if(!visited[edge[now][i]]){
                q.push(edge[now][i]);
                visited[edge[now][i]] = true;
            }
        }
    }
}


int main(){
    
    int n, m, v;
    
    cin &amp;gt;&amp;gt; n &amp;gt;&amp;gt; m &amp;gt;&amp;gt; v;
    
    for(int i = 0; i &amp;lt;= n; i++){
        edge.push_back(num);
        visited.push_back(0);
    }
    
    for(int i = 0; i &amp;lt; m; i++){
        int a, b;
        
        cin &amp;gt;&amp;gt; a &amp;gt;&amp;gt; b;
        
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    
    for(int i = 0; i &amp;lt;= n; i++){
        sort(edge[i].begin(), edge[i].end());
    }
    
    dfs(v);
    cout &amp;lt;&amp;lt; &quot;\n&quot;;
    
    for(int i = 0; i &amp;lt;= n; i++){
        visited[i] = false;
    }
    
    bfs(v);
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘/BOJ풀이</category>
      <category>1260 c++</category>
      <category>BFS</category>
      <category>BOJ1260</category>
      <category>C++</category>
      <category>dfs</category>
      <category>DFS와 BFS</category>
      <category>그래프</category>
      <category>그래프 탐색</category>
      <category>알고리즘</category>
      <author>whaeun</author>
      <guid isPermaLink="true">https://whaeun.tistory.com/44</guid>
      <comments>https://whaeun.tistory.com/44#entry44comment</comments>
      <pubDate>Sat, 8 Apr 2023 17:06:52 +0900</pubDate>
    </item>
    <item>
      <title>[ 02 ] 음성 재생 기능 구현</title>
      <link>https://whaeun.tistory.com/43</link>
      <description>&lt;blockquote style=&quot;color: #666666; text-align: start;&quot; data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;일자&lt;/b&gt;&lt;/blockquote&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1월 23일&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote style=&quot;color: #666666; text-align: start;&quot; data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;What I do?&lt;/b&gt;&lt;/blockquote&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;음성 재생 기능 구현&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;How?&lt;/b&gt;&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;audio player 패키지 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;Screenshot&lt;/b&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSfFYm/btr8P0DNKyS/ydZnt7krZLppgDwfdJ1zB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSfFYm/btr8P0DNKyS/ydZnt7krZLppgDwfdJ1zB1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSfFYm/btr8P0DNKyS/ydZnt7krZLppgDwfdJ1zB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSfFYm%2Fbtr8P0DNKyS%2FydZnt7krZLppgDwfdJ1zB1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1430&quot; height=&quot;426&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;426&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;재생 버튼을 누를 경우, mp3가 재생된다.&lt;/li&gt;
&lt;li&gt;슬라이더의 위치를 조정할 경우,그 시간대에 맞는 음성 부분이 재생된다.&lt;/li&gt;
&lt;li&gt;정지 버튼을 누를 경우, 재생되던 음성 파일이 일시 정지되고 이후 재생 버튼을 다시 누를 시 해당 지점부터 다시 재생된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;What I learned?&lt;/b&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1680936855441&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String formatTime(Duration duration){
    String twoDigits(int n) =&amp;gt; n.toString().padLeft(2, '0');

    final minutes = twoDigits(duration.inMinutes.remainder(60));
    final seconds = twoDigits(duration.inSeconds.remainder(60));

    return [
      minutes,
      seconds,
    ].join(&quot;:&quot;);
  }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;String formatTime 지정 &amp;rArr; 00:00 의 방식으로 표시될 수 있도록 지정&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;Trouble Shooting&lt;/b&gt;&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;링커 오류 발생&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;- [Xcode에서 설정] 빌드 설정 - OtherLinkerFlag - &amp;ldquo;-lc++ 추가&amp;rdquo;하여 해결&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1680936922737&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Undefined symbols for architecture arm64:
&quot;_dynamic_cast&quot;, referenced from:
applyAnimationTime(objc_object, POPAnimationState, double) in libPods.a(POPAnimator.o)&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;버전 업그레이드에 따른 패키지 내 함수 변경
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;.play(filePath, isLocal: true) &amp;rArr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;.play(DeviceFileSource(filePath))&lt;/li&gt;
&lt;li&gt;.onAudioPositionChanged.listen &amp;rArr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;.onPositionChanged.listen&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;iOS 권한 받기 &amp;rArr; 녹음 기능 구현 시 필요
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;info.plist 수정&lt;/li&gt;
&lt;li&gt;Podfile 수정 (Podfile 수정 시에는 반드시&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;pod install&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;해주어야 한다.)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;delete apps signed with your free account&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;내 계정으로 만든 앱이 디바이스에 이미 꽉차게 다운로드 되어 있음을 나타내는 오류이다.&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;rArr; 핸드폰에 깔아 놓은 기존의 앱들을 삭제하고 적당한 시간 간격 이후 다시 실행하여 오류를 해결하였다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;MissingPluginException (No implementation found for method play ...)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;처음에 run main.dart 부분을 계속 다시 눌러도 같은 오류가 나타났다. 실행 중인 앱을 아예 종료 시킨 후 다시 실행하기 위해 stop main.dart를 누른 후 다시 run main.dart를 눌러 해결했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;audioPlayer &lt;br /&gt;- &lt;a href=&quot;https://github.com/bluefireteam/audioplayers/blob/main/getting_started.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/bluefireteam/audioplayers/blob/main/getting_started.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;iOS 권한 설정&lt;br /&gt;- &lt;a href=&quot;https://velog.io/@manpkh95/Flutter-iOS-%EA%B6%8C%ED%95%9C-%EB%B0%9B%EA%B8%B0-Permission-Handler-Package&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://velog.io/@manpkh95/Flutter-iOS-%EA%B6%8C%ED%95%9C-%EB%B0%9B%EA%B8%B0-Permission-Handler-Package&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;-lc++ 추가&lt;br /&gt;- &lt;a href=&quot;https://github.com/facebookarchive/pop/issues/25&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/facebookarchive/pop/issues/25&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>프로젝트/Saera</category>
      <category>audioPlayer</category>
      <category>Flutter</category>
      <category>formatTime</category>
      <category>SAERA</category>
      <author>whaeun</author>
      <guid isPermaLink="true">https://whaeun.tistory.com/43</guid>
      <comments>https://whaeun.tistory.com/43#entry43comment</comments>
      <pubDate>Sat, 8 Apr 2023 16:04:14 +0900</pubDate>
    </item>
    <item>
      <title>[ 01 ] Interactive Screen 구현</title>
      <link>https://whaeun.tistory.com/42</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;일자&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1월 17일&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;What I do?&lt;/b&gt;&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;녹음 진행 상태에 따라 서로 다른 Widget이 나오도록 구현&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;How?&lt;/b&gt;&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;recordingState 변수를 두고 변수 값이 변경 될 때마다 각각의 Widget으로 변경되어 화면에 나오도록 구현&lt;/li&gt;
&lt;li&gt;억양 그래프가 나오는 부분의 경우, Stack Widget을 사용하여 icon Button 과 그래프가 중첩되어 나오도록 구현&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;Screenshot&lt;/b&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1422&quot; data-origin-height=&quot;620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDNqoc/btr8iZswZXu/tIiJlAljyZmWrjtUiK8610/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDNqoc/btr8iZswZXu/tIiJlAljyZmWrjtUiK8610/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDNqoc/btr8iZswZXu/tIiJlAljyZmWrjtUiK8610/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDNqoc%2Fbtr8iZswZXu%2FtIiJlAljyZmWrjtUiK8610%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1422&quot; height=&quot;620&quot; data-origin-width=&quot;1422&quot; data-origin-height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;What I learned?&lt;/b&gt;&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;child 내에서 if 문 활용시 아래와 같은 형식으로 사용할 수 있음을 알게 됨&lt;span&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;b&gt;- ❗️주의할 점:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;반환 값이 반드시 존재해야 한다. 반환 값이 존재하지 않을 경우, 에러가 발생한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1680719943741&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;child: (){
	if(){
	}
	else {

	}
}()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프로젝트/Saera</category>
      <author>whaeun</author>
      <guid isPermaLink="true">https://whaeun.tistory.com/42</guid>
      <comments>https://whaeun.tistory.com/42#entry42comment</comments>
      <pubDate>Fri, 7 Apr 2023 10:52:57 +0900</pubDate>
    </item>
    <item>
      <title>Solution Challenge Top10 진출 및 People's Choice Award 수상 후기</title>
      <link>https://whaeun.tistory.com/40</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt; ️&lt;span&gt;&amp;nbsp;&lt;/span&gt;Solution Challenge Top 10 진출&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Solution Challenge Top10 진출자 명단에 우리 팀의 이름이 걸려 있는 것을 확인한 그 순간의 감동은 지금도 너무 생생하게 기억난다. 전세계 대회에서 우리 팀이 10등 안에 들다니... Top10 발표가 나기 이틀 전에 우리 팀은 그간의 프로젝트 진행에 대한 뒷풀이를 하며 간절한 마음 반, 농담 반으로 Top10을 미리 축하해 보자며 케이크를 나누어 먹었었는데 우리의 간절함이 이루어져서 감사한 마음이 가득했다. 처음 Top10에 진출한 뒤로 사용자 테스트를 본격적으로 진행해 보고자 했지만 아쉽게도 연락이 어긋나는 바람에 우리는 보다 많은 사용자에게 사용자 테스트를 받지는 못하였다. 대신 Demo Day 발표를 위해 예상 질문을 적어보고 그에 대해 어떻게 답하면 좋을지에 대해 적어보는 방식으로 Demo Day를 준비했다.&lt;br /&gt;이번에도 Google Korea분들의 배려로 Demo Day 질문에 대한 답변의 전달력과 발음 등에 대해 멘토링을 받을 수 있었다. 우리 팀도 자체적으로 데모 데이 전까지 지속적으로 만나며 서로의 답변 자세와 답변 속도, 발음의 정확도, 전달력 등에 대해 지속적으로 상호 피드백을 진행하며 Demo Day 때 무사히 발표를 진행할 수 있도록 준비했다.&lt;br /&gt;Demo Day에는 팀 별로 미리 지정된 2개의 질문과 1개의 돌발 질문을 받게 된다고 하였는데 우리 팀은 비영어권 국가에 속해 있었기 때문에 대회 주최 측의 배려로 질문에 대한 답변을 미리 준비하여 Demo Day에 참여할 수 있었다. 우리가 받은 질문은 다음 3가지였다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;1.&amp;nbsp;What&amp;nbsp;was&amp;nbsp;the&amp;nbsp;hardest&amp;nbsp;part&amp;nbsp;about&amp;nbsp;implementing&amp;nbsp;each&amp;nbsp;feature&amp;nbsp;in&amp;nbsp;the&amp;nbsp;app,&amp;nbsp;and&amp;nbsp;how&amp;nbsp;did&amp;nbsp;you&amp;nbsp;overcome&amp;nbsp;it?&lt;br /&gt;2.&amp;nbsp;Did&amp;nbsp;you&amp;nbsp;take&amp;nbsp;inspiration&amp;nbsp;from&amp;nbsp;other&amp;nbsp;apps&amp;nbsp;and&amp;nbsp;what&amp;nbsp;were&amp;nbsp;they&amp;nbsp;missing?&amp;nbsp;How&amp;nbsp;does&amp;nbsp;Zero-Zone&amp;nbsp;do&amp;nbsp;a&amp;nbsp;better&amp;nbsp;job?&lt;br /&gt;3.&amp;nbsp;What&amp;nbsp;improvements&amp;nbsp;would&amp;nbsp;you&amp;nbsp;make&amp;nbsp;for&amp;nbsp;the&amp;nbsp;future&amp;nbsp;version&amp;nbsp;of&amp;nbsp;the&amp;nbsp;app?&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이에 대한 답변과 실제 데모 데이 영상은 다음의 유튜브 영상에서 확인해 볼 수 있다.&lt;span&gt; &lt;br /&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=PHpveYiS0OQ&quot;&gt;https://www.youtube.com/watch?v=PHpveYiS0OQ&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(19분 14초부터)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;a id=&quot;user-content--peopless-choice-award&quot; href=&quot;https://github.com/dsc-sookmyung/2022-DALGONA-SolutionChallenge/new/main#-peopless-choice-award&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;Peoples's Choice Award&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대망의 Demo Day 진행 날, 우리 팀의 목표는 하나였다. 제발 무사히 Demo Day 질의 응답을 무사히 끝내기를... 이란 바램이었다. 산학협력 인턴십을 진행하고 있었기 때문에 회사에서 퇴근한 후로 안정적인 Demo Day 질의 응답 진행을 위해 맹연습에 돌입했다. 미국 시간대와 한국 시간대가 달라 데모데이 Green Room에 입장해야 하는 시간인 자정까지 얼마나 많이 긴장했는지 모른다. Green Room에 입장하여 카메라 각도, 음향과 같은 사항들을 확인한 후 우리 팀원들의 얼굴을 보았는데 팀원들의 긴장한 모습이 눈에 들어왔다. 우리가 제출했던 Demo 영상이 나오고 우리가 접속해 있는 화면이 나오기 전 Demo Day 진행 요원 분이 30 seconds, 10 seconds, 5.. 4.. 3.. 2.. 1.. 하시는데 우리가 정말 Top10 안에 들어 중요한 순간을 앞두었다는 것이 실감남과 동시에 심장이 빠르게 뛰고 있는 것이 느껴졌다. 그래도 Demo Day전 리허설을 진행할 당시 진행 요원 분의 5.. 4.. 3.. 2.. 1..을 녹음해 두고 팀원들과 연습한 덕분에 리허설 때 느꼈던 머리의 백지화 상태는 다행히 오지 않았다.&lt;br /&gt;출근을 위해 우리의 발표를 마치자 마자 자겠다는 나의 생각은 오만이었다. 발표를 마치고 나니 도저히 잠이 오지 않아 팀원들과 구글 미트를 켜 다른 팀들의 발표를 보며 결과를 기다렸다. 대망의 결과 발표 시간, Top3 까지 발표되었는데 우리 팀이 불리지 않아 내심 아쉬운 마음을 뒤로 한 순간 우리 팀이 People's Choice Award 수상 팀으로 지목되어 팀원들과 구글 미트에서 환호성을 질렀다. 우리 팀에 투표를 해주시고 응원을 해주신 많은 분들께 감사한 마음이 가득하다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;770&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dDkBxN/btrT40ZD5mj/1ExknGGDHHdFmYWMt4sKUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dDkBxN/btrT40ZD5mj/1ExknGGDHHdFmYWMt4sKUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dDkBxN/btrT40ZD5mj/1ExknGGDHHdFmYWMt4sKUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdDkBxN%2FbtrT40ZD5mj%2F1ExknGGDHHdFmYWMt4sKUk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;927&quot; height=&quot;770&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;770&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;a id=&quot;user-content--solution-challenge-참여-후기&quot; href=&quot;https://github.com/dsc-sookmyung/2022-DALGONA-SolutionChallenge/new/main#-solution-challenge-%EC%B0%B8%EC%97%AC-%ED%9B%84%EA%B8%B0&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; &amp;zwj;  Solution Challenge 부상&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Solution Challenge Top10부터는 Google 로고가 박힌 백팩과 더불어 캡 모자, 파우치, 티셔츠, 후드 집업, 스티커와 같은 swag 물품을 받게 되는데 Google 굿즈에 둘러쌓인 내 자신을 볼 때면 없던 swag도 새롭게 생겨나는 기분을 느낄 수 있다. People's Choice Award의 부상으로는 Google Logo가 박힌 JBL 무선 헤드폰과 더플백을 받았다. JBL 무선 헤드폰의 경우, 평소에도 정말 유용하게 사용하고 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGqRI0/btrT4rKdH0Z/zoKb5Kqyc8MnzyYJsrPwE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGqRI0/btrT4rKdH0Z/zoKb5Kqyc8MnzyYJsrPwE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGqRI0/btrT4rKdH0Z/zoKb5Kqyc8MnzyYJsrPwE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGqRI0%2FbtrT4rKdH0Z%2FzoKb5Kqyc8MnzyYJsrPwE1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;4032&quot; height=&quot;3024&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; &amp;zwj;  Solution Challenge 참여 후기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1월 부터 7월까기 약 7개월 가량의 기간동안 Solution Challenge를 위해 달려왔던 그 간의 여정은 앞으로 잊지 못할 것 같다. 팀원들과 학교에서 밤을 새며 난생 처음 하늘에 빼곡히 자리해 있는 별을 보기도 하고 Google Developers 계정에 우리의 프로젝트 Demo 영상이 올라가는 것을 보기도 했던 새로운 것 투성이인 여정이었다.&amp;nbsp;&lt;br /&gt;이번 Solution Challenge를 진행하며 가장 크게 배운 것이 있다면 바로 &quot;개발자를 위한 앱이 아닌 사용자를 위한 앱을 만들어야 한다&quot;이다. 특히, 이번 앱의 사용자가 청각 장애인 분들이었기 때문에 사용자를 위한 앱을 만드는 것이 중요한 요소임을 더 크게 느낄 수 밖에 없었다. 청각 장애인 분들의 특성을 이해하기 위해 청각 장애인 분들의 삶을 만화로 그린 '나는 귀머거리다'라는 웹툰을 보며 청각 장애인 분들이 일상 생활 속에서 어떤 어려움을 겪게 되는지, 어떨 때 곤란함을 느끼는지 알아보고자 했다. 웹툰의 한 회차에서는 화장실에 리코더가 있는 이유에 대한 회차가 나온다. 이 회차를 보며 앱의 연습 페이지 진입시 음소거 상태로 진입할 수 있도록 하고 음소거 되어 있음을 버튼으로 보여주고자 결심하게 되었다. 이런 결심을 하게 된 이유는 바로 청각 장애인 분들의 경우, 스스로의 통제 하에 있지 않은 소리에 곤란함을 느낄 수 있다는 사실을 이 만화를 통해 알아차리게 되었기 때문이다. 이와 같은 상황처럼 앞으로 앱을 기획하고 개발을 진행함에 있어 사용자 집단의 특성을 반영한 사용자 중심의 앱을 만들 수 있는 개발자가 되어야 겠다고 생각했다.&lt;br /&gt;너무나도 좋은 일들이 가득했던 프로젝트였지만 이번 프로젝트에서 아쉬운 점을 한 가지 뽑자면 구현에 급급한 개발을 했다는 점이 아쉬움으로 다가온다. 새로운 언어를 사용해 기능을 구현하여 결과를 단시간 안에 구현해 내야 했기 때문에 결과물에 초점이 맞추어져 있어 디자인 패턴의 적용 및 클린 코드와는 약간 거리가 있는 개발이었던 것 같다. 현재 ZeroZone 프로젝트를 Swift를 이용하여 iOS 앱으로 다시 개발을 진행하고 있는 만큼 디자인 패턴을 적용하여 짜임새있는 개발을 진행해 보고 싶다.&lt;br /&gt;이번 2023 Solution Challenge에도 새로운 팀, 새로운 주제로 참여하게 될 예정이다. 벌써부터 우리 팀의 주제에 많은 애정이 생기고 있는 것 같다. 이번 프로젝트에서도 좋은 결과가 있었으면 하는 바람이다. 아자아자..!!&lt;/p&gt;</description>
      <category>프로젝트/ZeroZone</category>
      <category>dalgona</category>
      <category>GDSC Sookmyung</category>
      <category>Google</category>
      <category>People's Choice Award</category>
      <category>Solution Challenge</category>
      <category>top10</category>
      <category>ZeroZone</category>
      <category>구글</category>
      <category>솔루션 챌린지</category>
      <author>whaeun</author>
      <guid isPermaLink="true">https://whaeun.tistory.com/40</guid>
      <comments>https://whaeun.tistory.com/40#entry40comment</comments>
      <pubDate>Tue, 20 Dec 2022 00:56:49 +0900</pubDate>
    </item>
    <item>
      <title>Solution Challenge Top50 후기</title>
      <link>https://whaeun.tistory.com/39</link>
      <description>&lt;pre class=&quot;erlang-repl&quot;&gt;&lt;code&gt;도은 : flutter 기술을 체화하고 프로젝트 배포하기!  TOP50 
혜민 : TOP 50!! flutter 정복
효민 : TensorflowLite로 플젝 완성해보기. 나도 TOP50!!
민휘 : TOP 50 들기, 스프링 공부해서 활용, 서버 배포하기&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔루션 챌린지 팀을 모으고 처음 우리가 정했던 목표였다. 팀에서 Flutter를 처음 사용해 보기로 결정했었기 때문에 클라이언트 파트는 플러터 스터디부터 시작하게 되었고 아직 앱 배포 경험이 많지 않아 우리의 주된 목표를 '배포'로 잡았다. TOP50라는 목표도 회의 도중에 &quot;우리 꿈을 크게 가져야지!&quot;하면서 정했었는데 프로젝트를 계속 진행해 나가며 우리 모두 &quot;ZeroZone&quot;프로젝트에 애정을 가지게 되었다. 처음 프로젝트를 시작하며 &quot;ZeroZone 프로젝트에 들어가며&quot;에 대한 글을 썼었는데 어느덧 ZeroZone은 Version2까지 발전하게 되었다. 계획부터 배포까지 많은 노력을 들인 프로젝트인 만큼 ZeroZone은 학창 시절 만들어 보았던 프로젝트 중 가장 소중한 경험 중 하나로 남을 것 같다. 오늘은 &quot;ZeroZone 프로젝트에 들어가며&quot;에 나온 내용 이후의 이야기에 대해 적어보고자 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  &lt;b&gt;Solution Challenge Top 50 진출&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 밤 샌 고민 끝에 정했던 프로젝트 주제였던 만큼 내심 Top50 진출의 꿈을 가지긴 했지만 정말로 Top50에 진출할 줄은 몰랐던 만큼 너무 감격스러웠던 순간이었다. 하지만 우리는 결과 발표가 나자마자 감격스러운 상황을 뒤로 하고 Top10을 위한 재제출까지 우리에게 남은 현 ZeroZone의 발전 과제를 진행해야 했다. 우리가 Top50 진출 전 미뤄두었던 심화 과제 3가지를 뽑자면 다음과 같았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;1) 사용자 경험 중심의 앱 디자인&lt;br /&gt;&lt;/span&gt;2) 머신러닝 서비스 적용&lt;br /&gt;3) 동영상 로딩 지연 문제 해결&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 우리는 이 3가지 과제를 해결하고자 약 한 달여 기간 동안 총력을 다했다. 구글 현직자 분들의 UI/UX 멘토링까지 거친 후에는 앱이 말 그대로 '재탄생'했다고 할 수 있을 정도로 많은 발전을 이루어낼 수 있었다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 멘토링&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 영어로 멘토링을 받았었는데 다행히 Google Korea 분들의 배려로 한국인 멘토분께 멘토링을 받을 수 있었다. 우리는 UI/UX에 대한 멘토링과 GCP에 대한 멘토링을 선택하여 들었는데 멘토링을 받으며 그동안 고민해 왔던 내용들에 대해&amp;nbsp; 많은 질문을 할 수 있었고 멘토링 끝에 사용자의 경험을 고려한 ZeroZone version 2를 탄생시킬 수 있었다. 멘토 분들께 많은 도움을 받을 수 있었기에 이 글을 빌려 한국인 멘토 분께 멘토링 받을 수 있도록 도와주신 GDSC Korea 분들과 좋은 조언을 많이 해주신 멘토 분들께 정말 감사하다는 말씀을 드리고 싶다. 3분께 멘토링을 받고 3분 모두에게 많은 가르침을 얻었지만 이 프로젝트에서 클라이언트 포지션을 맡았던 만큼 이 글에서는 UI/UX 멘토링에 대한 내용을 적고자 한다. 정해진 시간동안 효율적으로 멘토링을 진행하기 위해 우리는 ZeroZone의 실행 흐름과 기능, UI/UX에 대해 질문할 내용을 미리 피피티로 만들어 어떤 부분들이 궁금한지 미리 여쭤본 후 멘토링에 참여했다. 대략적인 우리의 질문 내용은 다음과 같았다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 커스텀 연습 기능이 추가됨에 따라 화면 내에서 커스텀 연습 기능을 추가할 때 각 구화 학습, 발음 학습 페이지에 삽입해 놓는 것이 좋을지 혹은 커스텀 기능을 탭으로 빼 놓는 것이 더 효율적일지
2. 사용자의 앱 사용성의 측면에서 구화 학습 탭과 말하기 학습 탭을 합쳐 연습 페이지에 들어가기 까지 필요한 탭의 횟수를 줄이는 것이 좋을지 혹은 다른 방식을 사용하는 것이 좋을지&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 질문 내용처럼 우리가 앱의 기능을 배치함에 있어 어떻게 배치해야 사용자가 앱을 보다 편리하게 사용할 수 있을지 앱이 가진 기능을 돋보이게 디자인할 수 있을지에 대해 주로 질문했다. 멘토링 시간에 잘 질문하기 위해 학교에서 &lt;code&gt; UX/UI의 10가지 심리학 법칙 : 사용자의 마음을 읽는 인간 중심 제품과 서비스 디자인&lt;/code&gt; 이라는 책을 빌려 읽어 보기도 했다. 책을 읽으며 결정에 걸리는 시간이 선택지에 대한 사용자의 친숙도와 선택지의 형식에 영향을 받는다는 '힉의 법칙'에 대해 알게 되었고 연습 페이지까지 들어가는데 필요한 탭 수를 줄이기 위해 어떻게 하는 것이 좋을지에 대해 고민하고 질문을 하는 계기가 되었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;51&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bagR6O/btrT1G8UQxv/69gxVNRPUjvRZPt9KuLcg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bagR6O/btrT1G8UQxv/69gxVNRPUjvRZPt9KuLcg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bagR6O/btrT1G8UQxv/69gxVNRPUjvRZPt9KuLcg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbagR6O%2FbtrT1G8UQxv%2F69gxVNRPUjvRZPt9KuLcg0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1154&quot; height=&quot;51&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;51&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. 프로젝트의 변화&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재제출 기간동안 우리의 앱은 새로운 앱으로 다시 태어날 수 있었다. 사용자의 특성을 더 반영하여 세심함을 갖추고자 했고 동시의 사용자의 겸험을 고려하여 앱의 접근성과 편리성을 높이고자 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) Custom 연습 문제 기능 구현&lt;/b&gt;&lt;br /&gt;기존 연습 영상을 모두 직접 촬영하여 서버에 저장해 두었던 이전 버전과는 다르게 머신러닝 포지션에 있는 팀원이 Wav2Lip 모델을 통해 음성으로부터 입술 모양을 생성해주어 컨텐츠를 추가할 때마다 연습 영상을 직접 찍을 필요없이 Wav2Lip 모델로 연습 영상이 생성될 수 있도록 개발했다. 더불어 서버 포지션에 있는 팀원은 이렇게 생성된 영상이 자동으로 GCP 버켓에 올라갈 수 있도록 코드로 처리하여 기존 400개 가량의 연습 컨텐츠를 제공하던 버전 1과 다르게 버전 2에서는 2500개 가량의 연습 컨텐츠를 제공할 수 있게 되었다.&lt;br /&gt;더나아가 커스텀 연습 문제 기능을 제공하여 사용자가 별도로 연습을 원하는 단어/문장이 있을 때 사용자가 연습을 원하는 단어, 문장을 입력하면 머신러닝을 통해 연습 영상을 생성함으로 사용자가 이를 커스텀 구화 학습 목록/커스텀 말하기 학습 목록에서 연습할 수 있도록 서비스를 제공해 주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) UI/UX 개선&lt;/b&gt;&lt;br /&gt;UI/UX에도 많은 변화가 생겼다. 각 버전 별 정리해 놓은 README만 보아도 그 디자인의 차이가 확연히 들어날 정도이기 때문에 앱 UI를 거의 새로 만든 수준으로 개선했다고 할 수 있을 것이다. (디자이너의 중요성..⭐️)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;버전 1: &lt;a href=&quot;https://github.com/dsc-sookmyung/2022-DALGONA-SolutionChallenge/blob/main/First%20Demo.md&quot;&gt;https://github.com/dsc-sookmyung/2022-DALGONA-SolutionChallenge/blob/main/First%20Demo.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;버전 2: &lt;a href=&quot;https://github.com/dsc-sookmyung/2022-DALGONA-SolutionChallenge&quot;&gt;https://github.com/dsc-sookmyung/2022-DALGONA-SolutionChallenge&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발하는 친구들이 모여 디자인까지 진행하다 보니 아무래도 기능이 돋보이는 앱 디자인이라기 보다는 기능이 존재하는 앱 디자인이었다는 생각이 든다. 버전 2로의 프로젝트 업그레이드 진행에서 연습 페이지에도 많은 변화가 생겼다. 멘토링에서 멘토님께서 디자인 가이드를 참고하며 앱 디자인을 수정해 볼 것을 추천해 주셨고 Material Design Guide를 참고하며 48x48 size tap target과 색 선정 및 앱 내 기능이 가지는 중요도에 따른 버튼 크기 차별화에 대해 생각하며 연습 페이지 레이아웃 배치 및 색상 선택을 수정할 수 있었다.&lt;br /&gt;더불어 우리가 개발하고 있는 ZeroZone의 사용자가 청각 장애인 분들임을 고려해 연습 페이지 진입 시 소리가 mute된 상태임을 보여줄 수 있는 버튼을 투가하였고 청각 기능이 완전히 소실되지 않은 청각 장애인의 경우, 소리를 들으며 학습을 진행할 수 있도록 사용자가 mute 버튼 설정을 본인의 상황에 맞게 정할 수 있도록 구현했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;547&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byFN7r/btrT40ZCYJD/nkiXBwToft8ZvqKFKiR2UK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byFN7r/btrT40ZCYJD/nkiXBwToft8ZvqKFKiR2UK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byFN7r/btrT40ZCYJD/nkiXBwToft8ZvqKFKiR2UK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyFN7r%2FbtrT40ZCYJD%2FnkiXBwToft8ZvqKFKiR2UK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;776&quot; height=&quot;547&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;547&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.&lt;/b&gt; &lt;b&gt;이 글을 쓰며..&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저번 8월까지의 활동 회고 이후 Solution Challenge에 대한 글을 작성해야지하고 결심한지 꽤 오랜 기간이 지났지만 하루 빨리 이 때의 기억을 기록해야 겠다는 생각에 오늘에서야 Top50 그 이후의 일 들에 대해 작성하게 되었다. Top 10까지의 글까지 작성하여 올리려 했지만 막상 쓰다보니 글의 길이가 너무 길어짐을 느껴 Top10 선정 그 이후의 일은 다음 포스트에서 적고자 한다.&lt;br /&gt;많은 애정과 열정을 가지고 팀원들과 의지하며 끊임없는 고민을 거듭했던 프로젝트인 만큼 이 글을 적으며 이 때의 기억이 아직도 생생히 남아 있음을 알 수 있었다. Solution Challenge를 진행하며 가장 중요한 요소 중 하나는 바로 &quot;팀 워크&quot;가 아닐까 싶다. 서로를 이해해 주고 신뢰하며 한 사람이 바쁠 때 다른 사람들이 그 자리를 채워주고 지지해 줌으로 팀의 결속을 다질 수 있었고 프로젝트가 끝이 날 때까지 치열하게 고민하고 다양한 의견을 제시하며 프로젝트도 우리도 끊임없이 성장할 수 있었다.&lt;/p&gt;</description>
      <category>프로젝트/ZeroZone</category>
      <category>dalgona</category>
      <category>Flutter</category>
      <category>GDSC Sookmyung</category>
      <category>Google</category>
      <category>Google Solution Challenge</category>
      <category>Solution Challenge</category>
      <category>Top50</category>
      <category>Top50 후기</category>
      <category>ZeroZone</category>
      <author>whaeun</author>
      <guid isPermaLink="true">https://whaeun.tistory.com/39</guid>
      <comments>https://whaeun.tistory.com/39#entry39comment</comments>
      <pubDate>Mon, 19 Dec 2022 23:14:06 +0900</pubDate>
    </item>
    <item>
      <title>HTTP 통신</title>
      <link>https://whaeun.tistory.com/38</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. HTTP 통신에 이용되는 패키지&lt;/h2&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;import 'package:http/http.dart' as http;
import 'dart:convert';&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) &lt;code&gt; import 'package:http/http.dart' as http; &lt;/code&gt; &lt;br /&gt;http 패키지는 http의 get, post, put 등과 같은 메소드들을 사용할 수 있도록 도와주는 패키지로 'as http'를 붙여 http 패키지의 메소드들을 호출할 때, 프리픽스를 붙여 호출하도록 하여 메소드를 더욱 명확하게 사용할 수 있도록 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) &lt;code&gt; import 'dart:convert';&lt;/code&gt;&lt;br /&gt;dart:convert 패키지는 utf8을 지원해 주어 한글이 깨질 경우, 해당 패키지를 통해 한글이 깨지지 않도록 지원 받을 수 있다.&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;var body = jsonDecode(utf8.decode(response.bodyBytes));&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. HTTP 통신 사용 예시&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Flutter는 무언가 변경될 때마다 build() 메서드를 호출하기 때문에 네트워크 요청 코드를 build() 메서드 안이 아닌 initState()에서 호출하는 것이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[ 인터넷에서 데이터 가져오는 방법 ]&lt;br /&gt;1. http 패키지 추가하기.&lt;br /&gt;2. http 패키지를 사용하여 네트워크 요청 생성하기.&lt;br /&gt;3. 응답 정보를 커스텀 Dart 객체로 변환하기.&lt;br /&gt;4. 가져온 데이터를 Flutter에 보여주기.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) get 메소드 사용 예시&lt;/p&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;void userInfo() async {
    var url = Uri.http('${serverHttp}:8080', '/members/info');

    var response = await http.get(url, headers: {
      'Accept': 'application/json',
      &quot;content-type&quot;: &quot;application/json&quot;,
      &quot;X-AUTH-TOKEN&quot;: &quot;${authToken}&quot;
    });

    if (response.statusCode == 200) {
      var body = jsonDecode(utf8.decode(response.bodyBytes));

      var data = body[&quot;response&quot;];
      email = data[&quot;email&quot;].toString();
      name = data[&quot;name&quot;].toString();
    } 
    else {
      print('error : ${response.reasonPhrase}');
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) post 메소드 사용 예시&lt;/p&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;Future&amp;lt;void&amp;gt; changeName(String editName) async {
    var url = Uri.http('${serverHttp}:8080', '/members/name');

    final data = jsonEncode({'name': editName});

    var response = await http.patch(url, body: data, headers: {
      'Accept': 'application/json',
      &quot;content-type&quot;: &quot;application/json&quot;,
      &quot;X-AUTH-TOKEN&quot;: &quot;${authToken}&quot;
    });

    if (response.statusCode == 200) {
      var body = jsonDecode(response.body);
    } 
    else {
      print('error : ${response.reasonPhrase}');
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* Future Class : 미래의 특정 시점에 사용 가능한 잠재적인 값이나 에러를 나타내기 위해 사용된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 참고 자료&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://docs.flutter.dev/development/data-and-backend/networking&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.flutter.dev/development/data-and-backend/networking&lt;/a&gt;&lt;br /&gt;- &lt;a href=&quot;https://docs.flutter.dev/cookbook/networking/fetch-data&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.flutter.dev/cookbook/networking/fetch-data&lt;/a&gt;&lt;/p&gt;</description>
      <category>공부/flutter</category>
      <category>Convert</category>
      <category>Flutter</category>
      <category>future</category>
      <category>http</category>
      <category>HTTP 통신</category>
      <author>whaeun</author>
      <guid isPermaLink="true">https://whaeun.tistory.com/38</guid>
      <comments>https://whaeun.tistory.com/38#entry38comment</comments>
      <pubDate>Sun, 18 Dec 2022 21:59:20 +0900</pubDate>
    </item>
    <item>
      <title>Advanced UI &amp;amp; Animations</title>
      <link>https://whaeun.tistory.com/37</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. Advanced UI&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a id=&quot;user-content-1-gesture&quot; href=&quot;https://github.com/YeonJeans/flutter-study/tree/whaeundo25/%EA%B9%80%EB%8F%84%EC%9D%80/week3#1-gesture&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;1) Gesture&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;InkWell 제스쳐 기능을 제공하지 않는 위젯, 컨테이너를 InkWell 위젯으로 감싸면 onTap() 등의 기능을 제공해 주며 잉크가 번지는 듯한 애니메이션 효과를 준다.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;InkWell(
    onTap: () {
        print(&quot;click!&quot;);
    },
    child: Container(
        padding: EdgeInsets.all(15),
        child: Text(&quot;InkWell&quot;, style: TextStyle(fontSize: 16)),
    ),
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GestureDetector InkWell과는 다르게 사용자의 동작을 감지할 때 애니메이션 효과는 없지만 InkWell보다 다양하고 정밀한 Gesture들을 지원해 준다.&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;onTap() : 탭하는 동작&lt;/li&gt;
&lt;li&gt;onLongPress() : 길게 누르는 동작&lt;/li&gt;
&lt;li&gt;onDoubleTap() : 두 번 탭하는 동작&lt;/li&gt;
&lt;li&gt;onScaleUpdate() : 두 손가락으로 화면을 확대 및 축소하는 동작&lt;/li&gt;
&lt;li&gt;onHorizontalDragUpdate() : 수평으로 드래그하는 동작&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;GestureDetector(
    onTap: () {
        setState(() {
            _lightIsOn = !_lightIsOn;
        });
    },
    child: Container(
        color: Colors.yellow.shade600,
        padding: const EdgeInsets.all(8),
        child: Text(_lightIsOn ? 'TURN LIGHT OFF' : 'TURN LIGHT ON'),
    ),
),&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a id=&quot;user-content-2-slivers&quot; href=&quot;https://github.com/YeonJeans/flutter-study/tree/whaeundo25/%EA%B9%80%EB%8F%84%EC%9D%80/week3#2-slivers&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;2) Slivers&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SliverAppBar&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;pinned : 초기 값은 false이며 스크롤을 내렸을 때 앱바를 사라지게 할 것인지, 사라지게 안 할 것인지 설정&lt;/li&gt;
&lt;li&gt;floating : 초기 값은 false로 스크롤을 내린 후 올렸을 때 AppBar가 천천히 나오게 할 것인지, 맨 위에서 나오게 할 것인지를 설정&lt;/li&gt;
&lt;li&gt;snap : 초기값은 false로 floating과 함께 작성해야 함. 스크롤을 내린 후 올렸을 때 AppBar가 한 번에 내려오게 됨&lt;/li&gt;
&lt;li&gt;expandedHeight : appBar가 expandedHeight로 설정된 크기만큼 확장되고 스크롤 내릴 경우 크기가 줄어듦&lt;/li&gt;
&lt;li&gt;flexibleSpace : appBar에 어떤 UI를 구현할 건지 설정&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Sliver Widget&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SliverFillRemaining 스크롤 영역에 표시될 화면을 정의&lt;/li&gt;
&lt;li&gt;SliverGrid gridDelegate를 통해 Grid view를 어떻게 나열할 것인지 설정&lt;/li&gt;
&lt;li&gt;SliverFixedExtentList itemExtent를 통해 List의 크기를 정하고 delegate를 통해 화면에 표시될 위젯 설정&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;a id=&quot;user-content-3-animations&quot; href=&quot;https://github.com/YeonJeans/flutter-study/tree/whaeundo25/%EA%B9%80%EB%8F%84%EC%9D%80/week3#3-animations&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;2. Animations&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a id=&quot;user-content-1-implicit-animations&quot; href=&quot;https://github.com/YeonJeans/flutter-study/tree/whaeundo25/%EA%B9%80%EB%8F%84%EC%9D%80/week3#1-implicit-animations&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;1) Implicit animations&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위젯 내부에서 자체적으로 애니메이션이 일어나는 것을 이야기하며 이미 프로그래밍 되어 있거나, 스타일이 입혀져 있는 경우 암시적 애니메이션이라 한다. * 명시적 애니메이션 : 암묵적 애니메이션에서는 제공하지 않는, 애니메이션 커스터마이징을 할 수 있으며 반드시 애니메이션의 트리거를 지정해줘야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[여러가지 암시적 애니메이션 위젯]&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AnimatedAlign(Align) : 지정된 Align이 변경될 때마다 지정된 기한동안 자동으로 child의 위치를 전환하는 애니메이션 버전의 Align&lt;/li&gt;
&lt;li&gt;AnimatedContainer(Container) : 일정 기간 동안 점차적으로 값을 변경하는 Container 애니메이션&lt;/li&gt;
&lt;li&gt;AnimatedDefaultTextStyle(DefaultTextStyle) : TextSytle이 바뀔 때마다 자동적으로 애니메이션 진행&lt;/li&gt;
&lt;li&gt;AnimatedOpacity(Opacity) : 지정된 투명도가 변경될 때마다 지정된 기한동안 child의 투명도를 자동으로 애니메이션 진행&lt;/li&gt;
&lt;li&gt;AnimatedPadding(Padding) : 패딩이 변경되면 자동적으로 애니메이션 진행&lt;/li&gt;
&lt;li&gt;AnimatedPhysicalModel(PhysicalModel) : borderRadius와 elevation이 변경될 때마다 자동으로 애니메이션 진행&lt;/li&gt;
&lt;li&gt;AnimatedPositioned(Positioned) : Stack위젯에서 child의 위치를 제어하며 지정된 위치가 변경될 때마다 지정된 기간동안 child의 위치를 ​​자동으로 애니메이션&lt;/li&gt;
&lt;li&gt;AnimatedThemeSize : 지정된 Theme이 변경될 때마다 지정된 기한동안 색상 등을 자동으로 전환&lt;/li&gt;
&lt;li&gt;AnimatedSize : 주어진 child의 크기가 변할 때마다 주어진 기간 동안 자동으로 크기를 전환&lt;/li&gt;
&lt;li&gt;AnimatedCrossFade : 두 자식 사이에서만 페이드 되지만 크기를 보강하며 뒤집는 애니메이션&lt;/li&gt;
&lt;li&gt;AnimatedSwitcher : 새 위젯과, AnimatedSwitcher에서 자식으로 설정 한 위젯 간에 크로스 페이드를 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a id=&quot;user-content-2-hero-animations&quot; href=&quot;https://github.com/YeonJeans/flutter-study/tree/whaeundo25/%EA%B9%80%EB%8F%84%EC%9D%80/week3#2-hero-animations&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;2) Hero animations&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 경로에 공통된 시각적 기능이 있는 경우 경로가 전환되는 동안 기능이 한 페이지에서 다른 페이지로 물리적으로 이동하도록 사용자를 안내하는데 도움을 주는 애니메이션&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;480&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l64oz/btrTR9inDQO/HCJB2qiT6vkxNdfctabpK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l64oz/btrTR9inDQO/HCJB2qiT6vkxNdfctabpK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l64oz/btrTR9inDQO/HCJB2qiT6vkxNdfctabpK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl64oz%2FbtrTR9inDQO%2FHCJB2qiT6vkxNdfctabpK0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;900&quot; height=&quot;480&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;480&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a id=&quot;user-content-3-staggered-animations&quot; href=&quot;https://github.com/YeonJeans/flutter-study/tree/whaeundo25/%EA%B9%80%EB%8F%84%EC%9D%80/week3#3-staggered-animations&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;3) Staggered animations&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일련의 작업을 통해 시각적 변화를 주어 애니메이션 효과를 주는 방법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[특이사항]&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 애니메이션은 동일한 AnimationController에 의해 구동&lt;/li&gt;
&lt;li&gt;애니메이션이 실시간으로 지속되는 시간에 관계없이 컨트롤러의 값은 0.0에서 1.0 사이&lt;/li&gt;
&lt;li&gt;각 애니메이션의 값은 Interval 0.0에서 1.0 사이&lt;/li&gt;
&lt;li&gt;일정 간격으로 애니메이션을 적용하는 각 속성에 대해 Tween을 생성하고 이는 해당 속성의 시작 및 끝 값을 지정&lt;/li&gt;
&lt;li&gt;Tween은 컨트롤러에서 관리하는 Animation 객체 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;a id=&quot;user-content-4-참고-자료&quot; href=&quot;https://github.com/YeonJeans/flutter-study/tree/whaeundo25/%EA%B9%80%EB%8F%84%EC%9D%80/week3#4-%EC%B0%B8%EA%B3%A0-%EC%9E%90%EB%A3%8C&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;3. 참고 자료&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://api.flutter.dev/flutter/widgets/GestureDetector-class.html&quot;&gt;https://api.flutter.dev/flutter/widgets/GestureDetector-class.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://api.flutter.dev/flutter/widgets/ImplicitlyAnimatedWidget-class.html&quot;&gt;https://api.flutter.dev/flutter/widgets/ImplicitlyAnimatedWidget-class.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://api.flutter.dev/flutter/widgets/Hero-class.html&quot;&gt;https://api.flutter.dev/flutter/widgets/Hero-class.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>공부/flutter</category>
      <category>Advanced UI</category>
      <category>anmation</category>
      <category>Flutter</category>
      <category>gesture</category>
      <category>GestureDetector</category>
      <category>HERO</category>
      <category>ImplicitlyAnimation</category>
      <category>Slivers</category>
      <category>애니메이션</category>
      <author>whaeun</author>
      <guid isPermaLink="true">https://whaeun.tistory.com/37</guid>
      <comments>https://whaeun.tistory.com/37#entry37comment</comments>
      <pubDate>Sat, 17 Dec 2022 23:51:59 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 가장 가까운 같은 글자</title>
      <link>https://whaeun.tistory.com/36</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;문제: &lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/142086&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/142086&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1671167042758&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래머스&quot; data-og-description=&quot;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/142086&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cgCztF/hyQUYbAOCH/OOTHcJFVAOJpBARB1U5Jak/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/ncmN3/hyQU3cTVjP/s3gxCFDjcIrgqPeKOxwOg0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/142086&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/142086&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cgCztF/hyQUYbAOCH/OOTHcJFVAOJpBARB1U5Jak/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/ncmN3/hyQU3cTVjP/s3gxCFDjcIrgqPeKOxwOg0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  사담&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;급한 마음에 논스톱 알고리즘 풀기를 하다 보니 예전 출제진 조건을 맞출 당시 하루 종일 알고리즘 문제를 풀던 때가 생각이 나는 것 같다. 그래도 문제를 풀어나가며 Swift로 알고리즘 문제를 푸는 것에 그나마 익숙해 지고 있는 것 같아 다행이다. 앞으로는 C++로만 문제를 풀지 말고 Swift로 문제 푸는 것을 계속 병행해야 겠다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;  &lt;b&gt;문제 풀이&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 문제는&lt;span style=&quot;color: #000000;&quot;&gt; 문자열&amp;nbsp;s가&amp;nbsp;주어졌을 때,&amp;nbsp;s의 각 위치마다 자신보다 앞에 나왔으면서, 자신과 가장 가까운 곳에 있는 같은 글자가 자신과 얼마나 떨어져 있는지를 배열에 담아 반환하는 문제이다.&lt;br /&gt;이를 해결하기 위해 알파벳 각각의 마지막 위치 인덱스를 저장하는 배열 alpha를 생성했고 문제의 조건 중 주어지는 입력 값이 모두 소문자임이 보장되고 있었기 때문에 아스키코드를 a의 값이 97임을 활용해 주어진 문자열의 각 문자에 대해 &lt;b&gt;(문자의 아스키 코드 값 - 97)&lt;/b&gt;로 배열에 접근할 수 있도록 하여 아직 배열의 값이 -1일 경우, result 배열에 -1을 저장하고 배열의 다른 값이 존재할 경우, 현재 탐색하고 있는 인덱스와 배열에 저장되어 있는 인덱스의 차를 구하여 저장하도록 했다.&lt;br /&gt;&lt;br /&gt;- var alpha = [Int](repeating: -1, count: 27) : Int 형식의 배열을 27개의 -1로 초기화한다.&lt;br /&gt;- s.count : 문자열 s의 길이&lt;br /&gt;- Int(c.asciiValue!) : 문자 c의 아스키코드 값을 반환하여 Int형식으로 변환한다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1671167012351&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import Foundation

func solution(_ s:String) -&amp;gt; [Int] {
    var alpha = [Int](repeating: -1, count: 27)
    var result = [Int](repeating: 0, count: s.count)
    
    var i : Int = 0
    
    for c in s {
        
        var index :Int = Int(c.asciiValue!) - 97
        
        if alpha[index] == -1 {
            result[i] = alpha[index]
        }
        else {
            result[i] = i - alpha[index]
        }
        
        
        alpha[index] = i
        i+=1
    }
    
    return result
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘/프로그래머스 풀이</category>
      <category>swift</category>
      <category>가장 가까운 같은 글자</category>
      <category>가장 가까운 같은 글자 swift</category>
      <category>프로그래머스</category>
      <author>whaeun</author>
      <guid isPermaLink="true">https://whaeun.tistory.com/36</guid>
      <comments>https://whaeun.tistory.com/36#entry36comment</comments>
      <pubDate>Fri, 16 Dec 2022 14:18:09 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 옹알이(1)</title>
      <link>https://whaeun.tistory.com/35</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;문제: &lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/120956&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/120956&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1671115497468&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래머스&quot; data-og-description=&quot;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/120956&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cHTdjl/hyQTHoGP4R/ib68b5MqH8WkgMKJji0XkK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bse7d3/hyQUWYTHFj/U58JOQckJiRCVNWgVNBcq0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/120956&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/120956&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cHTdjl/hyQTHoGP4R/ib68b5MqH8WkgMKJji0XkK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bse7d3/hyQUWYTHFj/U58JOQckJiRCVNWgVNBcq0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코딩테스트 응시 언어를 기존에 사용하던 C++에서 Swift로 변경해야 하는 상황을 마주하여 프로그래머스에서 코팅테스트 입문 문제를 풀며 Swift 언어로의 응시 언어 변경을 위해 공부하게 되었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;옹알이 문제는 &quot;aya&quot;, &quot;ye&quot;, &quot;woo&quot;, &quot;ma&quot;만을 말할 수 있는 아기가 babbling 문자열 배열에 있는 단어들 중 몇 개의 단어를 말할 수 있는지 개수를 세야 하는 문제이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- words.contains(&quot;aya&quot;) : words 문자열에 &quot;aya&quot;가 포함되어 있으면 true를 반환한다.&lt;br /&gt;- words.replacingOccurrences(of: &quot;aya&quot;, with: &quot;-&quot;) : words 문자열에 있는 &quot;aya&quot;를 &quot;-&quot;로 대체한다.&lt;/p&gt;
&lt;pre id=&quot;code_1671115450221&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import Foundation

func solution(_ babbling:[String]) -&amp;gt; Int {
    var count = 0
    var word = &quot;&quot;
    
    for str in babbling {
        word = str
        
        if word.contains(&quot;aya&quot;) {
            word = word.replacingOccurrences(of: &quot;aya&quot;, with: &quot;-&quot;)
        }
        if word.contains(&quot;ye&quot;) {
            word = word.replacingOccurrences(of: &quot;ye&quot;, with: &quot;-&quot;)
        }
        if word.contains(&quot;woo&quot;) {
            word = word.replacingOccurrences(of: &quot;woo&quot;, with: &quot;-&quot;)
        }
        if word.contains(&quot;ma&quot;){
            word = word.replacingOccurrences(of: &quot;ma&quot;, with: &quot;-&quot;)
        }
        
        word = word.replacingOccurrences(of: &quot;-&quot;, with: &quot;&quot;)
        

        if word == &quot;&quot; { 
            count += 1
        }

    }

    return count
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘/프로그래머스 풀이</category>
      <category>swift</category>
      <category>옹알이</category>
      <category>옹알이 Swift</category>
      <category>프로그래머스</category>
      <author>whaeun</author>
      <guid isPermaLink="true">https://whaeun.tistory.com/35</guid>
      <comments>https://whaeun.tistory.com/35#entry35comment</comments>
      <pubDate>Fri, 16 Dec 2022 00:00:45 +0900</pubDate>
    </item>
    <item>
      <title>Statement vs PreparedStatement</title>
      <link>https://whaeun.tistory.com/34</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. SQL 동작 방식&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1) 쿼리 문장 분석

2) 컴파일

3) 실행
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Statement&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) Statement&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;String sqlstr = &quot;SELECT name, memo FROM TABLE WHERE num = &quot; + num 

Statement stmt = conn.credateStatement(); 

ResultSet rst = stmt.executeQuerey(sqlstr);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Statement executeQuery()나 executeUpdate() 를 실행하는 시점에 파라미터로 SQL문을 전달하는데, 이 때 전달되는 SQL 문은 완성된 형태로 한눈에 무슨 SQL 문인지 파악하기 쉽다. 하지만, Statement는 SQL문을 수행하는 과정에서 매번 컴파일을 하기 때문에 성능 문제가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) Statement를 사용하는 상황&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SQL 쿼리를 한 번만 실행하려는 경우 Statement 인터페이스를 사용한다. Dynamic SQL을 사용하게 될 경우, 매번 조건절이 틀려져 캐싱의 장점이 사라지기 때문에 Statement를 사용하는 것이 더 낫다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. PreparedStatement&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) PreparedStatement&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;String sqlstr = &quot;SELECT name, memo FROM TABLE WHERE num = ? &quot; 

PreparedStatement stmt = conn.prepareStatement(sqlstr); 

pstmt.setInt(1, num);

ResultSet rst = pstmt.executeQuerey();
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PreparedStatement는 준비된 Statement로 여기서 준비는 컴파일(Parsing) 을 이야기하며, 컴파일이 미리 되어있기 때문에 Statement 에 비해 성능상 이점이 있다. PreparedStatement는 보통 조건절과 함께 사용되며 재사용이 되는데, ? 부분에만 변화를 주어 지속적으로 SQL을 수행하기 때문에 한눈에 어떤 SQL문인지 파악하기에는 어렵움이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) PreparedStatement를 사용하는 상황&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Statement를 사용하면 매번 쿼리를 수행할 때마다 계속적으로 단계를 거치면서 수행하지만 PreparedStatement는 처음 한 번만 SQL 동작방식의 3단계를 거친 후 캐시에 담아 재사용한다. 따라서 동일한 쿼리를 반복적으로 수행한다면 PreparedStatement가 DB에 보다 적은 부하를 주며, 좋은 성능을 보인다. 더불어 사용자 입력 값으로 쿼리문을 실행하는 경우에도 PreparedStatement가 더 유리한데 이는pared Statement가 특수 기호가 들어오더라도 알아서 파싱해주므로 이로 인한 오류를 막을 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. Statement 와 PreparedStatement 비교&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 112px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;Statement&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;PreparedStatement&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;SQL 문이 한 번 실행될 경우 사용&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;SQL 문이 여러 번 실행될 경우 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;런타임에 매개변수 전달 불가능&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;런타임에 매개변수 전달 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;DDL문에 사용&lt;br /&gt;(CREATE, ALTER, DROP, TRUNCATE)&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;모든 SQL 쿼리에 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;성능이 낮음&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;Statement 보다 비교적 성능이 높음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;일반 SQL 쿼리 실행시 사용&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;동적 SQL 쿼리 실행시 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 출처&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://devbox.tistory.com/entry/Comporison&quot;&gt;https://devbox.tistory.com/entry/Comporison&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://velog.io/@ragnarok_code/DataBase-Statement와-Prepared-Statement-차이점&quot;&gt;https://velog.io/@ragnarok_code/DataBase-Statement와-Prepared-Statement-차이점&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/Database#statement-vs-preparedstatement&quot;&gt;https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/Database#statement-vs-preparedstatement&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>공부/CS 스터디</category>
      <category>Database</category>
      <category>PreparedStatement</category>
      <category>SQL</category>
      <category>Statement</category>
      <author>whaeun</author>
      <guid isPermaLink="true">https://whaeun.tistory.com/34</guid>
      <comments>https://whaeun.tistory.com/34#entry34comment</comments>
      <pubDate>Thu, 8 Dec 2022 12:30:12 +0900</pubDate>
    </item>
  </channel>
</rss>