<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>iou-bohun.log</title>
        <link>https://velog.io/</link>
        <description>.</description>
        <lastBuildDate>Tue, 18 Feb 2025 13:08:22 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>iou-bohun.log</title>
            <url>https://velog.velcdn.com/images/iou-bohun/profile/bdb22867-cef3-4080-9d57-d43932a2dc27/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. iou-bohun.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/iou-bohun" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[DFS 파이썬 ]]></title>
            <link>https://velog.io/@iou-bohun/DFS-%ED%8C%8C%EC%9D%B4%EC%8D%AC</link>
            <guid>https://velog.io/@iou-bohun/DFS-%ED%8C%8C%EC%9D%B4%EC%8D%AC</guid>
            <pubDate>Tue, 18 Feb 2025 13:08:22 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/iou-bohun/post/5cc1a224-539b-40a0-a5b5-e6620d4f4c67/image.png" alt=""></p>
<h1 id="dfsdepth-first-searching">DFS(Depth First Searching)</h1>
<p><strong>그래프 탐색 알고리즘</strong> 중 하나로, 한 노드에서 출발하여 <strong>최대한 깊이</strong> 내려간 뒤, 더 이상 갈 곳이 없으면 되돌아오면서 다른 경로를 탐색하는 방식이다. </p>
<hr>
<h3 id="특징">특징</h3>
<ul>
<li><strong>스택</strong> 또는** 재귀** 를 사용</li>
<li><blockquote>
<p>일반적으로 재귀 함수로 구현하지만, 스택을 활용한 반복문으로도 구현 가능하다.</p>
</blockquote>
</li>
<li><strong>백트래킹</strong> 과 자주 사용</li>
<li><blockquote>
<p> 모든 경우의 수를 탐색할 때, 필요 없는 경로는 가지 않고 되돌아오는 방식</p>
</blockquote>
</li>
<li>그래프 탐색에서 DFS vs BFS</li>
<li><blockquote>
<p>DFS: <strong>경로 탐색</strong>에 유리(미로 찾기, 백트래킹 문제)</p>
</blockquote>
</li>
<li><blockquote>
<p>BFS: <strong>최단 거리 탐색</strong>에 유리(길 찾기, 네트워크 문제)</p>
</blockquote>
</li>
</ul>
<hr>
<pre><code>예시 그래프
    1
   /|\
  2 3 4
 /| |
