<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jiwon_17.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Mon, 15 Sep 2025 05:29:26 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jiwon_17.log</title>
            <url>https://velog.velcdn.com/images/jiwon_17/profile/c623dfc3-0236-44f4-bb21-d205c5a3be4a/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jiwon_17.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jiwon_17" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[자바스크립트_스코프]]></title>
            <link>https://velog.io/@jiwon_17/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%8A%A4%EC%BD%94%ED%94%84</link>
            <guid>https://velog.io/@jiwon_17/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%8A%A4%EC%BD%94%ED%94%84</guid>
            <pubDate>Mon, 15 Sep 2025 05:29:26 GMT</pubDate>
            <description><![CDATA[<h2 id="스코프scope란">스코프(scope)란?</h2>
<p>변수(혹은 함수)의 유효 범위</p>
<blockquote>
<h3 id="주요-스코프-종류">주요 스코프 종류</h3>
<p><strong>전역 스코프 (Global Scope)</strong>
코드 전체에서 접근 가능
브라우저에선 window 객체가 전역 환경.</p>
</blockquote>
<p><strong>함수 스코프 (Function Scope)</strong>
함수 내부에서만 접근 가능.</p>
<blockquote>
</blockquote>
<p><strong>블록 스코프 (Block Scope)</strong>
{ }로 감싸진 영역(let, const).
ES6부터 생겼음.</p>
<blockquote>
</blockquote>
<p><strong>모듈 스코프 (Module Scope)</strong></p>
<blockquote>
</blockquote>
<p>모듈 파일 내부에서만 유효, 전역과 분리되어 있음.</p>
<pre><code>&lt;script type=&quot;module&quot;&gt;에서만 적용됨.</code></pre><h3 id="this와-스코프의-관계">this와 스코프의 관계</h3>
<p>this는 스코프(렉시컬 환경)와는 별개 개념
화살표 함수는 this를 “자신이 정의된 스코프의 this”에서 상속</p>
<h3 id="실행-환경별-최상위-스코프의-this">실행 환경별 최상위 스코프의 this</h3>
<p><strong>(1) type=&quot;javascript&quot; (또는 text/javascript)</strong>
전통적인 스크립트 실행 방식.
최상위 스코프 = 전역 스코프.
브라우저에서는 this === window.</p>
<p><strong>(2) type=&quot;module&quot;</strong>
ES 모듈 스펙을 따름.
모듈 파일 내부는 독립된 모듈 스코프.
최상위 스코프의 this = undefined (strict mode 자동 적용).</p>
<p><strong>(3) type=&quot;text/babel&quot;</strong>
사실 브라우저는 text/babel을 직접 이해하지 못함</p>
<p>Babel(standalone 같은 도구)이 이 코드를 변환해서 실행하는데, 보통은 type=&quot;text/javascript&quot;로 트랜스파일된 코드가 실행</p>
<p>그래서 Babel로 돌린 경우, 
최상위 스코프의 this는 → window가 되는 게 일반적이다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자바스크립트_함수표현식, 화살표함수]]></title>
            <link>https://velog.io/@jiwon_17/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%ED%95%A8%EC%88%98%ED%91%9C%ED%98%84%EC%8B%9D-%ED%99%94%EC%82%B4%ED%91%9C%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@jiwon_17/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%ED%95%A8%EC%88%98%ED%91%9C%ED%98%84%EC%8B%9D-%ED%99%94%EC%82%B4%ED%91%9C%ED%95%A8%EC%88%98</guid>
            <pubDate>Mon, 15 Sep 2025 05:11:51 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h4 id="화살표-함수로-5를-구현하는-함수-funcfunc1를-구현하고-호출">화살표 함수로 5를 구현하는 함수 funcFunc1()를 구현하고 호출</h4>
<pre><code>    const funcFunc1 = () =&gt; {
      console.log(this);    // this === obj
    };
    funcFunc1();</code></pre></blockquote>
<pre><code>**화살표 함수는 스코프를 무시하기때문에 obj참조 가능**


&gt; 
#### 함수 표현식으로 5를 구현하는 함수 funcFunc2()를 구현하되, obj을 바인딩하고, 호출</code></pre><pre><code>const funcFunc2 = function(){
  console.log(this);    // this === obj
}.bind(obj); //함수 표현식에서 강제로 바인딩 시켜주면 obj 참조 가능
funcFunc2();</code></pre><pre><code>
&gt; #### setTimeout()의 callback에서 this 값 확인
callback은 함수 선언문으로 구현하고, timeout은 0으로 지정</code></pre><pre><code>setTimeout(function(){
  console.log(this);    // this === Window
}, 0);</code></pre><blockquote>
</blockquote>
<blockquote>
<h4 id="settimeout의-callback에서-this-값-확인">setTimeout()의 callback에서 this 값 확인</h4>
<p> callback은 화살표 함수로 구현하고, timeout은 0으로 지정</p>
</blockquote>
<pre><code>    setTimeout(() =&gt; {
      console.log(this);    // this === obj
    }, 0);
    //화살표함수는 스코프 무시</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[script_type]]></title>
            <link>https://velog.io/@jiwon_17/scripttype</link>
            <guid>https://velog.io/@jiwon_17/scripttype</guid>
            <pubDate>Mon, 15 Sep 2025 04:58:32 GMT</pubDate>
            <description><![CDATA[<h2 id="script-type-차이">script type 차이</h2>
<blockquote>
</blockquote>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width&quot;/&gt;
  &lt;meta charset=&quot;utf-8&quot;&gt;
  &lt;title&gt;object and this&lt;/title&gt;
  &lt;script src=&quot;https://unpkg.com/babel-standalone@6.15.0/babel.min.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;Arrow Functions&lt;/h1&gt;
&lt;p&gt;Open the console&lt;/p&gt;
&lt;script type=&quot;module&quot;&gt;</code></pre><h3 id="script태그-안-type-속성-중-module-javascipt-babel-차이-알아보기">script태그 안 type 속성 중 module, javascipt, babel 차이 알아보기</h3>
<blockquote>
<p><strong>module</strong> → 최신 JS 모듈 (import/export 가능)</p>
</blockquote>
<p><strong>text/javascript / javascript</strong> → 일반 JS (기본값, 옛날 방식)</p>
<blockquote>
</blockquote>
<p><strong>text/babel</strong> → Babel로 변환해야 실행되는 JS/JSX (React에서 자주 사용)</p>
<h3 id="module의-최상위-스코프는-undefined">module의 최상위 스코프는 undefined</h3>
<blockquote>
</blockquote>
<pre><code>&lt;script type=&quot;module&quot;&gt;에서 **최상위 스코프의 this는 undefined
(만약 type=&quot;text/javascript&quot;였다면 전역 객체인 window가 됨)</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[소프트웨어공학_0527_테스트 프로세스_블랙박스 테스트]]></title>
            <link>https://velog.io/@jiwon_17/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%EA%B3%B5%ED%95%990527%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4</link>
            <guid>https://velog.io/@jiwon_17/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%EA%B3%B5%ED%95%990527%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4</guid>
            <pubDate>Tue, 27 May 2025 07:19:37 GMT</pubDate>
            <description><![CDATA[<h2 id="테스트-프로세스">테스트 프로세스</h2>
<p><strong>조직 테스트 프로세스</strong>
조직 레벨의 테스트 정책과 전략을 수립하는 프로세스</p>
<ul>
<li>테스트 정책과 테스트 전략을 수립</li>
</ul>
<p><strong>테스트 관리 프로세스</strong>
테스트 관리를 위한 프로세스</p>
<ul>
<li><p>테스트 계획에 따라 테스트가 수행되는지를 모니터링하고 문제가 발생하면 이에 대한 대책을 수립하여 대응하기위한 프로세스</p>
</li>
<li><p>테스트 프로세스는 측정되고 통제되어야 함</p>
</li>
<li><p>테스트 진행 상태를 알 수 있도록 여러 매트릭이 준비되고 측정되어야 하며 이를 정기적으로 보고할 수 있는 매커니즘이 구비되어있어야 함</p>
</li>
</ul>
<p><strong>동적 테스트 프로세스</strong>
테스트 계획에 따라 테스트 케이스를 설계하고 테스트 환경을 구축하여 테스트를 실제 수행하는 프로세스</p>
<ul>
<li>테스트 계획에 따라 테스트 케이스를 설계하고 테스트를 환경을 구축하여 실행하는 프로세스</li>
<li>만약 문제가 발견되면 인시던트 레포팅 프로세스 수행</li>
</ul>
<h3 id="테스트-케이스">테스트 케이스</h3>
<ul>
<li>테스트 항목을 정리한 문서</li>
<li>테스트를 체계적으로 진행할 수 있도록 구조화된 방법 제공</li>
<li>응용 프로그램의 기능 측정에 사용되는 시나리오로, 특정 조건이나 작업이 예상 결과와 동일하게 나타나는지 확인하는데 사용됨</li>
</ul>
<blockquote>
<h4 id="테스트-케이스-설계-기법">테스트 케이스 설계 기법</h4>
<p><strong>- 블랙박스 테스트</strong>
명세기반테스트(ISO 29119)
출력 인터페이스 정보나 명세정보를 이용하여 테스트 케이스를 설계</p>
</blockquote>
<ul>
<li>소스코드에 대한 정보 없이 요구사항 명세만 이용하여 테스트 케이스를 생성하는 기법</li>
<li>내부 구조나 세부 작동 원리를 모르는 상태에서 소프트웨어 동작을 검사하는 방법<blockquote>
</blockquote>
</li>
<li><em>- 블랙박스 테스트 기번에서 제공하는 휴리스틱*</em></li>
<li><ul>
<li>동치 분할</li>
</ul>
</li>
<li><ul>
<li>경계치 커버리지</li>
</ul>
</li>
<li><ul>
<li>특수치 커버리지</li>
</ul>
</li>
<li><ul>
<li>원인/효과 커버리지(의사결정 테이블 분석)<blockquote>
</blockquote>
</li>
</ul>
</li>
<li>소프트웨어 테스트 및 블랙박스 테스트 수행 절차</li>
<li>테스트 목표</li>
<li><ul>
<li>결함 제거를 통한 품질 향상이나 유지보수성 향상</li>
</ul>
</li>
<li>테스트 종료 조건</li>
<li><ul>
<li>기간 혹은 모듈당 결함 수</li>
</ul>
</li>
</ul>
<h3 id="블랙박스-테스트-기반에서-제공하는-휴리스틱">블랙박스 테스트 기반에서 제공하는 휴리스틱</h3>
<p><strong>동치 분할</strong></p>
<ul>
<li>모집단 구간을 동등한 처리를 수행하는 그룹으로 분할</li>
<li>모듈이 제공하는 인터페이스와 모듈의 기능을 중심으로 수행</li>
<li>모듈에 입력되는 데이터와 이를 이용하여 수행되는 기능 간 관계 이용하여 테스트 데이터 생성</li>
</ul>
<blockquote>
<p><strong>동치 분할 기법 고려할 상황</strong>
입력 조건이 일정 값의 영역을 갖는 경우, 주어진 영역의 값 범위 내에 존재하는 임의의 값과 범위 밖에 존재하는 임의의 값이 선정됨</p>
</blockquote>
<ul>
<li>예) 주어진 입력 변수의 범위: 1~99로 정의되었다면</li>
<li><ul>
<li>데이터 = (50, 120) =&gt; (범위 안, 범위 밖)</li>
</ul>
</li>
<li>특정 타입의 1개 데이터와 다른 타입의 1개 데이터를 테스트 데이터로 선정</li>
<li>동치 클래스 내에서 제약 조건을 갖는 경우</li>
<li><ul>
<li>하위 동치 클래스: 1=100보다 작은 정수형 </li>
</ul>
</li>
<li><ul>
<li>하위 동치 클래스: 2=100과 200사이의 정수형</li>
</ul>
</li>
<li><ul>
<li>하위 동치 클래스: 3=200보다 큰 정수형<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><em>반드시 테스트 데이터 이외에 올바르지 않은 데이터도 고려해야 함*</em></li>
</ul>
<p><strong>경계치 커버리지</strong></p>
<blockquote>
</blockquote>
<ul>
<li>동치 분할에 의해 분리된 동치 클래스의 경계에 해당하는 값을 테스트 데이터로 선정하는 방법<blockquote>
</blockquote>
</li>
<li>입력 변수가 특정 영역[-1.0, +1.0]으로 정의된 경우,</li>
<li><ul>
<li><strong>경계치 커버리지: (-1.1, -1.0, +1.0, +1.1)과 같은 4개의 데이터를 테스트 데이터로 선정</strong></li>
</ul>
</li>
</ul>
<p><strong>특수치 커버리지</strong></p>
<blockquote>
<p><strong>모듈의 인터페이스가 아닌 모듈의 기능을 중심으로 테스트 케이스를 선정 하는 방법</strong>
모듈의 알고리즘에 대한 특징을 반영하거나 내부적으로 특수한 함수를 사용하는 경우, 오류 발생이 빈번하다고 알려진 특정 변수를 사용하는 경우 사용</p>
<p>예) 변수 y값의 갑싱 -1 또는 1의 값을 갖는다고 하더라도 변수 x에 대한 테스트 데이터로 0, 파이/2, 파이, 3파이/2, 2파이와 같은 값이 선정 되어야 함</p>
</blockquote>
<p><strong>원인/결과 커버리지(의사결정 테이블 분석)</strong>
입력 조건에 따라 결과가 다르게 나타날 때 해당 입력 조건을 각각 테스트 데이터로 선정하는 방법</p>
<blockquote>
</blockquote>
<p><strong>의사결정 테이블</strong></p>
<ul>
<li>동치클래스와 이들의 조합 클래스 구조를 테이블 형태로 쉽게 표현한 테스트 데이터 선정 방법</li>
<li>테이블 상단에는 입력 변수 조건을 나열, 하단에는 상단 조건에 의해 수행될 수 있는 동작 기술</li>
<li>의사결정 테이블의 각 칼럼은 하나의 테스트 데이터가 될 수 있음</li>
</ul>
<p><strong>조합 테스팅(Combinatorial Testing)</strong>
다양한 입력 값의 조합을 통해 테스트를 수행하는 방법</p>
<blockquote>
</blockquote>
<ul>
<li><strong>페어와이즈 테스팅</strong></li>
<li><ul>
<li>모든 가능한 입력값 쌍에 대해 테스트를 수행, 가장 일반적인 조합 테스팅 방법 중 하나로 대부분의 결함이 두 개의 변수 간 상호작용에 의해 발생한다는 가정에 기반</li>
</ul>
</li>
<li><ul>
<li>장점</li>
</ul>
</li>
<li>-- 효율성, 결함 발견율 향상, 테스트 자동화</li>
<li><ul>
<li>단점</li>
</ul>
</li>
<li>-- 복잡성, 제한된 적용<blockquote>
<p>페어와이즈 테스팅 자동화 도구: ACTS, PICT, Hexawise 등</p>
</blockquote>
</li>
<li><strong>N-원(n-way) 테스팅</strong></li>
<li><ul>
<li>N개의 변수 간의 모든 가능한 조합을 테스트함</li>
</ul>
</li>
<li><ul>
<li>브라우저-서버-DB 3개의 조합을 동시에 커버</li>
</ul>
</li>
</ul>
<h3 id="테스트-시나리오-생성-방법">테스트 시나리오 생성 방법</h3>
<ul>
<li>객체지향 시스템에 시스템 테스트를 수행하기 위한 테스트 시나리오 생성 방법</li>
<li><ul>
<li>아웃라인 방법: 기능의 연계성을 고려하여 시나리오 구성</li>
</ul>
</li>
<li><ul>
<li>유스케이스 방법: 시스템의 엑터를 중심으로 시나리오 생성</li>
</ul>
</li>
</ul>
<blockquote>
<h4 id="아웃라인-방법에-의한-태스트-케이스-생성">아웃라인 방법에 의한 태스트 케이스 생성</h4>
</blockquote>
<ul>
<li>사용자(고객)가 시스템 사용을 시작하는 입력으로부터 서비스 종료까지 순차적인 과정을 식별해야 함<blockquote>
</blockquote>
</li>
<li><em>테스트 케이스 생성 방법*</em></li>
<li>구현된 시스템에서 각 화면 단위의 사용자 입력에 대하여 테스트 케이스 생성</li>
<li>테스트 결과는 화면 전환이 이루어지도록 구성</li>
<li>요구사항에 제시된 스펙에 따라 테스트 입력에 대한 결과를 예상 결과로 정의</li>
<li>각 화면에서 다음 화면으로 분기 가능한 모든 입력에 대하여 예상 결과 생성</li>
<li>예상 결과대로 구현한 시스템이 동작하는지를 점검하고 Pass 또는 Fail을 실제 결과에 기록</li>
</ul>
<blockquote>
<h4 id="유스케이스-방법에-의한-테스트-케이스-생성">유스케이스 방법에 의한 테스트 케이스 생성</h4>
</blockquote>
<ul>
<li>유스케이스를 이용하여 시스템 수준의 테스트 케이스를 생성하는 이유</li>
<li><ul>
<li>사용자 관점으로 분석 단계의 산출물인 유스케이스 설명서에서 시스템에 포함된 사용 사례를 얻기 위해</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[소프트웨어공학_0520_소프트웨어 테스트]]></title>
            <link>https://velog.io/@jiwon_17/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%EA%B3%B5%ED%95%990520%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%ED%85%8C%EC%8A%A4%ED%8A%B8</link>
            <guid>https://velog.io/@jiwon_17/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%EA%B3%B5%ED%95%990520%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%ED%85%8C%EC%8A%A4%ED%8A%B8</guid>
            <pubDate>Tue, 27 May 2025 06:14:21 GMT</pubDate>
            <description><![CDATA[<h2 id="소프트웨어-테스트">소프트웨어 테스트</h2>
<p>소프트웨어 개발의 인간 중심의 활동이며 지적 활동
오류가 발생하기 쉬운 활동</p>
<blockquote>
<p><strong>결합을 낮추는 방법</strong>
<strong>방지</strong></p>
</blockquote>
<ul>
<li>인스펙션, 정적 분석<blockquote>
</blockquote>
</li>
<li><em>식별과 제거*</em></li>
<li>테스트, 디버깅</li>
</ul>
<p>시험할 소프트웨어에 테스트 케이스를 주어 실행시킨 후 시스템 동작이 예상대로 실행되는지 확인하는 것</p>
<blockquote>
<p><strong>접근법</strong></p>
</blockquote>
<ul>
<li><strong>블랙박스 테스트</strong>
구현을 고려하지않고 테스트</li>
<li><strong>화이트박스 테스트</strong>
구현 방식ㅇ르 분석하여 테스트</li>
</ul>
<h3 id="검증과-확인">검증과 확인</h3>
<p><strong>검증(verification)</strong></p>
<ul>
<li>제품을 올바르게 구축하고 있는지</li>
<li>이전 단계 결과물과 현재 단계 결과물이 동일한지 확인하는 활동</li>
</ul>
<p><strong>확인(validation)</strong></p>
<ul>
<li>올바른 제품을 만들고 있는지</li>
<li>산출물이 사용자의 요구사항을 충족하는지 확인하는 활동</li>
</ul>
<blockquote>
<p><strong>활동 유형</strong></p>
</blockquote>
<ul>
<li><strong>정적 활동</strong>
소프트웨어를 실행하지않고 정적인 상태로 수행: 리뷰, 코드 리딩, 프로그램 증명</li>
<li><strong>동적 활동</strong>
코드를 실행하면서 그 과정을 상펴보는 것: 소프트웨어 테스트</li>
</ul>
<h3 id="소프트웨어-테스트-용어-정의">소프트웨어 테스트 용어 정의</h3>
<h4 id="reliability신뢰도">Reliability(신뢰도)</h4>
<p>관찰되었던 시스템 동작과 명세에 기술된 동작이 일치하는 정도</p>
<h4 id="mistakehuman-error">Mistake/Human Error</h4>
<p>잘못된 결과를 가져오는 인간의 행위를 의미하며 주어진 정보를 잘못 이해할 때 발생</p>
<h4 id="fault결함">Fault(결함)</h4>
<p>에러를 발생하게 하는 프로그램 부분
오류를 일으키는 기계적 또는 알고리즘적 원인</p>
<blockquote>
</blockquote>
<p><strong>commission</strong>
잘못된 정보를 반영하는 경우</p>
<blockquote>
</blockquote>
<p><strong>omission</strong>
올바른 정보를 빠뜨리는 경우</p>
<blockquote>
</blockquote>
<p><strong>알고리즘 결함</strong>
제어 흐름과 관련된 결함이나 대상이 되는 프로그램의 외부와 통신과 관련된 인터페이스 결함 및 잘못된 자료 구조의 사용으로 인한 결함</p>
<h4 id="error에러">Error(에러)</h4>
<p>프로그램의 올바르지 않은 내부 상태 
의도한 동작에서 거리가 멀어지는 상태
계산되거나 측정된 값과 기대 값 사이의 차이</p>
<h4 id="failure오작동">Failure(오작동)</h4>
<p>프로그램이 명세와는 다르게 동작하는 것이 외부에서 관찰되는 상황</p>
<p>오작동은 결함에 의해 발생하지만 결함이 있다고 해서 반드시 오작동이 발생하지는 않음</p>
<p>프로그램의 실행 결과와 기대 결과와의 관찰가능한 차이</p>
<blockquote>
<h3 id="테스트-관련-용어">테스트 관련 용어</h3>
<p><strong>- 테스트 케이스</strong>
고장을 일으키고 결함을 발견할 목적으로 컴포넌트를 검사하기 위한 입력과 예상 결과의 집합</p>
</blockquote>
<p><strong>- 테스트 스터브(test stub)</strong>
테스트될 컴포넌트와 호출하는 컴포넌트가 부분적으로 구현된 것
상위 모듈을 테스트하기 위해 하위 모듈 역할을 대체하는 코드
함수 A가 함수B를 호출하는데 B가 아직 구현되지 않았을 때 B를 대신하는 간단한 테스트용 Stub B를 만들어서 A를 테스트</p>
<blockquote>
</blockquote>
<ul>
<li>호출 받는 쪽(하위 모듈)개발 되지 않았을 때 만들어서 대신 수행하는 것<blockquote>
</blockquote>
</li>
<li><em>- 테스트 드라이버*</em>
테스트될 컴포넌트를 호출하는 컴포넌트의 부분적 구현
하위 모듈을 테스트하기 위해 상위 모듈 역할을 대체하는 코드<blockquote>
</blockquote>
</li>
<li>호출 하는 쪽(상위 모듈)이 만들어지지 않았을 때 대신 테스트 수행을 위해 만드는 것이 드라이버<blockquote>
</blockquote>
</li>
<li><em>- 오류 수정*</em></li>
<li>컴포넌트에 대한 변경</li>
</ul>
<h3 id="오류">오류</h3>
<p>오류가 있음을 보여주려는 작업</p>
<blockquote>
<h3 id="결함-확인을-위한-테스트-데이터-조건">결함 확인을 위한 테스트 데이터 조건</h3>
<p><strong>도달성 조건</strong>
프로그램의 결함이 있는 부분을 실행하여야 함</p>
</blockquote>
<p><strong>감염 조건</strong>
결함 부분을 실행하여 에러를 발생시켜야 함</p>
<blockquote>
</blockquote>
<p><strong>에러 전달 조건</strong>
발생된 에러가 관찰 가능한 지점까지 전달되어야 함</p>
<blockquote>
<h3 id="테스트-원리">테스트 원리</h3>
<p>테스트는 오류를 발견하려고 프로그램을 실행시키는 것
구현과 관계없는 독립된 팀에 의하여 수행되어야 함</p>
</blockquote>
<h3 id="소프트웨어-테스트-한계">소프트웨어 테스트 한계</h3>
<p><strong>완전한 테스트 Exhaustive Test</strong>
완전하게 테스트한다는 의미는 모든 입력 조건 조합에 대하여 테스트</p>
<h3 id="테스트-오라클">테스트 오라클</h3>
<p>프로그램의 실제 실행결과가 올바른 결과인지 판단하는 매커니즘
테스트 오라클은 보통 사람이 담당</p>
<p>테스트의 실행결과가 원하는 결과인지 판단하는 것은 
수작업으로 수행한다는 의미
=&gt; 테스트 오라클은 자동으로 생성 불가능</p>
<h4 id="오라클-생성을-위한-소스">오라클 생성을 위한 소스</h4>
<ul>
<li>테스터의 주관적인 판단</li>
<li>기존 유사 프로그램의 실행 결과 활용</li>
<li>회귀 테스트에서 사용된 테스트 결과 활용
수정에 대한 테스트인 경우</li>
</ul>
<blockquote>
<h3 id="오라클-종류">오라클 종류</h3>
<p><strong>True oracle</strong>
모든 입력들에 대해 원하는 결과들을 생성하여 발생된 오류를 놓치지 않고 검출할 수 있는 오라클</p>
</blockquote>
<p><strong>Sampling oracle</strong>
특정 몇몇 입력 값들에 대해서만 원하는 결과를 제공해주는 오라클</p>
<blockquote>
</blockquote>
<p><strong>Heuristic oracle</strong>
특정 몇몇 입력 값들에 대해서는 샘플링 오라클처럼 올바른 결과를 제공하고 나머지 입력값들에 대해서는 휴리스틱으로 처리하는 오라클</p>
<blockquote>
</blockquote>
<p><strong>Consistent oracle</strong>
수정되기 전의 프로그램의 실행결과와 수정된 후의 프로그램의 실행결과를 비교하는 역할을 담당하는 오라클</p>
<h3 id="테스트-작업-과정">테스트 작업 과정</h3>
<ul>
<li>테스트 방법 결정</li>
<li>테스트 케이스 개발</li>
<li>테스트의 예상되는 올바른 결과 작성</li>
<li>테스트 케이스로 실행시킴</li>
</ul>
<h3 id="단위-테스트">단위 테스트</h3>
<p>모듈이 정확히 동작하는 지 테스트하는 것</p>
<ul>
<li>모듈 내부를 구성하는 프로그램에 존재할 수 있는 결함을 찾아내는 것</li>
</ul>
<h3 id="통합-테스트">통합 테스트</h3>
<p>단위 테스트를 통과한 모듈들이 통합되어 실행될 때 발생할 수 있는 문제를 검사하기 위한 활동</p>
<ul>
<li>모듈 간의 상호작용, 인터페이스의 일관성에 관심</li>
</ul>
<blockquote>
<p><strong>- 비점증적 통합</strong>
모든 모듈을 한 번에 통합하여 테스트를 수행하는 방식
<strong>잠점</strong>
테스트 실행을 한번에 진행할 수 있음
<strong>단점</strong>
결함이 발견된 경우, 결함의 원인이 무엇인지, 어떤 모듈 간의 인터페이스에서 문제가 발생하였는지 식별하지 어려움</p>
</blockquote>
<ul>
<li><strong>점증적 통합</strong>
단위 모듈을 한 번에 하나만 통합하여 테스트를 수행하는 방식
장점
인터페이스 간에 발생하는 오류의 검출이 매우 쉬움
단점
통합되지않은 모듈에 대한 스텁 개발에 대한 노력 필요, 오래 걸림</li>
</ul>
<h4 id="모듈통합-방법">모듈통합 방법</h4>
<ul>
<li><p>상향식 통합
최하위의 단위 함수를 기준으로 상위 호출 모듈을 단계적으로 통합하면서 진행하는 방식</p>
</li>
<li><p>스레드 기반 통합
전체 모듈에서 제어의 중심에 있는 스레드를 기반으로 주변에 있는 모듈을 하나씩 통합하면서 테스트를 수행하는 방식</p>
</li>
<li><p>샌드위치 통합
하향식 통합과 상향식 통합이 동시에 진행되는 방식, 대형 프로그램 테스트에 적합</p>
</li>
<li><p>핵심 모듈 기반 통합
프로그램 전체에서 가장 중요한 모듈을 먼저 살펴보겠다는 의도가 담긴 방법</p>
</li>
</ul>
<blockquote>
<h3 id="시스템-테스트">시스템 테스트</h3>
<p>개발된 시스템을 시스템이 사용될 하드웨어 플랫폼에 설치한 뒤 수행하는 활동, 
전체 시스템을 대상으로 테스트 케이스를 생성하여 테스트 진행</p>
</blockquote>
<blockquote>
<h3 id="인수-테스트수락-테스트">인수 테스트(수락 테스트)</h3>
<p>개발 소프트웨어 시스템을 사용자에게 전달하기 전에 수행하는 활동, 
구축된 시스템에 각 요구사항이 올바르게 구현되었는지 점검하는 데모 형식으로 테스트 진행</p>
</blockquote>
<h3 id="회귀regression-테스트">회귀(regression) 테스트</h3>
<p>개발된 소프트웨어 혹은 운영 중인 소프트웨어에 대해 기능을 추가하거나 결함을 제거한 후 해당 소프트웨어 테스트하는 활동</p>
<p><strong>전수 회귀(Reset All) 테스트</strong>
수정 변경으로 발생 가능성이 있는 모든 경우에 대해 테스트
테스트 비용이 더 들어갈 수 있으나, 테스트 커버리지가 높아짐</p>
<p><strong>우선순위 기반 회귀 테스트</strong>
변경 추가된 부분을 포함하여 소프트웨어를 구성하는 핵심 기능 위주로 우선순위를 정하여 테스트 수행</p>
<p>중요도와 결함 위험 가능성을 기반으로 테스트를 수행하기 때문에 비용 효과적임
낮은 우선순위에 대한 변경 영향을 고려하지 못하는 상황이 발생 가능</p>
<h3 id="테스트-케이스">테스트 케이스</h3>
<p>결함을 발견할 목적으로 준비한 입력 데이터와 예상 결과의 집합</p>
<blockquote>
<p><strong>속성</strong></p>
</blockquote>
<ul>
<li>이름, 테스트 대상, 조건, 입력, 오라클, 로그<blockquote>
</blockquote>
</li>
<li><em>테스트 슈트*</em></li>
<li>테스트 케이스의 모임<blockquote>
</blockquote>
</li>
<li><em>테스트 절차*</em></li>
<li>테스트 케이스를 어떤 순서로 수행시킬 것인지 차례로 적은 것<blockquote>
</blockquote>
</li>
<li><em>테스트 스탭*</em></li>
<li>테스트 케이스를 실행하기 위한 최소 단위</li>
</ul>
<h3 id="오류-수정">오류 수정</h3>
<p>결함을 고치기 위해 컴포넌트 변경</p>
<p><strong>버그 트래킹</strong></p>
<ul>
<li>고장, 오류, 결함, 오류 수정 작업의 기록</li>
<li>형상관리 작업의 일부</li>
</ul>
<p><strong>리그레션 테스트</strong></p>
<ul>
<li>수정 후 영향도 평가 및 사이드 이펙트 테스트</li>
</ul>
<p><strong>문서화</strong></p>
<ul>
<li>변경 이유와 관계를 기록</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[확률및통계_0527_수업 메모]]></title>
            <link>https://velog.io/@jiwon_17/%ED%99%95%EB%A5%A0%EB%B0%8F%ED%86%B5%EA%B3%840527%EC%88%98%EC%97%85-%EB%A9%94%EB%AA%A8</link>
            <guid>https://velog.io/@jiwon_17/%ED%99%95%EB%A5%A0%EB%B0%8F%ED%86%B5%EA%B3%840527%EC%88%98%EC%97%85-%EB%A9%94%EB%AA%A8</guid>
            <pubDate>Tue, 27 May 2025 03:14:25 GMT</pubDate>
            <description><![CDATA[<p>확률및통계</p>
<p>6월 3일에 온라인강의 필수 =&gt; 시험문제
6월 10일 기말고사</p>
<p>Ch7 p67까지 했음
Ch6 P75까지 했음</p>
<p>주관식 Ch8에서 1번 엑셀
주관식 Ch10에서 희귀분석 2번 엑셀</p>
<p>객관식 중요!!
예제8-1의 귀무가설, 대립가설이 뭔지 적으시오.
예제8-3의 귀무가설, 대립가설이 뭔지 적으시오.</p>
<p>평균제곱 
자유도
F = MSt/MSE ~ F(k-1, n-k)</p>
<p>분석 분석 반복있는 이원배치법
표본당 행수는?</p>
<p>상관계수의 식, 모상관계수의 식 </p>
<p>표본상관계수의 성질</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[확률및통계_0520_수업 메모]]></title>
            <link>https://velog.io/@jiwon_17/%ED%99%95%EB%A5%A0%EB%B0%8F%ED%86%B5%EA%B3%840520%EC%88%98%EC%97%85-%EB%A9%94%EB%AA%A8</link>
            <guid>https://velog.io/@jiwon_17/%ED%99%95%EB%A5%A0%EB%B0%8F%ED%86%B5%EA%B3%840520%EC%88%98%EC%97%85-%EB%A9%94%EB%AA%A8</guid>
            <pubDate>Thu, 22 May 2025 07:55:56 GMT</pubDate>
            <description><![CDATA[<p><strong>귀무가설은 =이 있다.</strong></p>
<blockquote>
</blockquote>
<p>객관식 문제</p>
<ul>
<li>1종 오류, 2종 오류 </li>
<li>1종 오류에서 유의수준! 은 0.05%기준으로</li>
<li>2종오류를 생각할 때 병원에서 위험하다</li>
<li>제 1종조류와  제2종오류의 표 외우기<blockquote>
</blockquote>
</li>
<li><em>p값이 0.05보다 작다  기각된다 -&gt; 좋은 것*</em>
CH7 연습문제 2페이지 풀기
CH6 예제6-10 문제 풀기</li>
</ul>
<p>6월 10일 확통 기말고사</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[소프트웨어공학_0513_소프트웨어 아키텍처(2)]]></title>
            <link>https://velog.io/@jiwon_17/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%EA%B3%B5%ED%95%990513%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%982</link>
            <guid>https://velog.io/@jiwon_17/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%EA%B3%B5%ED%95%990513%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%982</guid>
            <pubDate>Sat, 17 May 2025 10:24:05 GMT</pubDate>
            <description><![CDATA[<h3 id="헥사고날-아키텍처">헥사고날 아키텍처</h3>
<p>포트와 어댑터 아키텍처, 
내부의 도메인 비지니스 로직이 외부 요소에 의존하지 않도록 설계된 아키텍처</p>
<p>핵심 비지니스 로직 중심으로 배치하고 
외부 시스템과의 상호작용은 포트와 어댑터를 통해 이루어짐</p>
<blockquote>
<p><strong>포트</strong>
외부 영역과 내부 영역 사이의 연결을 추상화한 인터페이스
도메인 로직과 외부 세계 사이의 명확한 경계를 형성
핵심 도메인 로직을 구현하는 중심 계층으로 비지니스 규칙 담당</p>
</blockquote>
<p><strong>인바운드 포트</strong>: 내부영역 사용을 위해 노출
<strong>아웃바운드 포트</strong>: 외부영역 사용을 위해 노출</p>
<blockquote>
<p><strong>어댑터</strong>
외부 시스템과 상호작용하는 역할</p>
</blockquote>
<p><strong>인바운드</strong>: 입력 어댑터(HTTP 요청을 받는 웹 어댑터)
<strong>아웃바운드</strong>: 출력 어댑터(DB에 접근하여 데이터를 읽고 쓸 수 있는 아웃바운드 영속성 어댑터)</p>
<h4 id="헥사고날-아키텍처의-구조">헥사고날 아키텍처의 구조</h4>
<p>사용자 인터페이스</p>
<ul>
<li>웹, 모바일 앱, CLI 등 다양한 인터페이스를 통해 시스템에 접근</li>
</ul>
<p>입력 어댑터</p>
<ul>
<li>외부 요청을 내부 도메인이 이해할 수 있는 형태로 변환</li>
</ul>
<p>출력 어댑터</p>
<ul>
<li>내부 도메인의 요청을 외부 시스템이 이해할 수 있는 형태로 변환</li>
</ul>
<p>핵심 도메인</p>
<ul>
<li>비지니스 로직이 구현된 시스템의 중심부</li>
</ul>
<p><strong>@transactional 어노테이션</strong>
모든 작업이 하나의 트랜잭션으로 처리되어야 함
과정 중 하나라도 실패하면 모든 변경사항이 롤백</p>
<p><strong>=&gt; 헥사고날 아키텍처의 핵심은 관심사 분리
비지니스 로직과 데이터 집근 로직이 명확히 분리되어 있어 용이성과 유지보수성이 향상</strong></p>
<blockquote>
<h4 id="헥사고날-아키텍처의-입력-포트">헥사고날 아키텍처의 입력 포트</h4>
<p>애플리케이션 핵심 비지니스 로직에 접근하기 위한 진입점 역할을 하는 인터페이스</p>
</blockquote>
<ul>
<li>외부 어댑터(Controller, UI)이 내부 비지니스 로직과 통신하기 위한 계약 정의</li>
<li>특정 기술에 종속되지 않는 순수한 자바 인터페이스로 구현</li>
<li>의존성 역전 원칙(DIP)를 적용하여 외부 시스템이 내부 비지니스 로직이 의존하게 함</li>
</ul>
<blockquote>
<h4 id="헥사고날-아키텍처의-웹-어댑터">헥사고날 아키텍처의 웹 어댑터</h4>
<p>웹에서 들어오는 요청을 내부 시스템이 처리할 수 있는 형태 </p>
<p><strong>특징</strong></p>
</blockquote>
<ul>
<li>스프링 MVC와 같은 기술 관련 코드는 어댑터 안에 숨김</li>
<li>REST API 접속 지점 정의</li>
<li>웹 요청/응답 처리만 담당</li>
<li>업무 처리 로직에 직접 연결되지 않고 인터페이스를 통해 소통<blockquote>
</blockquote>
의존성 역전 원칙을 적용해 핵심 업무 로직이 외부 기술에 의존하지  않도록 설계, 단일 책임 원칙에 따라 웹 요청 처리에 의해 한 가지 일만 담당</li>
</ul>
<blockquote>
<p><strong>헥사고날 아키텍처의 출력 포트</strong></p>
</blockquote>
<p>헥사고날 아키텍처에서 애플리케이션 코어가 외부 시스템과 통신하기 위한 인터페이스를 정의</p>
<blockquote>
</blockquote>
<p>애플리케이션 코어에 정의되며, 
실제 구현에는 JPA, MongoDB 등 다양한 기술을 사용할 수 있음</p>
<blockquote>
</blockquote>
<p>이를 통해 영속성 기술 변경 시 핵심 비즈니스 로직을 수정할 필요가 없어짐</p>
<blockquote>
<p><strong>헥사고날 아키텍처의 출력 어댑터</strong>
Spring Data JPA를 통해 데이터베이스와 상호작용 함</p>
</blockquote>
<p><strong>기술적 세부사항 은닉</strong>
JPA 관련 코드를 캡술화하여 도메인 계층이 데이터베이스 기술에 직접 의존하지 않도록 함</p>
<blockquote>
</blockquote>
<p><strong>도메인/인프라 모델 반환</strong>
데이터베이스 엔터티와 도메인 객체 간 매핑 처리</p>
<blockquote>
</blockquote>
<p><strong>트랜젝션 관리</strong>
데이터베이스 트랜젝션을 처리</p>
<blockquote>
<p><strong>특징</strong></p>
</blockquote>
<ul>
<li>도메인 객체와 JPA엔티티 간 변환을 통해 계층 간 명확한 경계 유지</li>
<li>기본 CRUD 작업(생성, 조회, 삭제)을 구현</li>
<li>데이터베이스 기술이 변경되어도 도메인 로직은 유지, 어댑터 계층만 교체하면 됨</li>
<li>테스트 용이성과 시스템 유연성을 향상 시킴</li>
</ul>
<blockquote>
<h4 id="헥사고날-아키텍처의-장점">헥사고날 아키텍처의 장점</h4>
</blockquote>
<ul>
<li><strong>핵심 비즈니스 로직 독립성</strong></li>
<li><strong>독립적인 테스트 용이성</strong></li>
<li><strong>높은 확장성과 유지보수성</strong></li>
<li><strong>의존성 역전 원칙(DIP)적용</strong>
의존성이 도메인을 향하도록 강제됨 이는 견고하고 유연한 애플리케이션 구조를 만드는데 기여</li>
</ul>
<blockquote>
<h4 id="헥사고날-아키텍처의-단점">헥사고날 아키텍처의 단점</h4>
</blockquote>
<ul>
<li><strong>구조적 복잡성</strong></li>
<li><strong>학습 곡선</strong></li>
<li><strong>표준화 부족</strong>
구현체마다 어댑터나 포트의 구조가 달라서 설계 일관성이 떨어질 수 있음</li>
</ul>
<blockquote>
<p><strong>헥사고날 아키텍처를 이용해서 사용자 인증 시스템</strong></p>
</blockquote>
<p>조건</p>
<ul>
<li>사용자가 이메일과 비밀번호로 로그인</li>
<li>인증 후 토큰 발급</li>
<li>다양한 프론트엔드에서 인증 로직 사용</li>
<li>향후 인증 채널이 추가될 수 있음<blockquote>
</blockquote>
</li>
<li>포트 인터페이스를 상속받아 클래스 구현</li>
<li><ul>
<li>InMemoryUserRepository.java(Map&lt;String, User&gt;을 db로)</li>
</ul>
</li>
<li>-- 이메일, 비밀번호 사용자 추가</li>
<li><ul>
<li>FakePasswordEncoder.java(문자열 접두사 비교)</li>
</ul>
</li>
<li>-- 입력으로 들어오는 비밀번호에 &#39;hashed&#39; 비교</li>
<li><ul>
<li>SimpleTokenGenerator.java(문자열 토큰 생성기)</li>
</ul>
</li>
<li>-- 정상적으로 로그인 완료되었을 때 토큰 반환</li>
<li>-- 토큰은 &#39;TOKEN_FOR_&#39; + 메일주소 형식으로 리턴</li>
<li><ul>
<li>AuthController.java 구현</li>
</ul>
</li>
<li>-- 멤버변수로 AuthService authService 가지고 있음</li>
<li><ul>
<li>구현 후 메인에서 로그인 성공/실패 테스트 수향<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><em>도메인 모델 User.java*</em><pre><code>package org.example;
&gt;
//도메인 모델 User.java
//User는 PasswordEncoder라는 추상화에만 의존
//PasswordEncoder는 어댑터(adapter)가 구현하게 될 포트(port) 역할
//도메인은 외부로부터 독립적
&gt;
public class User {
   //final은 생성 이후 값이 바뀌지 않음
   private final String email;
   private final String passwordHash;
&gt;
   public User(String email, String passwordHash) {
       this.email = email;
       this.passwordHash = passwordHash;
   }
&gt;
   //비밀번호 확인 로직
   //User 클래스가 해시 방법을 직접 몰라도 되도록 외부 인터페이스(encoder)에 위임했다는 점
   public boolean checkPassword(String rawPassword, PasswordEncoder encoder) {
       return encoder.matches(rawPassword, passwordHash);
   }
&gt;
   public String getEmail() {
       return email;
   }
}</code></pre><blockquote>
<p><strong>도메인이 외부에 의존하지 않도록 돕는 추상화 포트</strong>
<strong>포트: UserRepository/PasswordEncoder/TokenGenerator</strong></p>
</blockquote>
</li>
<li><em>UserRepository.java*</em><pre><code>package org.example;
&gt;
public interface UserRepository {
   User findByEmail(String email);
}</code></pre><blockquote>
</blockquote>
</li>
<li><em>PasswordEncoder.java*</em><pre><code>package org.example;
&gt;
public interface PasswordEncoder {
   boolean matches(String rawPassword, String encodedPassword);
}</code></pre><blockquote>
</blockquote>
</li>
<li><em>TokenGenerator.java*</em><pre><code>package org.example;
&gt;
public interface TokenGenerator {
   String generateToken(String subject);
}</code></pre><blockquote>
</blockquote>
</li>
<li><em>서비스 클래스(스켈레톤 코드)*</em><blockquote>
</blockquote>
<pre><code>package org.example;
&gt;
public class AuthService {
   private final UserRepository userRepo;
   private final PasswordEncoder encoder;
   private final TokenGenerator tokenGen;
&gt;
   public AuthService(UserRepository userRepo, PasswordEncoder encoder, TokenGenerator tokenGen) {
       this.userRepo = userRepo;
       this.encoder = encoder;
       this.tokenGen = tokenGen;
   }
&gt;
   public String login(String email, String password) {
       // TODO: 다음 요구사항을 만족하도록 구현하세요.
       // 1. 이메일로 사용자를 조회한다. 존재하지 않으면 예외를 던진다.
       // 2. 비밀번호가 일치하는지 확인한다. 불일치하면 예외를 던진다.
       // 3. 일치할 경우 토큰을 발급하여 반환한다.
&gt;
       User user = userRepo.findByEmail(email);
       if (user == null) {
           throw new RuntimeException(&quot;사용자 없음&quot;);
       }
&gt;
       if (!user.checkPassword(password, encoder)) {
           throw new RuntimeException(&quot;비밀번호 불일치&quot;);
       }
&gt;
       return tokenGen.generateToken(user.getEmail());
   }
}</code></pre><blockquote>
</blockquote>
</li>
<li><em>Main.java*</em><pre><code>package org.example;
&gt;
//TIP 코드를 &lt;b&gt;실행&lt;/b&gt;하려면 &lt;shortcut actionId=&quot;Run&quot;/&gt;을(를) 누르거나
// 에디터 여백에 있는 &lt;icon src=&quot;AllIcons.Actions.Execute&quot;/&gt; 아이콘을 클릭하세요.
public class Main {
   public static void main(String[] args) {
// 학습자가 직접 구현한 어댑터 인스턴스 사용
       UserRepository repo = new InMemoryUserRepository();
       PasswordEncoder encoder = new FakePasswordEncoder();
       TokenGenerator tokenGen = new SimpleTokenGenerator();
&gt;
       AuthService service = new AuthService(repo, encoder, tokenGen);
       AuthController controller = new AuthController(service);
&gt;
       controller.simulateLogin(&quot;test@example.com&quot;, &quot;123&quot;);   // 성공
       controller.simulateLogin(&quot;test@example.com&quot;, &quot;wrong&quot;); // 실패
       controller.simulateLogin(&quot;nobody@example.com&quot;, &quot;123&quot;); // 실패
&gt;
   }
}</code></pre><blockquote>
</blockquote>
</li>
<li><em>InMemoryUserRepository.java*</em><blockquote>
</blockquote>
<pre><code>package org.example;
&gt;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
&gt;
public class InMemoryUserRepository implements UserRepository{
   private final Map&lt;String, User&gt; db = new HashMap&lt;&gt;();
   @Override
   public User findByEmail(String email) {
&gt;
       return db.get(email);
   }
&gt;
   public InMemoryUserRepository() {
       db.put(&quot;test@example.com&quot;, new User(&quot;test@example.com&quot;, &quot;hashed123&quot;));
   }
}</code></pre><blockquote>
</blockquote>
</li>
<li><em>FakePasswordEncoder.java*</em><blockquote>
</blockquote>
<pre><code>package org.example;
&gt;
public class FakePasswordEncoder implements PasswordEncoder{
   @Override
   public boolean matches(String rawPassword, String encodedPassword) {
&gt;
       return encodedPassword.equals(&quot;hashed&quot; + rawPassword);
   }
}</code></pre><blockquote>
</blockquote>
</li>
<li><em>SimpleTokenGenerator.java*</em><blockquote>
</blockquote>
<pre><code>package org.example;
&gt;
public class SimpleTokenGenerator implements TokenGenerator{
   @Override
   public String generateToken(String subject) {
       return &quot;TOKEN_FOR_&quot; + subject;
   }
}</code></pre><blockquote>
</blockquote>
</li>
<li><em>AuthController.java*</em><blockquote>
</blockquote>
<pre><code>package org.example;
&gt;
public class AuthController {
   private final AuthService authService;
   &gt;
   public AuthController(AuthService authService){
       this.authService=authService;
   }
&gt;
   public void simulateLogin(String email, String password){
       try{
           String token = authService.login(email, password);
           System.out.println(&quot;로그인 성공!&quot; + token);
       }catch(RuntimeException e){
           System.out.println(&quot;로그인 실패 &quot;+e.getMessage());
       }
   }
}</code></pre><blockquote>
</blockquote>
</li>
<li><em>Main.java*</em><pre><code>package org.example;
&gt;
//TIP 코드를 &lt;b&gt;실행&lt;/b&gt;하려면 &lt;shortcut actionId=&quot;Run&quot;/&gt;을(를) 누르거나
// 에디터 여백에 있는 &lt;icon src=&quot;AllIcons.Actions.Execute&quot;/&gt; 아이콘을 클릭하세요.
public class Main {
   public static void main(String[] args) {
// 학습자가 직접 구현한 어댑터 인스턴스 사용
       UserRepository repo = new InMemoryUserRepository();
       PasswordEncoder encoder = new FakePasswordEncoder();
       TokenGenerator tokenGen = new SimpleTokenGenerator();
&gt;
       AuthService service = new AuthService(repo, encoder, tokenGen);
       AuthController controller = new AuthController(service);
&gt;
       controller.simulateLogin(&quot;test@example.com&quot;, &quot;123&quot;);   // 성공
       controller.simulateLogin(&quot;test@example.com&quot;, &quot;wrong&quot;); // 실패
       controller.simulateLogin(&quot;nobody@example.com&quot;, &quot;123&quot;); // 실패
&gt;
   }
}</code></pre></li>
</ul>
<h3 id="클라이언트-서버-스타일">클라이언트 서버 스타일</h3>
<p>가장 기본적인 분산 시스템 구조</p>
<p>서비스를 제공하는 서버와 
서비스를 요청하는 하나 이상의 클라이언트로 구성</p>
<blockquote>
<p><strong>Web Layer (Controller)</strong>
사용자의 요청을 받아 처리하는 계층
HTTP 요청을 처리하고 적절한 응답을 반환</p>
</blockquote>
<p><strong>Application Logic (Service Domain)</strong>
비즈니스 로직을 처리하는 계층</p>
<blockquote>
</blockquote>
<p><strong>Data Access Layer (Repository DB 연결)</strong>
데이터베이스와의 상호작용을 담당하는 계층
데이터 저장, 조회, 수정, 삭제 등의 기능을 제공</p>
<blockquote>
<h4 id="클라이언트">클라이언트</h4>
<p>클라이언트는 사용자 인터페이스에서 필요한 정보를 서버에 요청하고, 서버로부터 받은 데이터를 사용자에게 표시할 수 있음</p>
</blockquote>
<blockquote>
<h4 id="서버">서버</h4>
<p>클라이언트의 요청을 받아 처리하고, 적절한 응답을 반환</p>
</blockquote>
<blockquote>
<h4 id="db서버">DB서버</h4>
<p>SQL 쿼리를 통해 계좌 정보를 관리</p>
</blockquote>
<blockquote>
<h4 id="클라이언트-서버-스타일-장점">클라이언트 서버 스타일 장점</h4>
<p><strong>명확한 역할 분리</strong>
시스템 구조가 명확하고 이해하기 쉬워 
자신의 책임에만 집중할 수 있어 개발과 유지보수가 용이</p>
</blockquote>
<p><strong>중앙집중식 데이터 관리</strong>
서버에 데이터를 중앙 집중형으로 관리하여 백업, 보안, 권한 관리가 용이
모든 데이터가 한 곳에서 관리되므로 데이터 일관성과 정확성을 유지하기 쉬움</p>
<blockquote>
</blockquote>
<p><strong>확장성</strong>
클라이언트 수가 증가하더라도 대응이 가능
시스템의 성능과 용량을 필요에 따라 조절할 수 있게 해줌</p>
<blockquote>
</blockquote>
<p><strong>보안 통제 집중화</strong>
인증, 접근 제어 등 보안 정책을 서버에 집중시킬 수 있어 효율적인 보안 관리가 가능
표준화된 통신 프로토콜을 사용함으로써 상호운용성이 보장</p>
<blockquote>
<h4 id="클라이언트-서버-스타일-단점">클라이언트 서버 스타일 단점</h4>
<p><strong>서버 의존성</strong>
서버가 다운되면 전체 시스템이 마비되므로 서버에 대한 의존성이 매우 높음</p>
</blockquote>
<p><strong>성능 병목</strong>
트래픽 급증 시 서버 확장이 안되면 병목 현상이 초래됨
많은 클라이언트가 동시에 요청할 경우 서버의 처리 능력을 초과하여 
응답 시간이 같아지거나 서비스가 중단될 수 있음</p>
<blockquote>
</blockquote>
<p><strong>네트워크 의존성</strong>
클라인언트와 서버가 통신하므로 네트워크 연결에 의존성이 높음</p>
<blockquote>
</blockquote>
<p><strong>인프라 비용</strong>
서버 구축, 운영, 보안, 백업 등 인프라 편리 비용이 필요하고
추가 개발 요구됨, 초기 구축 비용과 유지보수 비용을 증가시킴</p>
<h3 id="브로커-스타일">브로커 스타일</h3>
<p>여러 노드에 투명하게 소프트웨어 시스템을 분산하는 방식
중간에 브로커가 위치하여 클라이언트와 서버 간의 통신을 중계한다는 점</p>
<h4 id="구성요소">구성요소</h4>
<p><strong>클라이언트</strong>: 서비스를 요청하는 주체</p>
<p><strong>서버</strong>: 요청받은 서비스를 제공하는 주체</p>
<p><strong>브로커</strong>: 이 둘 사이에서 클라이언트의 요청을 적절한 서버로 라우팅하고
서버의 응답을 다시 클라이언트에게 전달하는 중개자 역할
서비스 등록, 서비스 발견, 메시지 라우팅, 요청/응답 관리 기능을 제공하여
분산 시스템의 복잡성을 감추고 단순화된 인터페이스를 제공</p>
<p>분산 시스템에서 컴포넌트 간의 통신을 단순화하고 위치 투명성을 제공하여 시스템의 확장성과 유연성을 높이는데 기여</p>
<h4 id="브로커-스타일-장점">브로커 스타일 장점</h4>
<ul>
<li><p>위치 투명성</p>
</li>
<li><ul>
<li>클라이언트는 서비스의 실제 위치(IP나 포트)를 알 필요없이 이름만으로
서비스를 접근할 수 있음, 서비스 제공자의 물리적 위치가 변경되더라도
클라이언트 코드를 수정할 필요가 없게 함</li>
</ul>
</li>
<li><p>낮은 결합도</p>
</li>
<li><ul>
<li>컴포넌트 간의 직접적 참조 없이 브로커를 통해 통신하므로 결합도가 낮아짐
시스템 유연성을 높이고, 한 컴포넌트의 변경이 다른 컴포넌트에 미치는 영향을 최소화 함</li>
</ul>
</li>
<li><p>이기종 시스템 간 통신</p>
</li>
<li><ul>
<li>서로 다른 언어, 플랫폼, 시스템 간의 통신이 가능해짐</li>
</ul>
</li>
<li><ul>
<li>브로커는 다양한 시스템 간의 메시지 변환과 프로토콜 통합을 담당하여
이기종 환경에서의 상호운용성을 제공</li>
</ul>
</li>
<li><p>모듈성 및 재사용성</p>
</li>
<li><ul>
<li>컴포넌트가 독립적으로 설계, 모듈성 및 재사용성이 증가
런타임 중에 컴포넌트를 브로커에 등록하거나 제거할 수 있어 유연한 시스템 확장 가능</li>
</ul>
</li>
</ul>
<h4 id="브로커-스타일-단점">브로커 스타일 단점</h4>
<ul>
<li><p>단일 장애점 위험</p>
</li>
<li><ul>
<li>중앙 브로커에 장애가 발생하면 전체 통신이 중단될 위험이 있음</li>
</ul>
</li>
<li><p>성능 오버헤드</p>
</li>
<li><ul>
<li>모든 요청이 브로커를 가지므로 통신 지연이나 처리 병목 현상이 발생할 수 있음</li>
</ul>
</li>
<li><p>구현 복잡성</p>
</li>
<li><ul>
<li>서비스 등록, 요청 라우팅, 객체 직렬화/역직렬화 등 브로커 내부의 구현이 복잡
브로커를 통해 간접적으로 통신하므로 디버깅과 추적이 어려워질 수 있음</li>
</ul>
</li>
<li><p>높은 의존성</p>
</li>
<li><ul>
<li>시스템 구조가 브로커에 크게 의존하게 되어 브로커 대체나 마이그레이션이 어려울 수 있음, 특정 브로커 기술에 종속되면 기술 변경 시 시스템 전체를 재설계해야 할 수도 있음</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<p><strong>브로커 스타일 이용한 이미지 처리 스타일</strong></p>
<blockquote>
<p><strong>조건</strong></p>
</blockquote>
<ul>
<li>클라이언트는 이미지를 업로드</li>
<li>브로커는 처리 요청을 중개</li>
<li>워커는 이미지를 리사이징, 압축 후 반환</li>
<li>ResizeImage.java(크기 조정)</li>
<li>CompressImage.java(압축)</li>
<li>ServiceBroker.register()</li>
<li>ServiceBroker.dispatch()</li>
<li>Main<blockquote>
</blockquote>
</li>
<li><em>구현 요구사항*</em></li>
<li>ImageService 인터페이스를 구현한 크기조저ㅇ, 압축 클래스</li>
<li>ServiceBroker, Client의 스켈레톤 부분 채우기</li>
<li><ul>
<li>Client.run()에서는 resize, compress 요청 후 결과 출력</li>
</ul>
</li>
<li>Main 클래스에서 서비스를 등록하고 클라이언트를 실행<blockquote>
</blockquote>
</li>
<li><em>공통 인터페이스: ImageService.java*</em><blockquote>
</blockquote>
<pre><code>package org.example;
&gt;
public interface ImageService {
   String process(String image);
}</code></pre><blockquote>
<p><strong>ResizeImage.java</strong></p>
</blockquote>
<pre><code>package org.example;
&gt;
public class ResizeImage implements ImageService{
   @Override
   public String process(String image) {
       return &quot;[Resized]&quot; + image;
   }
}</code></pre><blockquote>
<p><strong>CompressImage.java</strong></p>
</blockquote>
<pre><code>package org.example;
&gt;
public class CompressImage implements ImageService{
   @Override
   public String process(String image) {
       return &quot;[Compressed]&quot;+image;
   }
}</code></pre><blockquote>
<p><strong>브로커 클래스(스켈레톤) ServiceBroker.java</strong></p>
</blockquote>
<pre><code>package org.example;
&gt;
import java.util.HashMap;
import java.util.Map;
&gt;
public class ServiceBroker {
   private final Map&lt;String, ImageService&gt; registry = new HashMap&lt;&gt;();
&gt;
   // 서비스를 등록하는 메서드
   public void register(String command, ImageService service) {
       // TODO: 명령어와 서비스를 registry에 등록하세요
       registry.put(command, service);
   }
&gt;
   // 명령어로 해당 서비스에 요청 위임
   public String dispatch(String command, String imagePath) {
       // TODO: 명령어에 해당하는 서비스를 찾아 실행 결과를 반환하세요
       return registry.get(command).process(imagePath);
&gt;
   }
}</code></pre><blockquote>
<p><strong>클라이언트 클래스 (스켈레톤) Client.java</strong></p>
</blockquote>
<pre><code>package org.example;
&gt;
public class Client {
   private final ServiceBroker broker;
&gt;
   public Client(ServiceBroker broker) {
       this.broker = broker;
   }
&gt;
   public void run() {
       // TODO: 아래 명령어 요청을 broker에 전달하고 결과를 출력하세요.
       System.out.println(broker.dispatch(&quot;resize&quot;, &quot;dog.png&quot;));
       System.out.println(broker.dispatch(&quot;compress&quot;, &quot;cat.png&quot;));
   }
}</code></pre><blockquote>
</blockquote>
</li>
<li><em>Main.java*</em><blockquote>
</blockquote>
<pre><code>package org.example;
&gt;
public class Main {
   public static void main(String[] args) {
       ServiceBroker broker = new ServiceBroker();
       broker.register(&quot;resize&quot;, new ResizeImage());
       broker.register(&quot;compress&quot;, new CompressImage());
&gt;
       Client client = new Client(broker);
       client.run();
   }
}</code></pre></li>
</ul>
<h3 id="트랜잭션-처리-스타일">트랜잭션 처리 스타일</h3>
<p>연달아 들어오는 입력을 하나씩 읽어서 처리하는 방식의 아키텍처
각 입력은 트랜잭션을 명시하며,
이는 시스템에 저장되어 있는 데이터를 조작하는 명령들로 구성</p>
<p>핵심요소는 트랜잭션 사령(dispatcher)컴포넌트
: 트랜잭션을 어디서 처리할 것인지를 결정하고 적절한 컴포넌트에 배치하는 역할</p>
<p><strong>특징</strong>
사령 컴포넌트가 프로시저 호출이나 메시지를 통해 트랜잭션을 처리할 컴포넌트에 전달
데이터의 일관성과 무결성을 유지하면서 복잡한 업무 처리를 가능하게 함</p>
<p>금융시스템, 예약 시스템, 재고 관리 시스템 등 데이터의 정확성과 일관성이 중요한 영역에서 널리 사용됨
@Transactional</p>
<h4 id="트랜잭션-처리-스타일-장점">트랜잭션 처리 스타일 장점</h4>
<ul>
<li><p>데이터 일관성 보장</p>
</li>
<li><ul>
<li>여러 작업이 한 개의 단위로 처리, 중간 상태 없이 일관된 데이터 유지가 가능</li>
</ul>
</li>
<li><ul>
<li>데이터베이스의 ACID(원자성, 일관성, 고립성, 지속성) 보장</li>
</ul>
</li>
<li><p>오류 복구 용이</p>
</li>
<li><ul>
<li>오류가 발생했을 때, 전체 작업을 쉽게 원상복구(롤백)할 수 있음</li>
</ul>
</li>
<li><ul>
<li>견고성을 높이고 데이터 손상 위험을 줄여줌</li>
</ul>
</li>
<li><p>무결성 유지</p>
</li>
<li><ul>
<li>데이터들이 논리적으로 함께 처리되므로 제약조건, 비즈니스 규칙 위반을 방지할 수 있음</li>
</ul>
</li>
<li><ul>
<li>애플리케이션의 비즈니스 로직이 항상 유효한 상태를 유지하도록 보장</li>
</ul>
</li>
<li><p>명확한 경계와 재사용성</p>
</li>
<li><ul>
<li>트랜잭션 경계가 명확하여 코드 재사용과 유지보수가 용이</li>
</ul>
</li>
<li><ul>
<li>또한 동시성 문제 해결 기반을 제공하여 트랜잭션 간 충돌이나 경쟁 조건을 방지할 수 있음</li>
</ul>
</li>
</ul>
<h4 id="트랜잭션-처리-스타일-단점">트랜잭션 처리 스타일 단점</h4>
<ul>
<li><p>성능 저하 가능성</p>
</li>
<li><ul>
<li>트랜잭션 지속 시간 동안 자원을 점유하므로 성능 저하나 병목 유발 가능성이 높이</li>
</ul>
</li>
<li><p>분산 시스템 복잡성</p>
</li>
<li><ul>
<li>여러 시스템에 걸친 트랜잭션은 구현이 복잡하고 신뢰성 유지가 어려움</li>
</ul>
</li>
<li><p>경계 설정의 어려움</p>
</li>
<li><ul>
<li>업무 로직이 복잡한 경우, 어디서 트랜잭션을 시작하고 끝낼지 경계 정의가 어려울 수 있음</li>
</ul>
</li>
<li><p>롱 트랜잭션 위험</p>
</li>
<li><ul>
<li>트랜잭션이 길어지면 락 점유 시간 증가로 교착 상태나 성능 저하가 유발
트랜잭션은 가능한 짧게 유지하는 것이 좋지만, 비즈니스 요구사항과 충돌할 수 있음<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><p><em>트랜잭션 스타일 이용한 은행 계좌 이체*</em></p>
<blockquote>
</blockquote>
</li>
<li><p>AccountRepository.java : JpaRepository&lt;Account, Long&gt;상속</p>
</li>
<li><p>BankTransaction.transfer() : 출금 계좌에서 인출 -&gt; 입금 계좌에 입금 예외 발생 시 전체 롤백</p>
</li>
<li><p>AppRunner.run() : 정상 이체/실패 이체 각각 테스트 코드 작성</p>
<blockquote>
</blockquote>
</li>
<li><p><em>계좌 클래스: Account.java*</em></p>
<blockquote>
</blockquote>
<pre><code>package com.example.banking;
&gt;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
&gt;
@Entity
public class Account {
&gt;
   @Id
   @GeneratedValue
   private Long id;
&gt;
   private String owner;
   private int balance;
&gt;
   protected Account() {} // JPA 기본 생성자
&gt;
   public Account(String owner, int balance) {
       this.owner = owner;
       this.balance = balance;
   }
&gt;
   public void withdraw(int amount) {
       if (balance &lt; amount) {
           throw new IllegalStateException(&quot;잔액 부족&quot;);
       }
       balance -= amount;
   }

   public void deposit(int amount) {
       balance += amount;
   }
&gt;
   public String getOwner() {
       return owner;
   }
&gt;
   public int getBalance() {
       return balance;
   }
&gt;
   public Long getId() {
       return id;
   }
}</code></pre><blockquote>
<p><strong>AccountRepository.java</strong></p>
</blockquote>
<pre><code>package com.example.banking;
&gt;
import org.springframework.data.jpa.repository.JpaRepository;
&gt;
// TODO: JPA Repository로 구현하세요
public interface AccountRepository extends JpaRepository&lt;Account, Long&gt; {
}</code></pre><blockquote>
</blockquote>
</li>
<li><p><em>이체 로직 클래스: BankTransaction.java*</em></p>
<blockquote>
</blockquote>
<pre><code>package com.example.banking;
&gt;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
&gt;
@Service
public class BankTransaction {
&gt;
   private final AccountRepository repository;
&gt;
   public BankTransaction(AccountRepository repository) {
       this.repository = repository;
   }
&gt;
   @Transactional
   public void transfer(Long fromId, Long toId, int amount) {
       // TODO:
       // 1. 출금 계좌와 입금 계좌를 ID로 조회
       // 2. 출금 → 입금 처리
       // 3. 예외 발생 시 전체 트랜잭션이 롤백되도록 구현
       Account from = repository.findById(fromId)
               .orElseThrow(()-&gt;new RuntimeException(&quot;보내는 계좌 없음&quot;));
       Account to = repository.findById(toId)
               .orElseThrow(()-&gt; new RuntimeException(&quot;받는 계좌 없음&quot;));
       from.withdraw(amount);
&gt;
       if(true){
           throw new RuntimeException(&quot;예외 발생으로 롤백되는지 확인&quot;);
       }
       &gt;
       to.deposit(amount);
   }
}</code></pre><blockquote>
</blockquote>
</li>
<li><p><em>AppRunner.java (스켈레톤)*</em></p>
<blockquote>
</blockquote>
<pre><code>package com.example.banking;
&gt;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
&gt;
@Component
public class AppRunner implements CommandLineRunner {
&gt;
   private final AccountRepository repository;
   private final BankTransaction service;
&gt;
   public AppRunner(AccountRepository repository, BankTransaction service) {
       this.repository = repository;
       this.service = service;
   }
&gt;
   @Override
   public void run(String... args) throws Exception{
       Account a = repository.save(new Account(&quot;철수&quot;, 10000));
       Account b = repository.save(new Account(&quot;영희&quot;, 5000));
       try{
           service.transfer(a.getId(), b.getId(), 3000);
           System.out.println(&quot;이체 성공!&quot;);
       }catch(Exception e){
           System.out.println(&quot;이체 실패: &quot;+e.getMessage());
       }
       Account updatedA = repository.findById(a.getId())
               .orElseThrow(()-&gt;new RuntimeException(&quot;A 계좌 없음&quot;));
       Account updatedB = repository.findById(b.getId())
               .orElseThrow(()-&gt; new RuntimeException(&quot;B 계좌 없음&quot;));
       System.out.println(updatedA.getOwner() + &quot; 잔액: &quot;+updatedA.getBalance());
       System.out.println(updatedB.getOwner() + &quot; 잔액: &quot;+updatedB.getBalance());
       // TODO: service.transfer(...) 호출하여 이체 수행 및 예외 테스트
   }
}</code></pre><blockquote>
</blockquote>
</li>
<li><p><em>BankingApplication.java(메인 클래스)*</em></p>
<blockquote>
</blockquote>
<pre><code>package com.example.banking;
&gt;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
&gt;
@SpringBootApplication
public class BankingApplication {
&gt;
   public static void main(String[] args) {
       SpringApplication.run(BankingApplication.class, args);
   }
}</code></pre></li>
</ul>
<h3 id="파이프필터-스타일">파이프필터 스타일</h3>
<p>시스템을 구성하는 각 컴포넌트는 필터라고 부르고 필터 간의 연결관계를 파이프라고 부름
데이터 스트림이 여러 처리 단계(필터)를 순차적으로 통과하며 변환되는 구조</p>
<p><strong>특징</strong>
매우 유연한 구조를 가짐
거의 모든 컴포넌트가 필요에 따라 삭제, 대체, 추가될 수 있으며
일부 컴포넌트는 순서를 재배치할 수 있음</p>
<p>각 필터는 독립적으로 동작하며 특정 작업만을 수행하므로, 
시스템 전체의 복잡성을 줄이고 유지보수성을 향상시킴</p>
<p>단순한 인터페이스를 통해 다양한 필터를 일관된 방식으로 구현하고 조합할 수 있음
각 필터는 이 인터페이스를 구현함으로써 파이프라인에 쉽게 추가되거나 제거될 수 있음
서로 다른 필터들이 동일한 인터페이스를 통해 상호작용할 수 있게 됨</p>
<p>새로운 필터가 필요할 경우, 기존 코드를 수정하지 않고 이 인터페이스를 구현하는
새로운 클래스를 추가하기만 하면 됨</p>
<h4 id="파이프필터-아키텍처의-고려사항">파이프필터 아키텍처의 고려사항</h4>
<ul>
<li><p>필터 독립성
필터들은 서로 상태정보를 공유하지 않아야 함</p>
</li>
<li><p>필터 간 무지성
필터는 자신에 앞서 수행하는 필터나 
자신의 출력 결과를 받는 필터에 대한 정보를 알지 못함</p>
</li>
<li><p>병렬 처리와 동기화
필터는 병렬적으로 수행되며 파이프를 통해 동기화가 이루어짐
시스템의 처리량을 높일 수 있음
동시에 데이터 흐름의 일관성을 유지하기 위한 동기화 매커니즘이 필요함</p>
</li>
</ul>
<h4 id="파이프필터-스타일-장점">파이프필터 스타일 장점</h4>
<ul>
<li>재사용성</li>
<li>병렬 처리
대용량 데이터 처리가 필요한 시스템에서 성능 향상에 기여</li>
<li>확장성
새로운 필터 추가가 용이하여 시스템의 확장성이 뛰어남</li>
</ul>
<h4 id="파이프필터-스타일-단점">파이프필터 스타일 단점</h4>
<ul>
<li><p>상태 관리의 어려움
상태를 저장하지 않는(stateless) 스타일
각 필터는 입력을 받아 출력을 생성할 뿐, 과거 처리 내역이나 컨텍스트 정보를 유지하지 않음</p>
</li>
<li><p>유연성 제한
처리 흐름이 고정되어 있어 동적으로 처리 경로를 변경하기 어려움</p>
</li>
<li><p>복잡한 제어 흐름 부적합
분기, 반복, 조건부 실행과 같은 복잡한 제어 흐름을 표현하기 어려움
단순한 변환 작업의 순차적 적용에 최적화되어 있음</p>
</li>
</ul>
<h3 id="아키텍처-문서화의-중요성">아키텍처 문서화의 중요성</h3>
<ul>
<li>설계품질 향상</li>
<li>이해관계자 간 소통</li>
</ul>
<h3 id="아키텍처-문서-구조">아키텍처 문서 구조</h3>
<ul>
<li>목적</li>
<li>우선순위</li>
<li>설계 개요</li>
<li>주요 설계 이슈</li>
<li>설계 상세 사항</li>
</ul>
<h3 id="아키텍처-평가의-목적과-방법">아키텍처 평가의 목적과 방법</h3>
<p><strong>아키텍처 평가</strong>
소프트웨어 아키텍처나 디자인 패턴이 속성, 강점 및 약점을 체계적으로 분석하는 과정
개발자가 선택한 아키텍처가 기능적 및 비기능적 품질 요구상항을 모두 충족시킬 수 있는지 검증할 수 있음</p>
<p><strong>주요 평가 방법</strong></p>
<blockquote>
<ul>
<li><strong>SAAM</strong>
시나리오 기반 평가 방법
아키텍처가 특정 시나리오를 얼마나 잘 지원하는지 분석
변경 용이성, 유지보수성 등을 평가하는데 효과적</li>
</ul>
</blockquote>
<p>시나리오 도출
시나리오 분류
아키텍처 평가
결과 분석 및 개선</p>
<blockquote>
<ul>
<li><strong>ATAM</strong>
여러 품질 속성에 초점을 맞춰 아키텍처를 평가하고
다양한 속성 간의 트레이드오프를 분석
성능, 보안, 가용성, 수정 용이성 등 여러 품질요소를 종합적으로 고려</li>
</ul>
</blockquote>
<p>위험 포인트 식별
설계 결정이 품질 요구사항을 충족시키지 못할 가능성이 있는 위험 포인트를 식별
여러 품질 속성에 영향을 미치는 민감한 지점과 트레이드오프 포인트를 분석</p>
<h3 id="mvc-스타일-실습">MVC 스타일 실습</h3>
<blockquote>
<p><strong>Book.java</strong></p>
</blockquote>
<pre><code>package org.example;
&gt;
public class Book {
    private final String title;
    private final String author;
&gt;
    public Book(String title, String author) {
        this.title = title;
        this.author = author;
    }
&gt;
    public String getInfo() {
        return &quot;\&quot;&quot; + title + &quot;\&quot; by &quot; + author;
    }
&gt;
    public boolean matches(String keyword) {
        return title.toLowerCase().contains(keyword.toLowerCase());
    }
}</code></pre><blockquote>
</blockquote>
<p><strong>Model.java</strong></p>
<pre><code>package org.example;
&gt;
import java.util.*;
import java.util.stream.Collectors;
&gt;
public class Model {
    private final List&lt;Book&gt; books = new ArrayList&lt;&gt;();
&gt;
    public Model() {
        books.add(new Book(&quot;Effective Java&quot;, &quot;Joshua Bloch&quot;));
        books.add(new Book(&quot;Clean Code&quot;, &quot;Robert C. Martin&quot;));
        books.add(new Book(&quot;Java Concurrency in Practice&quot;, &quot;Brian Goetz&quot;));
    }
&gt;
    public List&lt;Book&gt; search(String keyword) {
        return books.stream()
                .filter(book -&gt; book.matches(keyword))
                .collect(Collectors.toList());
    }
}</code></pre><blockquote>
</blockquote>
<p><strong>View.java</strong></p>
<pre><code>package org.example;
import java.util.List;
import java.util.Scanner;
public class View {
    private final Scanner scanner = new Scanner(System.in);
&gt;
    public String getSearchKeyword(){
        System.out.println(&quot;검색할 키워드 입력&quot;);
        return scanner.nextLine();
    }
&gt;
    public void displayResults(List&lt;Book&gt; books){
        if (books.isEmpty()){
            System.out.println(&quot;해당 도서를 찾을 수 없음&quot;);
        }else{
            System.out.println(&quot;검색 결과&quot;);
            for (Book book : books) System.out.println(&quot; - &quot; + book.getInfo());
        }
    }
}</code></pre><blockquote>
</blockquote>
<p><strong>Controller.java</strong></p>
<pre><code>package org.example;
&gt;
import java.util.List;
&gt;
public class Controller {
    private Model model;
    private View view;
&gt;
    public Controller(Model model, View view){
        this.model=model;
        this.view=view;
    }
&gt;
    public void run(){
        String result = view.getSearchKeyword();
        List&lt;Book&gt; results = model.search(result);
        view.displayResults(results);
    }
}</code></pre><blockquote>
</blockquote>
<p><strong>Main.java</strong></p>
<pre><code>package org.example;
&gt;
public class Main {
    public static void main(String[] args) {
        Model model = new Model();
        View view = new View();
        Controller controller = new Controller(model, view);
        controller.run();
    }
}</code></pre><h3 id="eda-스타일-실습">EDA 스타일 실습</h3>
<blockquote>
<p><strong>이벤트 기반 스타일</strong>
<strong>SensorEvent.java</strong></p>
</blockquote>
<pre><code>package org.example;
&gt;
public class SensorEvent {
    public final double temperature;
&gt;
    public SensorEvent(double temperature){
        this.temperature=temperature;
    }
}</code></pre><blockquote>
</blockquote>
<p><strong>EventBus.java</strong></p>
<pre><code>package org.example;
&gt;
import java.util.ArrayList;
import java.util.List;
&gt;
public class EventBus {
    public interface EventListener{
        void handle(SensorEvent event);
    }
&gt;
    private final List&lt;EventListener&gt; listeners = new ArrayList&lt;&gt;();
&gt;
    public void register(EventListener listener){
        listeners.add(listener);
    }
&gt;
    public void publish(SensorEvent event){
        for (EventListener listener : listeners) listener.handle(event);
    }
}</code></pre><blockquote>
</blockquote>
<p><strong>AlarmListener.java</strong></p>
<pre><code>package org.example;
&gt;
public class AlarmListener implements EventBus.EventListener{
    @Override
    public void handle(SensorEvent event) {
        if (event.temperature&gt;30){
            System.out.println(&quot;온도 초과! &quot;+event.temperature+&quot;도&quot;);
        }
    }
}</code></pre><blockquote>
<p><strong>LoggerListener.java</strong></p>
</blockquote>
<pre><code>package org.example;
&gt;
public class LoggerListener implements EventBus.EventListener{
    @Override
    public void handle(SensorEvent event) {
        System.out.println(&quot;로그 기록: 현재온도 &quot;+event.temperature+&quot;도&quot;);
    }
}</code></pre><p><strong>Main.java</strong></p>
<pre><code>package org.example;
&gt;
public class Main {
    public static void main(String[] args) {
        AlarmListener alarm = new AlarmListener();
        LoggerListener logger = new LoggerListener();
        EventBus bus = new EventBus();
        bus.register(alarm);
        bus.register(logger);
&gt;
        double[] temperatures={25.3, 29.8, 30.1, 32.5, 27.4};
        for (double temp: temperatures) bus.publish(new SensorEvent(temp));
    }
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[확률및통계_0513_수업 메모]]></title>
            <link>https://velog.io/@jiwon_17/%ED%99%95%EB%A5%A0%EB%B0%8F%ED%86%B5%EA%B3%840513%EC%88%98%EC%97%85-%EB%A9%94%EB%AA%A8</link>
            <guid>https://velog.io/@jiwon_17/%ED%99%95%EB%A5%A0%EB%B0%8F%ED%86%B5%EA%B3%840513%EC%88%98%EC%97%85-%EB%A9%94%EB%AA%A8</guid>
            <pubDate>Wed, 14 May 2025 06:27:57 GMT</pubDate>
            <description><![CDATA[<p>대면강의 - 3번남음
프로젝트 미리 해놓기</p>
<blockquote>
<p><strong>기말고사 시험문제</strong>
추정량과 그 성질</p>
</blockquote>
<p>증명 쪽 ppt 시험문제</p>
<blockquote>
</blockquote>
<p>수식 증명식 풀 수 있어야 함</p>
<blockquote>
</blockquote>
<p>위에서 3,4번째줄 설명가능해야 함
=&gt; 그러므로 표분분산 은 모분산의 비편향추정량이다.</p>
<blockquote>
</blockquote>
<p>유효추정량에서 우뚝 선 그래프가 더 좋다.
예제 6-3의 (b)는 시험 제외</p>
<blockquote>
</blockquote>
<p>일치추정량 페이지 밑 시험 제외</p>
<blockquote>
</blockquote>
<p>충분통계량 중 밑에 방정식 알아두기</p>
<blockquote>
</blockquote>
<p>적률법은 시험제외</p>
<blockquote>
</blockquote>
<p>likelihood fuction 중요</p>
<blockquote>
</blockquote>
<p><strong>예제 6-4 시험문제</strong>
표준오차 부분 객관식 나옴</p>
<blockquote>
</blockquote>
<p>추정량의 표준편자는 표준오차라고한다.</p>
<blockquote>
</blockquote>
<p><strong>예제 6-5의 (c)</strong></p>
<blockquote>
</blockquote>
<p><strong>어려운 예제 6-6문제</strong></p>
<blockquote>
</blockquote>
<p>30개 미만으로 뽑을 때 t분포를 사용해야한다</p>
<blockquote>
</blockquote>
<p>p value가 0.05보다 작으면 좋다.</p>
<blockquote>
</blockquote>
<p>Book1 Ch3.zip으로 프로젝트하기</p>
<blockquote>
<p>자신이 찾은 데이터셋 target value 꼭 찾아놓기</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[소프트웨어공학_0506_소프트웨어 아키텍처(1)]]></title>
            <link>https://velog.io/@jiwon_17/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%EA%B3%B5%ED%95%990506%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%981</link>
            <guid>https://velog.io/@jiwon_17/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%EA%B3%B5%ED%95%990506%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%981</guid>
            <pubDate>Tue, 13 May 2025 06:23:56 GMT</pubDate>
            <description><![CDATA[<h2 id="소프트웨어-아키텍처">소프트웨어 아키텍처</h2>
<p>시스템의 전체적인 구조를 정의하는 중요한 개념</p>
<p><strong>좋은 아키텍처 설계</strong>
소프트웨어의 품질, 유지보수성, 확정성을 결정하는 핵심요소</p>
<h3 id="아키텍처">아키텍처</h3>
<p><strong>시스템의 전체적인 구조 정의</strong></p>
<ul>
<li>시스템을 구성하는 주요 부분(컴포넌트)과 그 부분들이 어떻게 상호작용하는지 정의</li>
</ul>
<p><strong>ex)</strong> 웹기반 시스템에서는 
클라이언트와 서버 간의 HTTP연결 및 상호작용 포함</p>
<p><strong>비기능적 품질 요구사항 만족</strong>
좋은 아키텍처는 시스템의 비기능적 품질 요구사항을 만족시키기위해 필수, 품질 보장을 위해 매우 중요</p>
<h3 id="아키텍처-설계">아키텍처 설계</h3>
<p><strong>전반적인 구조 설계</strong>
소프트웨어 시스템에 대한 전반적인 구조를 설계하는 과정
시스템을 구성하는 서브시스템과 묘듈을 정의</p>
<p><strong>덩어리화(Chunking)작업</strong>
서브시스템 수준에서 관련 기능을 그룹화하고 이를 바탕으로 그룹 수준의 설계 진행</p>
<p><strong>추상화와 관계 정의</strong>
다양한 수준에서 구성 요소의 역할과 구성 요소 간의 관계에 집중하여, 클래스 수준 이상의 그루핑과 역할, 인터페이스를 정의</p>
<p>아키텍처 설계는 중요한 과정, 개발 효율성을 높이고 유지보수에 용이</p>
<h4 id="아키텍처-모델-개발-중요성">아키텍처 모델 개발 중요성</h4>
<blockquote>
<p><strong>1. 이해도 향상</strong>
-- 누구나 시스템을 이해할 수 있도록 도움
<strong>2. 독립적 작업</strong>
-- 시스템의 일부를 독립적으로 작업 가능
<strong>3. 확장성 준비</strong>
-- 시스템의 미래 확장을 위한 기반 제공
<strong>4. 재사용성 증대</strong>
-- 컴포넌트 재사용과 재사용 가능성 용이</p>
</blockquote>
<p>소프트웨어 아키텍처는 시스템 구조를 확립하는 개발의 중심축
설계, 구현, 통합, 테스팅까지 영향을 미치는 뼈대이고 
모든 개발 단계에 영향을 줄 수 있는 핵심적인 요소</p>
<h3 id="소프트웨어-아키텍처의-중요성">소프트웨어 아키텍처의 중요성</h3>
<p><strong>1. 소프트웨어도 특정 목적에 맞게 설계해야 함</strong></p>
<p><strong>2. 기능보다는 품질 속성이 더 많은 비중을 차지</strong></p>
<p><strong>같은 기능을 구현한 두 개의 구조가 다른 이유</strong>
달성하고자 하는 품질 속성(보안성, 확장성, 사용성 등)이 다르기 때문</p>
<blockquote>
<h3 id="좋은-아키텍처-모델">좋은 아키텍처 모델</h3>
<p><strong>논리적 분할</strong></p>
</blockquote>
<ul>
<li>시스템을 논리적으로 분할된 서브시스템으로 표현<blockquote>
<p><strong>물리적 배치</strong></p>
</blockquote>
</li>
<li>컴포넌트가 런타임에 존재하는 물리적 위치<blockquote>
<p><strong>인터페이스</strong></p>
</blockquote>
</li>
<li>서브시스템 사이의 인터페이스 정의<blockquote>
<p><strong>동적 상호작용</strong></p>
</blockquote>
</li>
<li>컴포넌트 사이의 동적인 인터렉션 방식<blockquote>
<p><strong>공유 데이터</strong></p>
</blockquote>
</li>
<li>서브시스템 사이에 공유하는 데이터 구조</li>
</ul>
<h3 id="아키텍처의-표현">아키텍처의 표현</h3>
<p><strong>블랙박스 표현</strong></p>
<ul>
<li>컴포넌트를 블랙박스로 명시하고, 외부에 보일 수 있는 구조적 속성만 나타냄</li>
<li>내부 구현 세부사항은 숨기고 인터페이스만 노출</li>
</ul>
<p><strong>계층적 분할식 표현</strong></p>
<ul>
<li>상세히 표현해야 할 부분은 더 작은 단위로 분할하여 표현</li>
</ul>
<p><strong>다양한 뷰 사용</strong></p>
<ul>
<li>같은 시스템이라도 관점에 따라 다르게 표현할 수 있다. </li>
<li>논리적 뷰, 프로세스 뷰, 물리적 뷰</li>
</ul>
<p>효과적인 아키텍처 표현은 복잡한 시스템을 이해하기 쉽게 만들고 커뮤니케이션을 원활하게 함</p>
<blockquote>
<h3 id="아키텍처-모델의-개발">아키텍처 모델의 개발</h3>
<p><strong>아키텍처 정제(Refine)</strong>
컴포넌트 간 상호작용 방식과 인터페이스를 파악하고
자료와 기능이 여러 컴포넌트 사이에 어떻게 분배되는지 결정</p>
</blockquote>
<p><strong>아키텍처 성숙화</strong>
반복적인 검토와 수정을 통해 아키텍처를 점차 성숙시킴</p>
<blockquote>
</blockquote>
<p><strong>아키텍처 모델은 초기 설계 후 완성되는 것이 아니라, 
프로젝트 진행 과정에서 지속적으로 발전하고 성숙해짐</strong></p>
<h3 id="아키텍처-패턴스타일">아키텍처 패턴(스타일)</h3>
<p><strong>독립적 컴포넌트 설계</strong>
컴포넌트를 이용하여 
융통성 있는 시스템을 설계하도록 도움</p>
<p>컴포넌트가 서로 독립적이여서 한 부분의 변경이 다른 부분에 영향을 최소화해야 함</p>
<p><strong>전체적인 조화 정의</strong></p>
<ul>
<li>시스템 분할 방식</li>
<li>전체 제어 흐름</li>
<li>오류 처리 방침</li>
<li>서브시스템 간의 통신 프로토콜
등을 포함한 일반적인 모양과 조화를 정의
구성 요소 유형과 런타임제어, 데이터 전송에 대한 패턴 제공</li>
</ul>
<blockquote>
<h3 id="mvc-스타일">MVC 스타일</h3>
<p><strong>모델(Model)</strong>
사용자에게 보여주고 조작될 수 있는 중요한 클래스의 인스턴스를 포함</p>
</blockquote>
<p>애플리케이션의 핵심 데이터와 가능을 제공
뷰와 컨트롤러에 영향받지 않도록 설계</p>
<blockquote>
</blockquote>
<p><strong>뷰(View)</strong>
모델에 있는 데이터를 사용자 인터페이스에 보여주는 역할 담당
동일한 모델에 대해 다양한 뷰를 쉽게 추가 가능</p>
<blockquote>
</blockquote>
<p><strong>컨트롤러(Controller)</strong>
사용자가 모델과 뷰와 상호작용하는 것을 제어하는 객체를 포함 
사용자가 요청을 처리하고, 모델을 생성, 적절한 뷰 선택</p>
<blockquote>
</blockquote>
<p><strong>MVC패턴은 모델과 뷰 간의 결합관계를 약화시켜 동일한 모델에 대해 다양한 뷰를 쉽게 추가할 수 있게 해줌</strong></p>
<blockquote>
</blockquote>
<p><strong>뷰가 변경되어도 모델에 영향을 주지 않도록 함</strong></p>
<blockquote>
</blockquote>
<p>ex) 옵서버 패턴, 스프링 프레임워크</p>
<blockquote>
</blockquote>
<h4 id="mvc-스타일의-사례">MVC 스타일의 사례</h4>
<p><strong>1. 사용자 요청</strong>
사용자가 컨트롤러에게 요청을 보냄
컨트롤러는 요청을 분석하고 처리</p>
<blockquote>
</blockquote>
<p><strong>2. 모델 처리</strong>
컨트롤러는 모델에 데이터 변경이나 조화를 요청
모델은 비지니스 로직을 수행하고 결과를 반환</p>
<blockquote>
</blockquote>
<p><strong>3. 뷰 업데이트</strong>
모델이 변경되면 뷰에 알림이 가고, 뷰는 모델의 최신 데이터를 반영하여 사용자에게 표시</p>
<blockquote>
<p><strong>MVC패턴은 웹 애플리케이션에서 널리 사용됨</strong></p>
</blockquote>
<p>사용자 인터페이스와 비지니스 로직을 분리하여 유지보수성과 확장성을 높임</p>
<blockquote>
</blockquote>
<p>스프링 MVC, ASP.NET MVC, Ruby on Rails 등 많은 프레임워크에서 이 패턴을 채택</p>
<p><strong>모델 디렉토리</strong>
데이터와 비즈니스 로직을 담당하는 클래스들이 위치</p>
<ul>
<li>사용자 정보와 관련 로직</li>
</ul>
<p><strong>뷰 디렉토리</strong>
사용자 인터페이스 관련 클래스들이 위치 </p>
<ul>
<li>사용자 정보 표시 로직</li>
</ul>
<p><strong>컨트롤러 디렉토리</strong>
모델과 뷰를 연결하는 클래스들이 위치</p>
<ul>
<li>사용자 요청 처리 로직 </li>
</ul>
<p><strong>메인 클래스</strong>
애플리케이션의 시작점이 되는 클래스 </p>
<ul>
<li>애플리케이션 실행 로직</li>
</ul>
<p>=&gt;** 이렇게 명확한 구조는 코드의 역할과 책임을 분리하여 유지보수와 확장을 용이하게 함**</p>
<p>각 디렉토리는 특정 기능에 집중된 클래스들을 포함하여, 개발자는 코드의 구조를 쉽게 이해할 수 있음</p>
<blockquote>
<h3 id="model-userjava">Model: User.java</h3>
<p><strong>데이터 관리</strong>
User클래스는 
사용자의 이름을 저장하고 관리하는 역할 담당
오로지 user에 관련된 것만 포함하는 클래스 </p>
</blockquote>
<p><strong>독립성 유지</strong>
뷰나 컨트롤러에 대한 어떠한 참조도 가지지 않으며, 이를 통해 다른 컴포넌트의 변경에 영향받지 않음</p>
<blockquote>
<h3 id="view-userviewjava">View: UserView.java</h3>
<p><strong>사용자 인터페이스 담당</strong>
UserView클래스는 사용자에게 정보를 표시하는 역할담당</p>
</blockquote>
<p><strong>모델에 의존</strong>
뷰는 모델의 데이터를 표시하기 위해 모델에 의존하지만 어떻게 데이터를 가져오는지는 알 필요가 없음</p>
<blockquote>
</blockquote>
<p>뷰는 사용자와의 상호작용을 담당하는 중요한 컴포넌트</p>
<blockquote>
<h3 id="controller-usercontrollerjava">Controller: UserController.java</h3>
<p><strong>모델과 뷰를 연결</strong>
두 객체에 대한 참조를 유지하며 상호작용을 조정</p>
</blockquote>
<p><strong>모델 업데이트</strong>
setUserName 메서드는 사용자 입력에 따라 모델의 데이터를 업데이트
이 과정에서 데이터 검증이나 변환 작업이 이루어질 수 있음</p>
<blockquote>
</blockquote>
<p><strong>뷰 업데이트</strong>
updateView메서드는 모델의 변경사항을 뷰에 반영하도록 지시, 사용자에게 최신 정보가 표시</p>
<blockquote>
</blockquote>
<p>컨트롤러는 사용자 입력을 처리하고, 모델을 업데이트하며, 적절한 뷰를 선택하여 사용자에게 결과를 보여줌 </p>
<blockquote>
</blockquote>
<p><strong>이를 통해 모델과 뷰의 독립성을 유지할 수 있음</strong></p>
<blockquote>
</blockquote>
<p>“모델과 뷰가 서로 직접 참조하거나 조작하지 않도록, 컨트롤러가 중간에서 그 역할을 대신한다&quot;</p>
<blockquote>
</blockquote>
<p>모델을 직접 변경하거나 조작하면, 뷰와 모델이 너무 밀접하게 연결됨 → 유지보수 어려워짐</p>
<blockquote>
</blockquote>
<p>그래서 모델-뷰 사이에 컨트롤러가 꼭 필요하다.</p>
<blockquote>
<h3 id="main">Main</h3>
<p><strong>객체 생성</strong>
Model, View, Controller객체를 생성하고 초기화
각 컴포넌트가 적절히 연결되도록 함</p>
</blockquote>
<p><strong>컨트롤러 설정</strong>
컨트롤러에 모델과 뷰 객체를 설정하여 세 컴포넌트가 함께 작동할 수 있도록 함</p>
<blockquote>
</blockquote>
<p><strong>사용자 상호작용</strong>
사용자 이름을 설정하고 화면에 표시하는 과정을 시뮬레이션</p>
<blockquote>
<h4 id="mvc-스타일-장점">MVC 스타일 장점</h4>
<p><strong>독립적 설계와 수정 용이성</strong>
각 구성요서(Model, View, Controller)가 독립젹으로 설계되어 수정이 쉬움
하나를 변경해도 다른 부분에 영향을 최소화할 수 있음</p>
</blockquote>
<p><strong>부분 수정 가능</strong></p>
<blockquote>
</blockquote>
<p><strong>기능 확장 용이</strong>
User.java 더 많은 사용자 속성(나이, 이메일)을 추가해도 Controller와 View는 그대로 유지 가능
이것은 시스템 확장성을 크게 향상시킴</p>
<blockquote>
</blockquote>
<p>관심사의 분리를 통해 코드의 유지보수와 확장을 용이하게 한다는 점
각 구성요서가 명확한 역할과 책임을 가지니까 개발자는 특정 부분만 집중해서 개발하거나 수정할 수 있음</p>
<blockquote>
</blockquote>
<p><strong>개별 컴포넌트 단위 테스트</strong>
분리해서 테스트를 하면 개별 컴포넌트 단위 테스트가 가능
버그를 초기에 발견할 수 있음</p>
<blockquote>
</blockquote>
<p><strong>컨트롤러 테스트</strong>
동적인 단위 테스트를 할 수 있음
이를 통해서 비지니스 로직의 정확성을 검증할 수 있음</p>
<blockquote>
</blockquote>
<p><strong>독립적 테스트</strong>
View가 없어도 Model과 Controller만으로 테스트가 가능
View를 여러 방식으로 바꿔도 Model과 Controller는 그대로 사용가능
하나의 모델과 컨트롤러로 다양한 인터페이스를 구현할 수 있어 개발 효율성이 높아짐</p>
<blockquote>
</blockquote>
<p><strong>명확한 역할 분담</strong>
<strong>백엔드 개발</strong>
데이터 처리와 로직 구현에 집중할 수 있게 함
<strong>프론트엔드 개발</strong>
디자인과 사용자 경험 향상에 집중할 수 있게 함</p>
<blockquote>
</blockquote>
<p><strong>UI와 비지니스 로직 분리</strong></p>
<h3 id="계층구조-스타일">계층구조 스타일</h3>
<p><strong>가장 많이 사용되는 아키텍처</strong></p>
<p>시스템을 여러 계층으로 나누어 설계하고 구현
각 계층은 바로 아래에 있는 계층과만 통신</p>
<p>상위 계층은 하위 계층을 서비스로 이용</p>
<ul>
<li>UI를 위한 별도의 층을 갖는 것이 중요</li>
<li>UI 바로 아래층은 사용사례애서 결정된 앱 기능들을 제공하는 것으로 설계</li>
<li>하위층은 공통적인 서비스를 제공</li>
<li>네트워크 커뮤니케이션, 데이터베이스 접근</li>
</ul>
<blockquote>
<h4 id="1-tier-아키텍처">1-tier 아키텍처</h4>
<p>단일 시스템 구조
모든 기능(UI, 비지니스 로직, 데이터 접근)이 하나의 시스템에 통합된 구조</p>
</blockquote>
<p><strong>장점</strong>
적은 비용으로 매우 쉽게 구성할 수 있다, 배포가 단순하고, 성능 측면에서도 유리할 수 있다. </p>
<blockquote>
</blockquote>
<p><strong>구현 단순성</strong>
<strong>낮은 학습 비용</strong>
<strong>빠른 실행 성능</strong>
<strong>소규모 프로젝트 적합성</strong></p>
<blockquote>
</blockquote>
<p><strong>단점</strong>
확장성, 이식성에 적합하지 않다. 
데이터베이스 내용을 여러 사람이 공유할 수 없어서 협업 환경에 적합하지 않다. 
유지보수가 어려워지고, 기능 확장이 제한적, 코드 재사용성이 낮다.</p>
<blockquote>
</blockquote>
<p><strong>유지보수가 어려움</strong>
<strong>낮은 재사용성</strong>
<strong>확장성 한계</strong>
사용자 수가 증가하거나 기능이 복잡헤질 경우 대응하기 어려움
<strong>테스트가 어려움</strong>
기능 테스트를 위해 전체 프로그램을 실행해야하므로 테스트 효율성이 낮음 자동화된 단위 테스트를 작성하기도 어려움</p>
<blockquote>
</blockquote>
<p><strong>실무 활용 사례</strong></p>
<ul>
<li>관리도구</li>
<li>개발도구</li>
<li>스트립트도구</li>
<li>임베디드 시스템</li>
</ul>
<blockquote>
<h4 id="2-tier-아키텍처">2-tier 아키텍처</h4>
<p><strong>클라이언트-서버 모델</strong>
클라이언트와 서버로 구성된 구조</p>
</blockquote>
<p>클라이언트: 사용자 인터페이스와 비지니스 로직을 처리
서버: 데이터베이스 관리를 담당</p>
<blockquote>
</blockquote>
<p><strong>장점</strong></p>
<ul>
<li>데이터베이스를 분리하여 여러 사용자가 공유 가능</li>
<li>데이터베이스 변경이 용이함</li>
<li>1-tier보다 확장성 향상</li>
<li>계층 분리</li>
<li>재사용성 향상</li>
<li>단위 테스트 가능</li>
<li>여러 클라이언트가 동일한 데이터 서비스를 공유할 수 있음<blockquote>
</blockquote>
</li>
<li><em>단점*</em></li>
<li>클라이언트 수가 늘어날수록 데이터베이스 서버에 부하 집중</li>
<li>전체 애플리케이션 성능 저하 가능성</li>
<li>비즈니스 로직 변경 시 모든 클라이언트 업데이트 필요</li>
<li>보안성 취약점 발생 가능성</li>
<li>소규모 네트워크 환경이나 부서별 애플리케이션에 적합하지만 대규모 기업 환경에서는 확장성 문제로 한계가 있음</li>
<li>비지니스 로직과 UI의 결합</li>
<li>확장성 부족</li>
<li>보안 및 권한 관리 어려움</li>
<li>계층간의 의존도가 높아 데이터 계층 구조가 바뀌면 UI계층까지 코드 변경이 필요<blockquote>
</blockquote>
<h4 id="2-tier-아키텍처-코드">2-tier 아키텍처 코드</h4>
<blockquote>
</blockquote>
코드 구조 구분
UserDAO.java 데이터 엑세스 계층(Tier 2)
UserApp.java 프레젠테이션 + 비즈니스 로직(Tier 1)<blockquote>
</blockquote>
</li>
<li><em>UserDAO.java*</em></li>
<li><em>데이터 관리 담당*</em>
사용자 정보를 관리하고 저장하는 역할 담당</li>
<li><em>추가 읽기 기능 제공*</em>
사용자 데이터에 대한 기본적인 생성, 조회 기능을 제공
데이터 관리의 기본 연산</li>
<li><em>구현 추상화*</em>
클라이언트 코드는 데이터가 어떻게 저장되는지 알 필요가 없음
UserDAO가 제공하는 메소드를 통해 데이터에 접근
데이터 저장방식이 변경되어도 클라이언트 코드는 수정할 필요가 없음<blockquote>
</blockquote>
</li>
<li><em>UserApp.java*</em>
프레젠테이션 계층과 비지니스로직 계층을 모두 포함하고 있어서 2-tier 아키텍처의 클라이언트 부분을 구성함
사용자와의 상호작용을 담당하면서 데이터 계층과 통신하는 역할</li>
<li><em>사용자 인터페이스*</em>
사용자와 상호작용하는 인터페이스를 제공</li>
<li><em>비지니스 로직*</em>
사용자 정보를 추가, 조회하는 기능을 구현하고 필요에 따라 데이터 검증도 수행</li>
<li><em>DAO 활용*</em>
UserDAO 객체를 통해 데이터 계층과 상호작용함
사용자 요청에 따라 적절한 DAO메서드를 호출하고 그 결과를 사용자에게 표시</li>
</ul>
<blockquote>
<h4 id="3-tier-아키텍처">3-tier 아키텍처</h4>
<p><strong>클라이언트</strong>
사용자 인터페이스</p>
</blockquote>
<ul>
<li>프레젠테이션 계층<blockquote>
</blockquote>
</li>
<li><em>웹/애플리케이션 서버*</em>
핵심 기능과 규칙 처리</li>
<li>프레젠테이션 계층</li>
<li>비지니스 로직 게층</li>
<li>데이터 접근 계층<blockquote>
</blockquote>
</li>
<li><em>데이터베이스 서버*</em>
데이터 저장 및 검색</li>
<li>데이터베이스<blockquote>
</blockquote>
작업이 복잡하고 비용이 많이 소모되는 단점이 있지만 
보안성, 성능, 확장성이 1-tier와 2-tier아키텍처에 비해 뛰어난 장점을 가지고 있다.
각 계층이 명확히 분리되어 유지보수와 확장성이 용이<blockquote>
<p><strong>물리적 분리 기능</strong>
각 계층은 논리적으로 분리될 뿐만 아니라, 물리적으로도 다른 서버에 배포할 수 있음</p>
</blockquote>
</li>
<li>클라이언트 티어: 웹 브라우저, 모바일 웹</li>
<li>미들 티어: 애플리케이션 서버</li>
<li>데이터 티어: 데이터베이스 서버<blockquote>
<p><strong>기술 스택 분리</strong>
각 계층의 전문가가 자신의 영역에 집중할 수 있게 하고 
특정 계층의 기술 변경이 다른 계층에 영향을 미치지 않도록 함</p>
</blockquote>
</li>
<li><em>장점*</em></li>
<li>관심사 분리</li>
<li>유지보수 및 확장 용이</li>
<li>보안성 향상</li>
<li>테스트 용이<blockquote>
</blockquote>
</li>
<li><em>단점*</em></li>
<li>초기 설계 복잡도</li>
<li>오버헤드 증가
성능 저하 가능성
계층 간 통신 비용이 불필요한 오버헤드가 될 수 있음</li>
<li>소규모 프로젝트에 과도함</li>
<li>계층 간 종속성 가능성 
잘못 설계하면 계층 간 의존성이 복잡해질 수 있음<blockquote>
</blockquote>
각 계층을 독립적으로 배포한다면 인프라 및 버전 관리 복잡성이 증가한다.</li>
</ul>
<h3 id="이벤트-기반-아키텍처">이벤트 기반 아키텍처</h3>
<p><strong>이벤트 중심 통신</strong>
이벤트 생산자가 이벤트를 발생시키고 이벤트 소비자가 이를 수신하는 방식으로 통신</p>
<p><strong>실시간 반응성</strong>
이벤트는 사용자 행동, 데이터 변경, 시스템 상태 변화 등 비지니스 내외부에서 발생하는 주목할만한 사건을 의미
이벤트는 실시간으로 전달되어야 함</p>
<p><strong>상태 기반 처리</strong>
발생된 이벤트의 종류와 시스템 상태에 따라 다른 처리가 이루어짐</p>
<h4 id="이벤트-기반-아키텍처-구성요소">이벤트 기반 아키텍처 구성요소</h4>
<p><strong>이벤트(Event)</strong>
시스템 또는 서비스의 상태 변화를 나타내는 신호나 데이터</p>
<p><strong>이벤트 생산자(Producer)</strong>
이벤트를 감지하거나 생성하여 메시지로 발행하는 역할
사용자 인터페이스, 외부 시스템, 내부 서비스 등</p>
<p><strong>이벤트 브로커(Broker)</strong>
이벤트 중개하고 여러 소비자에게 이벤트를 전달하는 역할
컴포넌트 간 직접적인 의존성 없이 상호작용할 수 있음
시스템의 결합도를 낮추고 유연성을 높임</p>
<p><strong>이벤트 소비자(Consumer)</strong>
이벤트 수신하여 적절한 처리를 수행하는 서비스나 컴포넌트
이메일 발송, 로깅, 알림 등 다양한 후속 작업</p>
<p><strong>이벤트 리스너(Listener)</strong>
이벤트 소비자의 인터페이스, 이벤트를 처리하는 메서드 정의
이벤트 소비자가 구현해야하는 계약을 정의</p>
<p>인터페이스를 통한 느슨한 결합을 구현하여 
이벤트 생산자와 소비자를 분리
새로운 이벤트 소비자를 쉽게 추가할 수 있고 기존 코드 수정없이 기능을 확장할 수 있음
이벤트 기반 아키텍처에서 가장 핵심적인 역할</p>
<p>이벤트 소비자의 표준 계약을 정의함으로써 일관된 이벤트 처리 방식 보장, 시스템의 확장성과 유연성을 높임</p>
<p>인터페이스
=&gt; 모든 것이 구현되지 않은 상태</p>
<h4 id="이벤트-기반-아키텍처-장점">이벤트 기반 아키텍처 장점</h4>
<ul>
<li>느슨한 결합</li>
<li>우수한 확장성
새로운 소비자를 추가해고 기존 생산자 코드를 수정할 필요가 없음</li>
<li>실시간 반응성 향상</li>
<li>높은 모듈화와 재사용성
소비자(리스너)들이 기능별로 분리되어있어 코드 관리와 재사용에 유리</li>
</ul>
<h4 id="이벤트-기반-아키텍처-단점">이벤트 기반 아키텍처 단점</h4>
<ul>
<li>이벤트 흐름 추적 어려움</li>
<li>설계 난이도 증가</li>
<li>테스트 복잡성</li>
<li>암묵적 의존성
비동기 이벤트가 큐에 쌓이면 처리 지연이나 병목현상이 발생할 수 있음
아벤트 실패나 예외 발생 시 어디서 어떻게 처리할 지 명확하지 않을 수 있다.</li>
</ul>
<blockquote>
<h3 id="마이크로-서비스-아키텍처">마이크로 서비스 아키텍처</h3>
<p>애플리케이션을 작고 독립적인 서비스들의 집합으로 나누어 구성하는 소프트웨어 아키텍처 스타일</p>
</blockquote>
<p>대규모 애플리케이션을 개발하고 유지보수하는데 효과적인 접근 방식</p>
<blockquote>
</blockquote>
<p><strong>각 서비스의 독립적인 개발과 배포를 통해 개발 속도와 시스템 안정성을 향상시킬 수 있음</strong></p>
<blockquote>
</blockquote>
<p><strong>독립적 서비스</strong>
각 기능이 별도의 서비스로 구현</p>
<blockquote>
</blockquote>
<p>각 서비스 자체가 자체 데이터베아스를 가지고 독립적으로 개발 및 배포될 수 있게 함</p>
<blockquote>
</blockquote>
<p><strong>작은 단위 서비스</strong>
단일 책임 원칙을 따르며 특정 도메인 기능만 담당</p>
<blockquote>
</blockquote>
<p><strong>독립적 배포</strong>
각 서비스는 별도로 개발 테스트 배포 가능
개발 사이클 빨라짐
특정 기능만 업데이트 가능</p>
<blockquote>
</blockquote>
<p><strong>자체 데이터 보유</strong>
자기만의 데이터베이스 소유</p>
<blockquote>
</blockquote>
<p><strong>네트워크 통신</strong>
REST API, gRPC, 메시지 큐 등을 사용</p>
<blockquote>
</blockquote>
<p><strong>경량화</strong>
Spring Boot, Node.js, Go등으로 빠르게 기동되고 가볍게 동작
리소스 효율성과 빠른 시작 시간을 확보</p>
<blockquote>
</blockquote>
<h4 id="마이크로-서비스-아키텍처-장점">마이크로 서비스 아키텍처 장점</h4>
<ul>
<li>서비스별 독립적 개발 가능</li>
<li>부분적 배포와 업데이트 지원</li>
<li>서비스 단위의 확장성 제공</li>
<li>장애 격리 (한 서비스의 문제가 전체에 영향을 미치지 않음)</li>
<li>기술 스택 다양화 가능</li>
<li>향상된 유지보수성</li>
<li>독립적인 배포</li>
<li>확장성 강화</li>
<li>기술 다양성<blockquote>
</blockquote>
<h4 id="마이크로-서비스-아키텍처-단점">마이크로 서비스 아키텍처 단점</h4>
</li>
<li>운영복잡성</li>
<li>통신 오버헤드</li>
<li>개발 어려움</li>
<li>데이터 일관성 문제</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조_단순연결리스트(3)]]></title>
            <link>https://velog.io/@jiwon_17/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EB%8B%A8%EC%88%9C%EC%97%B0%EA%B2%B0%EB%A6%AC%EC%8A%A4%ED%8A%B83-imhbkls8</link>
            <guid>https://velog.io/@jiwon_17/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EB%8B%A8%EC%88%9C%EC%97%B0%EA%B2%B0%EB%A6%AC%EC%8A%A4%ED%8A%B83-imhbkls8</guid>
            <pubDate>Fri, 02 May 2025 13:29:43 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="연결리스트로-구현한-다항식-덧셈-프로그램">연결리스트로 구현한 다항식 덧셈 프로그램</h3>
</blockquote>
<pre><code>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
&gt;
// 단지 하나의 항(노드)를 나타내는 구조체 ListNode
typedef struct ListNode {
    int coef;
    int expon;
    struct ListNode* link;
} ListNode;
&gt;
// 다항식 전체를 나타내는 구조체 ListType
typedef struct ListType {
    int size; //노드의 개수
    ListNode* head;
    ListNode* tail;
} ListType;
&gt;
ListType* create() {
    ListType *plist = (ListType *)malloc(sizeof(ListType)); //포인터는 주소를 저장하는 메모리 //ListType의 땅
    plist-&gt;size = 0;
    plist-&gt;head = plist-&gt;tail = NULL;
    return plist; //예) 주소값 100 들어감
}
&gt;
void insert_last(ListType *plist, int coef, int expon) {
    //새로운 항을 담을 노드를 동적으로 할당하고 포인터 temp에 저장
    ListNode *temp = (ListNode*)malloc(sizeof(ListNode)); //ListNode의 땅 
    temp-&gt;coef = coef;
    temp-&gt;expon = expon;
    temp-&gt;link = NULL;
&gt;
    if (plist-&gt;tail == NULL) {
        plist-&gt;head = temp; //첫번째 노드 가리킴
        plist-&gt;tail = temp;
    }
    else {
        plist-&gt;tail-&gt;link = temp; //현재 tail 노드 뒤에 새 노드를 연결하고, tail을 새 노드로 갱신
        plist-&gt;tail = temp;
    }
}
&gt;
void poly_add(ListType* plist1, ListType* plist2, ListType* plist3) {
    ListNode* a = plist1-&gt;head;
    ListNode* b = plist2-&gt;head;
&gt;
    while (a != NULL &amp;&amp; b != NULL) {
        int sum;
&gt;
        if (a-&gt;expon == b-&gt;expon) {
            sum = a-&gt;coef + b-&gt;coef;
            insert_last(plist3, sum, a-&gt;expon);
            a = a-&gt;link; b = b-&gt;link; //둘 다 전진
        }
        else if (a-&gt;expon &gt; b-&gt;expon) {
            insert_last(plist3, a-&gt;coef, a-&gt;expon);
            a = a-&gt;link; //a만 전진
        }
        else {
            insert_last(plist3, b-&gt;coef, b-&gt;expon);
            b = b-&gt;link; //b만 전진
        }
    }
    //남은 다항식을 모두 이동
    //연결 리스트는 인덱스가 없기 때문에 link 포인터를 따라가야함
    for(; a!=NULL; a=a-&gt;link) //a=a-&gt;link의 의미: 지금 노드의 다음 노드로 가자.
        insert_last(plist3, a-&gt;coef, a-&gt;expon);
    for (; b != NULL; b = b-&gt;link)
        insert_last(plist3, b-&gt;coef, b-&gt;expon);
}
&gt;
int main() {
    ListType* list1, *list2, *list3;
    list1 = create(); //주소값 100을 list1에 저장
    list2 = create();
    list3 = create();
&gt;
    //insert_last()로 추가하는 각 항은 ListNode
    //이 노드들을 연결한 전체 다항식은 ListType
    insert_last(list1, 3,12); //계수3, 지수12를 넣는다. 
    insert_last(list1, 2, 8);
    insert_last(list1, 1, 0);
&gt;
    insert_last(list2, 8, 12);
    insert_last(list2, -3, 10);
    insert_last(list2, 10, 6);
&gt;
    poly_add(list1, list2, list3);
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조_단순연결리스트(2)]]></title>
            <link>https://velog.io/@jiwon_17/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EB%8B%A8%EC%88%9C%EC%97%B0%EA%B2%B0%EB%A6%AC%EC%8A%A4%ED%8A%B82</link>
            <guid>https://velog.io/@jiwon_17/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EB%8B%A8%EC%88%9C%EC%97%B0%EA%B2%B0%EB%A6%AC%EC%8A%A4%ED%8A%B82</guid>
            <pubDate>Fri, 02 May 2025 07:46:46 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="리스트를-역순으로-만드는-연산">리스트를 역순으로 만드는 연산</h3>
<p><img src="https://velog.velcdn.com/images/jiwon_17/post/47272a0c-83e5-40cf-aef3-45e4886366a1/image.jpg" alt=""></p>
</blockquote>
<pre><code>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
&gt;
typedef int element;
typedef struct ListNode {
    element data;
    struct ListNode* link;
} ListNode;
&gt;
//head: 현재 연결 리스트의 첫 번째 노드를 가리키는 포인터
//value: 로 추가할 노드에 저장할 데이터
ListNode* insert_first(ListNode* head, element value) {
    //ListNode 구조체 크기만큼의 메모리를 동적할당
    //p는 새로 생성된 노드를 가리키는 포인터
    ListNode* p = (ListNode *)malloc(sizeof(ListNode)); //형 변환(ListNode*)을 해줌
    p-&gt;data = value;
    p-&gt;link = head; //기존의 첫 번째 노드가 새 노드의 다음 노드가
    head = p; //head 포인터를 새 노드를 가리키도록 변경, 새 노드가 리스트의 가장 앞에 위치
    return head; //새로 삽입된 노드를 첫 번째로 하는 리스트의 새 head를 반환
}
&gt;
void print_list(ListNode* head) {
    for (ListNode* p = head; p != NULL; p = p-&gt;link) {
        printf(&quot;%d -&gt;&quot;, p-&gt;data);
    }
    printf(&quot;NULL\n&quot;);
}
&gt;
ListNode* reverse(ListNode* head) {
    ListNode* p, * q, * r;
&gt;
    p = head;
    q = NULL;
    while (p != NULL) {
        r = q; //r은 역순으로 만들 리스트, r은 q
        q = p; //p는 q를 차례대로 따라감
        p = p-&gt;link;
        q-&gt;link = r; //q의 링크 방향을 바꿈
    }
    return q; //새롭게 만들어진 역순 리스트의 시작 주소
}
&gt;
int main() {
    ListNode* head1 = NULL;
    ListNode* head2 = NULL;
&gt;
    head1 = insert_first(head1, 10);
    head1 = insert_first(head1, 20);
    head1 = insert_first(head1, 30);
    print_list(head1);
&gt;
    head2 = reverse(head1);
    print_list(head2);
    return 0;
}</code></pre><blockquote>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jiwon_17/post/1b467afa-3d4c-4c2f-8956-6de6df05f606/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조_단순연결리스트(1)]]></title>
            <link>https://velog.io/@jiwon_17/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EB%8B%A8%EC%88%9C%EC%97%B0%EA%B2%B0%EB%A6%AC%EC%8A%A4%ED%8A%B8</link>
            <guid>https://velog.io/@jiwon_17/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EB%8B%A8%EC%88%9C%EC%97%B0%EA%B2%B0%EB%A6%AC%EC%8A%A4%ED%8A%B8</guid>
            <pubDate>Fri, 02 May 2025 06:33:01 GMT</pubDate>
            <description><![CDATA[<blockquote>
</blockquote>
<h3 id="두개의-리스트-하나로-합치기">두개의 리스트 하나로 합치기</h3>
<blockquote>
</blockquote>
<pre><code>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
&gt;
typedef int element;
&gt;
typedef struct ListNode {
    element data;
    struct ListNode* link;
} ListNode;
&gt;
ListNode* insert_first(ListNode* head, element value) {
    ListNode* p = (ListNode *)malloc(sizeof(ListNode));
    p-&gt;data = value;
    p-&gt;link = head;
    head = p;
    return head;
}
&gt;
void print_list(ListNode* head) {
    for (ListNode* p = head; p != NULL; p = p-&gt;link) {
        printf(&quot;%d -&gt; &quot;, p-&gt;data);
    }
    printf(&quot;NULL\n&quot;);
}
&gt;
ListNode* concat_list(ListNode *head1, ListNode *head2) {
    if (head1 == NULL) return head2;
    else if (head2 == NULL) return head1;
    else {
        ListNode* p;
        p = head1;
        while (p-&gt;link != NULL) {
            p = p-&gt;link;
        }
        p-&gt;link = head2;
        return head1;
    }
}
&gt;
int main() {
    ListNode* head1 = NULL;
    ListNode* head2 = NULL;
&gt;
    head1 = insert_first(head1, 10);
    head1 = insert_first(head1, 20);
    head1 = insert_first(head1, 30);
    print_list(head1);
&gt;
    head2 = insert_first(head2, 40);
    head2 = insert_first(head2, 50);
    print_list(head2);
&gt;
    ListNode* total = concat_list(head1, head2);
    print_list(total);
&gt;
    return 0;
}</code></pre><blockquote>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jiwon_17/post/cd1b0ad1-4d89-4512-ace4-7d3432e878c7/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[확률및통계_0429_수업 메모]]></title>
            <link>https://velog.io/@jiwon_17/%ED%99%95%EB%A5%A0%EB%B0%8F%ED%86%B5%EA%B3%840429%EC%88%98%EC%97%85-%EB%A9%94%EB%AA%A8</link>
            <guid>https://velog.io/@jiwon_17/%ED%99%95%EB%A5%A0%EB%B0%8F%ED%86%B5%EA%B3%840429%EC%88%98%EC%97%85-%EB%A9%94%EB%AA%A8</guid>
            <pubDate>Thu, 01 May 2025 03:54:17 GMT</pubDate>
            <description><![CDATA[<ul>
<li>프로젝트 오렌지 설치, 파이썬</li>
<li>코랩에서 데이터 불러오기</li>
<li>kaggle 에서 데이터셋 가져오기</li>
<li>9주차 강의동영상 다시 듣기</li>
<li>프로젝트 ppt 30장 이내 (발표) 3분</li>
<li>df.shape</li>
<li>kaggle에서 id값이 없으면 다른 것들로 확인이 가능한지 설명해야함
구분할 수 있는 id값이 있는 데이터셋을 찾는게 좋다</li>
</ul>
<blockquote>
<p><strong>두번째 데이터셋 불러오기 p171</strong>
df1 = pd.read_csv(&quot;/content/drive/MyDrive/Colab Notebooks/Book1 Lecture/Ch4/individual-2017.csv&quot;)
df1.shape</p>
</blockquote>
<p>데이터셋이 정규분포로 이루어지는 지 확인하는 프로그램</p>
<ul>
<li>freeplane 다운로드</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[소프트웨어공학_0425_이론_모듈화, 결합력, 응집력, SOLID원칙]]></title>
            <link>https://velog.io/@jiwon_17/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%EA%B3%B5%ED%95%990425%EC%9D%B4%EB%A1%A0SOLID%EC%9B%90%EC%B9%99</link>
            <guid>https://velog.io/@jiwon_17/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%EA%B3%B5%ED%95%990425%EC%9D%B4%EB%A1%A0SOLID%EC%9B%90%EC%B9%99</guid>
            <pubDate>Tue, 29 Apr 2025 07:33:13 GMT</pubDate>
            <description><![CDATA[<h2 id="묘듈화의-의미-중요성">묘듈화의 의미, 중요성</h2>
<blockquote>
</blockquote>
<p><strong>모듈화</strong>
독립적인 기능이 있는 논리적 묶음(조각)에 해당하는 모듈로 소프트웨어 시스템을 구성하는 접근 방식</p>
<blockquote>
</blockquote>
<p><strong>모듈화의 중요성</strong>
<strong>1. 변경사항 반영의 편의성</strong></p>
<blockquote>
</blockquote>
<p><strong>2. 재사용 가능성 향상</strong>
소프트웨어 모듈에는 독립적인 기능이 있기 때문에 추후 다른 소프트웨어 개발에서 쉽게 재사용될 수 있음</p>
<blockquote>
</blockquote>
<p><strong>3. 추적성 증진</strong>
기능 개선이나 변경을 반영하기 위한 작업을 수행할 때, 
모듈화 구조는 요구사항 분석부터 설계 및 구현까지 일관성 있고 체계적인 모듈 간의 연결 구조를 제공할 수 있음 </p>
<h2 id="효과적인-모듈화-구조">효과적인 모듈화 구조</h2>
<p><strong>내적 요소의 관련성</strong>
내적요소(변수, 함수, 연산 등) 상호 관련성이 있는 것들로 묶여 있어야 함</p>
<p><strong>간결한 상호작용</strong>
모듈 간의 상호작용이 가능한 한 간단한 형태로 구성되어야 함
복잡한 상호작용은 유지보수를 어렵게 만듦, 오류 발생 가능성을 높임</p>
<h2 id="결합력">결합력</h2>
<blockquote>
<p>*<em>모듈 간의 의존적 관계를 나타내는 척도 *</em></p>
</blockquote>
<p>*<em>결합력이 작을수록 좋은 설계 *</em></p>
<blockquote>
</blockquote>
<p><strong>독립적 기능</strong>: 불필요한 중복을 제거하는 것이 중요
<strong>상호작용 최소화</strong>: 가능한 모듈 간 상호작용을 줄여 의존성을 낮추는 것이 좋음</p>
<p><strong>결합력 최소화의 이점</strong></p>
<ol>
<li>시스템 구성 요소 간 결합이 느슨해짐</li>
<li>변경에 의한 파동효과를 막을 수 있음</li>
<li>소프트웨어에 대한 이해도를 높임</li>
<li>모듈의 인터페이스가 단순해짐</li>
</ol>
<h3 id="결합력의-유형과-스케일">결합력의 유형과 스케일</h3>
<ol>
<li>메시지 결합력 (가장 좋은 결합도)</li>
<li>데이터 결합력</li>
<li>스탬프 결합력</li>
<li>제어 결합력</li>
<li>외부 결합력</li>
<li>공유 결합력</li>
<li>내용 결합력 (가장 나쁜 결합도)</li>
</ol>
<blockquote>
<h4 id="1-메시지-결합력">1. 메시지 결합력</h4>
<p>결합의 정도가 가장 느슨한 유형, 객체지향 프로그래밍에서 나타남</p>
</blockquote>
<ul>
<li>객체 내 변수들은 Public 및 Private을 통해 캡슐화</li>
<li>서로 다른 상태를 갖는 객체가 서로 다른 모듈로 간주될 수 있음</li>
<li>객체 간 상호작용은 메시지 전달이라는 한 가지 개념으로 이루어짐</li>
</ul>
<blockquote>
<h4 id="2-데이터-결합력">2. 데이터 결합력</h4>
<p>2개의 모듈이 정수형, 문자형 등의 단순한 기본 데이터타입(원자 형태 데이터)를 갖는 변수들을 통해 상호작용하는 경우</p>
</blockquote>
<blockquote>
<h4 id="3-스탬프-결합력">3. 스탬프 결합력</h4>
<p><strong>복합 데이터 상호작용</strong>
<strong>두 모듈이 구조체와 같은 복합 데이터를 이용하여 상호작용</strong>
구조체 정의 시 의미상 상호 관련성 있는 데이터들을 묶음으로 정의</p>
</blockquote>
<p>불필요한 데이터까지 모두 전달하면 
실행 시간이나 메모리 사용 측면에서 손실이 발생함</p>
<blockquote>
<p>관련성이 적은 의미 없는 데이터를 묶지 않도록 주의해야함</p>
</blockquote>
<blockquote>
<h4 id="4-제어-결합력">4. 제어 결합력</h4>
<p><strong>한 모듈에서 다른 모듈로 매개변수를 전달할 때,</strong> 
그 매개변수가 호출되는 함수의 내부 행위를 제어하는 역할을 한다면 이 두 모듈은 제어 결합력 관계에 있음</p>
<p>플래그 변수</p>
</blockquote>
<blockquote>
<h4 id="5-외부-결합력">5. 외부 결합력</h4>
<p><strong>2개의 모듈이 외부에 존재하는 다른 정보를 공유하고 있을 때 발생</strong>,
파일, 디바이스, 인터페이스, 프로토콜 등이 해당</p>
<p>다른 모듈의 변수 변경이나 동시 접근으로 인한 데드락 등의 문제가 발생할 수 있어 주의가 필요함</p>
</blockquote>
<blockquote>
<h4 id="6-공유-결합력">6. 공유 결합력</h4>
<p><strong>2개의 모듈이 전역변수를 공유하고 있을 때 발생하는 결합 관계</strong></p>
</blockquote>
<p><strong>장점</strong>: 공유변수 사용은 메모리 사용량을 줄이고, 프로그램을 간단하게 작성할 수 있다
<strong>단점</strong>: 모듈 간의 의존성을 높이는 문제가 생김</p>
<blockquote>
</blockquote>
<p>꼭 필요한 변수만 광역 변수(전역 변수)로 선언해야 함</p>
<blockquote>
<h4 id="7-내용-결합력">7. 내용 결합력</h4>
</blockquote>
<p>한 모듈이 다른 모듈의 내부 구현에 직접 의존하는 가장 강한 형태의 결합력 (안좋음)</p>
<blockquote>
</blockquote>
<p><strong>직접 참조:</strong> 한 모듈에서 다른 모듈의 내부를 직접 참조할 때 내용 결합 관계가 발생</p>
<blockquote>
<p><strong>GOTO 명령어</strong>
절차적 언어에서 &#39;goto&#39;명령어가 내용 결합을 유발</p>
</blockquote>
<p><strong>최악의 결합</strong>
결합력 중 가장 강한 형태, 절대 피해야 함</p>
<blockquote>
</blockquote>
<p><strong>현대 프로그래밍</strong>
현대 프로그래밍 언어와 패러다임에서는 내용 결합력이 거의 발생하지 않음</p>
<h2 id="응집력">응집력</h2>
<p><strong>모듈을 구성하는 내적 요소 간의 기능적 관련성의 강도를 측정하는 척도</strong></p>
<blockquote>
</blockquote>
<p>높은 응집력이 좋음</p>
<blockquote>
</blockquote>
<p>응집력이 높은 모듈은 결합력이 낮은 경향이 있음</p>
<h3 id="응집력의-유형과-스케일">응집력의 유형과 스케일</h3>
<ol>
<li>기능 응집력 (가장 좋은 응집도)</li>
<li>순차 응집력</li>
<li>교환 응집력</li>
<li>절차 응집력</li>
<li>시간 응집력</li>
<li>논리 응집력</li>
<li>유연 응집력 (가장 나쁜 응집도)</li>
</ol>
<blockquote>
<h4 id="1-기능-응집력">1. 기능 응집력</h4>
</blockquote>
<p>모듈을 구성하는 모든 요소가 단지 하나의 기능을 구현, 모듈이 명확한 단일 책임을 가짐</p>
<blockquote>
<h4 id="2-순차-응집력">2. 순차 응집력</h4>
<p>모듈을 구성하는 문장 관계에서, 한 문장의 실행 결과가 다음 문장의 입력으로 사용되는 경우</p>
</blockquote>
<p>순차 응집력이 서로 입출력 관계에 있는 문장으로 구성되었다고 하더라도, 마지막 문장이 기능 응집력을 충족하지 못한다면 응집력의 효과는 저하됨</p>
<blockquote>
<h4 id="3-교환-응집력">3. 교환 응집력</h4>
<p>모듈을 구성하는 모든 요소가 동일한 입력 또는 출력을 사용한다면 존재하는 응집력</p>
</blockquote>
<p>같은 데이터에 대해 서로 다른 작업을 수행하는 기능들이 하나의 모듈에 포함됨</p>
<blockquote>
<p>각 정보를 개별적으로 처리하는 함수로 분리하는 것이 좋음</p>
</blockquote>
<blockquote>
<h4 id="4-절차-응집력">4. 절차 응집력</h4>
</blockquote>
<p>모듈을 구성하는 문장들이 의미상 서로 관련이 없지만 제어 흐름의 순서가 있는 경우</p>
<blockquote>
<h4 id="5-시간-응집력">5. 시간 응집력</h4>
</blockquote>
<p>모듈을 구성하는 각 문장이 소프트웨어 실행의 특정 시간과 관련이 있는 것으로만 구성된 경우</p>
<blockquote>
<h4 id="6-논리-응집력">6. 논리 응집력</h4>
</blockquote>
<p>모듈을 구성하는 모든 요소가 논리적으로 같은 유형의 외부 동작들로 구성되는 경우</p>
<blockquote>
</blockquote>
<p>모든 입력 처리를 하나의 모듈에, 모든 출력 처리를 다른 하나의 모듈에 넣는 방식</p>
<blockquote>
<h4 id="7-우연-응집력">7. 우연 응집력</h4>
</blockquote>
<p>가장 나쁜 응집력, 무작위적 구성</p>
<h2 id="사이클로매틱-복잡도">사이클로매틱 복잡도</h2>
<p>소프트웨어 복잡도 측정 지표, 순환 복잡도</p>
<p><strong>사이클로매틱 복잡도 계산 방법</strong></p>
<ul>
<li><p>간선 노드 방식
V(G) = E - N + 2</p>
</li>
<li><p>분기점 기반 방식 
V(G) = P + 1</p>
</li>
</ul>
<p>분기점은 if, for, while, case 등 프로그램의 흐름을 여러 방향으로 나누는 지점을 의미</p>
<p>사이클로매틱 복잡도가 높을수록 코드의 복잡성이 증가하고, 테스트와 유지보수가 어려워짐</p>
<h3 id="복잡도-수준과-품질-기준">복잡도 수준과 품질 기준</h3>
<p>1<del>10 : 관리하기 쉬움
11</del>20 : 리펙토링 권장
21~50 : 결함 가능성 높음
50 ~ : 테스트 거의 불가능</p>
<p><strong>사이클로매틱 복잡도의 실무적 활용</strong></p>
<ul>
<li><p><strong>테스트 케이스 수 결정</strong>
복잡도가 N이면, 코드의 모든 실행 경로를 커버하기 위해 최소 N개의 테스트 케이스가 필요</p>
</li>
<li><p><strong>모듈 분리 기준</strong>
복잡도 11이상일 경우 모듈을 더 작은 단위로 분해하는 것이 권고</p>
</li>
<li><p><strong>코드 품질 관리</strong>
정적 분석 도구를 통해 복잡도를 지속적으로 측정하고 모니터링함으로써 코드 품질을 관리할 수 있음</p>
</li>
</ul>
<blockquote>
<h3 id="사이클로매틱-복잡도의-장단점">사이클로매틱 복잡도의 장단점</h3>
<p><strong>장점</strong></p>
</blockquote>
<ul>
<li>수치화된 복잡도 평가가 가능, 객관적인 코드 품질 측정 지표로 활용</li>
<li>설계 단계에서부터 적용이 용이하여 초기단계에서 복잡도 관리 가능</li>
<li>테스트 케이스 수 결정에 명확한 기준 제공</li>
<li>자동화된 도구를 통해 쉽게 측정 가능</li>
<li>코드 리펙토링의 필요성을 판단하는 객관적 근거 제공<blockquote>
</blockquote>
</li>
<li><em>단점*</em></li>
<li>데이터 복잡성의 반영이 부족하며, 주로 제어 흐름에만 초점</li>
<li>Switch-case문에서 복잡도 값이 급증하는 문제 발생</li>
<li>모든 조건문을 동일한 가중치로 처리하여 실제 복잡성 차이 반영 못함</li>
<li>코드의 기능적 복잡성이나 알고리즘 복잡성 측정에 한계</li>
<li>상속, 다형성 등의 복잡성 측정에 제한적 </li>
</ul>
<blockquote>
<p><strong>사이클로매틱 복잡도 권장사항</strong>
마이크로소프트 기준</p>
</blockquote>
<ul>
<li>사이클로매틱 복잡도를 25이하로 유지할 것을 권장<blockquote>
</blockquote>
사이클로매틱 복잡도는 10이하가 안정적</li>
</ul>
<h2 id="solid-원칙">SOLID 원칙</h2>
<blockquote>
<p><strong>S</strong>
<strong>단일 책임 원칙 (SRP)</strong>
단 하나의 책임만 가져야 함</p>
</blockquote>
<blockquote>
<p><strong>O</strong>
<strong>개방 폐쇄 원칙 (OCP)</strong>
기존 코드를 변경하지 않으면서 기능을 추가할 수 있어야 함</p>
</blockquote>
<blockquote>
<p><strong>L</strong>
<strong>리스코프 대입 원칙 (LSP)</strong>
자식 클래스는 부모 클래스의 기능을 대체할 수 있어야 함</p>
</blockquote>
<p>선조건 관계 : 하위타입은 더 까다로운 선조건을 추가하면 안됨
오히려 선조건을 완화해야 함</p>
<blockquote>
</blockquote>
<p>후조건 관계 : 하위 타입은 더 강력한 결과를 보장할 수 있어야 함</p>
<blockquote>
<p><strong>I</strong>
<strong>인터페이스 분리 원칙 (ISP)</strong>
클라이언트는 자신이 사용하지 않는 인터페이스에 의존하지 않아야 함</p>
</blockquote>
<ul>
<li>인터페이스를 클라이언트에 특화되도록 분리시키는게 목적</li>
<li>클라이언트는 자신이 이용하지 않는 기능에 영향을 받지 않아야 함</li>
</ul>
<blockquote>
<p><strong>ISP위반의 문제점</strong></p>
</blockquote>
<ul>
<li>불필요한 구현</li>
<li>테스트 어려움</li>
<li>의존성 문제</li>
<li>변경의 영향</li>
</ul>
<blockquote>
<p><strong>D</strong>
<strong>의존성 역전 원칙 (DIP)</strong>
상위 모듈은 하위 모듈에서 의존해서는 안되며 둘 다 추상화에 의존해야 함</p>
</blockquote>
<p>구체적인 클래스보다 인터페이스나 추상 클래스에 의존관계를 
맺어야 함
추상적인 클래스가 중요함</p>
<blockquote>
<p><strong>DIP의 장점</strong></p>
</blockquote>
<ul>
<li>결합도 감소
클래스간의 결합도가 낮아져 변경에 유연해짐<blockquote>
</blockquote>
</li>
<li>재사용성 증가
컴포넌트를 쉽게 교체할 수 있음<blockquote>
</blockquote>
</li>
<li>변경 보호 
한 부분의 변경이 다른 부분에 영향을 미치지 않음<blockquote>
</blockquote>
</li>
<li>테스트 용이성
목(Mock)객체를 이용한 테스트가 쉬워짐</li>
</ul>
<blockquote>
<h3 id="디자인-패턴">디자인 패턴</h3>
<p><strong>재사용 가능한 해결책</strong>
특정 맥락에서 자주 발생하는 문제들에 대한 검증된 해결책</p>
</blockquote>
<p><strong>공통 언어</strong>
개발자들 간의 효율적인 의사소통을 가능하게 함</p>
<blockquote>
</blockquote>
<p><strong>경험 공유</strong>
경험 많은 엔지니어들의 지식을 쉽게 습득할 수 있음</p>
<blockquote>
<h4 id="gof-디자인패턴">GoF 디자인패턴</h4>
</blockquote>
<ul>
<li>생성 패턴
객체 생성 매커니즘을 다루는 패턴들<blockquote>
</blockquote>
</li>
<li>구조 패턴 
클래스와 객체를 더 큰 구조로 조합하는 패턴들<blockquote>
</blockquote>
</li>
<li>행위 패턴
객체 간의 커뮤니케이션을 다루는 패턴들</li>
</ul>
<p><strong>위의 내용 요약</strong></p>
<ul>
<li>모듈화와 결합력</li>
<li>응집력과 복잡도</li>
<li>SOLID 원칙</li>
<li>디자인 패턴</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[소프트웨어공학_0415_이론_UML다이어그램]]></title>
            <link>https://velog.io/@jiwon_17/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%EA%B3%B5%ED%95%990415%EC%9D%B4%EB%A1%A0UML%EB%8B%A4%EC%9D%B4%EC%96%B4%EA%B7%B8%EB%9E%A8</link>
            <guid>https://velog.io/@jiwon_17/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%EA%B3%B5%ED%95%990415%EC%9D%B4%EB%A1%A0UML%EB%8B%A4%EC%9D%B4%EC%96%B4%EA%B7%B8%EB%9E%A8</guid>
            <pubDate>Tue, 15 Apr 2025 07:17:56 GMT</pubDate>
            <description><![CDATA[<h2 id="uml-다이어그램">UML 다이어그램</h2>
<h3 id="클래스-다이어그램">클래스 다이어그램</h3>
<p><strong>요구사항 분석 -&gt; 설계 -&gt; 구현</strong> -&gt; 테스트 -&gt; 유지보수</p>
<blockquote>
<p><strong>클래스 다이어그램 그리기</strong></p>
</blockquote>
<ol>
<li>시나리오에서 자주 등장하고 중요한 명사를 중심으로 엔티티 추출</li>
<li>속성, 메서드 추가</li>
<li>구조 구성 - 클래스 간 관계 추출
 예) user -&gt; Reservation: 1:N</li>
</ol>
<h4 id="클래스-다이어그램-요약">클래스 다이어그램 요약</h4>
<ol>
<li>시나리오 읽기: 명사(객체)와 동사(기능) 중심으로 분석</li>
<li>클래스 후보 뽑기: 객체를 클래스로 전환</li>
<li>속성, 메서드 정의: 명사-&gt;속성, 동사-&gt;메서드</li>
<li>클래스 간 관계 정리: 연관, 집합, 상속</li>
<li>클래스 다이어그램 그리기</li>
</ol>
<h3 id="순차-다이어그램">순차 다이어그램</h3>
<p>요구사항 분석 -&gt; <strong>설계 -&gt; 구현</strong> -&gt; 테스트 -&gt; 유지보수</p>
<p>클래스 다이어그램을 그린 다음 순차 다이어그램을 그린다.</p>
<blockquote>
<p><strong>순차 다이어그램 그리기</strong></p>
</blockquote>
<ol>
<li>객체 그리기</li>
<li>메시지 추가</li>
</ol>
<h3 id="패키지-다이어그램">패키지 다이어그램</h3>
<p>요구사항 분석 <strong>-&gt; 설계</strong> -&gt; 구현 -&gt; 테스트 -&gt; 유지보수</p>
<blockquote>
<p><strong>패키지 다이어그램 그리기</strong></p>
</blockquote>
<ol>
<li>계층별 패키지 추출</li>
</ol>
<p><strong>HCI Layer</strong> : 사용자가 시스템과 상호작용하는 화면(UI) 담당
<strong>Application Layer</strong> : 핵심 비지니스 로직 처리
<strong>Database Layer</strong> : 데이터 저장 및 조회 처리(DB와 직접 연결)</p>
<blockquote>
</blockquote>
<ol start="2">
<li>패키지 의존 관계 확인(점선으로 표시)
 예) 사용자가 주문을 진행하는 과정에서는 결제 기능이 함계 수행되어야 함
 Ordering -&gt; Accounting<blockquote>
</blockquote>
</li>
</ol>
<p><strong>HCI Layer</strong> : 
사용자가 가장 먼저 보게 되는 계층
실제 비지니스 로직 없이 사용자의 입력만 받고 전달</p>
<p><strong>Application Layer</strong> : 
기능별 로직 중심 패키지
사용자 요청을 처리하는 로직(주문, 결제, 배송) 담당</p>
<p><strong>Database Layer</strong> : 
데이터 저장소
영속성 있는 데이터(고객 정보, 재고)를 다루는 계층 
데이터 저장 및 조회 처리(DB와 직접 연결)
데이터 객체를 보관함
CRUD 중심</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조_원형큐]]></title>
            <link>https://velog.io/@jiwon_17/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EC%84%A0%ED%98%95%ED%81%90-2kqbqntq</link>
            <guid>https://velog.io/@jiwon_17/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EC%84%A0%ED%98%95%ED%81%90-2kqbqntq</guid>
            <pubDate>Fri, 11 Apr 2025 11:25:58 GMT</pubDate>
            <description><![CDATA[<h3 id="원형큐">원형큐</h3>
<blockquote>
<p>front, rear의 초기값: 0</p>
</blockquote>
<p><strong>% 연산자를 이용한다!!</strong>
데이터가 추가 =&gt; rear를 하나 증가 =&gt; 그 위치에 데이터 저장
데이터를 삭제 =&gt; front를 하나 증가 =&gt; 그 위치에 데이터 삭제</p>
<blockquote>
<p><strong>원형큐 연습하기</strong></p>
</blockquote>
<pre><code>#define _CRT_SECURE_NO_WARNINGS
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
&gt;
//원형큐
#define MAX_QUEUE_SIZE 5
&gt;
typedef int element;
typedef struct {
    int front;
    int rear;
    element data[MAX_QUEUE_SIZE];
} QueueType;
&gt;
//초기화 함수
void init_queue(QueueType* q) {
    q-&gt;front = q-&gt;rear = 0;
}
&gt;
//is_full 함수
int is_full(QueueType *q) {
    return q-&gt;front == (q-&gt;rear + 1) % MAX_QUEUE_SIZE;
}
&gt;
//is_empty 함수
int is_empty(QueueType *q) {
    return q-&gt;front == q-&gt;rear;
}
&gt;
//데이터 삽입 함수
void enqueue(QueueType *q, element item) {
    if (is_full(q)) {
        printf(&quot;큐가 꽉 차있음\n&quot;);
        return;
    }
    else {
        q-&gt;rear = (q-&gt;rear + 1) % MAX_QUEUE_SIZE;
        q-&gt;data[q-&gt;rear] = item;
    }
}
&gt;
//데이터 삭제 함수
element dequeue(QueueType* q) {
    if (is_empty(q)) {
        printf(&quot;큐가 비어있음\n&quot;);
        exit(1);
    }
    else {
        q-&gt;front = (q-&gt;front + 1) % MAX_QUEUE_SIZE;
        return q-&gt;data[q-&gt;front];
    }
}
&gt;
//큐 출력 함수
void print_queue(QueueType *q) {
    printf(&quot;\n현재 큐 상태 (front: %d, rear: %d):\n&quot;, q-&gt;front, q-&gt;rear);
    printf(&quot;+-------------------------+\n&quot;);
    printf(&quot;| &quot;);
    if (!is_empty(q)) {
        int i = q-&gt;front;
        do {
            i = (i + 1) % (MAX_QUEUE_SIZE);
            printf(&quot;%d &quot;, q-&gt;data[i]);
            if (i == q-&gt;rear)
                break;
        } while (i != q-&gt;front);
    }
    printf(&quot;|\n+-------------------------+\n&quot;);
}
&gt;
int main() {
    QueueType q;
    init_queue(&amp;q);
    element item;
&gt;
    printf(&quot;--원형큐에 데이터 추가--\n&quot;);
    while (!is_full(&amp;q)) {
        printf(&quot;\n&quot;);
        printf(&quot;추가할 정수 입력: &quot;);
        scanf_s(&quot;%d&quot;, &amp;item);
&gt;
        enqueue(&amp;q, item);
        print_queue(&amp;q);
    }
    printf(&quot;큐는 현재 포화상태!\n&quot;);
    printf(&quot;\n&quot;);
&gt;
    printf(&quot;--원형큐에 데이터 삭제--\n&quot;);
    while (!is_empty(&amp;q)) {
        element item = dequeue(&amp;q);
        printf(&quot;꺼낸 정수 %d\n&quot;, item);
&gt;
        print_queue(&amp;q);
    }
    printf(&quot;큐는 현재 공백상태!\n&quot;);
    printf(&quot;\n&quot;);
    return 0;
}</code></pre><blockquote>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jiwon_17/post/c6e759d7-7c29-45ac-9732-145a5f5b512f/image.png" alt=""></p>
<blockquote>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jiwon_17/post/93ce48f7-c5d2-4b4e-a0de-8c069ac541d8/image.png" alt=""></p>
<blockquote>
<p><strong>원형큐 필기</strong>
<img src="https://velog.velcdn.com/images/jiwon_17/post/3acfdc5d-2ace-46e8-93e6-77c946e1da28/image.jpg" alt=""></p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jiwon_17/post/c844f0dd-99bf-4da5-8c63-789737644c38/image.jpg" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조_선형큐]]></title>
            <link>https://velog.io/@jiwon_17/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EC%84%A0%ED%98%95%ED%81%90</link>
            <guid>https://velog.io/@jiwon_17/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EC%84%A0%ED%98%95%ED%81%90</guid>
            <pubDate>Fri, 11 Apr 2025 08:52:33 GMT</pubDate>
            <description><![CDATA[<h2 id="큐">큐</h2>
<p><strong>나중에 들어온 데이터가 먼저 나가는 구조인 스택과 달리
큐(queue)는 먼저 들어온 데이터가 먼저 나가는 구조</strong></p>
<p><strong>즉, 큐는 FIFO</strong></p>
<h3 id="스택과-큐의-차이점">스택과 큐의 차이점</h3>
<p><strong>스택</strong>
삽입과 삭제가 <strong>같은 쪽</strong>에서 일어남</p>
<p><strong>큐</strong>
삽입과 삭제가 <strong>다른 쪽</strong>에서 일어남</p>
<p>삽입이 일어나는 곳 : rear(후단)
삭제가 일어나는 곳 : front(전단)</p>
<p><strong>enqueue 연산</strong>
큐에 요소를 추가하는 연산으로 큐의 맨 뒤에 새로운 요소를 추가</p>
<p><strong>dequeue 연산</strong>
큐의 맨 앞에 있는 요소를 꺼내서 외부로 반환</p>
<h3 id="선형큐">선형큐</h3>
<blockquote>
</blockquote>
<p><strong>front, rear의 초기값: -1</strong>
front는 큐의 첫번째 요소를 가리킴
rear는 큐의 마지막 요소를 가리킴</p>
<blockquote>
</blockquote>
<p><strong>데이터가 증가 =&gt; rear를 하나 증가 =&gt; 그 위치에 데이터 저장
데이터를 삭제 =&gt; front를 하나 증가 =&gt; 그 위치에 데이터 삭제</strong></p>
<blockquote>
<p><strong>선형큐 연습하기</strong></p>
</blockquote>
<pre><code>#define _CRT_SECURE_NO_WARNINGS
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
&gt;
//선형큐
&gt;
#define MAX_QUEUE_SIZE 5
&gt;
typedef int element;
typedef struct {
    int front;
    int rear;
    element data[MAX_QUEUE_SIZE];
} QueueType;
&gt;
//초기화 함수
void init_queue(QueueType *q) {
    q-&gt;front = -1;
    q-&gt;rear = -1;
}
&gt;
//is_full 함수
int is_full(QueueType *q) {
    return q-&gt;rear == MAX_QUEUE_SIZE - 1;
}
&gt;
//is_empty 함수
int is_empty(QueueType* q) {
    return q-&gt;front == q-&gt;rear;
}
&gt;
//데이터 삽입 함수
void enqueue(QueueType *q, element item) {
    if (is_full(q)) {
        fprintf(stderr, &quot;스택오버플로우\n&quot;);
        return;
    }
    else q-&gt;data[++(q-&gt;rear)] = item;
}
&gt;
//데이터 삭제 함수
element dequeue(QueueType* q) {
    if (is_empty(q)) {
        printf(&quot;큐가 비었음!\n&quot;);
        exit(1);
    }
    else return q-&gt;data[++(q-&gt;front)];
}
&gt;
int main() {
    QueueType q;
    init_queue(&amp;q);
    enqueue(&amp;q, 10); enqueue(&amp;q, 20); enqueue(&amp;q, 30);
&gt;
    for (int i = 0; i &lt;= q.rear; i++) {
        printf(&quot;%d\n&quot;, q.data[i]);
    }
    printf(&quot;\n&quot;);
    printf(&quot;삭제 item 출력\n&quot;);
&gt;
    element item = dequeue(&amp;q);
    printf(&quot;%d\n&quot;, item);
    item = dequeue(&amp;q);
    printf(&quot;%d\n&quot;, item);
    item = dequeue(&amp;q);
    printf(&quot;%d\n&quot;, item);
}</code></pre><blockquote>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jiwon_17/post/f113f518-4b38-4477-bd78-e0f6bd47a64b/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[소프트웨어공학_0408_이론_UML모델링]]></title>
            <link>https://velog.io/@jiwon_17/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%EA%B3%B5%ED%95%990408%EC%9D%B4%EB%A1%A0UML%EB%AA%A8%EB%8D%B8%EB%A7%81</link>
            <guid>https://velog.io/@jiwon_17/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%EA%B3%B5%ED%95%990408%EC%9D%B4%EB%A1%A0UML%EB%AA%A8%EB%8D%B8%EB%A7%81</guid>
            <pubDate>Tue, 08 Apr 2025 07:17:05 GMT</pubDate>
            <description><![CDATA[<h2 id="uml을-이용한-모델링">UML을 이용한 모델링</h2>
<h3 id="클래스-다이어그램의-구성요소">클래스 다이어그램의 구성요소</h3>
<p><strong>클래스</strong>
공통의 속성, 메서드(오퍼레이션), 관계, 의미를 공유하는 객체 집합에 대한 기술</p>
<p><strong>클래스의 속성</strong></p>
<ul>
<li>클래스가 가진 데이터</li>
<li>클래스의 구조적 특성에 이름을 붙인 것으로, 인스턴스가 보유할 수 있는 값을 범위를 기술</li>
</ul>
<p><strong>클래스의 메서드</strong></p>
<ul>
<li><p>클래스가 수행할 수 있는 작업을 정의</p>
</li>
<li><p>오퍼레이션</p>
</li>
<li><p>이름, 타입, 매개변수들과 연관된 행위를 호출할 때 제약사항이 요구되는데, 이 제약사항을 명세하는 클래스의 행위적 특성</p>
</li>
<li><p>public </p>
</li>
<li><ul>
<li>부호: +</li>
</ul>
</li>
<li><ul>
<li>자신의 속성이나 동작을 외부에 공개하는 접근 제어</li>
</ul>
</li>
<li><p>private</p>
</li>
<li><ul>
<li>부호: -</li>
</ul>
</li>
<li><ul>
<li>상속된 파생 클래스만 액세스할 수 있는 접근 제어</li>
</ul>
</li>
<li><p>protected</p>
</li>
<li><ul>
<li>부호: #</li>
</ul>
</li>
<li><ul>
<li>구조체의 멤버 함수만 접근할 수 있으며 외부에서 액세스할 수 없는 접근 제어</li>
</ul>
</li>
</ul>
<p><strong>클래스는 객체를 생성할 수 있는 구조와 정보를 갖는 틀</strong>
<strong>객체는 클래스의 인스턴스</strong></p>
<h3 id="객체-생성-다이어그램">객체 생성 다이어그램</h3>
<p>클래스 정의 &gt;&gt; 메인 메서드 실행 &gt;&gt; 객체 생성 &gt;&gt; 실행</p>
<h3 id="객체와-클래스-사이의-관계와-표현">객체와 클래스 사이의 관계와 표현</h3>
<h4 id="연관-관계">연관 관계</h4>
<p>멤버 변수로 참조</p>
<ul>
<li>한 클래스가 다른 클래스의 인스턴스를 <strong>필드로 가지고 있는 경우</strong></li>
<li><strong>A는 B를 가진다(has-a)관계</strong></li>
</ul>
<h4 id="의존-관계">의존 관계</h4>
<p>메서드로 참조</p>
<ul>
<li>한 클래스의 메서드가 다른 클래스의 객체를 <strong>일시적으로 사용</strong></li>
<li><strong>A는 B를 사용한다(uses-a)관계</strong></li>
<li>짧은 생명주기, 메서드 내에서만 사용하는 것이 일반적</li>
<li>메서드 호출이 완료되면 종료</li>
</ul>
<h4 id="연관-관계와-의존-관계의-차이">연관 관계와 의존 관계의 차이</h4>
<p><strong>연관 관계</strong></p>
<ul>
<li>지속성 있음</li>
<li>실선으로 표현</li>
</ul>
<p><strong>의존 관계</strong></p>
<ul>
<li>일시적임 </li>
<li>점선으로 표현</li>
</ul>
<h4 id="연관-관계-모델링">연관 관계 모델링</h4>
<ul>
<li>단방향 연관 관계 모델링</li>
<li>양방향 연관 관계 모델링</li>
</ul>
<h4 id="집합-관계">집합 관계</h4>
<ul>
<li>하나의 객체가 독립적인 객체 여러 개로 구성되는 has a 관계</li>
<li>부분이 전체에 속하지만 독립적 존재 가능</li>
<li>학생과 학교의 관계</li>
<li>차가 없어진다고해서 엔진, 휠, 샤시가 없어지진 않음</li>
</ul>
<h4 id="복합-관계">복합 관계</h4>
<ul>
<li>종속적인 관계</li>
<li>전체 객체의 생명주기와 부분 객체의 생명주기가 연결됨</li>
<li>사람과 심장의 관계</li>
</ul>
<h4 id="집합-관계와-복합-관계-모델링">집합 관계와 복합 관계 모델링</h4>
<p>스마트폰 시스템</p>
<ul>
<li>집합 관계 (충전기(스마트폰이 없어도 독립적으로 존재 가능))</li>
<li>복합 관계 (메인보드, 스피커, 내부 부품들)</li>
</ul>
<h4 id="실체화-관계">실체화 관계</h4>
<p>추상 클래스나 인터페이스를 상속받아 자식 클래스가 추상 메서드를 구현할 때 사용하는 관계</p>
<ul>
<li>UML에서는 점선 화살표와 빈 삼각형으로 표현</li>
<li>화살표는 인터페이스나 추상 클래스를 향함</li>
</ul>
<h3 id="순차-다이어그램의-구성-요소">순차 다이어그램의 구성 요소</h3>
<p><strong>순차 다이어그램</strong>
객체 간의 동적 상호작용을 시간 개념을 중심으로 
모델링하는 UML다이어그램</p>
<p><strong>주요 구성 요소</strong></p>
<ul>
<li>객체</li>
<li>생명선 (객체의 존재 기간)</li>
<li>활성화 (객체가 작업을 수행중임을 나타내는 사각형)</li>
<li>메시지 (객체 간 통신을 나타내는 화살표)</li>
<li>반환 메시지 (메서드 호출의 결과 반환)</li>
<li>자기 호출 (객체가 자신의 메서드 호출)</li>
<li>희귀 메시지 (같은 객체에 대한 함수(메서드)를 호출)</li>
</ul>
<h3 id="상호작용-다이어그램">상호작용 다이어그램</h3>
<h4 id="순차-다이어그램">순차 다이어그램</h4>
<p>객체들 사이의 이동 경로를 시간 흐름으로 표현, 시간 순서가 중요할 때 적합</p>
<h4 id="순자-다이어그램의-표현">순자 다이어그램의 표현</h4>
<blockquote>
<p>수직 방향이 시간의 흐름을 나타내는 특성</p>
</blockquote>
<ul>
<li>객체와 생명선</li>
<li>활성화 </li>
<li>메시지 유형</li>
</ul>
<h4 id="순차-다이어그램의-메시지-표현">순차 다이어그램의 메시지 표현</h4>
<ul>
<li>호출 메시지(동기 메시지)</li>
<li>답신 메시지</li>
<li>비동기 메시지</li>
</ul>
<h4 id="통신-다이어그램">통신 다이어그램</h4>
<p>메시지(데이터)의 흐름과 객체 간 관계를 중점적으로 표현, 메시지 흐름을 보려고 할 때 적합함</p>
<h3 id="의존-관계의-스테레오타입">의존 관계의 스테레오타입</h3>
<p><strong>access</strong>
한 패키지의 요소가 다른 패키지의 요소를 비공개적으로 사용할 수 있도록 허용하지만, 그 요소 자체를 가져오진 않는다. </p>
<p><strong>import</strong>
한 패키지의 요소가 다른 패키지의 요소에 공개적으로 접근할 수 있도록 허용, export하는 것이 가능</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[확률및통계_0408_수업 메모]]></title>
            <link>https://velog.io/@jiwon_17/%ED%99%95%EB%A5%A0%EB%B0%8F%ED%86%B5%EA%B3%840408%EC%88%98%EC%97%85-%EB%A9%94%EB%AA%A8</link>
            <guid>https://velog.io/@jiwon_17/%ED%99%95%EB%A5%A0%EB%B0%8F%ED%86%B5%EA%B3%840408%EC%88%98%EC%97%85-%EB%A9%94%EB%AA%A8</guid>
            <pubDate>Tue, 08 Apr 2025 05:33:24 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>확률과통계 중간고사</strong></p>
</blockquote>
<ul>
<li>Ch5까지</li>
<li>연속확률분포 중 감마 분포 안냄</li>
</ul>
<p><strong>연속확률분포</strong>
정규 분포 중요!!!!</p>
<p><strong>연속확률분포 지수분포</strong>
푸아송 분포와의 차이점을 확실하게 알아둘 것</p>
<p><strong>지수 분포는 특정한 사건이 발생할 때까지 걸린 시간의 분포이다.</strong></p>
<blockquote>
<p><strong>객관식</strong>
평균과 분산 계산식 </p>
</blockquote>
<blockquote>
<p>*<em>주관식 *</em>
종이로 A4 3장이내로 출력, 폰트 12pt</p>
</blockquote>
<p><strong>본문에 있는 연습문제 풀어보기</strong>
<strong>오렌지 설치하기</strong>
<img src="https://velog.velcdn.com/images/jiwon_17/post/4d7a256a-6fc0-4107-88d6-ec1bede1679e/image.png" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>