5 6 7
</code></pre><hr>
<h5 id="재귀-함수를-이용한-dfs-예제">재귀 함수를 이용한 DFS 예제</h5>
<pre><code>def dfs(graph, node, visited):
    visited[node] = True  # 현재 노드 방문 처리
    print(node, end=&#39; &#39;)  # 방문한 노드 출력

    for neighbor in graph[node]:  # 현재 노드의 인접 노드 탐색
        if not visited[neighbor]:  # 방문하지 않은 경우 DFS 호출
            dfs(graph, neighbor, visited)

# 예제 그래프 (인접 리스트 표현)  
# 각 노드가 어디와 연결되어있는지 표시 ex) 1은 2,3,4와 연결 
graph = {
    1: [2, 3, 4],
    2: [1, 5, 6],
    3: [1, 7],
    4: [1],
    5: [2],
    6: [2],
    7: [3]
}

# 방문 여부 리스트 (노드 번호에 맞게 크기 조정)
visited = {key: False for key in graph}

# DFS 실행 (1번 노드부터 시작)
dfs(graph, 1, visited)

**출력**
1 2 5 6 3 7 4</code></pre><h5 id="스택을-활용한-dfs-구현-예제">스택을 활용한 DFS 구현 예제</h5>
<pre><code>def dfs_stack(graph, start):
    visited = {key: False for key in graph}  # 방문 여부 초기화
    stack = [start]  # 스택에 시작 노드 추가

    while stack:
        node = stack.pop()  # 스택에서 노드 꺼내기
        if not visited[node]:  
            visited[node] = True
            print(node, end=&#39; &#39;)  # 방문한 노드 출력

            # 인접 노드를 스택에 추가 (역순으로 넣어야 작은 숫자부터 탐색)
            stack.extend(reversed(graph[node]))  

graph = {
    1: [2, 3, 4],
    2: [1, 5, 6],
    3: [1, 7],
    4: [1],
    5: [2],
    6: [2],
    7: [3]
}

# DFS 실행 (1번 노드부터 시작)
dfs_stack(graph, 1)


** 출력 **
1 2 5 6 3 7 4</code></pre><p>두 방식의 경우 </p>
<ul>
<li>재귀 방식은 코드가 간결하지만 스택 오버플로우 위험이 있음</li>
<li>스택 방식은 메모리 관리가 효율적이며 더 안전하다. </li>
</ul>
<h3 id="이해를-위한-일상예제">이해를 위한 일상예제</h3>
<p>상황 : 컴퓨터 파일 탐색</p>
<pre><code>C:\Users\내문서
 ├── 보고서
 │    ├── 2023
 │    ├── 2024
 ├── 사진
 │    ├── 여행
 │    ├── 가족
 ├── 동영상
</code></pre><p>이와 같이 파일 구조가 형성되어 있다면
-&gt; 보고서 폴더에 들어감
-&gt; 2023 폴더 확인 (찾는 파일 없으면 백트래킹)
-&gt; 2024 폴더 확인 (찾는 파일 없으면 백트래킹)
-&gt; 사진 폴더로 이동
-&gt; 여행 -&gt; 가족 -&gt; 동영상 
이와 같은 방식으로 이루어진다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[파이썬 Graph]]></title>
            <link>https://velog.io/@iou-bohun/%ED%8C%8C%EC%9D%B4%EC%8D%AC-Graph</link>
            <guid>https://velog.io/@iou-bohun/%ED%8C%8C%EC%9D%B4%EC%8D%AC-Graph</guid>
            <pubDate>Mon, 03 Feb 2025 12:57:56 GMT</pubDate>
            <description><![CDATA[<h1 id="graph">Graph</h1>
<p>그래프는 <strong>노드</strong>와 <strong>에지</strong>로 구성된 집합. </p>
<h5 id="노드---데이터를-표현하는-단위">노드 - 데이터를 표현하는 단위</h5>
<h5 id="에지---노드를-연결">에지 - 노드를 연결</h5>
<p>사용 알고리즘 </p>
<ul>
<li>유니온 파인드 <ul>
<li>그래프의 사이클이 생성되는지 판별하는 알고리즘</li>
</ul>
</li>
<li>위상 정렬 <ul>
<li>방향 그래프 에서 선행 작업이 완료된 후에 다음 작업을 수행해야 하는 경우의 순서를 정하는 알고리즘 Ex) 과목 선수 과목 순서</li>
<li>그래프의 각 노도들을 선형으로 정렬하는것 </li>
<li>값이 유일하지 않다는 특징이 있다. </li>
<li>사이클이 없는 방향 그래프 에서만 사용이 가능하다. </li>
</ul>
</li>
<li>다익스트라 <ul>
<li>최단거리 알고리즘</li>
<li>음수 간선 X</li>
</ul>
</li>
<li>벨만 - 포드 <ul>
<li>최단거리 알고리즘</li>
<li>음수 간선 O</li>
</ul>
</li>
<li>플로이드 - 워셜 <ul>
<li>최단거리 알고리즘 </li>
<li>시작점이 없다. </li>
</ul>
</li>
</ul>
<p>이 외의 길찾기 알고리즘
<img src="https://velog.velcdn.com/images/iou-bohun/post/16aa062c-52d1-4dc0-add4-a6c543912a5e/image.png" alt="">
<img src="https://velog.velcdn.com/images/iou-bohun/post/23a7d9ca-a818-4629-864f-bbe75b122335/image.png" alt=""></p>
<ul>
<li>최소 신장 트리 (MST)<ul>
<li>모든 노드를 연결할때 최소 가중치로 연결하는 알고리즘 
<img src="https://velog.velcdn.com/images/iou-bohun/post/39c3aff3-5873-46c3-979a-97bf74db945b/image.png" alt=""></li>
</ul>
</li>
</ul>
<p>   <img src="https://velog.velcdn.com/images/iou-bohun/post/f206a70c-c59b-4701-a0e3-e3602d11a43d/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[파이썬 Greedy]]></title>
            <link>https://velog.io/@iou-bohun/%ED%8C%8C%EC%9D%B4%EC%8D%AC-Greedy</link>
            <guid>https://velog.io/@iou-bohun/%ED%8C%8C%EC%9D%B4%EC%8D%AC-Greedy</guid>
            <pubDate>Fri, 24 Jan 2025 13:49:01 GMT</pubDate>
            <description><![CDATA[<h1 id="그리디-알고리즘">그리디 알고리즘</h1>
<p>그리디 알고리즘 = 현재 상태에서 선택가능한 수 중 최선의 선택지를 고르다 보면 전체 선택지 중 최선의 선택지가 될 것이다. 
= 매 순간 다음 선택지의 최선의 선택만을 고른다.</p>
<h4 id="쉬운-이해">쉬운 이해</h4>
<p>6430원을 쪼갠다고 생각.
5000 - 1개 
1000 - 1개 
500 - 0개 
100 - 4개 
10 - 3개 </p>
<p>이 알고리즘은 문제점이 존재한다. 순간순간의 최선책이 전체 상황에서의 최선을 보장하지 못한다는 것이다. </p>
<h3 id="핵심-이론">핵심 이론</h3>
<ol>
<li>해 선택 : 현재 상태에서 가장 최선이라고 생각되는 해를 선택한다. </li>
<li>적절성 검사 : 현재 선택한 해가 전체 문제의 제약 조건에 벗어나는것은 아닌지 검토한다. </li>
<li>해 검사 : 선택한 해 집합이 문제를 해결할 수 있는 선택인지 검사한다. 
!전체 문제를 해결하지 못한다 -&gt; 1로 돌아간다. </li>
</ol>
<h3 id="사용가능-검토방법">사용가능 검토방법</h3>
<ol>
<li><p>현재의 선택이 미래에 영향을 미치는가? 를 고려한다. 
<img src="https://velog.velcdn.com/images/iou-bohun/post/e3f4eec0-987d-4611-b649-97ebe3aa9592/image.png" alt="">
ex) 서울에서 부산까지 이동을 한다고 했을 때 서울에서 대전까지 가는 방법은 대전에서 부산까지 가는 방법에 영향을 미치지 않는다. </p>
</li>
<li><p>부분의 최적 해가 모이면 전체의 최적 해가 되야한다.</p>
</li>
<li><p>정렬을 잘 해야한다가 핵심! </p>
</li>
</ol>
<h2 id="사용-이유">사용 이유</h2>
<p>빠르다! </p>
<h1 id="문제풀이">문제풀이</h1>
<blockquote>
<ol>
<li>체육복<blockquote>
<h4 id="풀이-과정">풀이 과정</h4>
<ol>
<li>먼저 잃어버린 사람이 여유분을 가지고 있는지 체크해 잃어버린 사람 배열에서 제거한다.</li>
<li>여분이 있는 사람의 앖 뒤 사람이 잃어버린 경우 빌려주며 잃어버린 사람 배열에서 제거한다. </li>
<li>최대 인원에서 잃어버린 사람 배열의 남아있는 수를 빼줘서 리턴</li>
</ol>
</blockquote>
</li>
</ol>
</blockquote>
<pre><code>def solution(n, lost, reserve):
    answer = n
    reservecopy = reserve.copy() # 복사본 생성
    lostcopy = lost.copy()    # 복사본 생성
    for value in reservecopy:  # 잃어버린 사람이 여분을 가지고있는 경우 
        if value in lostcopy:
                lost.remove(value)
                reserve.remove(value)
                print(lost)
    lost.sort()
    reserve.sort()
    for value in reserve:  # 여분을 가지고있는 사람이 잃어버린사람을 빌려줄 수 있는 경우 
        min = value -1
        max = value +1
        for n in lost:
            if(n == min):  # 여분 소유자의 앞 사람 체크 
                lost.remove(min)  # 빌려줄 수 있으면 잃어버린 사람 리스트에서 제거 
            elif(n == max):  # 여분 소유자의 뒷 사람 체크 
                lost.remove(max)  # 빌려줄 수 있으면 잃어버린 사람 리스트에서 제거 
    return answer -len(lost) </code></pre><blockquote>
<blockquote>
<h4 id="트러블-슈팅">트러블 슈팅</h4>
</blockquote>
</blockquote>
<pre><code>    for value in reserve:  
        if value in lost:
                lost.remove(value)
                reserve.remove(value)
                print(lost)</code></pre><blockquote>
<blockquote>
<p><strong>문제상황</strong>: 배열의 중간중간 작동을 안하고 넘어가는 경우가 발생
<strong>원인</strong> : 리스트를 순회하는 도중에 수정을 하기때문에 문제가 발생했다.<br><strong>해결</strong> : 복사본을 생성해 순회를 하고 제거는 원본을 제거하는 방식으로 해결  </p>
</blockquote>
</blockquote>
<blockquote>
<ol start="2">
<li>구명보트 <blockquote>
<h4 id="풀이-과정-1">풀이 과정</h4>
<ol>
<li>정렬 </li>
<li>가장 무거운 사람과 가벼운 사람을 같이 태울수 있는지 확인</li>
</ol>
</blockquote>
</li>
</ol>
</blockquote>
<pre><code>from collections import deque
def solution(people, limit):
    answer = 0
    people.sort()
    people = deque(people)   # 오름차순 정렬 후 Que 
    while len(people)&gt;0:    #남은 사람이 없을때 까지 
        if len(people) == 1:
            answer += 1
            people.pop()    # 남은게 1명이라면 바로 pop
        else:
            wsum = people[0] + people[-1]   # 무거운 사람과 가벼운 사람의 무게합이 리미트 보다 크다면 무거운 사람만 먼저 
            if wsum &gt; limit:
                answer += 1
                people.pop()
            else:             
                people.pop()            # 2 사람의 무게합이 리미트 보다 작으면 양쪽 다 pop
                people.popleft()
                answer += 1
    return answer</code></pre><blockquote>
<ol start="3">
<li>큰 수 만들기</li>
</ol>
</blockquote>
<pre><code>def solution(number, k):
    answer = &#39;&#39;
    num_list = [int(x) for x in list(number)]         # 숫자 나누기 
    listt = []                         
    num_length = len(number) - k           
    for i in range(len(number)):
        while k &gt; 0 and listt and listt[-1] &lt; num_list[i]: #새로운 값이 더 크면 pop,listt 안 비었고
            listt.pop()
            k -= 1
        if k == 0: 
            listt += num_list[i:]             # 남은 값들 이어주기
            break                             
        listt.append(num_list[i])             # 숫자 추가
    if len(listt) &gt; num_length:               #숫자를 담은 리스트가 정답길이보다 길면 슬라이싱
        listt = listt[:num_length]
    answer = &#39;&#39;.join(map(str,listt))          #리스트들 join함수로 합쳐줌
    return answer</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[파이썬 Stack Que]]></title>
            <link>https://velog.io/@iou-bohun/%ED%8C%8C%EC%9D%B4%EC%8D%AC-Stack-Que</link>
            <guid>https://velog.io/@iou-bohun/%ED%8C%8C%EC%9D%B4%EC%8D%AC-Stack-Que</guid>
            <pubDate>Sun, 19 Jan 2025 08:28:53 GMT</pubDate>
            <description><![CDATA[<h1 id="stack">Stack</h1>
<p>LIFO - last in First out / 가장 마지막에 삽입된 데이터가 가장 먼저 나오는 구조 
ex) 그릇 쌓아놓기 </p>
<p>삽입 - append 
삭제 - pop
탑 데이터를 확인 - stack[-1]</p>
<p>활용되는 알고리즘 </p>
<ul>
<li>깊이우선 탐색(DFS)</li>
<li>백트래킹 </li>
</ul>
<h1 id="que">Que</h1>
<p>FIFO - First in First out / 가장 먼저 삽임된 데이터가 가장 먼저 나가는 구조 
선입선출 </p>
<p>삽입 - append 
최선입 삭제 - popleft 
최선입 데이터 확인 - Que[0]</p>
<p>rear - 큐의 가장 끝 데이터 
front - 큐의 가장 앞의 데이터 </p>
<p>활용되는 알고리즘 </p>
<ul>
<li>너비 우선 탐색(BFS)</li>
</ul>
<h3 id="우선순위큐">우선순위큐</h3>
<p>들어간 순서에 상관 없이 우선순위가 높은 데이터가 먼저 나오는 구조 </p>
<h1 id="문제풀이">문제풀이</h1>
<blockquote>
<ol>
<li>같은 숫자는 싫어</li>
</ol>
</blockquote>
<pre><code>def solution(arr):
    answer = []
    n = None;
    for value in arr:
        if(value != n):
            answer.append(value)
        n = value
    return answer</code></pre><blockquote>
<ol start="2">
<li>올바른 괄호 </li>
</ol>
</blockquote>
<pre><code>def solution(s):
    answer = True
    stack=[]
    for value in s:
        if(value ==&quot;(&quot;):
            stack.append(value)
        else:
            if(len(stack) ==0): answer = False
            else:
                stack.pop()
    if(stack !=[]): answer = False
    return  answer</code></pre><blockquote>
<ol start="3">
<li>기능개발</li>
</ol>
</blockquote>
<pre><code>def solution(progresses, speeds):
    answer =[]
    cnt = 0
    ans = 0
    while(len(progresses)&gt;0):
        if(progresses[0] + cnt*speeds[0])&gt;=100:
            ans = ans+1
            progresses.pop(0)
            speeds.pop(0)
        else:
            if(ans&gt;0):
                answer.append(ans)
                ans =0
            cnt = cnt+1
    answer.append(ans)
    return answer</code></pre><blockquote>
<ol start="4">
<li>프로세스</li>
</ol>
</blockquote>
<pre><code>def solution(priorities, location):
    compare = [chr(65 + i) for i in range(len(priorities))]
    char = compare[location]
    answer = 0
    ans=[]
    while(len(priorities)&gt;0):
        if(priorities[0]&lt;max(priorities)):
            priorities.append(priorities[0])
            priorities.pop(0)
            compare.append(compare[0])
            compare.pop(0)
        elif(priorities[0] == max(priorities)):
            ans.append(compare[0])
            priorities.pop(0)
            compare.pop(0)
    print(ans)
    return ans.index(char)+1</code></pre><blockquote>
<ol start="6">
<li>두 큐 합 같게하기 </li>
</ol>
</blockquote>
<pre><code>from collections import deque
def solution(queue1, queue2):
    answer = -1
    dq1,dq2 = deque(queue1),deque(queue2)
    sumq1, sumq2 = sum(queue1),sum(queue2)
    cnt = 0
    for i in range(300000):
        if(sumq1 == sumq2):
            answer =cnt
            break
        elif(sumq1 &lt; sumq2):
            sumq1 = sumq1 + dq2[0]
            sumq2 = sumq2 - dq2[0]
            dq1.append(dq2[0])
            dq2.popleft()
            cnt = cnt+1
        elif(sumq1 &gt; sumq2):
            sumq1 = sumq1 - dq1[0]
            sumq2 = sumq2 + dq1[0]
            dq2.append(dq1[0])
            dq1.popleft()
            cnt = cnt+1
    return answer</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[ 파이썬 Array/ List/ Map/ Set]]></title>
            <link>https://velog.io/@iou-bohun/%ED%8C%8C%EC%9D%B4%EC%8D%AC-Array-List-Map-Set</link>
            <guid>https://velog.io/@iou-bohun/%ED%8C%8C%EC%9D%B4%EC%8D%AC-Array-List-Map-Set</guid>
            <pubDate>Sat, 11 Jan 2025 07:07:18 GMT</pubDate>
            <description><![CDATA[<h3 id="배열">배열</h3>
<p> 메모리의 <strong>연속 공간</strong>에 값이 채워져 있는 형태 
 -&gt; 인덱스를 통해서 참조할 수 있다. (장점)
 -&gt; 메모리가 연속적으로 붙어있기에 새로운 값을 삽입하거나, 특정 인덱스의 값을 삭제하기가 어렵다. (단점)</p>
<h3 id="리스트">리스트</h3>
<p> <strong>값과 포인터</strong>를 묶은 노드라는 것을 포인터로 연결한 자료구조.
 인덱스를 통해서 접근을 할 수 없다.Head 포인터부터 순서대로 접근해야 한다. 
 -&gt; 접근하는 속도가 느리다.
 연결이 포인터로 이루어져있기에 데이터를 삽입하거나, 삭제하는 연산 속도가 빠르다.
 크기가 정해져 있지 않다.</p>
<p> *파이썬에서는 배열과 리스트를 크게 구별하여 사용하지 않는다. 
 각 자료구조의 장점만을 모아서 구현되어있다. </p>
<h3 id="map">Map</h3>
<p>Key Value쌍으로 이루어진 자료구조. </p>
<p>특징</p>
<ul>
<li>조회 속도가 빠르다.  = O(1) </li>
<li>값의 중복은 가능하지만, 키의 중복은 불가하다. </li>
</ul>
<p><code>dict ={}</code>
와 같이 생성한다. </p>
<h3 id="set">Set</h3>
<p>중복을 허용하지 않는 자료구조이다. 
수학에서의 집합의 개념을 생각하면 된다. </p>
<p><code>eset = set()</code>
<code>eset = {}</code>
하단의 경우 단순 값의 연속이 들어가면 Set 값 밸류 쌍이 들어가게 되면 Dict로 생성된다.
와 같이 생성한다. </p>
<blockquote>
</blockquote>
<p>set의 경우 중복이 삭제되는것을 확인할 수 있다. 
<img src="https://velog.velcdn.com/images/iou-bohun/post/3f0761c8-c7f1-43df-b7ca-48c32288a253/image.png" alt="">
<img src="https://velog.velcdn.com/images/iou-bohun/post/776b9798-5e50-4db2-afe4-d20e6a5b1543/image.png" alt=""></p>
<hr>
<p>코테문제 풀이 </p>
<blockquote>
<ol>
<li>평균구하기</li>
</ol>
</blockquote>
<pre><code>def solution(numbers):
    return sum(numbers)/len(numbers)  

&gt;2. 약수의 합 
```c#
def solution(num):
    return sum(value for value in range(1, num+1)
              if(num%value ==0))

&gt;3. 자릿수 더하기 </code></pre><p>def solution(n):
    llist = list(map(int,str(n)))
    return(sum(llist))</p>
<blockquote>
<blockquote>
<p>리스트 컴프리핸션 사용 </p>
</blockquote>
</blockquote>
<pre><code>def solution(n):
    return sum([int(value) for value in str(n)])

&gt;4. 주사위게임1</code></pre><p>def solution(a, b):
    answer =0;
    if(a%2!=0 and b%2!=0):
        answer = a<em>a + b*b
    elif(a%2==0 and b%2==0):
        answer = abs(a-b)
    else:
        answer = 2</em>(a+b)
    return answer</p>
<blockquote>
<p>5.포켓몬 </p>
</blockquote>
<pre><code>def solution(nums):
    group = set(nums)
    return min(len(group),len(nums)/2)

&gt;6. 숫자 문자열과 영단어</code></pre><p>def solution(s):
    num_list=[&#39;zero&#39;,&#39;one&#39;,&#39;two&#39;,&#39;three&#39;,&#39;four&#39;, &#39;five&#39;,&#39;six&#39;,&#39;seven&#39;,&#39;eight&#39;,&#39;nine&#39;]
    for a in range(0,10):
        s = s.replace(num_list[a],str(a))
    return int(s)</p>
<pre><code>
&gt;7. 달리기 경주</code></pre><p>def solution(players, callings):
    dict ={}
    n=0
    for i in players:
        dict[i] = n
        n= n+1
    for name in callings:
        score = dict[name]
        dict[name] -=1
        dict[players[score-1]] +=1
        players[score-1],players[score] = players[score],players[score-1]
    return players</p>
<pre><code>
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[넥슨게임 QA (Nexon Tag)_ AutoFlow]]></title>
            <link>https://velog.io/@iou-bohun/%EB%84%A5%EC%8A%A8%EA%B2%8C%EC%9E%84-QA-Nexon-Tag-AutoFlow</link>
            <guid>https://velog.io/@iou-bohun/%EB%84%A5%EC%8A%A8%EA%B2%8C%EC%9E%84-QA-Nexon-Tag-AutoFlow</guid>
            <pubDate>Tue, 26 Nov 2024 10:16:55 GMT</pubDate>
            <description><![CDATA[<h6 id="게임-qa에-대한-글을-읽고-작성한-글이다">게임 QA에 대한 글을 읽고 작성한 글이다.</h6>
<h3 id="게임-품질">게임 품질</h3>
<p>게임 품질은 관리하기가 까다로운 영역으로 알려져 있다. 일반적인 소프트웨어와 달리 기능 외에도, 게임플레이. 밸런스, 스토리 등 다양한 테스트가 동반되기 때문이다. </p>
<blockquote>
<p>내 생각에도 게임은 정말 장애률 0%를 목표로 해야하는 사업분야라고 생가한다. 잠깐이라도 서버가 멈추거나 버그가 있다면 게임 플레이어들은 아예 그 게임을 떠나기도 하기 때문이다. 
넥슨의 경우 넥슨 네트웍스 QA 전문가들과 AI/빅데이터 기반 연구개발을 전담하고있는 넥슨 인텔리전스랩스가 솔루션 개발을 진행했다. </p>
</blockquote>
<h3 id="한정된-자원으로-효율성을-얻자">한정된 자원으로 효율성을 얻자</h3>
<p>QA영역은 방대한 게임 컨탠츠와 테스트 시나리오 케이스 등으로 많은 반복이 필요했기에 물리적 시간과 인원에 한계가 존재했다. 
넥슨 네트웍스의 테스트 자동화 솔루션의 필요성에 공감하고  -&gt;  인텔리전스랩스 운영개발실에서 솔루션 개발에 참여하게됨. 
이후 _<strong>AutoFlow</strong>_라는 이름의 자동화 테스트 QA 솔루션이 개발되었다. </p>
<h3 id="autoflow">AutoFlow</h3>
<p>노드 베이스 비주얼 스크립팅 방식의 AutoFlow가 탄생했다. 
<img src="https://velog.velcdn.com/images/iou-bohun/post/25a017ff-097f-40c1-bcd9-e9ed54711bf9/image.png" alt="">
누구나 쉽게 적응이 가능하도록 비주얼 스크립팅 방식을 채택했고, 그 결과 1달이면 대부분의 기능을 익히고 사용할 수 있었다. 
자동화 테스트에 특화가 되어있다. </p>
<h3 id="casemanager">CaseManager</h3>
<p>수많은 테스트 케이스들을 생성하고 효율적으로 관리할 수 있는 솔루션인 CaseManager가 개발되었다.  파편화되어있는 테스트 케이스를 한곳에서 관리하여 누구나 쉽고 빠르게 필요한 테스트 케이스를 찾거나, 테스트 진행 상황을 즉시 식별할 수 있도록 돕는 통합 관리 솔루션. </p>
<p>테스트 케이스 설계부터, 작성. 수행결과. 리포팅까지 모두 하나의 시스템에서 공동 관리가 가능하다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[QA는 어떻게 일하나요(쏘카 테크블로그)]]></title>
            <link>https://velog.io/@iou-bohun/QA%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%9D%BC%ED%95%98%EB%82%98%EC%9A%94%EC%8F%98%EC%B9%B4-%ED%85%8C%ED%81%AC%EB%B8%94%EB%A1%9C%EA%B7%B8</link>
            <guid>https://velog.io/@iou-bohun/QA%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%9D%BC%ED%95%98%EB%82%98%EC%9A%94%EC%8F%98%EC%B9%B4-%ED%85%8C%ED%81%AC%EB%B8%94%EB%A1%9C%EA%B7%B8</guid>
            <pubDate>Thu, 21 Nov 2024 15:51:58 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/iou-bohun/post/4346a4d6-224f-480b-989a-d2d28a9ccfb0/image.png" alt=""></p>
<h6 id="쏘카-테크블로그의--쏘카-qa는-무슨일을-하고-어떻게-일하나요-httpstechsocarcorpkrqa20220318probationary-period_qahtml를-읽고-작성한-글이다">쏘카 테크블로그의  [쏘카 QA는 무슨일을 하고 어떻게 일하나요?] (<a href="https://tech.socarcorp.kr/qa/2022/03/18/probationary-period_QA.html)%EB%A5%BC">https://tech.socarcorp.kr/qa/2022/03/18/probationary-period_QA.html)를</a> 읽고 작성한 글이다.</h6>
<h3 id="채용-과정">채용 과정</h3>
<p>서류 제출 후 1차 면접전까지 <strong><em>사전과제</em></strong>가 존재했다.  = 쏘카의 서비스 중 하나를 선택하여 테스트 케이스를 작성하는 것. 
이후 1차면접(기술) / 2차면접 / 3차면접으로 진행</p>
<h3 id="qa-뭐하는-팀이지">QA? 뭐하는 팀이지?</h3>
<p>QA팀은 <strong>서비스의 기능을 검증하고 관리하기 위한 일련의 활동을 하는 팀</strong>
QA는 프로젝트의 시작부터 마무리까지 모든 과정에 참여하여 각 단계별로 품질을 저하시키거나 리소스가 낭비될 수 있는 요소를 발견한 뒤, 해당 프로젝트의 품질을 향상시키고 리소스 낭비를 방지하는것을 목적으로 한다. <img src="https://velog.velcdn.com/images/iou-bohun/post/03e00098-f8d1-437f-9ac1-85a15e31dfd5/image.png" alt=""></p>
<h3 id="qa가-일반적으로-하는일들">QA가 일반적으로 하는일들</h3>
<h4 id="킥오프-참여">킥오프 참여</h4>
<p>프로젝트의 방향성, 목적, 요구사항 등 프로젝트의 근본적인 목적을 명확히 파악해야 올바른 검증을 진행할 수 있다. 또한 초기 단계에서 발생할 수 있는 오류를 사전에 방지하여 낭비될 수 있는 리소스를 졸이기 위함. <img src="https://velog.velcdn.com/images/iou-bohun/post/9068a7e9-996c-4036-941c-68aa3a9cfacf/image.png" alt=""></p>
<h3 id="분석--qa-plan-작성">분석 &amp; QA Plan 작성</h3>
<p>기획서를 분석하여 프로젝트 수행 시 발생할 수 있는 리스크를 예상해보고 테스트 전략을 수립한다. 
이후 <em><strong>QA Plan</strong></em> 이라 하는 문서를 작성한다.
 _<strong>QA Plan</strong>_은 테스트를 하기 위해 필요한 리소스들을 요약해놓은 문서로, QA가 정해진 프로세스대로 업무를 수행하기 위한 청사진 역할을 한다. 
QA Plan의 내용들 </p>
<blockquote>
<p>[프로젝트 명] QA Plan</p>
</blockquote>
<ul>
<li><p>요약</p>
</li>
<li><p>프로젝트명</p>
</li>
<li><p>프로젝트 자료</p>
<ul>
<li>기획서</li>
<li>디자인</li>
<li>Test Case</li>
<li>Test Data</li>
<li>참여자</li>
<li>배포되는 버전</li>
<li>QA 기간<ul>
<li>Test Case 작성 기간</li>
<li>테스트 기간</li>
<li>Sign off 날짜 </li>
<li>배포 요청일 </li>
<li>모니터링</li>
</ul>
</li>
<li>테스트 범위</li>
<li>테스트 제외 범위</li>
<li>품질 목표 설정 </li>
<li>테스트 종료 조건 설정 </li>
<li>테스트 환경 <ul>
<li>디바이스</li>
<li>OS 버전</li>
</ul>
</li>
<li>테스트 오청사항</li>
</ul>
<h3 id="테스트-케이스-작성">테스트 케이스 작성</h3>
<p>테스트 케이스를 작성하는 과정에서 요구사항에 대한 오류를 찾을 수도 있고 고려되지 않았던 부분을 찾아낼 수 있다. 또한 테스트 케이스 리뷰 과정을 통해 팀 구성원들에게 테스트 케이스 적정성을 점검하고 잘못된 이해로 인한 오류도 점검할 수 있다. </p>
<h5 id="케이스-작성-예시">케이스 작성 예시</h5>
<p><img src="https://velog.velcdn.com/images/iou-bohun/post/2318f72f-75a5-4180-abee-0037805339b0/image.png" alt=""></p>
</li>
</ul>
<h3 id="테스트-데이터와-환경-준비">테스트 데이터와 환경 준비</h3>
<p>테스트를 수행하기 위한 기본 데이터들을 정리하고 어떤 환경에서 테스트가 시작될지를 미리 준비하는 과정.</p>
<h3 id="테스트-수행--버그-리포트-작성">테스트 수행 &amp; 버그 리포트 작성</h3>
<p>준비된 테스트켕스 외에도 탐색적 테스트, ad-hoc 테스트 등을 통해 이슈 발견 
버그리포트는 다음과 같은 내용으로 작성 </p>
<blockquote>
<p>[버그리포트 제목]</p>
</blockquote>
<ul>
<li>발생 환경(os 버전, 앱/웹 버전, 서버)</li>
<li>재현율</li>
<li>이슈 설명</li>
<li>사전 조건</li>
<li>재현 절차</li>
<li>예상 결과</li>
<li>실제 결과</li>
<li>담당 부서</li>
<li>우선순위/심각도</li>
<li>발생 버전/수정 버전</li>
<li>이슈 카테고리</li>
<li>첨부파일</li>
</ul>
<h3 id="테스트-결과-공유">테스트 결과 공유</h3>
<p>프로젝트 구성원들에게 결과를 공유한다. 릴리즈가 가능한 상태인지를 알려주고, 테스트 수행 결과와 품질 목표 달성에 따른 판단 결과, 테스트 진행하면서 발생한 이슈 현환들에 대한 정보를 담는다. </p>
<p>여기까지가 QA의 수행 단계들에 대한 내용이었다. 당연히 이 내용뿐만이 아니라 유기적으로 유관부서와 함께 품질의 향상에 도움이 되는 모든일들을 수행한다. </p>
<h3 id="이슈-찾기">이슈 찾기</h3>
<p>이슈는 작성한 테스트 케이스로만 찾을수는 없다. <strong>테스트 케이스</strong>는 기획서를 기반으로 재현 조건과 기대 결과를 도출하여 기대 결과가 정상적으로 출력되는지 확인하는 <strong>긍정 테스트</strong>에 가깝다. </p>
<blockquote>
<p>개발 전에 프로젝트의 목적과 기획서를 바탕으로 다양한 시나리오를 생각해보고, 명확히 정의되지 않은것들을 확인한 뒤, 이해관계에 따라 발생할 수 있는 문제점들을 발견하여 개선되도록 한다. </p>
</blockquote>
<blockquote>
<p>유저 입장에서 미래에 발생할 수 있는 문제들을 미리 예측해보는것 </p>
</blockquote>
<hr>
<h4 id="-참고">* 참고</h4>
<p><a href="https://tech.socarcorp.kr/qa/2022/03/18/probationary-period_QA.html">https://tech.socarcorp.kr/qa/2022/03/18/probationary-period_QA.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[QA란? (우아한 기술블로그)]]></title>
            <link>https://velog.io/@iou-bohun/QA%EB%9E%80-%EC%9A%B0%EC%95%84%ED%95%9C-%EA%B8%B0%EC%88%A0%EB%B8%94%EB%A1%9C%EA%B7%B8</link>
            <guid>https://velog.io/@iou-bohun/QA%EB%9E%80-%EC%9A%B0%EC%95%84%ED%95%9C-%EA%B8%B0%EC%88%A0%EB%B8%94%EB%A1%9C%EA%B7%B8</guid>
            <pubDate>Thu, 21 Nov 2024 14:36:49 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/iou-bohun/post/94c04d95-5724-446c-afa5-e2b145d32510/image.png" alt=""></p>
<h6 id="우아한-형제들에서-운영하는-기술블로그---우아한-기술블로그-에서-qa란-무었인가에-대한-글을-보고-작성한-내용이다">우아한 형제들에서 운영하는 기술블로그  = 우아한 기술블로그 에서 QA란 무었인가에 대한 글을 보고 작성한 내용이다.</h6>
<h3 id="qa--통합테스트">QA != 통합테스트</h3>
<p>필자는 QA란 통합테스트가 아니다! 라는 말로 글을 시작한다. 나도 인턴을 하기 전에는 QA = 테스트 와 동일상에 놓고 생각을 했었다. 학교에서 배운 기능테스트, 비기능테스트, 단위, 통합 ... 이런 테스트들이 QA란 말을 들으면 가장 먼저 생각나는 내용들이었다. </p>
<p>실제로 첫 인턴을 했던 회사에서(품질경영실) 테스트케이스를 작성하고 이를 테스트하는 일을 하시는 분은 본적이 없었다.
다만, 내 책임님이 대외 프로젝트를 담당하시는 분이었기에 품질점검 체크리스드를 가지고 대외에서 하는 프로젝트를 검수하는 외근을 나가시는것을 보았었다. 체크리스트들의 내용들은  산출물들이 잘 작성되어있나, 파일들이 올바른 위치에 존재하나,... 등과 같이 실제 소프트웨어의 기능에 직결되는 내용들보단, 프로젝트 자체의 신뢰도를 높이기 위한 점검내용들이 주였던것 같다. </p>
<p>그렇기에 필자가 말하는 QA != 통합테스트 라는 말이 와닿았던것 같다. </p>
<h3 id="유관부서의-qa에-대한-몰이해">유관부서의 QA에 대한 몰이해</h3>
<blockquote>
<p>상황 1. (한 달도 넘게 진행된 프로젝트 내용을 미리 공유받지 못한 상황에서) &quot;다음주 오픈 예정인데 일주일만 QA해주세요.&quot;</p>
</blockquote>
<p>기능테스트만 하더라도 몇일은 테스트 대상과 범위를 분석하는데 거의 모든 시간을 소모하게 된다. </p>
<blockquote>
<p>(상황1 +) 상황2. &quot;QA했는데 왜 운영 이슈가 계속 나와요? (QA한 거 맞나요?)&quot;</p>
</blockquote>
<p>짧은 기간 안에 파악한 내용으로는 정말 어떻게 동작하는게 맞는 방향인지 알기 어려워 국지적으로 확인만 하는 체커(Checker)에 지나지 않을 수 밖에 없다. </p>
<blockquote>
<p>상황 3. QA담당자가 프로젝트 킥오프 회의와 회고 회의들에서 누락되는 상황.</p>
</blockquote>
<p>킥 오프 회의에서 이번 프로젝트가 어땠는지에 대해 듣지 못한다면, 다음 어떤 활동을 할 지 발전이 없을수 있다. </p>
<h3 id="qa가-사용하는-기술적-지식들"><a href="l">QA가 사용하는 기술적 지식들</a></h3>
<ul>
<li>Appium </li>
<li>Selenium</li>
<li>SiteSpeed.io(+yslow)</li>
<li>postman-newman</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JIRA_대시보드 ]]></title>
            <link>https://velog.io/@iou-bohun/JIRA%EB%8C%80%EC%8B%9C%EB%B3%B4%EB%93%9C</link>
            <guid>https://velog.io/@iou-bohun/JIRA%EB%8C%80%EC%8B%9C%EB%B3%B4%EB%93%9C</guid>
            <pubDate>Fri, 08 Nov 2024 05:00:38 GMT</pubDate>
            <description><![CDATA[<p>Jira의 대시보드를 구성했던 과정</p>
<p>목적 </p>
<ul>
<li>Redmine에서 작성된 품질점검결과 리스트를 Jira롤 옮겨서 시각화를 한다면 어떻게 해야할까? 에서 출발 </li>
</ul>
<p>과정</p>
<ol>
<li>Redmine의 내용들을 CSV파일로 내보내기</li>
<li>내보낸 CSV파일을 Jira의 이슈들로 Import할 수 있도록 전처리 </li>
<li><ol>
<li>전처리 과정 = 대시보드에서 사용가능한 JQL 쿼리문 필터 만들기 / 필터로 활용하기 위한 Jira 커스텀필드 구상</li>
</ol>
</li>
<li>임포트한 이슈들을 활용해 대시보드 구성하기</li>
</ol>
<h3 id="trouble-shooting">Trouble Shooting</h3>
<h4 id="1-jira대시보드의-기능-알아보기">1. Jira대시보드의 기능 알아보기</h4>
<p>Jira의 대시보드에 어떠한 기능들이 있는지를 알아보는것이 가장 큰 이슈였다. 
여러 Gadget들 중에서 커스텀필드를 활용할 수 있고, x,y축의 두가지 정보에 대해서 값을 나타낼수 있는 (2차원 필터 통계)Gadget을 활용하게 되었다. </p>
<h4 id="2-jira의-이슈의-depth가-3단계밖에-되지-않는-문제">2. Jira의 이슈의 Depth가 3단계밖에 되지 않는 문제</h4>
<p>기존 Redmine으로 구성된 데이터의 경우 최대 5Depth까지 확장이 되어있었다. Jira의 경우 <strong>_에픽(고정) -&gt; 자식이슈로 Task -&gt; SubTask _</strong> 의 3단계까지만 확장이 가능했다. 
기존 5단계의 표현을 줄여서 3단계와 Linked이슈의 형태로 변경하여 문제 해결 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Addressable 작업중 오류]]></title>
            <link>https://velog.io/@iou-bohun/Addressable-%EC%9E%91%EC%97%85%EC%A4%91-%EC%98%A4%EB%A5%98</link>
            <guid>https://velog.io/@iou-bohun/Addressable-%EC%9E%91%EC%97%85%EC%A4%91-%EC%98%A4%EB%A5%98</guid>
            <pubDate>Thu, 11 Jul 2024 01:57:01 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/iou-bohun/post/20dfefa3-552e-4407-a6ba-21a96f31bbc3/image.png" alt="">
System.Exception: Unable to load dependent bundle from location Assets/_Main/_Base/_Addressable/Prefabs/Probs/Fruit.prefab
UnityEngine.AddressableAssets.Addressables:InstantiateAsync (object,UnityEngine.Transform,bool,bool)
AddressableInstantiator:OnSpawn () (at Assets/_Main/_Base/_Addressable/Scripts/AddressableInstantiator.cs:20)
UnityEngine.EventSystems.EventSystem:Update () (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:530)</p>
<p><img src="https://velog.velcdn.com/images/iou-bohun/post/8b37f5f2-12a1-4c6a-bfb7-21cd68c17543/image.png" alt="">
OperationException : Dependency operation failed with System.Exception: Unable to load dependent bundle from location Assets/_Main/_Base/_Addressable/Prefabs/Probs/Fruit.prefab.</p>
<p>UnityEngine.AddressableAssets.Addressables:InstantiateAsync (object,UnityEngine.Transform,bool,bool)
AddressableInstantiator:OnSpawn () (at Assets/_Main/_Base/_Addressable/Scripts/AddressableInstantiator.cs:20)
UnityEngine.EventSystems.EventSystem:Update () (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:530)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Addressable 카탈로그]]></title>
            <link>https://velog.io/@iou-bohun/Addressable-%EC%B9%B4%ED%83%88%EB%A1%9C%EA%B7%B8</link>
            <guid>https://velog.io/@iou-bohun/Addressable-%EC%B9%B4%ED%83%88%EB%A1%9C%EA%B7%B8</guid>
            <pubDate>Tue, 09 Jul 2024 06:11:52 GMT</pubDate>
            <description><![CDATA[<h3 id="콘텐츠-카탈로그">콘텐츠 카탈로그</h3>
<p>어드레서블이 시스템에 제공된 키를 기반으로 에셋의 실제 위치를 조회하는데 사용되는 데이터 저장소.</p>
<p>어드레서블을 사용할 때 <em><strong>원격 카탈로그</strong></em> 를 사용하게 된다. 
<img src="https://velog.velcdn.com/images/iou-bohun/post/9832b811-a3e8-4f8a-9f4b-725d3dc4d615/image.png" alt="">
AddressaleAssetSettings의 인스펙터창에서 확인이 가능하다. </p>
<h3 id="콘텐츠-업데이트-빌드-개요">콘텐츠 업데이트 빌드 개요</h3>
<p>어드레서블 시스템은 런타임에 *(초기화) 할 때 업데이트된 콘텐츠 카탈로그를 확인합니다. 업데이트된 콘텐츠 카탈로그가 있는 경우 시스템은 새 카탈로그를 다운로드하고 에셋을 로드할 때 모든 에셋 번들의 최신 버전을 다운로드합니다.</p>
<h5 id="초기화--addressablesinitializeasync함수를-실행할때-addressable세팅에-only-update-catalogs-manually를-체크해제-했다면-카탈로그의-확인과-업데이트가-자동으로-진행된다">*(초기화) =&gt; Addressables.InitializeAsync()함수를 실행할때 Addressable세팅에 Only Update Catalogs Manually를 체크해제 했다면 카탈로그의 확인과 업데이트가 자동으로 진행된다.</h5>
<h3 id="프로젝트-활용내용">프로젝트 활용내용</h3>
<p>AddressableAssetSetting 의 인스팩터에 Only Update Catalogs Manually 라는 항목이 있다.
<img src="https://velog.velcdn.com/images/iou-bohun/post/97e6404e-65e1-473f-8480-fe2eb98f8417/image.png" alt="">
이걸 체크하게 된다면 <code>Addressables.UpdateCatalogs()</code>함수를 이용해 직접 업데이트를 해줘야 한다. 
<code>Addressables.CheckForCatalogUpdates();</code> 로 카탈로그 업데이트 내용이 있는지 체크를 할 수 있다. </p>
<pre><code>IEnumerator UpdateCatalogs() //카탈로그가 변경점이 있는지 체크
{
    List&lt;string&gt; catalogsToUpdate = new List&lt;string&gt;();
    AsyncOperationHandle&lt;List&lt;string&gt;&gt; checkForUpdateHandle = Addressables.CheckForCatalogUpdates();
    checkForUpdateHandle.Completed += op =&gt;
    {
        catalogsToUpdate.AddRange(op.Result);
    };
    yield return checkForUpdateHandle;
    if (catalogsToUpdate.Count &gt; 0)
    {
        debug.text = catalogsToUpdate.Count.ToString();
       // StartCoroutine(UpdateCatalog());  
    }
}</code></pre><p>catalogsToUpdate.Count의 수가 0 초과라면 업데이트 내용이 있다는 것이다. </p>
<pre><code> IEnumerator UpdateCatalog() // 카탈로그 업데이트 
 {
     AsyncOperationHandle updatehandle  = Addressables.UpdateCatalogs();
     yield return updatehandle;
 }</code></pre><p> 업데이트가 있다면 위와같이 <code>UpdateCatalogs()</code>를 사용해 업데이트를 직접 해준다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Adderssable 처음에 업데이트 확인하기 ]]></title>
            <link>https://velog.io/@iou-bohun/Adderssable-%EC%B2%98%EC%9D%8C%EC%97%90-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-%ED%99%95%EC%9D%B8%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@iou-bohun/Adderssable-%EC%B2%98%EC%9D%8C%EC%97%90-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-%ED%99%95%EC%9D%B8%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 05 Jul 2024 12:23:47 GMT</pubDate>
            <description><![CDATA[<p><a href="https://neive.tistory.com/1051">https://neive.tistory.com/1051</a>
<a href="https://hesterdiary.tistory.com/36">https://hesterdiary.tistory.com/36</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Addressable 6-24]]></title>
            <link>https://velog.io/@iou-bohun/Addressable-6-24</link>
            <guid>https://velog.io/@iou-bohun/Addressable-6-24</guid>
            <pubDate>Wed, 03 Jul 2024 01:59:52 GMT</pubDate>
            <description><![CDATA[<p>Addressable이어서 공부한 내용 
이전에 그냥 Addresssables.InstantiateAsync로 오브젝트들을 생성했을 때는 변경사항이 적용되기 전 오브젝트들을 생성하는 경우들이 많았는데, </p>
<pre><code>private void Update()
{
    if (Input.GetKeyUp(KeyCode.T)) {
        AsyncOperationHandle&lt;GameObject&gt; asyncOperationHandle =
            Addressables.LoadAssetAsync&lt;GameObject&gt;(&quot;Assets/Prefabs/Circle.prefab&quot;);

        asyncOperationHandle.Completed += AsyncOperationHandle_Completed;
        Debug.Log(&quot;1&quot;);
    }
}

private void AsyncOperationHandle_Completed(AsyncOperationHandle&lt;GameObject&gt; asyncOperationHandle)
{
    Debug.Log(&quot;2&quot;);
    if(asyncOperationHandle.Status == AsyncOperationStatus.Succeeded)
    {
        Instantiate(asyncOperationHandle.Result);
    }
    else
    {A
        Debug.Log(&quot;Failed to Load&quot;);
    }
}</code></pre><p>이런식으로 다운로드가 완료 된 이후에 오브젝트가 생성되게끔 코드를 바꾸니 위와같은 오류가 없어지게 되었다. </p>
<h3 id="여러-에셋들-동시에-로드하기">여러 에셋들 동시에 로드하기</h3>
<p><code>LoadAssetsAsync</code>를 사용하면 된다. 하나하나 다 이름으로 로드하거나, Lable로 한번에 로드가 가능하다 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Addressable 6-27]]></title>
            <link>https://velog.io/@iou-bohun/Addressable-6-27</link>
            <guid>https://velog.io/@iou-bohun/Addressable-6-27</guid>
            <pubDate>Wed, 03 Jul 2024 01:59:36 GMT</pubDate>
            <description><![CDATA[<h3 id="리소스-폴더-resource-folder">리소스 폴더 (Resource folder)</h3>
<ul>
<li>단점<ol>
<li>빌드 사이즈 커짐 </li>
<li>앱 시작 시간이 길어짐</li>
<li>에셋 이름 변경이 어렵다.</li>
</ol>
</li>
</ul>
<h3 id="addressable-profiler">Addressable Profiler</h3>
<ul>
<li>어드레서블 전용 프로파일러를 유니티에서 제공해준다. </li>
<li>어드레서블 에셋을 로드한 이후 Clear버튼을 누르면 작동이 된다. 
<img src="https://velog.velcdn.com/images/iou-bohun/post/78627272-04f8-4c64-b5a8-73cf5925d33a/image.png" alt=""></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Addressable 로 메모리 관리하기]]></title>
            <link>https://velog.io/@iou-bohun/Addressable-%EB%A1%9C-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B4%80%EB%A6%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@iou-bohun/Addressable-%EB%A1%9C-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B4%80%EB%A6%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 13 Jun 2024 15:08:30 GMT</pubDate>
            <description><![CDATA[<p>유니티 블로그를 참고해서 정리해 본 Addressable로 메모리 관리하는 방법 </p>
<p>예시로 씬에는 InventoryManager스크립트가 있고, 인벤토리 에셋인 검, 보스검, 방패 프리팹 에 대한 참조가 있다. </p>
<p>1단계 : 강한 참조, 어드레서블 X
씬에 있는 Monobehavior내의 프리펩에 강한 참조(인스팩터에서 직접 할당)<img src="https://velog.velcdn.com/images/iou-bohun/post/952d4db2-f5a9-4c95-8464-053219a4eaa5/image.png" alt=""></p>
<p>이 경우 씬을 로드하면 씬에 있는 모든 오브젝트도 종속성과 함께 메모리에 로드됩니다. 이는 InventorySystem에 포함된 모든 프리팹이 모든 종석성(텍스처, 메시, 오디오 등)과 함께 메모리에 상주하게 된다. </p>
<p>2단계 : 어드레서블 구현
원치 않는 에셋이 로드되지 않도록 하기 위해 어드레서블을 사용하도록 인벤토리 시스템을 변경합니다. 직접 참도 대신 에셋 참조를 사용하면 오브젝트가 씬과 함께 로드되지 않는다. </p>
<p>이 경우 일부 아이템을 삭제하더라도 텍스처가 메모리에 남게되는 문제가 생긴다. 에셋번들은 부분적으로 로드할 수 있는 반면, 자동으로 언로드 할 수는 없기 때문이다. </p>
<p>3단계 : 소규모 번들
문제를 해결하기 위해서 에셋 번들의 구성 방식을 소규모로 변경한다. 
변경하는 방법은 어드레서블 그룹을 선택한 다음 BuildMode를 Pack Together에서 Pack Separately로 변경하면 된다. 
<img src="https://velog.velcdn.com/images/iou-bohun/post/b03b03c6-6229-4685-a53b-0bdbdc0676a5/image.png" alt=""></p>
<p>하지만 이 경우 중복된 에셋들이 메모리에 나타나게 되는 문제가 생긴다. </p>
<p>4단계 :에셋 중복 문제 해결
소규모로 번들을 나누어 에셋을 로드할때 에셋은 단순히 프리펩만 있는것이 아니라 그 내부에는 Mesh, Material 등과같은 종속적인 요소가 있다. 여러 번들에서 같은 종속 요소를 사용한다면, 중복이 발생하게된다. </p>
<p>이러한 중복은 </p>
<ol>
<li>종속성을 공유하도록 프리팹을 동일한 번들에 배치한다. </li>
<li>어드레서블의 다른 위치에 중복된 에셋을 명시적으로 포함한다. 
의 방법으로 해결을 할 수 있다. </li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[유나이트 서울 2020 Addressable ]]></title>
            <link>https://velog.io/@iou-bohun/%EC%9C%A0%EB%82%98%EC%9D%B4%ED%8A%B8-%EC%84%9C%EC%9A%B8-2020-Addressable</link>
            <guid>https://velog.io/@iou-bohun/%EC%9C%A0%EB%82%98%EC%9D%B4%ED%8A%B8-%EC%84%9C%EC%9A%B8-2020-Addressable</guid>
            <pubDate>Sun, 09 Jun 2024 14:50:52 GMT</pubDate>
            <description><![CDATA[<h3 id="addressables-개요---why">Addressables 개요 - Why?</h3>
<ul>
<li>큰 게임 빌드와 배포 <ul>
<li>에셋 빌드가 간편하다</li>
<li>에셋 패킹과 참조를 분리하여 관리하여 변경사항을 최소화 </li>
</ul>
</li>
<li>런타임 중 에셋 관리 <ul>
<li>알아서 의존관계를 확인하여 리소스르 로드 </li>
<li>런타임 에셋 메모리 관리 </li>
</ul>
</li>
<li>개발 중에 반복 작업에 대한 편의성 <ul>
<li>Play Mode 를 유연하게 설정, 개발 중에도 실제와 같은 테스트 가능</li>
<li>Editor에서 Local Hosting사용 가능 </li>
</ul>
</li>
</ul>
<h3 id="adderssables-시작---buildmodes">Adderssables 시작 - BuildModes</h3>
<ul>
<li>Play Mode Script &gt;<ul>
<li>Use Asset Dataase<ul>
<li>에디터용 테스트 가능/ 로직에 대한 테스트</li>
</ul>
</li>
<li>Simulate Groups<ul>
<li>어드레스의 기능에 대한 테스트이며, 번들을 이용한 테스트는 아니다. </li>
</ul>
</li>
<li>Use Existing Build<ul>
<li>릴리즈 패키지와 동일한 환경에서의 테스트 
<img src="https://velog.velcdn.com/images/iou-bohun/post/2c896234-652c-4ed2-9595-f9250f8fc925/image.png" alt=""></li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="addressable-사용">Addressable 사용</h3>
<ul>
<li>Headers <pre><code class="language-c#">using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;</code></pre>
</li>
<li>DownloadDependenciesAsync<ul>
<li>먼저 GetDownloadSizeAsync함수를 통해서 다운로드 사이즈에 대한 내용을 받을수 있다. 
리턴값이 0이라면 다운로드 할 내용이 없다는것.</li>
<li>이후 위 함수르 통해 CDN에 올라가있는 번들들을 다운로드 할 수 있다. </li>
<li><img src="https://velog.velcdn.com/images/iou-bohun/post/42475716-1536-4fe0-b376-034de8fbbd3a/image.png" alt=""></li>
</ul>
</li>
<li>LoadAssetAsync<ul>
<li>에셋을 메모리에 로드하는 함수 </li>
</ul>
</li>
<li>InstantiateAsync<ul>
<li>실제 게임오브젝트 생성 </li>
</ul>
</li>
</ul>
<p>add..
어드레서블 에셋을 로드하는 방법</p>
<ol>
<li>어드레서블 명으로 로드하기 </li>
</ol>
<ul>
<li><img src="https://velog.velcdn.com/images/iou-bohun/post/dd3aed8d-6816-4628-9138-9a430bbee847/image.png" alt=""></li>
<li><img src="https://velog.velcdn.com/images/iou-bohun/post/8aa04d0b-fc51-4315-a6be-1c7aee10d2bf/image.png" alt=""></li>
</ul>
<ol start="2">
<li>레이블로 로드하기 </li>
</ol>
<ul>
<li></li>
</ul>
<ol start="3">
<li><code>AssetReference</code>클래스로 로드하기 </li>
<li><code>IResourceLocation</code>으로 로드하기 </li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[새로운 프로젝트 시작  [6.8]]]></title>
            <link>https://velog.io/@iou-bohun/%EC%83%88%EB%A1%9C%EC%9A%B4-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%8B%9C%EC%9E%91-6.8</link>
            <guid>https://velog.io/@iou-bohun/%EC%83%88%EB%A1%9C%EC%9A%B4-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%8B%9C%EC%9E%91-6.8</guid>
            <pubDate>Sun, 09 Jun 2024 08:50:25 GMT</pubDate>
            <description><![CDATA[<p>새로운 프로젝트를 시작하게 됐다. 
이번에 사전 작업으로 대장님이 어드레서블을 작업하라고 하셔서 
어드레서블 부터 공부하고 시작한다. </p>
<blockquote>
<h3 id="에셋번들">에셋번들</h3>
<p> 프로젝트에 있는 에셋들을 일정한 규칙을 정해 묶어놓은것 </p>
</blockquote>
<ul>
<li>에셋 번들 빌드<ul>
<li>에셋 번들 빌드를 완료한 후에 전체 프로젝트를 빌드하면 에셋 번들을 제외한 나머지 부분들만 빌드를 하게된다. -&gt; 빌드의 총 용량이 줄어들게 된다. 
<img src="https://velog.velcdn.com/images/iou-bohun/post/7153ab0b-aff4-4231-9917-bcd7deda30e3/image.png" alt="">
이 에셋 번들을 더 업그레이드 한 것이 어드레서블 이라고 생각하면 된다. </li>
</ul>
</li>
</ul>
<h3 id="동기-비동기">동기 비동기</h3>
<p>동기 - 그 작업이 끝날때까지 기다렸다가 이후 코드 실행 
비동기 - 작업을 호출만 해주고 이후 코드 바로 실행</p>
<h3 id="addressable-개요">Addressable 개요</h3>
<p>어드레서블 시스템의 주요 기능은 에셋에 주소를 할당하고 사용하여 런타임에 로드하는것 이다.</p>
<ul>
<li>에셋들은 <ul>
<li>어플리케이션에 빌트인 되거나 </li>
<li>로컬로 캐싱되거나 </li>
<li>원격으로 호스팅 </li>
</ul>
</li>
<li>될 수 있다. </li>
</ul>
<h3 id="오늘-해본-어드레서블-테스트">오늘 해본 어드레서블 테스트</h3>
<blockquote>
<h3 id="게임-오브젝트-만들기">게임 오브젝트 만들기</h3>
<p>실행 과정</p>
</blockquote>
<p> 1) Addresasble 패키지 다운로드 
 2) Window&gt;Asset Management&gt;Addressables&gt;Groups 에서 Addressable로 등록한 Asset들을 확인할 수 있다. 
  <img src="https://velog.velcdn.com/images/iou-bohun/post/0953ec4a-ac27-41b1-9ad0-5874a6d830d4/image.png" alt="">
3) 처음에는 Default Local Group으로 등록이 된다.
 이때 각각의 그룹은 하나의 AssetBundle로 봐도 무방하다.
4) 오브젝트를 생성하는 코드 작성
<img src="https://velog.velcdn.com/images/iou-bohun/post/f0e56b0a-bbe3-46b9-a832-4362e3179bba/image.png" alt="">
5) Addressable 세팅들
<img src="https://velog.velcdn.com/images/iou-bohun/post/d9e4ccee-5bb2-420f-960e-60829c667d88/image.png" alt=""></p>
<ul>
<li>위 인스팩터에서 아래부분에 위치한 
<img src="https://velog.velcdn.com/images/iou-bohun/post/1e27b137-8396-4c55-9f61-bae3ed4970d5/image.png" alt="">
Packed ASsets을 타고 들어가서 
<img src="https://velog.velcdn.com/images/iou-bohun/post/83792b19-f147-4919-b9ea-a0236009120e/image.png" alt=""></li>
<li>Default Local Group 
<img src="https://velog.velcdn.com/images/iou-bohun/post/45f9b1aa-d582-4a0e-8287-a217ad29b016/image.png" alt=""></li>
<li>Schema 폴더에서도 확인하기 
<img src="https://velog.velcdn.com/images/iou-bohun/post/ef41750e-3d54-4995-99b7-aa5a03ea3762/image.png" alt="">
6) Addressable 경로 설정
<img src="https://velog.velcdn.com/images/iou-bohun/post/76c73c0a-e1d9-4509-a638-e11db5f92b3b/image.png" alt="">
이 경로를 유니티에서 지원하는 CCD(Cloud Contant Delivery)를 활용한다. 
7)Adderssable 컴파일 
<img src="https://velog.velcdn.com/images/iou-bohun/post/0ef251e5-91c2-4377-8bbf-7eff6e404e3a/image.png" alt="">
Addressable Groups에서 빌드과정을 거친다. 
8)CCD에 파일 업로드 하기 </li>
<li>유니티 파일 경로의 SecverData에 있는 파일들을 CCD에 올리면 된다. 
<img src="https://velog.velcdn.com/images/iou-bohun/post/e43779e4-722c-4157-a7eb-b44680902337/image.png" alt=""><h3 id="가장-중요한-빌드한-상태에서-gameobject를-바꾸는-과정">가장 중요한 빌드한 상태에서 GameObject를 바꾸는 과정</h3>
1) 유니티에서 변경이 필요한 오브젝트를 변경 한 후
2) 위의 7~8번 과정을 다시 거치면 된다. </li>
<li>이때 ServerData의 내용들은 삭제를 하고 7번 과정을</li>
<li>CCD에 올라가있는 
<img src="https://velog.velcdn.com/images/iou-bohun/post/f3e840ec-f37c-4775-8a5c-0c6bf1fcf04e/image.png" alt="">
Current Entreis를 Remove All Entires를 한 뒤 8번 과정을 하면 완료 </li>
</ul>
<hr>
<h3 id="이후-과제">이후 과제</h3>
<p>일단 이번 연습으로 빌드 프로그램에서의 게임 오브젝트가 잘 바뀌게 되는것은 확인을 했다. </p>
<ol>
<li>실제 게임개발에서는 image, Sound, VFX등 다양한 리소스에 대해서 관리가 필요하고, 업데이트가 되어야 할 텐데 이 것을 어떻게 정리해야 하는지   </li>
<li>내가 알고있던 게임 다운로드 후, 게임 실행한 후 추가다운로드 하는 과정에 대해서 자세히 공부하기. </li>
</ol>
<hr>
<h3 id="트러블-슈팅">트러블 슈팅</h3>
<p><img src="https://velog.velcdn.com/images/iou-bohun/post/40dcb1e0-1e26-4709-b9c8-56d11209fd89/image.png" alt="">
Addressable 그룹 Build 를 했을때 위와 같은 오류가 발생했다. </p>
<h4 id="해결-방법">해결 방법</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL, 카메라르 기준으로 동심원이 생기는 이슈]]></title>
            <link>https://velog.io/@iou-bohun/TIL-%EC%B9%B4%EB%A9%94%EB%9D%BC%EB%A5%B4-%EA%B8%B0%EC%A4%80%EC%9C%BC%EB%A1%9C-%EB%8F%99%EC%8B%AC%EC%9B%90%EC%9D%B4-%EC%83%9D%EA%B8%B0%EB%8A%94-%EC%9D%B4%EC%8A%88</link>
            <guid>https://velog.io/@iou-bohun/TIL-%EC%B9%B4%EB%A9%94%EB%9D%BC%EB%A5%B4-%EA%B8%B0%EC%A4%80%EC%9C%BC%EB%A1%9C-%EB%8F%99%EC%8B%AC%EC%9B%90%EC%9D%B4-%EC%83%9D%EA%B8%B0%EB%8A%94-%EC%9D%B4%EC%8A%88</guid>
            <pubDate>Wed, 24 Apr 2024 05:32:47 GMT</pubDate>
            <description><![CDATA[<p>유니티 에딧 기준에서는 이슈가 생기지 않지만, 빌드를 할 경우 생기는 이슈
<img src="https://velog.velcdn.com/images/iou-bohun/post/8176582e-c355-4c22-81be-1655e27493eb/image.png" alt="">
위 그림과 같이 카메라를 기준으로 동심원의 그림자가 생기는 이슈가 발생했다. </p>
<p>팀원분의 도움으로 해결을 하였는데, URP 2022버전 이후의 경우 생기는 이슈로 쉐이더의 일부 코드가 존재할 경우 생기는 이슈였다. </p>
<p>쉐이더의 
<code>REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR</code>
부분이 존재하는 경우 바닥에 그림자가 생기게 된다. 
이 부분을 주석처리한 이후 문제가 해결이 됐다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[배칭]]></title>
            <link>https://velog.io/@iou-bohun/%EB%B0%B0%EC%B9%AD</link>
            <guid>https://velog.io/@iou-bohun/%EB%B0%B0%EC%B9%AD</guid>
            <pubDate>Wed, 24 Apr 2024 05:25:31 GMT</pubDate>
            <description><![CDATA[<p>유니티 최적화를 위한 배칭공부 </p>
<h3 id="drawcall이란">DrawCall이란?</h3>
<p>cpu가 Gpu 에게 읽어들인 데이터를 그리라고 하는것 
이때 따라오는 데이터들을 <span style="color:orange">Command Buffer  </span>라고 하며 이 데이터들중, 
메테리얼, 쉐이더 등을 묶어놓은것을 <span style="color:orange">SetPass </span>라고 하며, 이를 전달하는것을 SetPassCall이라고 한다.  </p>
<p>DrawCall뿐만 아니라, 그래픽을 구성하고있는 상태의 데이터들도 함께 Gpu에게 건내주는것을 <span style="color:orange"> Batch </span>라고 한다.</p>
<h3 id="batch에-해당되는-컴포넌트들">Batch에 해당되는 컴포넌트들</h3>
<p><img src="https://velog.velcdn.com/images/iou-bohun/post/05b10591-6f1c-4ad4-8fd6-ff855a7be829/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[3-20)TIL 가비지 컬렉션]]></title>
            <link>https://velog.io/@iou-bohun/3-20TIL-%EA%B0%80%EB%B9%84%EC%A7%80-%EC%BB%AC%EB%A0%89%EC%85%98</link>
            <guid>https://velog.io/@iou-bohun/3-20TIL-%EA%B0%80%EB%B9%84%EC%A7%80-%EC%BB%AC%EB%A0%89%EC%85%98</guid>
            <pubDate>Wed, 20 Mar 2024 10:18:08 GMT</pubDate>
            <description><![CDATA[<h3 id="가비지-컬렉션">가비지 컬렉션</h3>
<p>힙 영역에 할당했던 메모리 중 필요 없게 된 메모리를 모아서 주기적으로 제거해주는것 </p>
<p>가비지 컬렉터가 메모리 영역을 검색하고 참조하고있는것은 살아있다고 표시하고, 
아닌것들은 모아서 비우는 프로세스를 가비지 컬렉션이라고 한다. </p>
<p>GC에서는 이제 0세대 1세대 2세대로 메모리를 관리하는데, 처음 메모리에 할당되는 애들을 0 세대에 두고, 검증해 사용하지 않는 애들은 해제하고, 이래도 사용하는게 있다면 1세대로 가고, 이후에도 사용하는게 있으면 2세대로 간다. </p>
<p>세대가 높아질수록 관리를 하는 빈도가 줄어든다. </p>
<p>개채의 크기에 따라서 기준치보다 크면 LOH, 작으면SOH로 구분하여 관리한다. 
구분하는 이유는 크기가 크다면 더 중요할 가능성이 높기에 따로 관리하기위해서이다. </p>
<p>OS에서 메모리 부족을 알릴 경우GC가 동작한다</p>
<p>메모리가 큰 애들은 생성할때, 삭제할때 시간이 많이 걸리기 때문에 -&gt; 부하가 많이 먹는다 
그래서 나누어서 관리한다. </p>
]]></description>
        </item>
    </channel>
</rss>