<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>fma_.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sun, 15 Dec 2024 05:56:31 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>fma_.log</title>
            <url>https://velog.velcdn.com/images/fma_/profile/6ac6185d-2ec4-413e-ba1a-6eb48cfd43bf/social_profile.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. fma_.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/fma_" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[JMeter] CLI Mode로 부하 테스트하기, Dashboard 해석하기]]></title>
            <link>https://velog.io/@fma_/JMeter-CLI-Mode%EB%A1%9C-%EB%B6%80%ED%95%98-%ED%85%8C%EC%8A%A4%ED%8A%B8%ED%95%98%EA%B8%B0-Dashboard-%ED%95%B4%EC%84%9D%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@fma_/JMeter-CLI-Mode%EB%A1%9C-%EB%B6%80%ED%95%98-%ED%85%8C%EC%8A%A4%ED%8A%B8%ED%95%98%EA%B8%B0-Dashboard-%ED%95%B4%EC%84%9D%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 15 Dec 2024 05:56:31 GMT</pubDate>
            <description><![CDATA[<h2 id="jmeter-cli-mode로-부하-테스트-수행하기"><strong>JMeter CLI Mode로 부하 테스트 수행하기</strong></h2>
<p>부하 테스트란 임계치에 도달할 때까지 시스템에 부하를 꾸준히 증가시키며 진행하는 테스트이다. 소위 말해 시스템이 &#39;뻗을&#39; 때까지 부하를 주고, 그렇게 한계치에 도달한 시스템이 어떻게 동작하는지를 테스트하는 것이다.</p>
<p>JMeter를 통해서도 당연히 부하 테스트가 가능하지만, <a href="https://jmeter.apache.org/"><strong>Apache JMeter 공식 홈페이지</strong></a>에서는 부하 테스트(load test) 진행 시 GUI모드가 아닌 CLI모드를 사용할 것을 명시하고 있다.</p>
<p>부하 테스트를 위해서는 먼저 JMeter에서 사용 가능한 HEAP 메모리를 수정해야 한다. JMeter.bat에서 다음 부분을 수정하면 된다.</p>
<pre><code class="language-jsx">if not defined HEAP (
    rem See the unix startup file for the rationale of the following parameters,
    rem including some tuning recommendations
    set HEAP=-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m
)</code></pre>
<p>set HEAP= 뒤의 설정값이 다르게 설정되어 있을 것이다. 나는 컴퓨터 환경이 좋은 편이 아니라 얼마 늘리지 못했지만, 본인의 환경에 따라 적당히 맞춰주면 된다. (6g까지 설정한 예제도 어렵지 않게 찾을 수 있었다.)</p>
<p>PC 환경과 수행할 부하 테스트를 고려하여 적절한 용량을 맞춰주면 된다. 용량이 너무 작을 경우 부하 테스트가 정상 실행되지 않고, PC 환경 대비 너무 많은 메모리를 할당할 시 JMeter가 아예 실행되지 않을 수 있다.</p>
<h2 id="부하-테스트를-위한-시나리오-작성하기"><strong>부하 테스트를 위한 시나리오 작성하기</strong></h2>
<p>CLI 모드로 부하 테스트를 수행하기 위해서는 먼저 GUI 모드에서 작성된 테스트 시나리오가 필요하다. 기본적인 시나리오 작성은 아래 포스트를 참고하자.</p>
<p><a href="https://velog.io/@fma_/JMeter-JMeter%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%8B%9C%EB%82%98%EB%A6%AC%EC%98%A4-%EC%9E%91%EC%84%B1-%EB%B0%A9%EB%B2%95jmx%ED%8C%8C%EC%9D%BC">[JMeter] JMeter를 활용한 테스트 시나리오 작성 방법(jmx파일)</a></p>
<p>해당 포스트의 시나리오와 코드를 조금 수정해 부하 테스트 예제를 시행해보도록 하겠다.</p>
<p>먼저, FastAPI 코드의 login 부분을 다음과 같이 수정하였다.</p>
<pre><code class="language-python">@app.post(&quot;/login&quot;)
def login(user: User):
    id = random.randrange(1, 100)
    token = None if id &lt; 30 else str(uuid.uuid4())
    return {&quot;id&quot;: id, &quot;token&quot;: token}</code></pre>
<p>이렇게 수정하면 30% 확률로 token 값에 None을 반환한다. 이렇게 되면 회원 가격 조회 시 30% 확률로 테스트 실패가 발생한다. 테스트 실패가 이후 Dashboard에서 어떻게 나타나는지를 확인하기 위함이다.</p>
<p>이렇게 수정하면 30% 확률로 token 값에 None을 반환한다. 이렇게 되면 회원 가격 조회 시 30% 확률로 테스트 실패가 발생한다. 테스트 실패가 이후 Dashboard에서 어떻게 나타나는지를 확인하기 위함이다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/f32637fb-fc50-46b0-a0f5-45a710b1da74/image.png" alt=""></p>
<p>유저 수, 시간, 반복 횟수는 각각 300,5,200으로 설정했다.</p>
<p>300명의 유저가 5초 동안 시나리오에 작성된 action을 수행하며, 그 과정을 200번 반복한다.</p>
<p>결과적으로 시나리오가 300x200=60000번 실행될 것이라 기대할 수 있다.</p>
<p>수정이 완료되었으면 해당 변경사항 또한 jmx 파일로 저장해두도록 하자.</p>
<h2 id="부하-테스트-수행하기"><strong>부하 테스트 수행하기</strong></h2>
<p>JMeter CLI 실행을 위해서는 JMeter.bat이 있는 폴더의 터미널에서 다음 명령어를 입력하면 된다.</p>
<p>(윈도우의 경우 PowerShell이 아닌 명령 프롬프트에서 실행해야 한다.)</p>
<pre><code class="language-jsx">jmeter.bat -n -t [jmx file] -l [results file] -e -o [Path to web report folder]</code></pre>
<ul>
<li><code>jmx file</code> : 실행하고자 하는 시나리오의 jmx 파일 경로</li>
<li><code>results file</code> : 실행 결과를 담은 csv 파일 저장 경로</li>
<li><code>Path to web report folder</code> : 실행 결과 시각화 파일을 저장할 폴더 경로</li>
</ul>
<p>나는 다음과 같이 입력해 부하 테스트를 시행했다.</p>
<pre><code class="language-jsx">jmeter -n -t &quot;D:\JMeter\test_plan.jmx&quot; -l &quot;D:\JMeter\example_test_plan_result.csv&quot; -e -o &quot;D:\JMeter\20231005&quot;</code></pre>
<p>상세한 명령어 해설은 다음과 같다.</p>
<ul>
<li><code>n</code> : CLI 모드로 실행</li>
<li><code>t</code> : [테스트 계획이 포함된 JMX 파일 이름]을 입력</li>
<li><code>l</code> : [샘플 결과를 기록할 JTL 파일 이름]을 입력</li>
<li><code>j</code> : [JMeter 실행 로그 파일 이름]을 입력</li>
<li><code>r</code> : JMeter 속성 &quot;remote_hosts&quot;로 지정된 서버에서 테스트를 실행</li>
<li><code>R</code> : [원격 서버 목록] 지정된 원격 서버에서 테스트를 실행</li>
<li><code>g</code> : [CSV 파일 경로] 보고서 대시보드만 생성</li>
<li><code>e</code> : 부하 테스트 후 리포트 대시보드 생성</li>
<li><code>o</code> : 로드 테스트 후 보고서 대시보드를 생성할 출력 폴더 (폴더가 존재하지 않거나 비어 있으면 안)</li>
<li><code>H</code> : [프록시 서버 호스트 이름 또는 IP 주소]</li>
<li><code>P</code> : [프록시 서버 포트]</li>
</ul>
<p><img src="https://velog.velcdn.com/images/fma_/post/065b1229-f992-43a6-a4ec-b8864abb4f55/image.png" alt=""></p>
<p>명령 프롬프트에 해당 명령어를 입력하면 위와 같이 부하 테스트가 실행된다. (실행 내용에 따라 다소 시간이 소요될 수 있다.)</p>
<h2 id="부하-테스트-결과-분석하기"><strong>부하 테스트 결과 분석하기</strong></h2>
<h3 id="csv-파일-결과-분석하기"><strong>csv 파일 결과 분석하기</strong></h3>
<p><img src="https://velog.velcdn.com/images/fma_/post/b89e9141-c9ef-4f16-a6c8-b33a8b6947d8/image.png" alt=""></p>
<p>csv 파일을 엑셀로 열어보면 위와 같은 결과가 나오는 것을 확인할 수 있다. 각 열별 의미는 다음과 같이 해석할 수 있다.</p>
<ul>
<li><code>timeStamp</code> : 요청이 발생한 시각</li>
<li><code>elapsed</code> : 요청에 소요된 총 시간. Latency와 IdleTime을 포함한다.</li>
<li><code>label</code> : 보낸 request의 이름</li>
<li><code>responseCode</code> : 응답 코드</li>
<li><code>responseMessage</code> : 응답 메시지</li>
<li><code>threadName</code> : 쓰레드 그룹 이름</li>
<li><code>dataType</code> : 응답 데이터의 타입</li>
<li><code>success</code> : 테스트 성공 여부</li>
<li><code>failureMessage</code> : 테스트가 실패했을 경우 실패 메시지를 표시한다.</li>
<li><code>bytes</code> : 응답 데이터 바이트</li>
<li><code>sentBytes</code> : 요청 데이터 바이트</li>
<li><code>grpThreads</code> : 현재 활성 스레드 수 (=액티브 유저 수)</li>
<li><code>allThreads</code> : 전체 스레드 수를 의미하지만, 현재 스레드 그룹이 하나뿐이므로 활성 스레드와 같다.</li>
<li><code>URL</code> : 요청 URL</li>
<li><code>Latency</code> : 지연시간. 요청 시작 시점부터 응답 시작 시점까지의 시간을 의미한다.</li>
<li><code>IdleTime</code> : 유휴시간. 작동 가능한데도 작업을 하지 않는 시간.</li>
<li><code>Connect</code> : 연결을 설정하는 데 걸리는 시간 (클라이언트와 서버가 TCP 연결을 설정하는 데 걸리는 시간. 이 시간 이후부터 클라이언트가 서버에 요청을 보낼 수 있다. Latency를 포함한다.)</li>
</ul>
<p>latency가 눈에 띄게 증가하는 구간이 있는 것을 보아 유저가 몰림에 따라 서버가 느려지는 것을 확인할 수 있다. 그에 따라 elapsed도 천차만별이다.</p>
<h3 id="html-시각화-결과-분석하기"><strong>HTML 시각화 결과 분석하기</strong></h3>
<p>csv 파일로도 대략적인 경향은 확인할 수 있지만 사람이 한눈에 보고 판단하기는 어려움이 있다. 따라서 JMeter에서는 csv 파일의 데이터를 기반으로 한 시각화 결과를 함께 제공한다. 실행 시 [ Path to web report folder ] 에 입력했던 경로에 가면 HTML 파일로 확인할 수 있다.</p>
<p><strong><code>대시보드</code></strong>는 수행한 작업에 대한 대략적인 통계를 한눈에 보여주는 페이지이다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/5fb4a55c-2705-4e31-9f77-3f452cb05ef4/image.png" alt=""></p>
<p>분석에 대한 기본적인 정보와 Apdex(Application Performance Index), 성공 및 실패 요청의 비율을 보여주는 그래프를 확인할 수 있다. Apdex는 소프트웨어 애플리케이션 성능 평가 지표 중 하나로, 자세한 내용은 <a href="https://en.wikipedia.org/wiki/Apdex"><strong>위키백과 링크</strong></a>를 참고하길 바란다.</p>
<p>3개 중 1개 응답에 30% 확률로 FAIL을 주었으므로, 10% 언저리로 기댓값에 준하는 비율이 나왔다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/30a07021-257e-49bb-80bc-583523f7d214/image.png" alt=""></p>
<p>Statistics는 3개의 구성 가능한 백분위수를 포함하여 트랜잭션당 모든 메트릭의 요약을 하나의 테이블에 제공하는 통계 테이블이다. 전체 샘플 수와 성공/실패 비율, 응답시간의 요약 통계, Throughput과 Network의 성능 평가 지수를 확인할 수 있다. 이를 통해 대략적인 성능을 파악할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/89019042-cd59-47e0-bbd0-df24483bb058/image.png" alt=""></p>
<p>하단에는 Error 관련 지표를 확인할 수 있다. Errors는 모든 오류의 요약과 전체 요청에서 차지하는 비율을 제공하며, Top 5 Errors by sampler는 모든 샘플러(트랜잭션 컨트롤러 제외)에 대해 상위 5가지 오류를 제공한다. 나는 &#39;회원 가격을 조회했으나 비회원 가격을 응답으로 받아온 경우&#39;의 하나만을 실패로 처리해주었으므로, 이 실패 유형이 100%가 나왔다.</p>
<p><strong><code>Charts</code></strong>는 <code>Over time(시간별 지표)</code>, <code>Throughput(성능 평가 지표)</code>, <code>Response Times(응답 시간)</code>을 그래프로 시각화하여 보여 주는 부분이다. 각각의 그래프는 접혀 있으므로 펼쳐서 확인할 수 있다. 포스팅에서는 대표적인 몇 가지 그래프만 살펴보도록 하겠다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/4adaaf63-4833-4b55-924f-6bbe843cc732/image.png" alt=""></p>
<p>Response Times Over Time은 트랜잭션 컨트롤러 샘플 결과를 포함한 시간 경과에 따른 응답 시간 그래프이다. Sampler별로 응답시간 증가율을 비교할 수 있는데, 이 차트의 경우 로그인, 회원 가격 확인, 비회원 가격 확인 Sampler가 전부 비슷한 비율로 응답시간이 증가하거나 감소하고 있음을 알 수 있다. 3분여의 테스트에서 1분가량은 응답시간이 급격히 증가하다가 그 후 1분 동안은 완만하게 증가했고, 이후로 감소하는 추세를 보이고 있다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/e80b9f38-b2e7-4d50-a181-79b88c907adf/image.png" alt=""></p>
<p>Throughput(처리량)은 네트워크에서 초당 실제로 처리되는 패킷의 양을 의미하는데, 그중 Hits Per Second는 사용자가 1초 동안 웹 서버로 전송한 HTTP 요청의 수를 나타낸다. 응답 시간 그래프와 비슷한 모양을 띄고 있는데, 이를 통 응답 시간 지연이 HTTP 요청의 수가 늘어나서 발생했다고 유추할 수 있다. 따라서 테스트 실행 후 1~2분 사이에 트래픽이 급격히 증가해 응답 시간 지연이 일어났음을 알 수 있다.</p>
<p>그 밖에 그래프들이 의미하는 바는 JMeter 공식 문서의 <a href="https://jmeter.apache.org/usermanual/generating-dashboard.html"><strong>Generating Report Dashboard</strong></a> 부분을 참고하면 좋다.</p>
<hr>
<p><a href="https://jmeter.apache.org/usermanual/generating-dashboard.html"><strong>Apache JMeter 공식문서 Generating Report Dashboard</strong></a>
<a href="https://jmeter.apache.org/usermanual/get-started.html#non_gui"><strong>Apache JMeter 공식문서 CLI Mode (Comment Line mode was called NON GUI mode)</strong></a>
<a href="https://gruuuuu.github.io/testing/jmeter-tuto/#load-test%EB%B6%80%ED%95%98"><strong>GRU - [JMeter]JMeter Basics</strong></a>
<a href="https://like-tomato.tistory.com/299"><strong>토마토조아 - IT/Server [Apache] Jmeter(제이미터) 부하 테스트 방법(콘솔 명령어 기반)</strong></a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JMeter] JMeter를 활용한 테스트 시나리오 작성 방법(jmx파일)]]></title>
            <link>https://velog.io/@fma_/JMeter-JMeter%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%8B%9C%EB%82%98%EB%A6%AC%EC%98%A4-%EC%9E%91%EC%84%B1-%EB%B0%A9%EB%B2%95jmx%ED%8C%8C%EC%9D%BC</link>
            <guid>https://velog.io/@fma_/JMeter-JMeter%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%8B%9C%EB%82%98%EB%A6%AC%EC%98%A4-%EC%9E%91%EC%84%B1-%EB%B0%A9%EB%B2%95jmx%ED%8C%8C%EC%9D%BC</guid>
            <pubDate>Sun, 15 Dec 2024 05:36:56 GMT</pubDate>
            <description><![CDATA[<p>웹 애플리케이션을 개발하다 보면 반드시 개발한 기능을 검증하는 과정을 거친다.
테스트는 개발만큼이나 중요한 작업으로, 이용자의 예상 시나리오를 작성하여 해당 과정이 성공적으로 이루어지는지 판단하는 과정을 거치고는 한다.
테스트를 수행하는 툴은 다양하지만, 그중에서도 java 오픈 소스 툴인 Apache JMeter로 테스트 시나리오를 작성하는 방법을 알아보자.
본 포스팅에서는 JMeter가 이미 설치되어 있음을 가정한다. JMeter 설치 방법은 이미 여러 블로그에 있으니 검색해서 참고하면 좋겠다.</p>
<h2 id="jmeter를-활용한-테스트-시나리오-작성"><strong>JMeter를 활용한 테스트 시나리오 작성</strong></h2>
<p>테스트 시나리오는 <a href="https://jybaek.tistory.com/889"><strong>Jaeyeon Beak님의 &#39;테스트 명장, Apache JMeter&#39; 포스트</strong></a>를 참고하였다.</p>
<p>JMeter를 통해 통신할 서버 또한 해당 포스트의 FastAPI 서버 예제를 활용한다.</p>
<p>해당 포스트에서 공유된 <a href="https://github.com/jybaek/shopping-mall/tree/feature/blog"><strong>Github</strong></a>에서 다운받을 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/6fe3a200-c74d-47c2-af21-a6283998a8bc/image.png" alt=""></p>
<ul>
<li>login API 는 request body에 회원정보(email, password)를 받고 response로 회원의 id와 token을 내려준다.</li>
<li>products API 는 헤더에 토큰 정보를 검사해서 토큰이 있으면 회원가(10% 할인)로 상품 정보를 내려주고 없으면 소비자가를 내려준다.</li>
</ul>
<p>fastapi 서버 실행을 위해서는 해당 코드가 있는 폴더의 터미널에서 다음 명령어를 실행한다.</p>
<pre><code class="language-bash">uvicorn main:app</code></pre>
<p>그 뒤 <a href="http://127.0.0.1:8000/docs"><strong>localhost/docs</strong></a> 또는 <a href="http://127.0.0.1:8000/docs"><strong>127.0.0.1:8000/docs</strong></a> 로 접속하면 fastapi 문서를 확인할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/c064efbe-d468-4933-b65b-b10cef8e6abe/image.png" alt=""></p>
<p>JMeter는 크게 세 가지의 계층 구조로 이루어져 있다.</p>
<ul>
<li><code>Test Plan</code> : 전체 시나리오를 관장하는 글로벌한 설정 영역이다.</li>
<li><code>Thread Group</code> : 하나의 시나리오 덩어리를 저장하는 영역이다. 실행하는 스레드 수, 램프업 시간, 테스트 수행 시간을 지정하며, 하나의 테스트 플랜에는 여러개의 Thread Group을 지정할 수 있다. 본 예제에서는 로그인해서 상품을 보고 결제하는 일련의 과정을 의미한다.</li>
<li><code>Sampler</code> : JMeter가 대상 시스템에 요청해야 하는 정보를 설정한다. 본 예제에서는 로그인, 상품 조회, 가격 조회 등 각각의 수행을 의미한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/fma_/post/6ea654e1-db6f-48af-810c-488df4f1d2fe/image.png" alt=""></p>
<p>Test Plan에 우클릭을 하면 위와 같은 메뉴를 확인할 수 있다.</p>
<p>메뉴에 대한 설명은 다음과 같다.</p>
<ul>
<li><code>Thread Group</code> : 위에서 설명했듯 하나의 시나리오를 저장하는 영역이다.</li>
<li><code>Config Element</code> : Sampler의 요청 정보를 관리할 수 있다.</li>
<li><code>Listener</code> : JMeter를 통해 테스트하는 결과 정보 및 진행 상태 정보를 표시한다. 진행 추이를 그래프로 표시하거나 xml, csv 등으로 저장할 수 있다.</li>
<li><code>Timer</code> : 요청과 요청 사이에 특정 시간 간격이 필요한 경우 사용한다.</li>
<li><code>Logical Controllers</code> : JMeter가 언제 서버에 요청을 전달할지 결정한다.</li>
<li><code>Assertions</code> : JMeter의 HTTP 프로토콜을 활용해 성능 테스트를 할 경우 기본적으로 HTTP 응답 코드가 200이면 성공, 그외에 다른 코드 값은 실패로 판단한다. 하지만 업무적으로 200번 코드가 리턴되더라도 실패로 판단해야 하는 경우 Assertion를 이용해서 응답 정보에 특정한 메시지를 필터링해서 성공/실패 여부를 판단할 수 있다.</li>
<li><code>Pre Processors</code> : 샘플러를 실행하기 전에 수행해야 할 내용을 정의한다.</li>
<li><code>Post Processors</code> : 샘플러를 실행한 후에 수행해야 할 내용을 정의한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/fma_/post/44fb91cc-589c-43cf-b96f-b63cbbd5f7a0/image.png" alt=""></p>
<p>먼저 Config Element &gt; User Defined Variables에서 HOST, PORT 값을 지정했다. 이 설정은 모든 Sampler에서 사용되므로 사용자 지정 변수를 활용하면 테스트 서버 주소가 변경될 시 번거로움을 덜어줄 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/87f2b3fc-8967-4883-9180-44ff00a89e9a/image.png" alt=""></p>
<p>다음으로 Thread (Users) &gt; Thread Group 을 통해 Thread Group을 추가한다.</p>
<ul>
<li><code>Action to be taken after a Sampler error</code> : 테스트 도중 에러가 발생할 시 취할 액션을 정의한다. &#39;Continue&#39;로 설정되어 있으므로 오류가 발생하더라도 무시하고 계속해서 테스트를 수행한다.</li>
<li><code>Number of Threads (users)</code> : 몇 명의 스레드 수(유저 수)로 테스트할지 정의한다.</li>
<li><code>Ramp-up period (seconds)</code> : Number of Threads 만큼의 요청을 몇 초에 걸쳐서 만들지 정의한다.예를 들어 Number of Threads가 10이고 Ramp-up period가 1일 때, 1초 동안 10개의 요청을 발생시킨다.요청 간의 간격은 일정하다고 보장할 수 없으며, 디테일한 시간 설정은 timer를 활용해야 한다.</li>
<li><code>Loop Count</code> : 요청을 몇 번 반복할지 정의한다.예를 들어 Number of Threads가 10이고 Loop Count가 5일 때, 10개의 스레드를 5번 반복해 발생시키므로 50번의 요청이 발생한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/fma_/post/cfa85e47-22c8-4100-9613-239de146cb28/image.png" alt=""></p>
<p>HTTP 요청을 발생시키기 위해 Thread Group 하위에 Sampler &gt; HTTP Request를 추가한다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/c8281f07-9961-4693-bd10-181254142ecb/image.png" alt=""></p>
<p>로그인 API 테스트를 위해 위와 같이 설정해준다. Protocol은 http, IP와 Port Number은 User Defined Variables에서 지정했던 변수명을 ${HOST}, ${PORT} 처럼 셸스크립트의 문법으로 사용한다. Request Body를 이용한 요청이므로 Body data에 email, password를 넣어 준다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/073e1238-8876-42be-9d6b-00dd01cdc3a3/image.png" alt=""></p>
<p>모니터링을 위해서는 Listener가 필요하다. 전체적인 값을 한번에 확인하기 위해서 Test Plan 밑에 생성해 준다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/2135618c-9fe1-4a61-9fc2-4a71f958dbcf/image.png" alt=""></p>
<p>View Results Tree, Summart Report, View Results in Table, 그리고 jp@gc 플러그인의 Transcations per Second를 적용해주었다. jp@hc 플러그인 설치는 <a href="https://mosei.tistory.com/entry/JMeter-%EC%A0%9C%EC%9D%B4%EB%AF%B8%ED%84%B0-%EC%82%AC%EC%9A%A9%EB%B0%A9%EB%B2%95"><strong>포스트</strong></a>를 참고하면 된다.</p>
<p>View Results Tree는 각각의 요청에 대해 HTTP 프로토콜의 Request와 Response data의 생김새를 살펴볼 수 있다. 크롬 개발자모드 Network 탭과 유사하다고 생각하면 된다.</p>
<p>이제 Listener도 추가했으니 가운데 상단의 녹색 플레이 버튼만 눌러주면 테스트를 시행할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/4df53c8a-238e-4554-b442-57bdda7c0eae/image.png" alt=""></p>
<p>테스트 시행 후 View Results Tree를 보자, 빨간색으로 422 에러가 발생했다. Response data 탭을 통해 에러 메시지를 확인할 수 있다. 이 경우 Request body의 형식이 맞지 않아 생기는 문제이다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/bb6679cf-ea52-4178-80fa-f1d5bd76585d/image.png" alt=""></p>
<p>해당 형식을 맞춰주기 위해 로그인 API Request 하위에 HTTP Header Manager를 추가해 준다. HTTP Header에 값을 직접 추가할 수 있는 기능이다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/8a772288-cca5-4b9d-a2ae-a70123ab223d/image.png" alt=""></p>
<p>User Defined Variable을 추가할 때처럼 content-type을 application/json으로 설정해 준다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/3cce0fc1-a729-4457-8394-f6bce161862c/image.png" alt=""></p>
<p>드디어 오류가 수정되고 로그인 API를 테스트할 수 있게 되었다. 유저 id와 토큰 값이 정상적으로 출력된 것을 확인할 수 있다. fastapi 문서에 같은 파라미터를 넣고 실행한 뒤 비교해보면, 같은 형태로 출력된 것을 알 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/b7117615-ee85-4dd1-aa3e-5a41e8fc692d/image.png" alt=""></p>
<p>이제 다시 Thread Group으로 돌아가 비회원 상품 조회 Sampler를 생성하도록 하자. 로그인 Sampler를 생성할 때와 똑같이 ${HOST}, ${PORT}로 서버 정보를 지정해 주고, HTTP Request를 Get으로, Path를 /products로 지정해주면 된다.</p>
<p>다만 이 경우, 똑같은 서버 정보를 계속해서 입력해주어야 하는 번거로움이 있다. 지금은 비교적 간단한 예제이지만, 테스트가 복잡해지고 Request가 많아지면 오류 발생 가능성이 높아질 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/03ddb92a-6dcb-48ae-9020-eb8827ab5b18/image.png" alt=""></p>
<p>Config Element &gt; HTTP Request Defaults를 추가해 주면 HTTP Request에서의 기본값을 설정할 수 있다. Thread의 모든 HTTP Request에 적용되는 값이 있다면, 일일히 입력할 필요 없이 이곳에만 적용해주면 되는 것이다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/c65c45dd-6220-4ebc-a734-1e527634e37f/image.png" alt=""></p>
<p>이곳에 서버 정보를 지정해 주면 로그인과 비회원 가격 확인 테스트 Sampler에 서버 정보를 따로 지정하지 않아도 된다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/f9ce6d50-e5fb-4a43-9aa7-9957369d43a7/image.png" alt=""></p>
<p>회원 상품 조회 Sampler는 login API의 결과값인 token을 헤더에 입력해 동작한다. 따라서 다음으로는 login API에서 내려준 token 값을 사용할 수 있도록 설정해줘야 한다. login Sampler 하위에 Post Processors &gt; JSON Extractor을 추가해 준다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/0cad5ade-1861-4ebc-a90b-0ac53aa0dfd9/image.png" alt=""></p>
<p>JSON Extractor는 JSON형식 내부의 값을 파싱해서 변수로 사용할 수 있다. 여기서는 token값을 파싱한다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/bcb5f88e-0f0b-4479-ad20-8cf51072ba4d/image.png" alt=""></p>
<p>다음으로 회원 상품 조회 Sampler을 추가해 준다. 회원 상품 조회 Sampler는 비회원 상품 조회 Sampler를 복제해서 사용한다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/05daf13e-0f17-4ee2-9d47-c8115114d9f6/image.png" alt=""></p>
<p>login Sampler에서와 같이 회원 상품 조회 Sampler 하위에 HTTP Header Manager를 추가하고, login Sampler 하위의 JSON Extractor에서 파싱했던 token값을 넣어 준다. 이렇게 되면 회원 상품 조회 Sampler의 헤더에 token값을 직접적으로 추가해 요청할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/9bb11449-dee4-4aee-a256-a3e065a6718c/image.png" alt=""></p>
<p>회원가는 10% 할인이 적용된 가격으로 출력되어야 하므로, HTTP 프로토콜이 200이더라도 10% 할인된 가격이 출력되지 않으면 테스트에 실패한 것으로 간주할 수 있다. Assertions &gt; Response Assertion으로 테스트 조건을 추가적으로 설정해 주자.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/09bb72f7-1818-4f2b-ab35-30c10b3df033/image.png" alt=""><img src="https://velog.velcdn.com/images/fma_/post/9247f704-80e2-493a-88d7-25008a37a9d1/image.png" alt=""></p>
<p>회원 가격을 조회했을 때 비회원 가격과 같은 가격이 출력되어서는 안되므로, 비회원 가격 조회 Sampler의 결과값을 가져와 Substring, Not으로 설정해주었다. 이렇게 되면 비회원 가격의 결과값에 회원 가격이 포함되지 않을 때에만 테스트 성공으로 간주하게 된다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/9e47d282-4901-4633-a366-ddb87d5c2492/image.png" alt=""></p>
<p>이렇게 로그인, 비회원 상품 가격 조회, 회원 상품 가격 조회 Sampler가 전부 완성되었다. 그러나 이 흐름은 이용자의 사용 측면에서 자연스럽지가 않다. &#39; 비회원 상품 가격 조회 &gt; 로그인 &gt; 회원 상품 가격 조회 &#39;의 흐름이 더욱 자연스럽다. 드래그 앤 드롭으로 순서를 조정해 준다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/f209e7cb-e6ec-4c28-ac08-d355ff4bcf95/image.png" alt=""></p>
<p>이제 가운데 위쪽의 초록색 재생 버튼을 눌러 테스트를 진행한다. View Result Tree 확인 결과, 성공적으로 테스트가 수행된 것을 확인할 수 있다.</p>
<p>이제 테스트 코드 작성이 끝났으니 저장 버튼을 눌러 꼭 jmx파일로 저장해두도록 하자. 저장하지 않고 cmd가 꺼질 시 내용이 모두 날아간다(!)
<img src="https://velog.velcdn.com/images/fma_/post/fd5cc310-4f26-4745-8743-76ac68c516e0/image.png" alt=""><img src="https://velog.velcdn.com/images/fma_/post/8c93f50f-9191-4591-affa-b16b2274dc0a/image.png" alt=""></p>
<p>나머지 Listener를 통해서도 결과값을 확인할 수 있다. 나머지 결과값과 부하 테스트에 대해서는 다음 포스팅에서 알아보도록 하자.</p>
<hr>
<p>참고자료
Apache JMeter 공식 홈페이지 <a href="https://jmeter.apache.org/"><strong>https://jmeter.apache.org/</strong></a>
먹세 - [JMeter] 제이미터 사용방법 <a href="https://mosei.tistory.com/entry/JMeter-%EC%A0%9C%EC%9D%B4%EB%AF%B8%ED%84%B0-%EC%82%AC%EC%9A%A9%EB%B0%A9%EB%B2%95"><strong>https://mosei.tistory.com/entry/JMeter-%EC%A0%9C%EC%9D%B4%EB%AF%B8%ED%84%B0-%EC%82%AC%EC%9A%A9%EB%B0%A9%EB%B2%95</strong></a>
Jaeyeon Beak - 테스트 명장, Apache JMeter <a href="https://jybaek.tistory.com/889"><strong>https://jybaek.tistory.com/889</strong></a>
ysk(0soo) - Apache JMeter를 사용해보자 <a href="https://0soo.tistory.com/220"><strong>https://0soo.tistory.com/220</strong></a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 프로토타입(prototype) :: 클래스, 인스턴스, 프로토타입의 관계]]></title>
            <link>https://velog.io/@fma_/JavaScript-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85prototype-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85%EC%9D%98-%EA%B4%80%EA%B3%84</link>
            <guid>https://velog.io/@fma_/JavaScript-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85prototype-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85%EC%9D%98-%EA%B4%80%EA%B3%84</guid>
            <pubDate>Sun, 15 Dec 2024 05:28:07 GMT</pubDate>
            <description><![CDATA[<p>JavaScipt는 프로토타입 기반 언어</p>
<ul>
<li>모든 객체들이 메소드와 속성들을 상속받기 위한 템플릿으로써 프로토타입 객체(prototype object)를 가짐</li>
<li>상속되는 속성과 메소드들은 각 객체가 아니라 객체의 생성자(constructor)의 prototype이라는 속성에 정의되어 있음</li>
</ul>
<h2 id="프로토타입과-클래스">프로토타입과 클래스</h2>
<p>간단한 예제를 통해 살펴보자.</p>
<pre><code class="language-jsx">class Human {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  sleep() {
    console.log(`${this.name}은 잠에 들었습니다`);
  }
}

let dyract = new Human(&#39;Dyract&#39;, 30);

Human.prototype.constructor === Human; //true, Human 클래스의 생성자 함수는 Human
Human.prototype === dyract.__proto__; //true, Human 클래스의 프로토타입은 Human 클래스의 인스턴스인 dyract의 __proto__
Human.prototype.sleep === kimcoding.sleep; //true
// Human 클래스의 sleep 메서드는 프로토타입에 있으며, Human 클래스의 인스턴스인 dyract에서 dyract.sleep으로 사용할 수 있음
</code></pre>
<p>Human이라는 클래스의 생성자(constructor)에 name, age 속성을 정의하고, Human 클래스 안에 sleep() 메서드를 정의해주었다.</p>
<p>이를 기반으로 dyract라는 개별 객체(인스턴스)를 생성했다.</p>
<p>Human 클래스와 인스턴스, 그리고 프로토타입의 관계를 한눈에 보기 쉽게 그림으로 정리하면 다음과 같다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/eec32577-1b5c-4b4a-a2b5-ff669b7110cc/image.png" alt=""></p>
<p>이를 기반으로 각 용어를 정리하면 다음과 같다.</p>
<table>
<thead>
<tr>
<th>.constructor</th>
<th>생성자의 속성 중 하나인 객체 초기화 함수, 객체의 생성 시 호출됨</th>
</tr>
</thead>
<tbody><tr>
<td>.prototype</td>
<td>생성자의 속성 중 하나로, 자녀가 사용할 수 있는 속성</td>
</tr>
<tr>
<td>.<strong>proto</strong></td>
<td>생성자의 속성 중 하나로, 부모로부터 가져올 수 있는 속성을 의미</td>
</tr>
<tr>
<td>instantiation</td>
<td>특정한 클래스 또는 프로세스에 대하여 인스턴스를 만들어 내는 일</td>
</tr>
</tbody></table>
<p>JavaScript 내장 클래스 중 이와 비슷한 예시로는 Object, Array, Date, Number 등이 있다.</p>
<p>이중 Array를 위와 같은 구조도로 나타내보았다. Array에 포함된 .push, .slice, .map 등을 우리가 단순히 배열 선언만을 통해서 사용할 수 있는 것도 이러한 이유이다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/2977e467-dc40-411f-83f0-d1a2e0a41238/image.png" alt=""></p>
<h1 id="프로토타입-체인"><strong>프로토타입 체인</strong></h1>
<p>프로토타입은 객체지향의 특성 포스트에서 설명했던 상속(inheritance)의 개념과 유사하다.</p>
<p>상속 개념을 복습하자면 다음과 같다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/e3d5d263-2b7d-44b1-844d-59a3e11f0cf2/image.png" alt=""></p>
<p>프로토타입 객체는 또 다시 상위 프로토타입 객체로부터 메소드와 속성을 상속받을 수 있고, 그 상위 프로토타입 객체도 마찬가지이다.</p>
<p>이런 방식으로 프로토타입 객체가 상속으로 연결되어 있는 것을 프로토타입 체인이라고 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 비동기]]></title>
            <link>https://velog.io/@fma_/JavaScript-%EB%B9%84%EB%8F%99%EA%B8%B0</link>
            <guid>https://velog.io/@fma_/JavaScript-%EB%B9%84%EB%8F%99%EA%B8%B0</guid>
            <pubDate>Sun, 15 Dec 2024 05:22:05 GMT</pubDate>
            <description><![CDATA[<h2 id="동기synchronos-vs-비동기asynchronos"><strong>동기(Synchronos) vs 비동기(Asynchronos)</strong></h2>
<p>동기 : 일을 순차적으로 처리하는 것, 전 일의 완료 시점과 다음 일의 시작 시점이 같다.</p>
<p>비동기 : 전 일의 완료 시점과 다음 일의 시작 시점이 같을 필요가 없다.</p>
<p>그림으로 나타내면 다음과 같다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/ed97a178-3e0d-453e-8687-4f812562e4d6/image.png" alt=""></p>
<p>위 그림에서 동기 방식에 비해 비동기 방식이 같은 일을 하는데 걸리는 시간이 훨씬 짧은 것을 알 수 있다.</p>
<p>쉬운 예시를 들자면, 커피를 주문을 받는 과정을 생각해볼 수 있다.</p>
<p>만약 커피 주문이 동기적으로 작용한다면, 다음과 같은 과정을 거친다.</p>
<ol>
<li>손님 1이 아메리카노를 주문한다.</li>
<li>접수를 받은 직원이 아메리카노를 건넨다.</li>
<li>직원이 손님 1에게 아메리카노를 전달한다.</li>
<li>손님 2가 카페라떼를 주문한다.</li>
<li>접수를 받은 직원이 카페라떼를 만든다.</li>
<li>직원이 손님 2에게 카페라떼를 전달한다.</li>
</ol>
<p>이렇게 되면 손님 2는 손님 1이 아메리카노를 전달받을 때까지 주문을 하지 못하고 대기열에 머물러 있어야 한다.</p>
<p>한편 커피 주문이 비동기적으로 작용한다면, 다음과 같은 방식으로 동작한다.</p>
<ol>
<li>손님 1이 아메리카노를 주문한다.<ol>
<li>접수를 받은 직원이 아메리카노를 내린다.</li>
<li>아메리카노가 완성되면 직원이 손님 1을 부른다.</li>
<li>아메리카노를 손님 1에게 건넨다.</li>
</ol>
</li>
<li>손님 2가 카페라떼를 주문한다.<ol>
<li>접수를 받은 직원이 카페라떼를 내린다.</li>
<li>카페라떼가 완성되면 직원이 손님 2를 부른다.</li>
<li>카페라떼를 손님 2에게 건넨다.</li>
</ol>
</li>
</ol>
<p>이 경우 손님 2는 손님 1이 아메리카노를 받을 때까지 주문을 기다릴 필요가 없다.</p>
<h2 id="비동기asynchoros를-사용하는-이유"><strong>비동기(Asynchoros)를 사용하는 이유</strong></h2>
<p>웹사이트 등은 대부분 *클라이언트와 *서버 간의 통신에 의해 작동한다.</p>
<ul>
<li>클라이언트 : 서버로 접속하는 컴퓨터 (보통 우리가 접속하는 컴퓨터라고 생각해도 무방하다.)</li>
<li>서버 : 서비스, 리소스 등을 제공하는 컴퓨터 (웹 서버, 게임 서버 등)</li>
</ul>
<p>이렇듯 클라이언트와 서버가 통신할 때 동기 방식을 사용할 때보다 비동기 방식을 사용할 때의 장점이 확연히 드러난다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/d892830c-8471-43be-9672-ac739d68ff03/image.png" alt=""></p>
<p>그림에서 확인할 수 있듯, 같은 시간 동안 클라이언트가 상대적으로 훨씬 더 많은 일을 처리할 수 있게 된다.</p>
<p>서버의 응답을 가만히 기다리는 시간 동안 다른 일을 처리할 수 있기 때문이다.</p>
<h2 id="callback"><strong>Callback</strong></h2>
<pre><code class="language-jsx">const printString = (string) =&gt; {
    setTimeout (
        () =&gt; {
            console.log(string)
        },
        Math.floor(Math.random() * 100) + 1
    )
}

const printAll = () =&gt; {
    printString(&quot;A&quot;)
    printString(&quot;B&quot;)
    printString(&quot;C&quot;)
}

printAll()</code></pre>
<p>위 코드는 랜덤한 시간 이후에 문자 &#39;A&#39;, &#39;B&#39;, &#39;C&#39;를 각각 출력하는 비동기 방식의 코드이다.</p>
<p>위 코드는 A, B, C의 순서가 랜덤으로 출력되며, 해당 순서를 조절할 수는 없다.</p>
<p>그렇다면 A, B, C의 출력 순서를 조절하려면 어떻게 해야 할까?</p>
<pre><code class="language-jsx">const printString = (string, callback) =&gt; {
    setTimeout (
        () =&gt; {
            console.log(string)
            callback()
        },
        Math.floor(Math.random() * 100) + 1
    )
}

const printAll = () =&gt; {
    printString(&quot;A&quot;, () =&gt; {
        printString(&quot;B&quot;, () =&gt; {
            printString(&quot;C&quot;, () =&gt; {})
        })
    })
}

printAll()</code></pre>
<p>이는 callback 함수를 통해 해결할 수 있다.</p>
<p>callback 함수 인자로서 다음으로 출력할 함수를 전달하는 방식이다.</p>
<p>그러나 이는 동기로 실행할 함수가 많아질수록 계속 함수가 밀린다는 문제가 있다. (callback hell)</p>
<p>이를 해결하기 위해 Promise 방식을 이용한다.</p>
<h2 id="promise"><strong>Promise</strong></h2>
<pre><code class="language-jsx">const printString = (string) =&gt; {
    return new Promise((resolve, reject) =&gt; 
        setTimeout (
            () =&gt; {
                console.log(string)
                callback()
            },
            Math.floor(Math.random() * 100) + 1
        )
     })
}

const printAll = () =&gt; {
    printString(&quot;A&quot;)
    .then(() =&gt; {
        return printString(&quot;B&quot;)
    })
    .then(() =&gt; {
        return printString(&quot;C&quot;)
    })
}

printAll()</code></pre>
<p>함수 선언 시 callback 함수를 받지 않고, return문에 Promise 함수를 사용한다.</p>
<p>그러면 함수의 실행 순서를 .then을 사용해 조절할 수 있다.</p>
<p>Promise - then은 js 내장 함수로, .then()으로 작업 성공 시의 task, .catch()으로 작업 실패 시의 task를 따로 지정해줄 수 있다.</p>
<p>자세한 내용은 <a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise/then"><strong>#Promise.prototype.then</strong></a> 링크에서 확인할 수 있다.</p>
<h2 id="asyncawait"><strong>async/await</strong></h2>
<pre><code class="language-jsx">function printA() {
    return new Promise((resolve, reject) =&gt; {
        setTimeout(() =&gt; { resolve(&#39;A&#39;)}, 100)
    })
}

function printB() {
    return new Promise((resolve, reject) =&gt; {
        setTimeout(() =&gt; { resolve(&#39;B&#39;)}, 100)
    })
}

function printC() {
    return new Promise((resolve, reject) =&gt; {
        setTimeout(() =&gt; { resolve(&#39;C&#39;)}, 100)
    })
}

function printD() {
    return new Promise((resolve, reject) =&gt; {
        setTimeout(() =&gt; { resolve(&#39;D&#39;)}, 100)
    })
}

const result = async () =&gt; {
    const one = await printA();
    console.log(one)

    const two = await printA();
    console.log(two)

    const three = await printA();
    console.log(three)

    const four = await printA();
    console.log(four)
}

result();
</code></pre>
<p>promise와 같은 구조, 표기만 조금 다른 것.</p>
<p>비동기함수를 동기함수인것처럼 실행한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[전시] <히토 슈타이얼 - 데이터의 바다>]]></title>
            <link>https://velog.io/@fma_/%EC%A0%84%EC%8B%9C-%ED%9E%88%ED%86%A0-%EC%8A%88%ED%83%80%EC%9D%B4%EC%96%BC-%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%9D%98-%EB%B0%94%EB%8B%A4</link>
            <guid>https://velog.io/@fma_/%EC%A0%84%EC%8B%9C-%ED%9E%88%ED%86%A0-%EC%8A%88%ED%83%80%EC%9D%B4%EC%96%BC-%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%9D%98-%EB%B0%94%EB%8B%A4</guid>
            <pubDate>Sun, 15 Dec 2024 05:15:33 GMT</pubDate>
            <description><![CDATA[<p>국립현대미술관에서 진행한 <strong>&lt;히토 슈타이얼 - 데이터의 바다&gt;</strong> 전시를 감상하고 왔다.</p>
<p>2022.4.29 ~ 2022.9.18로 약 다섯 달 간 진행하였으며, 나는 이 전시를 뒤늦게 알아서 마지막날인 9월 18일에 다녀왔다.</p>
<blockquote>
<p>히토 슈타이얼(1966, 독일)은 디지털 기술, 글로벌 자본주의, 팬데믹 상황과 연관된 오늘날 가장 첨예한 사회, 문화적 현상을 영상 작업과 저술 활동을 통해 심도 있게 탐구해오고 있는 동시대 가장 영향력 있는 미디어 작가이다. 또한 예술, 철학, 정치 영역을 넘나들며 미디어, 이미지, 기술에 관한 흥미로운 논점을 던져주는 시각예술가이자 영화감독, 뛰어난 비평가이자 저술가이기도 하다. 또한 그는 현재 『이플럭스』를 비롯한 다양한 매체, 학술지 및 미술 잡지에 글을 기고하고 있다.
(중략)
 전시의 부제 ‘데이터의 바다’는 슈타이얼의 논문 「데이터의 바다: 아포페니아와 패턴(오)인식」(2016) 에서 인용한 것으로, 오늘날 또 하나의 현실로 재편된 데이터 사회를 성찰적으로 바라보고자 하는 전시의 의도를 함축한다. 따라서 이번 전시는 빅데이터와 알고리즘에 의해 조정되고 소셜 미디어를 통해 순환하는 정보 및 이미지 생산과 이러한 데이터 재현 배후의 기술, 자본, 권력, 정치의 맥락을 비판적으로 바라보는 작가의 최근 영상 작업을 집중적으로 소개한다.</p>
<ul>
<li>국립현대미술관, &lt;히토 슈타이얼 - 데이터의 바다&gt; 전시 소개 中</li>
</ul>
</blockquote>
<p>국립현대미술관의 전시 소개 중 일부이다.</p>
<p>저번에 부산에서 이형구 작가님 전시를 본 이후로 과학과 예술이 통합된 전시에 꽂혔는데... 데이터와 미디어가 결합된 형태의 전시라고 하니 안 볼수가 없었다. 원래 공학 분야(특히 데이터, 인공지능 분야)와 현실을 연결짓는 걸 좋아했기에 더욱 흥미가 갔다.</p>
<p>결론부터 말하자면, 내가 감상했던 전시 중 가장 &#39;뒷통수를 맞은 것 같은&#39; 느낌을 많이 받은 전시였다. 이 전시는 내가 생각지도 못했던 기술과 결합의 현실을 꼬집어주면서도 아름답고 충격적인 형태로 내 앞에 보여주었다. 개발 공부를 하면서 한동안은 기술 그 자체를 공부하는 데에 몰두했는데, 학창시절 개발자의 꿈을 꾸면서 많이 생각했던 &#39;어떤 공학자가 되어야 할까&#39;의 질문을 다시금 끄집어내어주는 전시이기도 했다.</p>
<p>워낙 많은 작품이 전시되어 있고 영상길이도 20~50분 정도로 길었기에 모든 작품을 감상하지는 못했고, 입장 전 팜플렛을 읽고 흥미가 가는 작품들을 선정해 찾아다니는 방식으로 관람했다. 작품마다 담고 있는 내용이 매우 상이하기에 기억에 남는 몇 작품의 감상평을 써보려 한다.</p>
<blockquote>
<p><strong>아래 글은 작품의 구체적인 내용을 포함하고 있습니다.</strong></p>
</blockquote>
<p>관람 예정이 있으신 분들은 열람을 권장하지 않습니다.</p>
<h2 id="1-안-보여주기--빌어먹게-유익하고-교육적인-mov-파일how-not-to-be-seen---digital-visuality--2013"><strong>1. &lt;안 보여주기 : 빌어먹게 유익하고 교육적인 .MOV 파일(How Not to Be Seen - Digital Visuality)&gt; , 2013</strong></h2>
<p><img src="https://velog.velcdn.com/images/fma_/post/506d2157-1304-47a5-afb6-98e7f1d0c275/image.jpeg" alt=""></p>
<blockquote>
<p>디지털 기술 기반 세상에서 우리는 안 보여질 수 있을까? 사적∙공적 데이터가 수집∙등록되고, 감시 카메라가 도처에 널려 있는 디지털 세상에서 우리는 완전히 숨을 수 있을까? 빅데이터와 빅브라더가 지배하는 세상에서 보이지 않는 존재란 과연 누구인가? 구글맵, 인공위성, 감시카메라, 드론, 항공지도 등의 장치를 통해 세상을 위에서 아래로 조망하게 된 시대, 세상과 인간을 인식하는 방식은 그 이전 시기와 어떻게 다른가? 슈타이얼은 영상 설치 작품 &lt;안 보여주기 : 빌어먹게 유익하고 교육적인 .MOV 파일&gt;에서 위와 같은 질문들을 이어간다.</p>
</blockquote>
<p>전시장에 들어가서 처음 보게 된 작품이자, 정말 풍자의 끝을 보여주는 작품이었다 ㅋㅋㅋㅋ 내용답게 영국의 전설적인 코미디 시리즈에서 제목을 따왔다고 한다.</p>
<p>&lt;안 보여주기 : 빌어먹게 유익하고 교육적인 .MOV 파일&gt;은 크게 다섯 장의 구성으로 &#39;안 보일 수 있는 방법&#39;을 설명한다. 이는 카메라에 안 보이게 하는 방법, 시야에서 안 보이게 하는 방법, 이미지가 되는 방법, 사라짐으로써 안 보이게 되는 방법, 이미지로 만들어진 세계에 병합됨으로써 안 보이게 하는 방법의 다섯 가지이다. 초반에는 디지털 기록 말소를 위한 현실적인 방법을 설명하는 것 같다가도, 나중에 가면 현실과 가상세계의 구별을 모호하게 하는 비현실적인 방법으로, 사람은 보이지 않더라도 데이터로서는 사라지지 않는다는 사실의 풍자를 여실히 드러낸다.</p>
<p>작가가 이 작품으로 말하고자 하는 바는 두 가지라고 생각한다. 하나는 디지털 기술 기반 세계에서는 개인의 사생활이 없이 모든 데이터가 수집되고 있다는 것이다. 우리가 어디를 가는지는 CCTV에 찍히고, 무엇을 궁금해하는지는 검색창에 기록되며, 무엇을 사유하는지는 웹사이트 쿠키에 남는다. 우리는 의식하지 못하는 사이에 우리의 모든 정보를 제공하고 있다. 이는 더 나은 디지털 서비스로 돌아오기 때문에 마냥 나쁘다고는 할 수 없지만, 가끔 이를 지우고 싶을 때에도 뜻대로 되지 않는다는 것이 문제가 된다. &#39;잊힐 권리&#39;가 실질적으로 지켜지지 않는다는 것이다. SNS에 적힌 한 마디의 말은 이미지가 다 낡아 헤질 때까지 퍼날라지고, 의도치 않게 찍힌 사진과 영상이 인터넷에 수없이 복제되어 떠돌아 지우기 쉽지 않은 경지까지 놓이기도 한다. 히토 슈타이얼은 이를 꼬집으며, 이것이 &#39;어쩔 수 없는 현실&#39;임과 동시에 우리가 이를 자각하고 경계할 필요가 있다고 말하는 것 같았다.</p>
<p>다른 하나는 디지털 소외계층에 관한 이야기이다. 디지털 소외계층은 일전에 포스트로 한번 다룬 적이 있다. <a href="https://algorithmknow.tistory.com/53"><strong>#링크</strong></a> 4장 &#39;사라짐으로써 안 보이게 되는 방법&#39;에는 불량 화소 되기, 필터에 걸린 스팸 되기, 무등록자 되기 등이 언급되는데, 이 장의 마지막에는 &#39;디지털 혁명 시대에 17만 명이 사라진다.&#39;라는 말이 덧붙여진다. 이는 말 그대로 타의로 사라지는 사람들을 의미하기도 하지만, 모든 것이 데이터로 구성되는 세상에서 기술 이용에 소외되는 사람들을 의미한다는 생각이 들었다. 국가 데이터에 포함되지 않으면 국가의 사람이 아니게 되고, 바뀐 기술에 적응하지 못하면 일상적으로 하던 일조차 어려움을 겪고, 특정 인터넷 사이트 이용자에 포함되지 않으면 그곳에 자신의 정보가 떠돌아다녀도 그 사실조차 모르듯이 말이다.</p>
<h2 id="2-hell-yeah-we-fuck-die-2016">2.&lt; Hell Yeah We Fuck Die&gt;, 2016</h2>
<p><img src="https://velog.velcdn.com/images/fma_/post/4f81dc3a-8f17-493a-bd37-0f0898b79cb1/image.jpeg" alt="">
<img src="https://velog.velcdn.com/images/fma_/post/7378349e-4233-4ae6-afbf-f6dc5b380b56/image.jpeg" alt=""></p>
<p><Hell Yeah We Fuck Die>는 2010년부터 5년동안 빌보드 차트 노래 제목에서 가장 많이 사용된 영어 단어를 제목으로 하는 총 3채널 영상 작품이다. 하나는 재난 현장에 인명 구조를 위해 투입될 휴머노이드 로봇이 끊임없이 발길질을 당하며 균형 훈련을 받고 있는 장면, 그리고 세대를 거듭할수록 진화되는 걷기 유전 알고리즘 학습 과정이 나온다. 다른 영상은 전쟁으로 파괴된 쿠르드족 도시 디야르바르크를 비추며, 또다른 영상은 인명 구조 휴머노이드 로봇의 제작과정을 다룬다.</p>
<p>작가는 재난 로봇이 훈련을 받는 과정과 그 로봇으로 도움을 받고 기술에 의존하는 사람들을 병치함으로써 인륜적인 목적으로 만들어진 로봇 제작 과정의 반인륜적인 모습을 강조하고 싶었던 것 같다... 그러나 내가 마음 깊이 동의하는 사상은 아니기에 감명깊게 본 작품은 아니었다. 매정해 보일 수 있지만, 인간의 고통을 본땄을지라도 인간이 받아야 할 고통을 로봇이 대신 받음으로써 인간에게 향하는 고통을 줄여줄 수 있다면 좋은 일이 아닌가...? 라는 생각에 조금은 반발심도 들었다. 내게 아직 인권보다 우선되는 가치관은 없는 것 같다...</p>
<h2 id="3-경호원들guards-2012"><strong>3. &lt;경호원들(Guards)&gt;, 2012</strong></h2>
<blockquote>
<p>&lt;경호원들&gt;은 전쟁과 동떨어져 있다고 인식되어 온 미술관에서 전쟁을 역설적으로 언급한다. 미국 시카고 현대미술관에서 촬영된 이 작품은 군인과 경찰 및 군사시설에서 법을 집행하는 업무 경력이 있는 론 힉스와 마틴 휫필드라는 미술관 경호 요원과의 인터뷰를 중심으로 전개된다. 그들은 본인들이 경험한 교전 상황을 열띤 어조로 설명하며 미술관 안에서 총을 겨누는 자세를 취하는 등 전술의 제스처를 극적으로 재상연한다.</p>
</blockquote>
<p>사전에 안내책자를 읽을 때는 별 생각이 없었다가 함께 간 일행이 이쪽에 시선을 뺏기길래 옆에 서서 같이 봤는데, 보면 볼수록 생각이 많아지는 작품이었다. 작품의 주인공은 일전에 겪었던 교전 상황을 미술관을 배경으로 설명하며, 미술관 안에서 전술 제스쳐를 취하고 적을 물리치는 방법을 설명한다. 가장 기억에 남는 연출은 작품에서 교전 상황을 설명하는 내내 FPS게임에서 보일 법한 조준경의 시야처럼 사각형 격자무늬가 화면에 자리하고 있었다는 점이다. 이는 외부의 적으로부터 미술관을 보호하고자 하는 경호원의 의지를 나타내려는 것처럼 보였다.</p>
<p>히토 슈타이얼은 지속적으로 &#39;미술관은 전쟁처인가?&#39; 라는 질문을 던져왔다고 한다. 예술은 어떠한 방식으로든 작가의 가치관을 드러내기에, 미술관은 언제든 억압과 통제 하에 놓일 수 있다는 것이다. 나는 이를 보고 우리나라에서 일제 시대에 이루어진 문화 통제가 떠올랐다. 문화예술은 사람들의 저항정신을 상기하므로, 그러한 사상을 전파시키지 못하게 하기 위해 불온서적을 등록하는 등 문화를 통제한 것이다. 이렇게 우리나라의 역사와도 겹쳐보이고, 이 전시관에 있는 작품들도 사회현상에 대한 히토 슈타이얼의 가치관을 뚜렷하게 드러내주는 작품들이 많아 더 와닿았다. 지나친 예술만능주의는 물론 좋지 않겠지만, 개개인의 가치를 존속하기 위해 예술은 많은 사람에게 공유되고 유지될 수 있게끔 &#39;미술관을 지켜야&#39;한다는 생각이 들었고, 이를 위한 미술관 경호 요원들의 행적이 정말 가치있게 느껴졌다.</p>
<p>이러한 통제 속에서도 자신의 가치를 드러내기 위해 발버둥치는 것이 예술이라는 사실을 생각하면, 내가 예술에 매력을 느끼는 이유를 상기시켜주는 작품이었다.</p>
<h2 id="4-이것이-미래다this-is-the-future-2019"><strong>4. &lt;이것이 미래다(This is the Future)&gt;, 2019</strong></h2>
<p><img src="https://velog.velcdn.com/images/fma_/post/bdd6b511-7782-42ad-99e9-c947b3cc4a98/image.jpeg" alt=""></p>
<p>설명을 보자마자 꽂혀서 일행을 졸라서 보러 갔고, 그만큼 정말 감명깊게 보고 나온 작품이다! 이 후기는 이 작품을 위해 쓰고있는 거나 다름없다. 시간만 많았으면 세 번은 돌려봤을 것 같다.</p>
<p>&lt;이것이 미래다&gt;는 신경 네트워크와 인공지능이 예견한 미래에 대한 이야기이다.</p>
<p>나는 알고리즘에 관심을 가진 이래로 항상 예측 알고리즘과 인공지능에 관심이 많았고, 그것이 인간의 삶을 질을 높임으로써 더 나은 미래를 가져올 거라고 확신했다. 그러나 이 작품을 보면서 처음으로 내 머릿속에 이런 생각이 스쳤다. &#39;알고리즘은 항상 미래를 예측하는데, 그래서 그 미래는 대체 언제 현재로 다가오지?&#39;</p>
<p>이러한 생각은 항상 미래를 예측하고 대비하는 일에 관심을 가지면서도 과거를 돌아보고 예측이 얼마나 들어맞았는지 확인하는 일에는 소홀했던 내 태도를 반성하게 하면서도, 이조차도 무슨 의미가 있는지를 고민하게 만들었다. 작품에 등장하는 미래 정원의 식물들은 SNS 중독으로 뇌가 병든 사람을 치유하거나, 혐오와 선동에 둔감하게 하거나, 독재자를 독살하기도 하는 등의 마술적인 치유의 힘을 갖고 있다. 기술만능주의를 꼬집는 것이다. 주인공의 독백 중 &#39;네트워크는 내가 나의 정원을 찾을 거라고 예측한다.&#39;라는 대사에서 보이는 현재를 외면한 채 미래만을 예측하고 인간 개개인의 삶을 데이터로서 예측하여 조종하는 모습은 먼 과거 신화에 나오는 &#39;신탁&#39;의 모습을 연상케 한다. 미래를 대비하기 위해 발전하였을 기술이 오히려 미래의 가능성을 좁히고, 예측된 미래에 인류의 모습을 맞춰나가는 모습이다. 이런 기술의 발전이 사회에 허무주의를 전파시키는 게 아닌가 하는 생각도 들었다.</p>
<p>또한 중간중간 뜨는 &#39;경고 : 네트워크의 예측은 맞지 않을 수 있습니다&#39;라는 문구가 예측 알고리즘의 회의를 더해주는 것 같았다. 과거를 바탕으로 미래를 예측하고는 있지만, 항상 그 미래가 맞지 않을 가능성을 염두에 두면 미래 예측은 무슨 의미가 있는가? 라는 의문이다.</p>
<p>기술에 대한 깊은 이야기를 다룰수록 회의적인 면모만 보여주던 다른 작품과는 달리, &lt;이것이 미래다&gt;는 이 회의감을 일축하는 한 마디를 주인공의 입을 빌려 던져 준다.</p>
<p>&quot;미래가 무엇이든 간에 언제나 지금 여기서 시작하기 때문입니다. 이게 내가 말할 수 있는 전부입니다.&quot;</p>
<p>개인의 미래를 정하는 것은 예측 알고리즘도 인공지능도 아닌 개인이고, 과거에 쌓인 데이터가 아닌 현재의 결정이 미래에 더 많은 영향을 끼친다는 것이다. 이는 세상이 알고리즘에 매몰되고 능동적인 개인의 가치는 점점 줄어들지라도, 인간이 직접 그려가는 서사는 의미있고 아름답다는 사실을 보여준다고 생각한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Pandas] 데이터 프레임]]></title>
            <link>https://velog.io/@fma_/Pandas-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%94%84%EB%A0%88%EC%9E%84</link>
            <guid>https://velog.io/@fma_/Pandas-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%94%84%EB%A0%88%EC%9E%84</guid>
            <pubDate>Sun, 15 Dec 2024 05:07:06 GMT</pubDate>
            <description><![CDATA[<h2 id="1-데이터-프레임이란"><strong>1. 데이터 프레임이란?</strong></h2>
<p><strong><code>데이터 프레임</code></strong> : 데이터를 다룰 때 가장 많이 사용하는 데이터 형태로, 행과 열로 구성된 사각형 모양의 표처럼 생겼다.</p>
<p><strong><code>열</code></strong> : 속성을 나타냄, 세로로 나열</p>
<p><strong><code>행</code></strong> : 각 사람(도시, 거래 내역 등)의 정보를 나타냄. 가로로 나열</p>
<table>
<thead>
<tr>
<th></th>
<th>1열</th>
<th>2열</th>
<th>3열</th>
<th>4열</th>
</tr>
</thead>
<tbody><tr>
<td>1행</td>
<td>성별</td>
<td>연령</td>
<td>학점</td>
<td>연봉</td>
</tr>
<tr>
<td>2행</td>
<td>남자</td>
<td>26</td>
<td>3.8</td>
<td>2,700만원</td>
</tr>
<tr>
<td>3행</td>
<td>여자</td>
<td>42</td>
<td>4.2</td>
<td>4,000만원</td>
</tr>
<tr>
<td>4행</td>
<td>남자</td>
<td>35</td>
<td>2.6</td>
<td>3,500만원</td>
</tr>
</tbody></table>
<ul>
<li>행이 많아지는 것보다 열이 많아지는 게 더 중요 - 열이 많아지면 변수를 조합할 수 있는 경우의 수가 늘어나기 때문</li>
</ul>
<h2 id="2-데이터-프레임-만들기"><strong>2. 데이터 프레임 만들기</strong></h2>
<h3 id="2-1-데이터-프레임-만들기"><strong>2-1. 데이터 프레임 만들기</strong></h3>
<p>pandas 패키지의 DataFrame() 을 이용한다.</p>
<pre><code class="language-python">import pandas as pd
df = pd.DataFrame({&#39;name&#39; : [&#39;윤이수&#39;, &#39;김민지&#39;, &#39;이유정&#39;, &#39;김민수&#39;],
                   &#39;english&#39; : [90, 80, 70, 60],
                   &#39;math&#39; : [50, 60, 70, 80]})
df</code></pre>
<p><img src="https://velog.velcdn.com/images/fma_/post/73fe7930-1244-44b8-a86f-d415089398aa/image.png" alt=""></p>
<h3 id="2-2-데이터-프레임으로-분석하기"><strong>2-2. 데이터 프레임으로 분석하기</strong></h3>
<p>특정 변수의 값 추출하기</p>
<pre><code class="language-jsx">df[&#39;english&#39;] #영어점수만 출력하기</code></pre>
<blockquote>
<p>0    90
1    80
2    70
3    60
Name: english, dtype: int64</p>
</blockquote>
<p>변수의 값으로 합계 구하기</p>
<pre><code class="language-jsx">sum(df[&#39;english&#39;]) #영어점수 합계 출력하기</code></pre>
<blockquote>
<p>300</p>
</blockquote>
<p>변수의 값으로 평균 구하기</p>
<pre><code class="language-python">sum(df[&#39;english&#39;]) / len(df)#영어점수 평균</code></pre>
<blockquote>
<p>75.0</p>
</blockquote>
<h2 id="3-외부-데이터-사용하기"><strong>3. 외부 데이터 사용하기</strong></h2>
<p>실습을 위해 Do it! 쉽게 배우는 파이썬 데이터 분석의 실습 데이터를 사용한다.</p>
<h3 id="3-1-엑셀-불러오기"><strong>3-1. 엑셀 불러오기</strong></h3>
<p>pandas의 read_excel()을 이용한다. 이때, 현재 사용중인 워킹 디렉터리에 불러올 파일이 있어야 한다.</p>
<pre><code class="language-jsx">df_exam = pd.read_excel(&#39;excel_exam.xlsx&#39;) #엑셀 파일을 불러와 df_exam에 할당
df_exam #출력</code></pre>
<p><img src="https://velog.velcdn.com/images/fma_/post/1acf6f00-73d2-4241-8181-eb3f71b88967/image.png" alt=""></p>
<p>만약 첫 번째 행이 변수명이 아닐 경우에는 read_excel()에 header = None을 입력한다.</p>
<pre><code class="language-python">df_exam_novar = pd.read_excel(&#39;excel_exam_novar.xlsx&#39;, header = None)
df_exam_novar</code></pre>
<p><img src="https://velog.velcdn.com/images/fma_/post/3966e78c-127e-4926-8e6b-1ff6a3e88d25/image.png" alt=""></p>
<p>엑셀 파일에 시트가 여러 개 있을 경우 : sheet_name 파라미터에 시트 이름 또는 숫자를 입력한다.</p>
<p>이때, 시트 숫자는 0부터 센다.</p>
<pre><code class="language-python"># Sheet2의 데이터 불러오기
df_exam = pd.read_excel(&#39;excel_exam.xlsx&#39;, sheet_name = &#39;Sheet2&#39;)
# 세 번째 시트의 데이터 불러오기
df_exam = pd.read_excel(&#39;excel_exam.xlsx&#39;, sheet_name = 2)</code></pre>
<h3 id="3-2-csv파일-불러오기"><strong>3-2. CSV파일 불러오기</strong></h3>
<p>CSV파일은 값이 쉼표로 구분된 형태의 범용 데이터이다.</p>
<p>pandas의 read_csv()를 이용해 불러올 수 있다.</p>
<pre><code class="language-python">df_csv_exam = pd.read_csv(&#39;exam.csv&#39;)
df_csv_exam</code></pre>
<p><img src="https://velog.velcdn.com/images/fma_/post/cc05e089-28a5-4134-8e20-2355fcff9b8b/image.png" alt=""></p>
<h3 id="3-3-데이터-프레임을-csv-파일로-저장하기"><strong>3-3. 데이터 프레임을 csv 파일로 저장하기</strong></h3>
<p>데이터 프레임을 csv 파일로 저장하면 파이썬 외에도 R, SPSS 등 데이터를 다루는 대다수의 프로그램에서 불러올 수 있다.</p>
<p><code>to_csv()</code>를 사용한다.</p>
<pre><code class="language-python">df.to_csv(&quot;output_df.csv&quot;)</code></pre>
<p>인덱스 번호를 제외하고 저장하려면 <code>index = False</code> 속성을 사용하면 된다.</p>
<pre><code class="language-python">df.to_csv(&quot;output_df.csv&quot;, index = False)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Pandas] 데이터 파악하기, 변수명 바꾸기]]></title>
            <link>https://velog.io/@fma_/Pandas-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%8C%8C%EC%95%85%ED%95%98%EA%B8%B0-%EB%B3%80%EC%88%98%EB%AA%85-%EB%B0%94%EA%BE%B8%EA%B8%B0</link>
            <guid>https://velog.io/@fma_/Pandas-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%8C%8C%EC%95%85%ED%95%98%EA%B8%B0-%EB%B3%80%EC%88%98%EB%AA%85-%EB%B0%94%EA%BE%B8%EA%B8%B0</guid>
            <pubDate>Sun, 15 Dec 2024 05:03:57 GMT</pubDate>
            <description><![CDATA[<h1 id="1-데이터-파악하기"><strong>1. 데이터 파악하기</strong></h1>
<p>데이터 파악에는 기본적으로 다음의 여섯 가지 명령어를 사용한다.</p>
<table>
<thead>
<tr>
<th>함수</th>
<th>기능</th>
</tr>
</thead>
<tbody><tr>
<td>head()</td>
<td>앞부분 출력</td>
</tr>
<tr>
<td>tail()</td>
<td>뒷부분 출력</td>
</tr>
<tr>
<td>shape</td>
<td>행, 열 개수 출력</td>
</tr>
<tr>
<td>info()</td>
<td>변수 속성 출력</td>
</tr>
<tr>
<td>describe()</td>
<td>요약 통계량 출력</td>
</tr>
</tbody></table>
<p>예제를 위해 mpg(mile per gallon) 데이터를 사용한다. mpg는 미국 환경 보호국에서 공개한 데이터로, 1999~2008년 미국에 출시된 자동차 234종의 정보를 담고 있다.</p>
<pre><code class="language-python">import pandas as pd
mpg = pd.read_csv(&#39;./Doit_Python-main/Data/mpg.csv&#39;)</code></pre>
<p>head(), tail()을 통해 데이터의 형태를 확인한다. 기본 5행을 출력하며, 괄호 안에 숫자를 넣으면 입력한 숫자만큼의 행을 출력한다.</p>
<pre><code class="language-python">mpg.head()
mpg.tail()</code></pre>
<p><img src="https://velog.velcdn.com/images/fma_/post/4627d082-7b64-49d3-9463-cd834d90e304/image.png" alt=""></p>
<p><code>shape</code> : 데이터 프래임의 행, 열 개수를 출력한다.</p>
<pre><code class="language-python">mpg.shape</code></pre>
<ul>
<li>shape는 함수가 아니라 데이터 프레임이 갖고 있는 속성인 어트리뷰트이므로 명령어 뒤에 괄호를 입력하지 않는다</li>
</ul>
<p><img src="https://velog.velcdn.com/images/fma_/post/7a22cc89-c4b3-485c-8222-adcf42ea752f/image.png" alt=""></p>
<p><code>info()</code> 를 통해 변수 속성을 파악한다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/227f1886-56c3-4efc-8c8c-fc20bfbacdc4/image.png" alt=""></p>
<p>(1) pandas.core.frame.Dataframe을 보면 mpg가 pandas로 만든 데이터 프레임이라는 것을 알 수 있다.</p>
<p>(2) 234행으로 되어 있고, 행 번호가 0부터 233까지라는 것을 알 수 있다.</p>
<p>(3) pmg가 변수 11개로 구성되어 있다는 것을 알 수 있다.</p>
<p>(4) 데이터 프레임에 들어있는 변수들의 속성이 표시된다. 각 행에 변수 순서(#) , 이름(Column), 변수에 들어있는 값의 개수(non-null), 속성(Dtype)을 보여 준다. 예를 들어, 2행의 displ은 234개의 값이 있고 실수(float64)이다.</p>
<p><code>describe()</code>를 통해 요약 통계량을 구한다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/3aed3c44-0ae2-45ef-8ee2-0c2e65a65d7d/image.png" alt=""></p>
<p>출력되는 통계량은 다음의 의미를 갖는다.</p>
<table>
<thead>
<tr>
<th>출력값</th>
<th>통계량</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>count</td>
<td>빈도(frequency)</td>
<td>값의 개수</td>
</tr>
<tr>
<td>mean</td>
<td>평균(mean)</td>
<td>모든 값을 더해 값의 개수로 나눈 값</td>
</tr>
<tr>
<td>std</td>
<td>표준편차(standard deviation)</td>
<td>변수의 값들이 평균에서 떨어진 정도를 나타낸 값</td>
</tr>
<tr>
<td>min</td>
<td>최소값(minimum)</td>
<td>가장 작은 값</td>
</tr>
<tr>
<td>25%</td>
<td>1사분위수(1st quantile)</td>
<td>하위 25%(4분의 1)지점에 위치한 값</td>
</tr>
<tr>
<td>50%</td>
<td>중앙값(median)</td>
<td>하위 50%(중앙) 지점에 위치한 값</td>
</tr>
<tr>
<td>75%</td>
<td>3사분위수(3rd quantile)</td>
<td>하위 75%(4분의 3)지점에 위치한 값</td>
</tr>
<tr>
<td>max</td>
<td>최대값(maximum)</td>
<td>가장 큰 값</td>
</tr>
</tbody></table>
<h2 id="2-변수명-바꾸기"><strong>2. 변수명 바꾸기</strong></h2>
<p>변수명을 바꾸기 전, 먼저 copy()를 사용해 데이터 프레임의 복사본을 작성한다.</p>
<pre><code class="language-jsx">mpg_new = mpg.copy()</code></pre>
<p><code>rename()</code>을 통해 변수명을 수정할 수 있다. columns 파라미터를 추가한 다음, {&#39;기존 변수명&#39; : &#39;새 변수명&#39;}을 입력하면 된다.</p>
<pre><code class="language-jsx">mpg_new = mpg_new.rename(columns = {&#39;cty&#39; : &#39;city&#39;})
mpg_new = mpg_new.rename(columns = {&#39;hwy&#39; : &#39;highway&#39;})</code></pre>
<p>변수명 cty가 city로, hwy가 highway로 변경된 것을 확인할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/ac2c887a-8310-42ad-b3d0-baa987127b6d/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Pandas] 데이터 분석 기초 - 데이터 파악하기, 다루기 쉽게 수정하기 예제]]></title>
            <link>https://velog.io/@fma_/Pandas-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D-%EA%B8%B0%EC%B4%88-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%8C%8C%EC%95%85%ED%95%98%EA%B8%B0-%EB%8B%A4%EB%A3%A8%EA%B8%B0-%EC%89%BD%EA%B2%8C-%EC%88%98%EC%A0%95%ED%95%98%EA%B8%B0-%EC%98%88%EC%A0%9C</link>
            <guid>https://velog.io/@fma_/Pandas-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D-%EA%B8%B0%EC%B4%88-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%8C%8C%EC%95%85%ED%95%98%EA%B8%B0-%EB%8B%A4%EB%A3%A8%EA%B8%B0-%EC%89%BD%EA%B2%8C-%EC%88%98%EC%A0%95%ED%95%98%EA%B8%B0-%EC%98%88%EC%A0%9C</guid>
            <pubDate>Sun, 15 Dec 2024 05:02:02 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><code>midwest.csv</code>는 미국 동북중부(East North Central States) 437개 지역의 인구통계 정보를 담고 있다. <code>midwest.csv</code>를 이용해 데이터 분석 문제를 해결하시오.</p>
</blockquote>
<h1 id="문제1">문제1</h1>
<p><code>midwest.csv</code>를 불러와 데이터의 특징 파악하기</p>
<pre><code class="language-jsx">import pandas as pd
mw = pd.read_csv(&#39;./Doit_Python-main/Data/midwest.csv&#39;)</code></pre>
<p>head(), tail(), shape, info(), describe()를 통해 대략적인 데이터의 특징을 파악한다.</p>
<pre><code class="language-jsx">mw.head() #앞에서부터 5행 출력</code></pre>
<p><img src="https://velog.velcdn.com/images/fma_/post/bc85ad2d-7904-4e63-be33-216bbac5930f/image.png" alt=""></p>
<pre><code class="language-jsx">mw.tail() #뒤에서부터 5행 출력</code></pre>
<p><img src="https://velog.velcdn.com/images/fma_/post/39b01c4b-9788-4b0c-86b2-2fc5b9ee9a92/image.png" alt=""></p>
<pre><code class="language-jsx">mw.shape</code></pre>
<blockquote>
<p>(437, 28)</p>
</blockquote>
<pre><code class="language-jsx">mw.info() #변수의 속성 파악</code></pre>
<p><img src="https://velog.velcdn.com/images/fma_/post/e881aec9-69ba-472e-8b78-504c414fc704/image.png" alt=""></p>
<p>위 분석결과를 통해 다음과 같은 사실을 알 수 있다.</p>
<ol>
<li>midwest는 pandas로 만든 데이터 프레임이다.</li>
<li>437행으로 이루어져 있으며, 행번호는 0부터 436이다.</li>
<li>총 28열이며, 정수(int)와 실수(float), 문자(object)로 구성된다.</li>
</ol>
<pre><code class="language-jsx">mw.describe() #요약 통계량 구하기</code></pre>
<p><img src="https://velog.velcdn.com/images/fma_/post/f1e36a75-263d-4aaf-8dc1-6b447f755b65/image.png" alt=""></p>
<h2 id="문제2">문제2</h2>
<p><code>poptotal</code>(전체 인구) 변수를 <code>total</code>로, <code>popasian</code>(아시아 인구) 변수를 <code>asian</code>으로 수정하기</p>
<pre><code class="language-jsx">mw_new = mw.copy() #복사본 만들기
mw_new.head()</code></pre>
<p><img src="https://velog.velcdn.com/images/fma_/post/9de3b5aa-a5f0-4fdc-aff6-752a4737291d/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[북리뷰] 기술발전의 K-속도 :: <K속도 한국 경쟁력의 뿌리>]]></title>
            <link>https://velog.io/@fma_/%EB%B6%81%EB%A6%AC%EB%B7%B0-%EA%B8%B0%EC%88%A0%EB%B0%9C%EC%A0%84%EC%9D%98-K-%EC%86%8D%EB%8F%84-K%EC%86%8D%EB%8F%84-%ED%95%9C%EA%B5%AD-%EA%B2%BD%EC%9F%81%EB%A0%A5%EC%9D%98-%EB%BF%8C%EB%A6%AC</link>
            <guid>https://velog.io/@fma_/%EB%B6%81%EB%A6%AC%EB%B7%B0-%EA%B8%B0%EC%88%A0%EB%B0%9C%EC%A0%84%EC%9D%98-K-%EC%86%8D%EB%8F%84-K%EC%86%8D%EB%8F%84-%ED%95%9C%EA%B5%AD-%EA%B2%BD%EC%9F%81%EB%A0%A5%EC%9D%98-%EB%BF%8C%EB%A6%AC</guid>
            <pubDate>Thu, 20 Jun 2024 03:50:06 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>[2022 가을맞이 독후감 공모전 최우수상 수상작]</strong></p>
</blockquote>
<h2 id="한국인의-강점--k-속도"><strong>한국인의 강점 : K-속도</strong></h2>
<p>한국인을 흔히 &#39;빨리빨리의 민족&#39;이라고 부른다. 빠른 속도는 당장 우리의 일상생활 곳곳에 녹아 있다. 제자리에 앉아 택배 주문 한 번만 하면 다음날 아침에 눈을 뜨기 전에 물건이 집 앞으로 도착해 있고, 배달 앱 클릭 몇 번이면 한 시간도 안 되어 음식을 바로 앞으로 받아볼 수 있으며, 스마트폰을 몇 번 두드리면 몇 분만에 당장 필요한 자료와 기사를 찾아낼 수 있다. 그뿐이랴, 와이파이 두 칸이 답답해 연결을 몇 번이고 다시 하고, 웹브라우저가 로딩되는 몇 초가 답답해 몇 번이고 새로고침을 누른다. 한국인만큼 속도를 중시하고, 전 국민이 속도에 &#39;집착&#39;하는 나라는 세상에 없다시피 하다. 그렇게 &#39;빨리빨리&#39;는 우리 민족을 나타내는 대명사가 되었다.</p>
<p>그 덕에 예나 지금을 불문한 세계의 치열한 경쟁상태 속에서, 한국은 매우 특별한 위치를 차지하게 되었다. 전쟁 이후 세계 최빈곤 국가에서 30여 년 만에 산업화와 민주화를 동시에 달성했으며, 앞선 그룹들을 차례로 추월하여 세계 최선두 그룹에 가까운 정도까지 도달하였다. 이 책은 한국의 이러한 급격한 성장의 원동력을 &#39;빨리빨리의 민족&#39;의 특성, 즉, &#39;속도&#39;라고 평한다. 우리나라 국민 개개인의 의지와 경쟁력, 성취동기와 신분상승 욕구, 특히 속도감 있는 능력은 다른 민족에 비해 탁월하다. 경쟁력은 남보다 잘할 수 있는 것을 열심히 할 때에 나오기에, <strong>한국이 확실히 잘할 수 있고 지금도 잘하는 것은 모든 면에서의 &#39;빠름&#39;이라는 것이다.</strong></p>
<blockquote>
<p>예나 지금이나, 어른이나 아이든, 또 기업이고 조직이고 간에 가장 확실히 성공할 수 있는 길은 자기가 제일 잘 할 수 있는 것을 발견해서 그것을 제대로, 열심히 하는 것이다. 예외가 있을 수 없다. 동시에 이 세상의 어떤 일이나 어느 부문에도 좋은 면만 있는 것이 아니고 부정적이거나 위험한 면 등의 반대 측면도 같이 존재한다. 그래서 세상은 공평한 것이다.</p>
</blockquote>
<h2 id="과학기술에서-속도의-중요성"><strong>과학기술에서 속도의 중요성</strong></h2>
<p>컴퓨터공학, 그중에서도 인공지능을 공부하던 내게 이러한 시각은 도리어 큰 충격으로 다가왔다. 경제학에 그다지 관심이 없던 내가 &#39;속도&#39;라는 단어 하나만으로 이 책을 집어 든 이유도 그것이다. 인류 발전의 핵심기술이라고 불리어오는 인공지능임에도, 그에 관해 내가 읽어온 기술 관련 서적과 칼럼에서 &#39;속도&#39;는 대체로 부정적인 단어로 등장했다. 기술 발전의 속도는 인간이 제어하지 못할 만큼 빠르며, 과학의 비약적인 발전을 두려워하는 사람들은 인공지능이 인간의 지능을 뛰어넘는 시점인 &#39;특이점&#39;이 머지않았다며 일찍이 두려워하고는 한다. 기술 발전의 속도에 비해 사회규범은 이를 따라잡지 못하며 그로 인한 윤리∙도덕적인 부작용을 고려해야 한다는 내용으로 끝을 맺고는 했다. 당연히 공학자로서 가져야 할 마음가짐이며, 마음 깊이 동의하는 바이다. 이 책에서도 이러한 속도의 부작용을 결코 간과하고 있지 않다. 도리어 너무 빠른 속도의 부작용을 직시하며, 그것을 보완하는 방향을 물색해야 한다는 것을 강조한다. 그러나 이 책이 과학기술계에서 금기시되던 속도에 대한 예찬을 다시 입에 올리고 &#39;속도&#39;와 &#39;발전&#39;의 상관성을 직설적으로 강조함으로써 속도의 중요성을 다시금 우리 눈앞에 일깨워주었다는 사실만은 자명하다. <strong>우리는 &#39;속도&#39;가 우리가 발전된 기술을 당연하다는 듯 가까이할 수 있는 이유이자, 더 높은 수준의 기술에 의한 질 높은 삶을 위한 발전의 원천이라는 사실을 잠시 잊고 있었던 거다.</strong></p>
<h2 id="코로나19와-기술-적용"><strong>코로나19와 기술 적용</strong></h2>
<p>이 책에서 인상깊었던 부분 중 하나는 K속도의 방향성을 결정짓는 요인 중 하나로 최근에 전 세계를 휩쓸었던 팬데믹 현상을 꼽았다는 것이다. 코로나19는 경제, 사회를 비롯한 대부분의 측면에서 보았을 때, 발전의 가속도를 저해하고 앞만 보고 달려 나가던 발전 과정에 브레이크를 걸어준 큰 사건이다. 그러나 기술적인 측면에서 본다면 조금 이야기가 달라진다. 기술은 특히 발전과 실제 제도적 적용 간의 간극이 큰 분야였는데, 코로나19는 다양한 가능성만을 염두에 두고 발전해나간 기술을 실제 삶에 적용할 수 있는 큰 기회였다. 특히 언택트(Untact) 기술이 그렇다. 스마트폰과 인터넷의 발달로 우리는 일찍이 시간과 공간에 상관없이 사람과 대화를 주고받고 정보를 나눌 수 있게 되었지만, 그것이 피부에 와닿을 정도로 확대된 것은 코로나19 이후이다. 팬데믹이 시작된 지 2년 남짓이 지난 지금, 우리는 자연스럽게 Google meet를 켜서 직접 만나지 않고도 회의와 업무를 하며, Zoom으로 수업을 하고, 음식점이나 영화관에 가면 직원 대신 키오스크로 주문을 하는 것이 자연스러워졌다. 뿐만 아니라 메타버스 공간에서 실제 사람을 만나듯 아바타를 만나고, 인터넷으로 이어진 인연으로 관계를 발전시키는 것도 이제 이상하지 않은 일이 되었다. 이는 공통적으로 사람들이 시간과 공간을 초월해 일상생활을 영위하고, 일과 생활의 양가적인 측면에서 모두 삶의 질을 높여주는 행위이다. 기술이 발전의 속도를 비약적으로 높여주는 요소라는 사실은 다시금 증명된 셈이다.</p>
<blockquote>
<p>기술 발전과 실제 그 제도적 적용은 때로는 일치하지 않는다. 기술의 관점에서 인류 역사 이래 지속된 지식 습득과 전파 방법이 근본적으로 달라질 수밖에 없는 시대를 맞이하였으나 실제로 그 변화를 수용하고 적용하면서 생활하는 것은 다른 차원이었다. 결코 쉽지 않은 이 과제를 실제로 경험해 보면서 보편적으로 느끼게 되는 계기가 2020 코로나 전염병 사태로 앞당겨지게 되었다. 어떤 제도나 관행의 변화가 시행착오를 거쳐 한 나라나 전 세계에 정착되는 과정은 어렵고 긴 과정일 수밖에 없는데 코로나 사태가 경험과 실행을 한 번에 앞당길 수 있게 만들었다.</p>
</blockquote>
<h2 id="k-속도의-방향성"><strong>K-속도의 방향성</strong></h2>
<p>이렇듯 한국이 걸어온 30년간의 급격한 발전을 보며, 기술발전에서의 &#39;속력&#39;의 중요성이 검증되었다. 하지만 <strong>&#39;속도&#39;는 속력과 방향이 합쳐진 개념이다. 즉, 방향성 또한 발전에 지대한 영향을 끼친다는 것이다.</strong> 특히 비약적인 발전으로 인해 발전의 속력이 느려진 지금은 겨우 그렇다. 이에 대해 이 책에서는 &#39;시스템&#39;을 강조한다. 경제발전은 혁신과정으로 설명할 수 있는데, 경제성장의 세 가지 주요 요소인 자본, 노동, 기술 중 기술 없이는 나머지 두 가지는 제대로 효용을 발휘할 수 없으므로 기술의 변화를 곧 혁신으로 정의하기도 한다. 그러한 기술의 발전은 해가 지날수록 더 새로운 변화를 요구하며, 그렇기에 속도를 더 높이게 만들거나 빠름을 인정받게 하는 것은 사람이 만든 방법이나 시스템에 의한 것이다.</p>
<p>작가는 이를 이와 같은 인용문을 통해 이야기한다. &quot;디지털 기술이 아톰의 세계에 스며든 지 10여년만에 기술을 쓰는 주체가 사람이며 그들이 대단히 다양한 존재라는 인식이 생기기 시작한 것이다. 그래서 스마트 시대는 속도의 시대가 아니라 창의성의 시대다... 그동안 한국은 근면과 속도로 지금의 자리에 올랐다. 한 방향으로 빠르게 진화할 테니 열심히 투자하라고 했다. 하지만 그런 시대는 서서히 끝나가고 있다.&quot; 기술의 발전은 더 큰 도약(퀀텀 점프)을 야기하고 이 기술을 사용하는 주체가 사람임을 기억해야 한다. 즉, <strong>인간이 인간을 위한 기술을 만들 때 성장할 수 있다.</strong> 인간은 더 빠르고 편리한 기술을 선호하기도 하지만, 그와 동시에 믿을 수 있고, 안전하고, 정직한 기술을 누리고 싶어한다. 이제는 발전을 빠름으로만 판단할 수 없다는 것이다. <strong>한국인의 고유한 특성인 &#39;속력&#39;을 손상하지 않으면서 인간이 원하는 기술로 나아가는 것. 그것이 우리나라의 발전이 나아가야 할 &#39;방향&#39;이다.</strong></p>
<p><img src="https://velog.velcdn.com/images/fma_/post/84756660-9ab6-430a-9bb6-c50ee9b919c8/image.jpeg" alt=""><img src="https://velog.velcdn.com/images/fma_/post/657e95d2-427e-4141-897d-541260758d6b/image.jpeg" alt=""></p>
<p><a href="https://search.shopping.naver.com/book/catalog/32466561883">도서 정보 바로가기</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Web] 나만의 질의응답 사이트 만들기]]></title>
            <link>https://velog.io/@fma_/Web-%EB%82%98%EB%A7%8C%EC%9D%98-%EC%A7%88%EC%9D%98%EC%9D%91%EB%8B%B5-%EC%82%AC%EC%9D%B4%ED%8A%B8-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@fma_/Web-%EB%82%98%EB%A7%8C%EC%9D%98-%EC%A7%88%EC%9D%98%EC%9D%91%EB%8B%B5-%EC%82%AC%EC%9D%B4%ED%8A%B8-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Sat, 30 Mar 2024 08:32:09 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>2022년 9월 작업물입니다.</p>
</blockquote>
<p>부트캠프 과제로 &#39;나만의 질의응답 사이트 만들기&#39;를 진행했다.</p>
<p>과제를 진행했던 과정과 어려웠던 점, 그리고 그걸 해결해나간 과정을 백업해보고자 한다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/47e34d1c-8ca2-40c2-9f8c-56ae3d558335/image.png" alt=""></p>
<p>배포 링크 : <a href="https://fmapark.github.io/fe-sprint-my-agora-states/">https://fmapark.github.io/fe-sprint-my-agora-states/</a></p>
<h2 id="1-mock-up"><strong>1. Mock-up</strong></h2>
<h3 id="1-1-전체적인-구조-짜기">1-1. 전체적인 구조 짜기</h3>
<p>부트캠프에서 제공한 가이드를 따라 아고라 스테이츠(부트캠프의 질의응답 사이트)의 구조와 부트캠프에서 제공해준 코드를 참고하여 전체적인 웹페이지의 구상도를 그려보았다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/a1cbb2eb-e38e-45ed-98be-d447803429fd/image.png" alt=""></p>
<p>전체적으로는 질문을 입력하는 부분과 입력된 질문을 출력하는 부분의 두 섹션으로 나누어 구상하였다.</p>
<p>질문을 입력받는 부분은 모두 줄바꿈이 일어나므로 block 엘리먼트 중 하나인 <code>&lt;div&gt;</code>를 활용하고, 출력 부분은 질문의 개수에 따라 유동적으로 늘어나는 형태이므로 <code>&lt;ul&gt; &lt;li&gt;</code>를 활용하기로 결정했다.</p>
<p>각 섹션을 감싸는 클래스 이름도 미리 지정해두었으나, 이 부분은 막상 html으로 구현해보니 조금 바뀌었다. (head와 body 부분을 나누어주어야 하고, 섹션 부분의 태그를 따로 지정해주어야 한다는 사실을 간과했다.)</p>
<h3 id="1-2-컴포넌트-구성하기">1-2. 컴포넌트 구성하기</h3>
<p>위의 구상도를 바탕으로 html을 작성했다.</p>
<p>index.html</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;

&lt;head&gt;
  &lt;meta charset=&quot;UTF-8&quot;&gt;
  &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
  &lt;title&gt;My Agora States&lt;/title&gt;
&lt;/head&gt;

&lt;body&gt;
  &lt;main&gt;
    &lt;h1&gt;My Agora States&lt;/h1&gt;
    &lt;section class=&quot;form__container&quot;&gt;
      &lt;form action=&quot;&quot; method=&quot;get&quot; class=&quot;form&quot;&gt;
        &lt;div class=&quot;form__input--wrapper&quot;&gt;
          &lt;div class=&quot;form__input--name&quot;&gt;
            &lt;label for=&quot;name&quot;&gt;이름: &lt;/label&gt;
            &lt;input type=&quot;text&quot; name=&quot;name&quot; id=&quot;name&quot; required&gt;
          &lt;/div&gt;
          &lt;div class=&quot;form__input--title&quot;&gt;
            &lt;label for=&quot;name&quot;&gt;제목: &lt;/label&gt;
            &lt;input type=&quot;text&quot; name=&quot;name&quot; id=&quot;name&quot; required&gt;
          &lt;/div&gt;
          &lt;div class=&quot;form__textbox&quot;&gt;
            &lt;label for=&quot;story&quot;&gt;질문: &lt;/label&gt;
            &lt;textarea id=&quot;story&quot; name=&quot;story&quot; placeholder=&quot;질문을 작성하세요&quot; required&gt;&lt;/textarea&gt;
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&quot;form__submit&quot;&gt;
          &lt;input type=&quot;submit&quot; value=&quot;제출&quot;&gt;
        &lt;/div&gt;
      &lt;/form&gt;
    &lt;/section&gt;
    &lt;section class=&quot;discussion__wrapper&quot;&gt;
      &lt;ul class=&quot;discussions__container&quot;&gt;
        &lt;li class=&quot;discussion__container&quot;&gt;
          &lt;div class=&quot;discussion__avatar--wrapper&quot;&gt;
            &lt;img class=&quot;discussion__avatar--image&quot;
              src=&quot;https://avatars.githubusercontent.com/u/12145019?s=64&amp;u=5c97f25ee02d87898457e23c0e61b884241838e3&amp;v=4&quot;
              alt=&quot;avatar of kimploo&quot;&gt;
          &lt;/div&gt;
          &lt;div class=&quot;discussion__content&quot;&gt;
            &lt;h2 class=&quot;discussion__title&quot;&gt;&lt;a href=&quot;https://github.com/codestates-seb/agora-states-fe/discussions/6&quot;&gt;[notice] 좋은 질문하는 법&lt;/a&gt;&lt;/h2&gt;
            &lt;div class=&quot;discussion__information&quot;&gt;kimploo / 2022-04-22T14:08:33Z&lt;/div&gt;
          &lt;/div&gt;
          &lt;div class=&quot;discussion__answered&quot;&gt;&lt;p&gt;☑&lt;/p&gt;&lt;/div&gt;
        &lt;/li&gt;
      &lt;/ul&gt;
    &lt;/section&gt;
  &lt;/main&gt;
&lt;/body&gt;

&lt;/html&gt;</code></pre>
<p>아직 css를 아무것도 입히지 않았으므로 아래와 같은 형태가 나왔다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/a311f64e-972d-4e4e-9770-18a49774e5b8/image.png" alt=""></p>
<h2 id="2-기능-구현하기">2. 기능 구현하기</h2>
<p>너무너무 못생긴 모습에 css를 먼저 입힐까 잠깐 고민했지만 꾹 참고 기능부터 구현했다.</p>
<p>부트캠프 측에서 함수명과 기본 구조, 그리고 답변 데이터셋은 제공해주어, 이를 이해하는 것을 우선으로 한 뒤 내가 추가해서 구현할 부분이 무엇인지 생각해보았다.</p>
<p>일단 최소한의 질의응답 사이트 구현을 위해 필요한 기능은 이름과 제목, 질문을 입력했을 때 해당 질의응답을 화면에 출력하는 것이라고 생각했다.</p>
<p>이를 위해 추가해야 할 부분은 다음과 같았다.</p>
<ul>
<li>데이터를 DOM형식으로 바꿔주기</li>
<li>이벤트리스너 함수 작성 -&gt; &#39;제출&#39; 버튼을 누르면 질의응답이 추가되도록 함</li>
<li>추가된 질의응답을 데이터셋에도 추가</li>
</ul>
<p>이를 차례로 구현해보았다.</p>
<h3 id="2-1-데이터를-dom형식으로-바꿔주기"><strong>2-1. 데이터를 DOM형식으로 바꿔주기</strong></h3>
<p>script.js</p>
<pre><code class="language-jsx">const convertToDiscussion = (obj) =&gt; { //매개변수로 객체 받기
  const li = document.createElement(&quot;li&quot;); // li 요소 생성
  li.className = &quot;discussion__container&quot;; // 클래스 이름 지정

  //html element를 DOM형식으로 바꿀 수 있게 받아오기
  const avatarWrapper = document.createElement(&quot;div&quot;);
  avatarWrapper.className = &quot;discussion__avatar--wrapper&quot;;
  const discussionContent = document.createElement(&quot;div&quot;);
  discussionContent.className = &quot;discussion__content&quot;;
  const discussionAnswered = document.createElement(&quot;div&quot;);
  discussionAnswered.className = &quot;discussion__answered&quot;;

  //받아온 element를 DOM에 넣어주기

  //1. 아바타 영역
  const avatarImg = document.createElement(&quot;img&quot;);
  avatarImg.src = obj.avatarUrl;
  avatarImg.alt = &quot;avatar of &quot; + obj.author;
  avatarWrapper.append(avatarImg);

  //2. 콘텐츠 영역
  //2-1 제목
  const contentTitle = document.createElement(&#39;h2&#39;);
  const titleAnchor = document.createElement(&#39;a&#39;);
  contentTitle.className = &quot;discussion__title&quot;;
  titleAnchor.textContent = obj.title;
  titleAnchor.href = obj.url;

  contentTitle.append(titleAnchor);

  //2-2. 정보
  const contentInfo = document.createElement(&#39;div&#39;)
  contentInfo.textContent = `${obj.author} / ${new Date(obj.createdAt).toLocaleString()}` //날짜표기
  contentInfo.className = &quot;discussion__information&quot; 
  discussionContent.append(contentTitle, contentInfo);

  //3. 체크박스 영역
  const checked = document.createElement(&#39;p&#39;);
  discussionAnswered.append(checked);
  checked.textContent = obj.answer ? &quot;☑&quot; : &quot;☒&quot; //네모안에 엑스 있는 특수문자

  li.append(avatarWrapper, discussionContent, discussionAnswered);
  return li;
};</code></pre>
<p>아직 DOM 구조도 익숙지 않고 다른 사람의 코드를 기반으로 작성하는 것도 익숙지 않아 이곳에서 애를 많이 먹었다.</p>
<p>몇 번의 시도 끝에 &#39;element 받아오기 - DOM 구조로 변수 설정 - 변수를 통해 조작&#39; 이 세 단계를 차례로 거치면 조금 더 수월하다는 것을 알아내었고, 그 이후로는 큰 어려움 없이 진행할 수 있었다.</p>
<p>Date를 활용한 한국에 맞는 날짜 표기는 생각지 못한 부분이었지만 실시간 세션을 통해 추가할 수 있었다. 덕분에 가독성이 조금 더 깔끔해졌다.</p>
<h3 id="2-2-이벤트리스너-함수-작성"><strong>2-2. 이벤트리스너 함수 작성</strong></h3>
<p>script.js (일부 데이터가 삭제된 코드입니다.)</p>
<pre><code class="language-jsx">//이벤트 리스너
const form = document.querySelector(&#39;.form&#39;);
const author = document.querySelector(&#39;.form__input--name &gt; input&#39;);
const title = document.querySelector(&#39;.form__input--title &gt; input&#39;);
const textArea = document.querySelector(&#39;.form__textbox &gt; textarea&#39;)

form.addEventListener(&#39;submit&#39;, (event) =&gt; {
  event.preventDefault();
  // 객체를 하나 만든다
  const obj = {
    id: &quot;unique number&quot;,
    createdAt: new Date(), //앞에서 만들였던 날짜객체 불러오기 - &gt; 지금시간
    title: title.value,
    url: &quot;&quot;,
    author: author.value,
    answer: {
      id: &quot;&quot;,
      createdAt: &quot;2022-05-16T02:09:52Z&quot;,
      url: &quot;&quot;,
      author: &quot;Dyract&quot;,
      bodyHTML:
        &#39;&#39;
        avatarUrl: &quot;&quot;,
    },
    bodyHTML:
      &#39;&#39;
      avatarUrl:
      &quot;&quot;,
  }

  //제출 시 초기화
  title.value = &quot;&quot;;
  author.value = &quot;&quot;;
  textArea.value = &quot;&quot;;

})</code></pre>
<p>질의응답 데이터는 data.js라는 파일에 따로 저장되어 있다.</p>
<p>데이터셋 전체를 새로 설정하기에는 무리가 있어 기존에 제공되어 있는 데이터셋 객체 중 하나를 그대로 불러온 뒤, 입력값인 &#39;이름&#39;, &#39;제목&#39;, &#39;질문&#39;, 그리고 작성 시점을 나타내는 날짜만 수정하여 추가하는 방식으로 구현하였다.</p>
<p>질의응답 url과 답변까지 표시해주려면 추가적인 페이지 구현이 더 있어야 할 것 같다.</p>
<h3 id="2-3-데이터셋에-질의응답-추가"><strong>2-3. 데이터셋에 질의응답 추가</strong></h3>
<p>이벤트리스너 함수 안에 data.js의 객체에 unshift 해주는 부분만 추가해주었다.</p>
<p>위의 코드가 아래와 같이 변경되었다.</p>
<p>script.js (일부 데이터가 삭제된 코드입니다.)</p>
<pre><code class="language-jsx">//이벤트 리스너
const form = document.querySelector(&#39;.form&#39;);
const author = document.querySelector(&#39;.form__input--name &gt; input&#39;);
const title = document.querySelector(&#39;.form__input--title &gt; input&#39;);
const textArea = document.querySelector(&#39;.form__textbox &gt; textarea&#39;)

form.addEventListener(&#39;submit&#39;, (event) =&gt; {
  event.preventDefault();
  // 객체를 하나 만든다
  const obj = {
    id: &quot;unique number&quot;,
    createdAt: new Date(), //앞에서 만들였던 날짜객체 불러오기 - &gt; 지금시간
    title: title.value,
    url: &quot;&quot;,
    author: author.value,
    answer: {
      id: &quot;&quot;,
      createdAt: &quot;2022-05-16T02:09:52Z&quot;,
      url: &quot;&quot;,
      author: &quot;Dyract&quot;,
      bodyHTML:
        &#39;&#39;
        avatarUrl: &quot;&quot;,
    },
    bodyHTML:
      &#39;&#39;
      avatarUrl:
      &quot;&quot;,
  }
  //더미데이터에 작성한 데이터 추가
  agoraStatesDiscussions.unshift(obj);
  // 그 객체를 convertToDiscussion에 넣어서 DOM으로 변환
  // 그걸 또 render함수에 넣어서 브라우저에 렌더링 -&gt;  맨앞으로
  ul.prepend(convertToDiscussion(obj));

  //제출 시 초기화
  title.value = &quot;&quot;;
  author.value = &quot;&quot;;
  textArea.value = &quot;&quot;;

})</code></pre>
<p>데이터셋을 화면에 렌더링하는 부분은 제공받은 코드에도 작성되어 있어 따로 건드리지 않았다.</p>
<p>script.js</p>
<pre><code class="language-jsx">// agoraStatesDiscussions 배열의 모든 데이터를 화면에 렌더링하는 함수입니다.
const render = (element) =&gt; {
  // 더미데이터의 길이만큼, 더미데이터 안에 있는 모든 요소를 탐색
  for (let i = 0; i &lt; agoraStatesDiscussions.length; i += 1) {
    // i번째 요소를 convertToDiscussion에 전달해서 ul에 append
    element.append(convertToDiscussion(agoraStatesDiscussions[i]));
  }
  return;
};

// ul 요소에 agoraStatesDiscussions 배열의 모든 데이터를 화면에 렌더링합니다.
const ul = document.querySelector(&quot;ul.discussions__container&quot;);
render(ul);</code></pre>
<h2 id="3-css-작성">3. CSS 작성</h2>
<p><img src="https://velog.velcdn.com/images/fma_/post/2ffcf7ad-9b28-4987-88ff-6d15ac8426b6/image.png" alt=""></p>
<p>CSS를 덧씌워 처음 사진과 같은 디자인을 완성시켰다.</p>
<p>요즘 다크모드에 꽂혔기 때문에 검흰 베이스로 파스텔톤을 더하고, margin, padding 조정과 줄 추가를 통해 가독성을 높였다.</p>
<p>style.css</p>
<pre><code class="language-jsx">@import url(&#39;https://fonts.googleapis.com/css2?family=Do+Hyeon&amp;family=Jua&amp;display=swap&#39;);

* {
    margin : 0;
    padding : 0;
    box-sizing: border-box;
    font-family: &#39;Jua&#39;, sans-serif;
}

body {
    margin : 0;
    padding : 0;
    background-color: black;
    display: flex;
    justify-content: center;
    align-items: center;
}

main {
    width : 540px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

li {
    list-style: none;
}

h1 {
    color : white;
    font-family: Georgia, serif;
    margin-top: 1.5rem;
}

.form__input--wrapper input {
    width : 200px;
}

.form__input--wrapper textarea {
    width : 200px;
}

.form__container {
    margin-top: 2rem;
    margin-bottom: 2rem;
}

.form__input--wrapper &gt; div {
    padding: 0.6rem;
}

.form__submit {
    display: flex;
    align-items: center;
    justify-content: center;
    margin-top: 0.5rem;
}

.form__submit input {
    padding: 0.3rem 1.5rem;
    font-size: 17px;
    border-radius: 10px;
}

.form label {
    color : white;
    vertical-align : top;
    margin-right: 0.5rem;
}

.discussion__container {
    display: flex;
    width: 540px;
    justify-content: space-between;
    border-bottom: 1px solid white;
    margin-top: 1.5rem;
    padding-bottom: 1.5rem;
}

.discussion__avatar--wrapper &gt; img {
    border-radius: 50%;
    width : 48px
}

.discussion__avatar--wrapper {
    display:flex;
    justify-content: center;
    align-items: center;
    margin-right: 1rem;
}

.discussion__content {
    flex-grow: 1;
    display: flex;
    flex-direction: column;
    justify-content: space-around;
}

.discussion__title{
    margin-bottom: 0.5rem;
}

.discussion__title &gt; a {
    text-decoration: none;  
    font-size: 22px;
    color : #9b92ff;
}

.discussion__information {
    text-align: right;
    color: white;
}

.discussion__answered {
    display: flex;
    justify-content: center;
    align-self: center;
    font-size: xx-large;
    margin-left: 1.2rem;
    color : white;
}</code></pre>
<h2 id="깃허브-배포">깃허브 배포</h2>
<p>전체 코드는 아래 github 레포지토리에서 확인할 수 있다.</p>
<p><a href="https://github.com/fmaPark/fe-sprint-my-agora-states">https://github.com/fmaPark/fe-sprint-my-agora-states</a></p>
<p>배포 링크 : <a href="https://fmapark.github.io/fe-sprint-my-agora-states/">https://fmapark.github.io/fe-sprint-my-agora-states/</a></p>
<h2 id="결론-및-피드백"><strong>결론 및 피드백</strong></h2>
<h3 id="배운-점"><strong>배운 점</strong></h3>
<ul>
<li>비교적 이해가 미흡했던 DOM구조를 직접 구현해보며 감을 잡을 수 있었다.</li>
<li>이전 과제에서는 css 속성을 어떤 걸 사용해야 할지 전혀 감을 잡지 못했지만, 지금은 머릿속에 있는 디자인을 어느정도 코드로 끌어낼 수 있게 되었다.</li>
</ul>
<h3 id="아쉬웠던-점"><strong>아쉬웠던 점</strong></h3>
<ul>
<li>html은 구조도를 통해 개요를 짠 상태로 개발해 수월하게 코드를 작성했던 반면, css는 내가 어떤 웹페이지를 만들고자 하는지 모르는 상태로 무작정 코드를 두들겨 완성에 어려움이 있었다.어휘의 부족이라고 생각한다. css를 통해 구현할 수 있는 부분에 어떤 것이 있는지 잘 모르는 상태로 개발을 시작했기 때문에 머릿속에 그려보는 데도 한계가 있었을 것이다. 예제를 통해 디자인적 요소의 공부가 더 필요할 것 같다.머릿속에만 웹사이트를 그려보았기 때문에 구체화가 힘들었다고 생각한다. html에 구조도를 그렸듯 눈에 보이는 디자인 구상을 해보아야겠다고 생각했다. (일종의 프로토타입의 필요성을 느낀 게 아닐까?)</li>
<li>시간 부족으로 단순 내용 업데이트 이외의 기능 구현을 생각해보지 못했다. 이는 그대로 완성도에 영향을 주었다.이건 내 일정 조정 미스였다... 이번 프로젝트는 주말 휴식을 반납해서 어떻게든 따라가보겠지만, 앞으로 부트캠프 프로젝트 기간에는 웬만하면 다른 일을 병행하지 말자.</li>
<li>깃 사용이 미숙했던 탓에 중간에 브런치가 꼬여버렸고, 발표시간이 다가오자 급한 마음에 커밋 기록을 싹 삭제해버리고 새로 push했다. 그래서 커밋 기록이 싹 날아갔다...커밋 메시지 작성 연습은 수정 시에 다시 하는걸로 해야겠다.리셋 대신 커밋 기록삭제 기능을 적극적으로 이용했다면 어땠을까... 하는 아쉬움이 있다.</li>
</ul>
<h3 id="앞으로-개선할-점-추가하고자-하는-기능"><strong>앞으로 개선할 점 (추가하고자 하는 기능)</strong></h3>
<ul>
<li>질문 삭제 기능</li>
<li>질문 검색 기능</li>
<li>css 호버 효과 적용</li>
<li>페이지네이션 기능</li>
<li>디스커션 유지 기능</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 원시 자료형과 참조 자료형]]></title>
            <link>https://velog.io/@fma_/JavaScript-%EC%9B%90%EC%8B%9C-%EC%9E%90%EB%A3%8C%ED%98%95%EA%B3%BC-%EC%B0%B8%EC%A1%B0-%EC%9E%90%EB%A3%8C%ED%98%95</link>
            <guid>https://velog.io/@fma_/JavaScript-%EC%9B%90%EC%8B%9C-%EC%9E%90%EB%A3%8C%ED%98%95%EA%B3%BC-%EC%B0%B8%EC%A1%B0-%EC%9E%90%EB%A3%8C%ED%98%95</guid>
            <pubDate>Sat, 30 Mar 2024 08:27:08 GMT</pubDate>
            <description><![CDATA[<h2 id="1-원시-자료형-vs-참조-자료형">1. 원시 자료형 <strong>vs 참조 자료형</strong></h2>
<p><code>원시 자료형(primitive data type)</code> : 고정된 저장 공간을 차지하는 데이터</p>
<ul>
<li>string, number, bigint, boolean, undefined, symbol, (null)</li>
<li>할당될 때 변수에 값(value) 자체가 담김</li>
<li>데이터를 복사한 뒤 변경해도 원래의 데이터에 영향이 가지 않음</li>
</ul>
<pre><code class="language-jsx">let a = 1;
let b = a;
b = 2;
a; //1</code></pre>
<p><code>참조 자료형(reference data type)</code> : 대량의 데이터를 다루기 적합</p>
<ul>
<li>배열(array), 객체(object), 함수(function)</li>
<li>할당될 때 보관함의 주소(reference)가 담김</li>
<li>데이터를 복사한 뒤 변경하면 원래의 데이터에 영향이 감</li>
</ul>
<pre><code class="language-jsx">let e = [10,20]let f = e;
f[0] = 50;
e;//[50,20]</code></pre>
<h2 id="2-원시-자료형">2. 원시 자료형</h2>
<p>원시 자료형의 변수에는 하나의 데이터만 담긴다.</p>
<ul>
<li>값 자체에 대한 변경이 불가능하지만, 변수에 다른 데이터를 할당할수는 있다.</li>
</ul>
<pre><code class="language-jsx">let word = &quot;hello world!&quot;
word = &quot;hello dyract!&quot;
// word라는 변수에 &gt;&gt;재할당&lt;&lt;을 하여 변수에 담긴 내용을 변경할 수 있음

const num1 = 123;
num1 = 123456789; // 에러 발생
// const 키워드로 선언하면 재할당은 불가</code></pre>
<h2 id="3-참조-자료형">3. <strong>참조 자료형</strong></h2>
<p>참조 자료형은 데이터가 위치한 곳(메모리상 주소)를 가리키는 주소가 변수에 저장된다.</p>
<p>데이터 보관함은 동적(dynamic)으로 변하며, heap이라고 부른다.</p>
<ul>
<li><blockquote>
<p>대량의 데이터를 관리하는 경우에는 고정된 데이터 공간을 사용하는 것이 비효율적이기 때문.</p>
</blockquote>
</li>
</ul>
<pre><code class="language-jsx">console.log(&#39;dyract&#39; === &#39;dyract&#39;); //true
console.log(3.14 === 3.14); //true
console.log([1,2,3] === [1,2,3]); //false, 주소값이 같은지를 확인하기 때문
console.log({ foo: &#39;bar&#39; } === { foo: &#39;bar&#39; }) //false, 주소값이 같은지를 확인하기 때문</code></pre>
<h3 id="함수로-인자를-전달할-때">*함수로 인자를 전달할 때</h3>
<pre><code class="language-jsx">let score = 80;
function doStuff(value) {
  value = 90;
}

doStuff(score)</code></pre>
<p>함수 doStuff에 score의 값을 인자로 전달하여 실행하면 매개변수 value에 score의 값 80이 전달되고, vaule에 90이 할당된다. 다만 score의 값 80은 주소값이 아닌 값 자체를 복사해서 전달하기 때문에 함수에서 어떤 일이 발생하건 관계없이 score는 초기에 할당된 값 80이 그대로 유지된다.</p>
<pre><code class="language-jsx">let player = { score: 3 };
function doStuff(obj) { 
  obj.score = 2;
}

doStuff(player); //play.score : 2</code></pre>
<p>함수가 실행되면 매개변수 obj에 변수 player의 값이 할당되며, 이것은 { score : 3 }의 주소값이다. obj.score에 2를 할당하면 obj와 plauyer은 같은 주소값을 가지고 있기 때문에 player.score도 2가 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 스코프, 클로저 개념정리]]></title>
            <link>https://velog.io/@fma_/JavaScript-%EC%8A%A4%EC%BD%94%ED%94%84-%ED%81%B4%EB%A1%9C%EC%A0%80-%EA%B0%9C%EB%85%90%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@fma_/JavaScript-%EC%8A%A4%EC%BD%94%ED%94%84-%ED%81%B4%EB%A1%9C%EC%A0%80-%EA%B0%9C%EB%85%90%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Sat, 30 Mar 2024 08:26:24 GMT</pubDate>
            <description><![CDATA[<h2 id="1-스코프">1. <strong>스코프</strong></h2>
<h3 id="1-스코프-주요-규칙"><strong>1. 스코프 주요 규칙</strong></h3>
<ul>
<li>스코프는 블록(중괄호) 또는 함수에 의해 나뉜다.</li>
<li>바깥 스코프에 정의된 변수는 안쪽 스코프에서 사용할 수 있다.안쪽 스코프에 정의된 변수는 바깥 스코프에서 사용하지 못한다.</li>
</ul>
<pre><code class="language-jsx">let username = &#39;Dyract&#39;;
if (username) {let message = `Hello, ${username}!`;
console.log(message);// ?}console.log(message);// ?</code></pre>
<p>출력 :</p>
<pre><code class="language-html">&quot;Hello, Dyract!&quot;
ReferenceError</code></pre>
<p>4번째 줄에서 message를 출력할 때는 3번째 줄의 username을 바깥 스코프에서 가져왔으므로 정상적으로 출력한다.</p>
<p>6번째 줄에서는 message라는 변수 자체가 안쪽 스코프에 선언되어 있으므로 바깥쪽에서 접근할 수 없다.</p>
<ul>
<li>스코프는 중첩이 가능하다.<ul>
<li>전역 스코프(Global Scope) : 가장 바깥쪽의 스코프</li>
<li>지역 스코프(local Scope) : 전역이 아닌 다른 스코프</li>
</ul>
</li>
<li>지역 변수는 전역 변수보다 더 높은 우선순위를 가진다.<ul>
<li>전역 변수 : 전역 스코프에서 선언한 변수</li>
<li>지역 변수 : 지역 스코프에서 선언한 변수</li>
</ul>
</li>
</ul>
<pre><code class="language-jsx">let name = &#39;김영희&#39;;

function showName() {
    let name = &#39;김철수&#39;;// 지역 변수
    console.log(name);// 두 번째 출력
}

console.log(name);// 첫 번째 출력
showName();
console.log(name);// 세 번째 출력</code></pre>
<p>출력 :</p>
<pre><code class="language-html">김영희
김철수
김영희</code></pre>
<p>전역 변수 name과 function showName에 선언된 지역 변수 name은 서로 다른 변수이다.</p>
<pre><code class="language-jsx">let name = &#39;김영희&#39;;

function showName() {name = &#39;김철수&#39;;
console.log(name);// 두 번째 출력}console.log(name);// 첫 번째 출력showName();
console.log(name);// 세 번째 출력</code></pre>
<p>출력 :</p>
<pre><code class="language-html">김철수
김영희
김영희</code></pre>
<p>지역 스코프에서 새로 선언되지 않은 변수는 전역 변수와 같은 변수이다.</p>
<h3 id="2-스코프의-종류"><strong>2. 스코프의 종류</strong></h3>
<ul>
<li>블록 스코프(block scope) : 중괄호를 기준으로 범위 구분<ul>
<li>화살표 함수는 블록 스코프로 취급</li>
<li>블록 스코프 안에서 정의된 변수는 블록 범위를 벗어나는 즉시 접근할 수 없음</li>
</ul>
</li>
<li>함수 스코프(function scope) : function 키워드가 등장하는 함수 선언식 및 함수 표현식이 만드는 스코프</li>
</ul>
<h3 id="3-var-let-const"><strong>3. var, let, const</strong></h3>
<ul>
<li>var : 블록 스코프를 무시하고 함수 스코프만 따름. -&gt; var보다는 let으로 선언하는 것을 권장</li>
<li>let : 재선언 방지(에러 출력)</li>
<li>const : 값이 변하지 않는 상수를 정의할 때 사용, 값을 새롭게 할당할 일이 없다면 const 사용 권장</li>
</ul>
<table>
<thead>
<tr>
<th></th>
<th>let</th>
<th>const</th>
<th>var</th>
</tr>
</thead>
<tbody><tr>
<td>유효 범위</td>
<td>블록 스코프 및 함수 스코프</td>
<td>블록 스코프 및 함수 스코프</td>
<td>함수 스코프</td>
</tr>
<tr>
<td>값 재할당</td>
<td>가능</td>
<td>불가능</td>
<td>가능</td>
</tr>
<tr>
<td>재선언</td>
<td>불가능</td>
<td>불가능</td>
<td>가능</td>
</tr>
</tbody></table>
<h3 id="4-변수-선언-시-유의할-점"><strong>4. 변수 선언 시 유의할 점</strong></h3>
<ul>
<li>var로 선언된 전역 변수 및 지역 변수는 window 객체에 속한다.<ul>
<li>window 객체는 브라우저의 창을 의미하는 객체이지만, 전역 영역을 담고 있기도 하다.</li>
</ul>
</li>
<li>전역 변수에 너무 많은 변수를 선언하면 안 된다.<ul>
<li>앱을 만들 때에는 직접 작성하지 않은 수많은 다른 함수와 로직이 포함되어 전역 변수의 이름이 겹칠 수 있음. (side effect)</li>
<li>-&gt; 전역변수 최소화는 side effect를 줄일 수 있는 좋은 방법</li>
</ul>
</li>
<li>var은 블록 스코프를 무시하며, 재선언을 해도 에러를 내지 않는다.<ul>
<li>같은 스코프에서 동일한 이름의 변수를 재선언하는 것은 에러 유발</li>
</ul>
</li>
<li>전역 변수를 var로 선언하는 경우 문제가 될 수 있다.<ul>
<li>var로 선언한 변수가 window 기능을 덮어씌워서 내장 기능을 사용할 수 없게 만들 수 있음</li>
</ul>
</li>
<li>선언 키워드(var, let, const) 없이 변수를 할당해서는 안 된다.<ul>
<li>선언 키워드 없이 할당하면 var로 선언한 전역 변수처럼 취급</li>
<li>실수 방지하기 위해 Strict Mode 사용 가능</li>
</ul>
</li>
</ul>
<pre><code class="language-jsx">&#39;user strict&#39;;//문법적으로 실수할 수 있는 부분을 에러로 판단
finction showAge() {‌
    age = 90;// 여기서 에러가 발생
    console.log(age);//90
}
showAge();</code></pre>
<h2 id="2-클로저">2. 클로저</h2>
<p>클로저 : 함수와 함수가 선언된 어휘적(lexical) 환경의 조합. 환경은 클로저가 생성된 시점의 유효 범위 내에 있는 모든 지역변수로 구성됨.</p>
<p>클로저 함수 : 외부 함수의 변수에 접근할 수 있는 내부 함수</p>
<h3 id="1-클로저-함수의-특징">1. 클로저 함수의 특징</h3>
<ul>
<li>함수를 리턴하는 함수</li>
</ul>
<pre><code class="language-jsx">const adder = x =&gt; y =&gt; x + y;
adder(5)(7);//12</code></pre>
<p>이와 같이 화살표를 두 번 사용한 함수를 기본 형태로 바꾸면 다음과 같다.</p>
<pre><code class="language-jsx">const adder = function(x) {‌
    return function(y) {
        ‌‌return x + y;
    ‌}
}</code></pre>
<p>함수에 의해 스코프가 구분된다.</p>
<ul>
<li>외부 함수는 y에 접근 불가능</li>
<li>내부 함수는 x에 접근 가능</li>
</ul>
<h2 id="2-클로저-함수의-활용">2. 클로저 함수의 활용</h2>
<ul>
<li>데이터 보존하기</li>
</ul>
<p>: 외부 함수의 실행이 끝나더라도 외부 함수 내 변수를 사용할 수 있음</p>
<pre><code class="language-jsx">const adder = function(x) {
    ‌return function(y) {
        ‌‌return x + y;
    ‌}
}
const add5 = adder(5);
add5(7)//12
add5(10)//15</code></pre>
<ul>
<li>클로저 모듈 패턴</li>
</ul>
<p>: 내부 함수를 단 하나만 리턴하는 것에 그치지 않고, 객체에 담아 여러 개의 내부 함수를 리턴하도록 만듦.</p>
<pre><code class="language-jsx">const makeCounter = () =&gt; {‌
    let value = 0;

    return {
        ‌increase: () =&gt; {
            ‌value = value + 1
        },
        decrease: () =&gt; {
            ‌value = value - 1
        },
        getValue: () =&gt; value
        }
}

const counter1 = makeCounter();
counter1// { increase : f, decrease : f, getValue : f }, type: 객체</code></pre>
<p>value라는 변수에 값을 새롭게 직접 할당할 수 없음. (지역변수)</p>
<p>=&gt; 정보의 접근 제한(<code>캡슐화</code>), 의도치 않은 전역 변수 생성 방지</p>
<pre><code class="language-jsx">const counter1 = makeCounter();
const1.increase();
const1.increase();
const1.decrease();
const1.getValue();// 1const counter2 = makeCounter();
const2.decrease();
const2.decrease();
const2.decrease();
const2.getValue();// -3</code></pre>
<p>counter1에서의 value와 counter2에서의 value는 각자 독립적.</p>
<p>=&gt; 함수 재사용성 극대화, 함수 하나를 완전히 독립적인 부품 형태로 분리 (<code>모듈화</code>)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[HTML/CSS] 계산기 목업(Mock-up) 실습]]></title>
            <link>https://velog.io/@fma_/HTMLCSS-%EA%B3%84%EC%82%B0%EA%B8%B0-%EB%AA%A9%EC%97%85Mock-up-%EC%8B%A4%EC%8A%B5</link>
            <guid>https://velog.io/@fma_/HTMLCSS-%EA%B3%84%EC%82%B0%EA%B8%B0-%EB%AA%A9%EC%97%85Mock-up-%EC%8B%A4%EC%8A%B5</guid>
            <pubDate>Sat, 30 Mar 2024 08:25:56 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/fma_/post/3a0aec39-c910-4618-9d2a-cfbc5dfd8d58/image.png" alt=""></p>
<p>HTML/CSS 실습으로 계산기를 목업(Mock-up, 작동을 제외한 부분을 구현) 해보았다.</p>
<p>윈도우 계산기를 모티브로 작성했으며, ul/li의 리스트 구조에 css를 덧씌워서 구현했다.</p>
<p><strong>&lt;calculator.html&gt;</strong></p>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;calculator.css&quot;&gt;
    &lt;title&gt;Calculator&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;!--계산기--&gt;
    &lt;div class=&quot;calculator&quot;&gt;

        &lt;!--결과출력창--&gt;
        &lt;ul&gt;
            &lt;li&gt; &lt;p class=&#39;result&#39;&gt; 0 &lt;/p&gt; &lt;/li&gt;
        &lt;/ul&gt;

          &lt;!--버튼--&gt;
          &lt;ul&gt;
            &lt;li class=&#39;numberli&#39;&gt; &lt;button class=&#39;numberac&#39;&gt;AC&lt;/button&gt; &lt;/li&gt;
            &lt;li class=&#39;numberli&#39;&gt; &lt;button class=&#39;numberac&#39;&gt;+/-&lt;/button&gt; &lt;/li&gt;
            &lt;li class=&#39;numberli&#39;&gt; &lt;button class=&#39;numberac&#39;&gt;%&lt;/button&gt; &lt;/li&gt;
            &lt;li class=&#39;numberli&#39;&gt; &lt;button class=&#39;operator&#39;&gt;/&lt;/button&gt; &lt;/li&gt;
        &lt;/ul&gt;
          &lt;ul&gt;
            &lt;li class=&#39;numberli&#39;&gt; &lt;button class=&#39;number&#39;&gt;7&lt;/button&gt; &lt;/li&gt;
            &lt;li class=&#39;numberli&#39;&gt; &lt;button class=&#39;number&#39;&gt;8&lt;/button&gt; &lt;/li&gt;
            &lt;li class=&#39;numberli&#39;&gt; &lt;button class=&#39;number&#39;&gt;9&lt;/button&gt; &lt;/li&gt;
            &lt;li class=&#39;numberli&#39;&gt; &lt;button class=&#39;operator&#39;&gt;*&lt;/button&gt; &lt;/li&gt;
        &lt;/ul&gt;
        &lt;ul&gt;
            &lt;li class=&#39;numberli&#39;&gt; &lt;button class=&#39;number&#39;&gt;4&lt;/button&gt; &lt;/li&gt;
            &lt;li class=&#39;numberli&#39;&gt; &lt;button class=&#39;number&#39;&gt;5&lt;/button&gt; &lt;/li&gt;
            &lt;li class=&#39;numberli&#39;&gt; &lt;button class=&#39;number&#39;&gt;6&lt;/button&gt; &lt;/li&gt;
            &lt;li class=&#39;numberli&#39;&gt; &lt;button class=&#39;operator&#39;&gt;-&lt;/button&gt; &lt;/li&gt;
        &lt;/ul&gt;
        &lt;ul&gt;
            &lt;li class=&#39;numberli&#39;&gt; &lt;button class=&#39;number&#39;&gt;1&lt;/button&gt; &lt;/li&gt;
            &lt;li class=&#39;numberli&#39;&gt; &lt;button class=&#39;number&#39;&gt;2&lt;/button&gt; &lt;/li&gt;
            &lt;li class=&#39;numberli&#39;&gt; &lt;button class=&#39;number&#39;&gt;3&lt;/button&gt; &lt;/li&gt;
            &lt;li class=&#39;numberli&#39;&gt; &lt;button class=&#39;operator&#39;&gt;+&lt;/button&gt; &lt;/li&gt;
        &lt;/ul&gt;

          &lt;ul&gt;
            &lt;li class=&#39;number0li&#39;&gt; &lt;button class=&#39;number&#39;&gt;0&lt;/button&gt; &lt;/li&gt;
            &lt;li class=&#39;numberli&#39;&gt; &lt;button class=&#39;number&#39;&gt;.&lt;/button&gt; &lt;/li&gt;
            &lt;li class=&#39;numberli&#39;&gt; &lt;button class=&#39;operator&#39;&gt;=&lt;/button&gt; &lt;/li&gt;
        &lt;/ul&gt;

    &lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;</code></pre><p>&lt;calculator.css&gt;</p>
<pre><code>/*레이아웃 리셋*/
* {
    box-sizing: border-box;
  }


body {
    /*레이아웃 리셋*/
    margin: 0;
    padding: 0;
    /*계산기 정중앙에 위치*/
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;

  }

/*계산기 테두리*/
.calculator {
    width: 350px;
    height: 500px;
    /*border: 1px solid blue;*/
    display: flex;
    flex-direction : column;
    background-color: #5c5959;
    padding-bottom : 4px
  }

.result{
    display: flex;
    overflow: hidden;
    justify-content: flex-end;
    align-items: flex-end;
    font-size : 40px;
    width : 300px;
    height : 50px;
    line-height : 50px;
    padding : 5px;
    margin : 15px 5px;
    background-color: #5c5959;
    color : white;
}

ul{
    display: flex;
    justify-content: center;
    align-items: center;
    list-style: none;
    padding: 0;
    margin : 2px;
    flex : 1 1 auto;
   /* border: 1px solid red;*/
    flex-direction : row;
}

.numberli{
    list-style: none;
    display: flex;
    flex : 1 1 auto;
    width : 100%;
    height : 100%;
}

.number0li{
    width : 43rem;
    height : 100%;
    list-style: none;
    display: flex;
    flex : 2 1 auto;
}

.number{
    width : 100%;
    height : 100%;
    background-color: #808080;
    border-radius : 1px;
    border : #424242;
    color : white;
    margin : 2px;
    font-size: 18px;
}

.operator{
    width : 100%;
    height : 100%;
    background-color: #da9409;
    border-radius : 1px;
    border : #424242;
    color : white;
    margin : 2px;
    font-size: 18px;
}

.numberac{
    width : 100%;
    height : 100%;
    background-color: #3b3a36;
    border-radius : 1px;
    border : #424242;
    color : white;
    margin : 2px;
    font-size: 18px;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[HTML/CSS] Wireframe, Flexbox]]></title>
            <link>https://velog.io/@fma_/HTMLCSS-Wireframe-Flexbox</link>
            <guid>https://velog.io/@fma_/HTMLCSS-Wireframe-Flexbox</guid>
            <pubDate>Sat, 30 Mar 2024 08:24:35 GMT</pubDate>
            <description><![CDATA[<h1 id="chapter-1-와이어프레임"><strong>CHAPTER 1. 와이어프레임</strong></h1>
<p><strong>1. 와이어프레임</strong> : 웹 또는 애플리케이션을 개발할 때 레이아웃의 뼈대를 그리는 단계</p>
<p>아주 단순하게 레이아웃과 제품의 구조를 보여주는 용도</p>
<p><strong>2. 목업(Mock-up)</strong> : 실제 제품이 작동하는 모습과 동일하게 HTML 문서를 작성 (하드코딩)</p>
<ul>
<li>하드코딩 : 변수값을 html 문서 내에 하나하나 입력하는 방식</li>
</ul>
<p><strong>3. HTML 구성하기</strong> : 수직 분할과 수평 분할을 차례대로 적용하여 콘텐츠의 흐름에 따라 작업 진행</p>
<ul>
<li>수직 분할 : 화면을 수직으로 구분하여, 콘텐츠가 가로로 배치될 수 있도록 요소를 배치</li>
<li>수평 분할 : 분할된 각각의 요소를 수평으로 구분하여, 내부 콘텐츠가 세로로 배치될 수 있도록 요소를 배치수평으로 구분된 요소에 height 속성을 추가하면, 수평 분할을 보다 직관적으로 할 수 있음</li>
</ul>
<p><strong>4. 레이아웃 리셋</strong> : HTML 문서가 갖는 기본 스타일이, 레이아웃을 잡는 데 방해가 되는 경우, 기본 스타일을 제거해 줌.</p>
<pre><code class="language-css">* {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 0;
}</code></pre>
<h1 id="chapter-2-flexbox"><strong>CHAPTER 2. Flexbox</strong></h1>
<p><strong>1. Flexbox</strong> : 박스를 유연하게 늘리거나 줄여 레이아웃을 잡는 방법</p>
<p>display: flex 는 부모 박스 요소에 적용해, 자식 박스의 방향과 크기를 결정하는 레이아웃 구성 방법</p>
<p><strong>2. 부모 요소에 적용해야 하는 Flexbox 속성들</strong></p>
<p>flex-direction : 정렬 축 정하기</p>
<pre><code class="language-css">ain {
    display: flex;
    **flex-direction : row;**
}</code></pre>
<ul>
<li>row(기본값), column, row-reverse, column-reverse</li>
</ul>
<p>flex-wrap : 줄 바꿈 설정하기</p>
<pre><code class="language-css">main {
    display: flex;
    **flex-wrap : nowrap;**
}</code></pre>
<ul>
<li>nowrap(기본값), wrap, wrap-reverse</li>
</ul>
<p>justify-content : 축 수평 방향 정렬</p>
<ul>
<li>가로로 정렬되어 있다면 가로 방향으론 어떻게 정렬할 것인지, 세로로 정렬되어 있다면 세로 방향으론 어떻게 정렬할 것인지 결정</li>
<li>주요 속성값 : flex-start , flex-end, center, space-between, space-around</li>
</ul>
<p>!<a href="https://blog.kakaocdn.net/dn/b2aluX/btrKU6Of7IE/FIG7cd79rpW3dapKua4in1/img.png">https://blog.kakaocdn.net/dn/b2aluX/btrKU6Of7IE/FIG7cd79rpW3dapKua4in1/img.png</a></p>
<p>align-items : 축 수직 방향 정렬</p>
<ul>
<li>요소들이 가로로 정렬되어 있다면 세로 방향으론 어떻게 정렬할 것인지, 세로로 정렬되어 있다면 가로 방향으론 어떻게 정렬할 것인지 결정</li>
<li>주요 속성값 : tretch , flex-start , flex-end , center , baseline</li>
</ul>
<p>!<a href="https://blog.kakaocdn.net/dn/Hu240/btrKTPfwOYi/BHpZeX8tOwsfxrsS74xrHK/img.png">https://blog.kakaocdn.net/dn/Hu240/btrKTPfwOYi/BHpZeX8tOwsfxrsS74xrHK/img.png</a></p>
<p><strong>3, 자식 요소에 적용해야 하는 Flexbox 속성</strong></p>
<ul>
<li>부모 요소에 적용해야 하는 속성들이 자식 요소들의 정렬과 관련이 있었다면, 자식 요소에게 적용해야 하는 속성인 flex 는 요소가 차지하는 공간과 관련이 있다.</li>
</ul>
<p>flex 속성의 값 : 세 가지 값을 지정해줄 수 있음.</p>
<pre><code class="language-css">flex:   &lt;grow(팽창 지수)&gt;    &lt;shrink(수축 지수)&gt;    &lt;basis(기본 크기)&gt;</code></pre>
<ul>
<li>grow(팽창 지수) : 요소의 크기가 늘어나야 할 때 얼마나 늘어날 것인지. / 팽창지수의 절대적 크기가 아닌 총합에서의 비율로 빈 공간을 차지</li>
<li>shrink(수축 지수) : 요소의 크기가 줄어들어야 할 때 얼마나 줄어들 것인지 / flex-grow 속성으로 비율을 변경하는 경우, flex-shrink 속성은 기본값인 1로 두어도 무방함.</li>
<li>basis(기본 크기) : 늘어나고 줄어드는 것과 상관없이 요소의 기본 크기는 얼마인지 / flex-grow 가 0일 때, basis 크기를 지정하면 그 크기는 유지</li>
<li>기본값 :</li>
</ul>
<pre><code class="language-css">flex: 0 1 auto;</code></pre>
<ul>
<li>width와 flex-basis를 동시에 적용하는 경우, flex-basis가 우선</li>
<li>콘텐츠가 많아 자식 박스가 넘치는 경우, width가 정확한 크기를 보장하지 않음</li>
<li>(flex-basis를 사용하지 않는다면) 콘텐츠가 많아 자식 박스가 넘치는 경우를 대비해, width 대신 max-width를 쓸 수 있음</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CSS] CSS 기초, 박스모델, 셀렉터]]></title>
            <link>https://velog.io/@fma_/CSS-CSS-%EA%B8%B0%EC%B4%88-%EB%B0%95%EC%8A%A4%EB%AA%A8%EB%8D%B8-%EC%85%80%EB%A0%89%ED%84%B0</link>
            <guid>https://velog.io/@fma_/CSS-CSS-%EA%B8%B0%EC%B4%88-%EB%B0%95%EC%8A%A4%EB%AA%A8%EB%8D%B8-%EC%85%80%EB%A0%89%ED%84%B0</guid>
            <pubDate>Sat, 30 Mar 2024 08:24:07 GMT</pubDate>
            <description><![CDATA[<h2 id="1-css-기초"><strong>1. CSS 기초</strong></h2>
<h3 id="1-css--웹-페이지-스타일-및-레이아웃을-정의하는-스타일시트-언어">1. CSS : 웹 페이지 스타일 및 레이아웃을 정의하는 스타일시트 언어</h3>
<ul>
<li>좋은 사용자 경험을 제공하기 위한 도구</li>
</ul>
<h3 id="2-css-기본구조">2. CSS 기본구조</h3>
<ul>
<li>셀렉터 : 요소 이름이나 id, 또는 클래스를 선택</li>
<li>선언 블록 : 중괄호 안에서 요소에 적용할 내용을 작성</li>
<li>속성 : 요소에 적용할 수 있는 내용, 속성에 적용할 적절한 값을 입력하여 스타일을 표현</li>
</ul>
<h3 id="3-css를-html과-연결하기">3. CSS를 HTML과 연결하기</h3>
<ul>
<li><link> 태그 안에서 href 속성을 통해 파일을 연결</li>
<li>rel : 연결하고자 하는 파일의 역할이나 특징을 나타냄</li>
</ul>
<pre><code class="language-xml">&lt;link rel=&quot;stylesheet&quot; href=&quot;index.css&quot; /&gt;</code></pre>
<ul>
<li>모든 요소를 선택해서 스타일링할 수 있음</li>
</ul>
<pre><code class="language-css">li {
  text-decoration: underline;
}</code></pre>
<ul>
<li>id가 있는 요소를 선택할 때는 # 기호 사용</li>
</ul>
<pre><code class="language-html">&lt;h4 id=&quot;navigation-title&quot;&gt;This is the navigation section.&lt;/h4&gt;</code></pre>
<pre><code class="language-css">#navigation-title {
  color: red;
}</code></pre>
<ul>
<li>class를 지정해서 스타일링할 때는 .을 사용</li>
</ul>
<pre><code class="language-html">&lt;!-- 바른 예제 --&gt;
&lt;ul&gt;
  &lt;li class=&quot;menu-item&quot;&gt;Home&lt;/li&gt;
  &lt;li class=&quot;menu-item&quot;&gt;Mac&lt;/li&gt;
  &lt;li class=&quot;menu-item&quot;&gt;iPhone&lt;/li&gt;
  &lt;li class=&quot;menu-item&quot;&gt;iPad&lt;/li&gt;
&lt;/ul&gt;</code></pre>
<pre><code class="language-css">.menu-item {
  text-decoration: underline;
}</code></pre>
<ul>
<li>여러 개의 class를 하나의 엘리먼트에 적용 : 띄어쓰기로 구분</li>
</ul>
<pre><code class="language-html">&lt;li class=&quot;menu-item selected&quot;&gt;Home&lt;/li&gt;</code></pre>
<pre><code class="language-css">.selected {
  font-weight: bold;
  color: #009999;
}</code></pre>
<h3 id="4-텍스트-꾸미기">4. 텍스트 꾸미기</h3>
<table>
<thead>
<tr>
<th>기능</th>
<th>속성</th>
<th>기능</th>
<th>속성</th>
</tr>
</thead>
<tbody><tr>
<td>글자 색상</td>
<td>color</td>
<td>굵기</td>
<td>font-weight</td>
</tr>
<tr>
<td>배경 색상</td>
<td>background-color</td>
<td>밑줄, 가로줄</td>
<td>text-decoration</td>
</tr>
<tr>
<td>테두리 색상</td>
<td>border-color</td>
<td>자간</td>
<td>letter-spacing</td>
</tr>
<tr>
<td>글꼴</td>
<td>font-family* google font 활용</td>
<td>행간</td>
<td>line-height</td>
</tr>
<tr>
<td>크기</td>
<td>font-size</td>
<td>정렬</td>
<td>가로 : text-align세로 : vertical-align</td>
</tr>
<tr>
<td>- 정렬 관련 유의사항</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>- 가로정렬 text-align - 유효한 값 : left, right, center, justify(양쪽 정렬)</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>- 세로정렬 vertical-align - 부모 요소의 display 속성이 반드시 table-cell이어야 함, 정렬하고자 하는 글자를 둘러싸고 있는 박스의 높이가 글자 높이보다 큰 경우에만 적용</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>- <center> <font>를 사용하지 말아야 하는 이유 : 관심사 분리. 구조설계는 html에서.</td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<h3 id="5-절대-단위와-상대-단위">5. 절대 단위와 상대 단위</h3>
<ul>
<li>절대 단위: px, pt 등</li>
<li>상대 단위: %, em, rem, ch, vw, vh 등</li>
</ul>
<p>글꼴 사이즈를 정할 때</p>
<ul>
<li>환경에 영향을 받지 않는 절대적인 크기로 정하는 경우 : px(픽셀)</li>
<li>일반적인 경우 : 상대 단위인 rem</li>
</ul>
<p>화면 사이즈를 정할 때</p>
<ul>
<li>반응형 웹(responsive web)에서 기준점을 만들 때 : px</li>
<li>화면 너비나 높이에 따른 상대적인 크기가 중요한 경우 : vw, vh1vw : 보이는 영역 너비의 1/1001초 : 영역 높이의 1/100</li>
</ul>
<h2 id="2-박스모델"><strong>2. 박스모델</strong></h2>
<h3 id="1-block-vs-inline-block-vs-inline"><strong>1. block vs inline-block vs inline</strong></h3>
<table>
<thead>
<tr>
<th></th>
<th>block</th>
<th>inline-block</th>
<th>inline</th>
</tr>
</thead>
<tbody><tr>
<td>줄바꿈 여부</td>
<td>줄바꿈이 일어남</td>
<td>줄바꿈이 일어나지 않음</td>
<td>줄바꿈이 일어나지 않음</td>
</tr>
<tr>
<td>기본적으로 갖는 너비 (width)</td>
<td>100%</td>
<td>글자가 차지하는 만큼</td>
<td>글자가 차지하는 만큼</td>
</tr>
<tr>
<td>width, height 사용가능 여부</td>
<td>가능</td>
<td>가능</td>
<td>불가능</td>
</tr>
<tr>
<td>- block 엘리먼트 목록 : <strong><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements">https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements</a></strong></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>- inline 엘리먼트 목록 : <strong><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements">https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements</a></strong></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<p><strong><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements">
Block-level elements - HTML: HyperText Markup Language | MDN
developer.mozilla.org</a></strong></p>
<p><strong><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements">
Inline elements - HTML: HyperText Markup Language | MDN
developer.mozilla.org</a></strong></p>
<h3 id="2-css-박스를-구성하는-요소"><strong>2. CSS 박스를 구성하는 요소</strong></h3>
<p>!<a href="https://blog.kakaocdn.net/dn/bbW5Ny/btrKURDdcBu/kakiW0LFPda8I94WJLF031/img.png">https://blog.kakaocdn.net/dn/bbW5Ny/btrKURDdcBu/kakiW0LFPda8I94WJLF031/img.png</a></p>
<ul>
<li><p>Border : 테두리각각의 값 : 테두리 두께(border-width), 테두리 스타일(border-style), 테두리 색상(border-color)</p>
<pre><code class="language-css">  p {
    border: 1px solid red;
  }</code></pre>
</li>
<li><p>margin : 바깥 여백</p>
<pre><code class="language-css">  p {
    margin: 10px 20px 30px 40px;
  }</code></pre>
</li>
<li><p>각각의 값 : top, right, bottom, left (시계방향)</p>
<pre><code class="language-css">  p {
      margin: 10px 20px;
  }</code></pre>
</li>
<li><p>값을 두 개만 넣을 경우 : 각각 top bottom / right left</p>
<pre><code class="language-css">  p {
      margin: 10px;
  }</code></pre>
</li>
<li><p>값을 하나만 넣을 경우 : 모든 방향의 바깥 여백에 적용</p>
<pre><code class="language-css">  p {
      margin-top: 10px;
      margin-right: 20px;
      margin-bottom: 30px;
      margin-left: 40px;
  }</code></pre>
</li>
<li><p>방향을 특정한 속성도 존재</p>
<pre><code class="language-css">  p {
    margin-top: -2rem;
  }</code></pre>
</li>
<li><p>음수 값을 지정할 경우 : 다른 엘리먼트와의 간격이 줄어들거나 겹치게 만들 수 있음</p>
</li>
<li><p>padding : 안쪽여백값 설정은 margin과 동일</p>
<pre><code class="language-css">  p {
    padding: 10px 20px 30px 40px;
  }</code></pre>
</li>
</ul>
<h3 id="3-박스를-벗어나는-콘텐츠-처리"><strong>3. 박스를 벗어나는 콘텐츠 처리</strong></h3>
<ul>
<li>박스 크기보다 콘텐츠 크기가 더 큰 경우에는 콘텐츠가 박스 바깥으로 빠져나옴</li>
<li>p 태그에 overflow 속성을 지정해 박스보다 큰 콘텐츠에 스크롤을 표시할 수 있음</li>
<li>overflow: hidden;을 사용하면 초과한 컨텐츠를 보이지 않게 할 수 있음</li>
</ul>
<pre><code class="language-css">p {
  height: 40px;
  overflow: auto;
}</code></pre>
<h3 id="4-박스-크기-측정-기준"><strong>4. 박스 크기 측정 기준</strong></h3>
<pre><code class="language-css">#container {
  width: 300px;
  padding: 10px;
  background-color: yellow;
  border: 2px solid red;
}

#inner {
  width: 100%;
  height: 200px;
  border: 2px solid green;
  background-color: lightgreen;
  padding: 30px;
}</code></pre>
<p>위 코드에서 #container의 넓이는 300px가 아니라 324px, #inner의 100%는 300px가 아니라 364px</p>
<table>
<thead>
<tr>
<th>#container</th>
<th>#inner</th>
</tr>
</thead>
<tbody><tr>
<td>300px (콘텐츠 영역)+ 10px (padding-left)+ 10px (padding-right)+ 2px (border-left)+ 2px (border-right)</td>
<td>300px  (300px의 100%)+ 30px (padding-left)+ 30px (padding-right)+ 2px (border-left)+ 2px (border-right)</td>
</tr>
<tr>
<td>- <strong>(모든 요소를 선택하는 셀렉터)로 box-sizing 속성값을 border-box로 지정하면 여백과 테두리 두께를 포함해서 박스 크기를 지정할 수 있음</strong></td>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-css">* {
  box-sizing: border-box;
}</code></pre>
<h2 id="3-css-selector">3. CSS selector</h2>
<p>전체 셀렉터 참고 : <strong><a href="https://www.w3schools.com/cssref/css_selectors.asp">https://www.w3schools.com/cssref/css_selectors.asp</a></strong></p>
<p><strong><a href="https://www.w3schools.com/cssref/css_selectors.asp">
CSS Selectors Reference
www.w3schools.com</a></strong></p>
<p>요약</p>
<table>
<thead>
<tr>
<th>종류</th>
<th>명칭</th>
<th>표기</th>
<th>종류</th>
<th>명칭</th>
<th>표기</th>
</tr>
</thead>
<tbody><tr>
<td>기본</td>
<td>전체</td>
<td>* { }</td>
<td>자식 / 후손 / 형제</td>
<td>자식</td>
<td>header &gt; p { }</td>
</tr>
<tr>
<td></td>
<td>태그</td>
<td>h1 { }</td>
<td></td>
<td>후손</td>
<td>header p { }</td>
</tr>
<tr>
<td></td>
<td>ID</td>
<td>#id { }</td>
<td></td>
<td>형제</td>
<td>section ~ p  { }</td>
</tr>
<tr>
<td></td>
<td>class</td>
<td>.class { }</td>
<td></td>
<td>인접 형제</td>
<td>section + p { }</td>
</tr>
<tr>
<td></td>
<td>attribute</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<h3 id="1-기본-셀렉터"><strong>1. 기본 셀렉터</strong></h3>
<p>전체 셀렉터 : 문서의 모든 요소 선택</p>
<pre><code class="language-css">* { }</code></pre>
<p>태그 셀렉터 : 같은 태그명을 가진 모든 요소 선택 (복수선택 가능)</p>
<pre><code class="language-css">h1 { }
div { }
section, h1 { }</code></pre>
<p>ID 셀렉터 : #id, 해당 id의 요소 선택</p>
<pre><code class="language-css">#id { }</code></pre>
<p>class  셀렉터 : .class, 같은 class를 가진 모든 요소 선택</p>
<pre><code class="language-css">.widget { }
.center { }</code></pre>
<p>attribute 셀렉터 : 같은 속성을 가진 요소를 선택</p>
<pre><code class="language-css">a[href] { }
p[id=&quot;only&quot;] { }
p[class~=&quot;out&quot;] { }
p[class|=&quot;out&quot;] { }
section[id^=&quot;sect&quot;] { }
div[class$=&quot;2&quot;] { }
div[class*=&quot;w&quot;] { }</code></pre>
<h3 id="2-자식--후손--형제-셀렉터"><strong>2. 자식 / 후손 / 형제 셀렉터</strong></h3>
<p>자식 셀렉터 : 첫 번째로 입력한 요소의 바로 아래 자식인 요소를 선택</p>
<pre><code class="language-css">header &gt; p { }</code></pre>
<p>후손 셀렉터 : 첫 번째로 입력한 요소의 후손을 선택. 자식뿐만 아니라 자식의 자식들 중의 같은 요소(아래 예시에서는 p요소) 까지 선택</p>
<pre><code class="language-css">header p {}</code></pre>
<p>형제 셀렉터 : 같은 부모 요소를 공유하면서, 첫 번째 입력한 요소 뒤에 오는 두 번째 입력한 요소를 모두 선택</p>
<pre><code class="language-css">section ~ p { }</code></pre>
<ul>
<li>아래 예시의 경우 : <section> 요소 뒤에 있는 세 개의 <p> 요소를 모두 선택</li>
</ul>
<pre><code class="language-html">&lt;header&gt;‌
    &lt;section&gt;&lt;/section&gt;‌
    &lt;p&gt;&lt;/p&gt;&lt;!-- 선택 --&gt;
    ‌&lt;p&gt;&lt;/p&gt;&lt;!-- 선택 --&gt;‌
    &lt;p&gt;&lt;/p&gt;&lt;!-- 선택 --&gt;
&lt;/header&gt;</code></pre>
<p>인접 형제 셀렉터 : 같은 부모 요소를 공유하면서 첫 번째 입력한 요소 바로 뒤에 오는 두 번째 입력한 요소를 선택</p>
<pre><code class="language-css">section + p { }</code></pre>
<h3 id="3-기타-셀렉터"><strong>3. 기타 셀렉터</strong></h3>
<p>가상 클래스 셀렉터 : 요소의 상태 정보에 기반해 요소를 선택</p>
<pre><code class="language-css">a:link { }/*사용자가 방문하지 않은 &lt;a&gt;요소를 선택합니다.*/
a:visited { }/*사용자가 방문한 &lt;a&gt;요소를 선택합니다. *
/a:hover { }/* 마우스를 요소 위에 올렸을 때 선택합니다. */
a:active { }/* 활성화 된(클릭된) 상태일 때 선택합니다. */
a:focus { }/* 포커스가 들어와 있을 때 선택합니다. */</code></pre>
<p>UI 요소 상태 셀렉터</p>
<pre><code class="language-css">input:checked + span { }/*체크 상태일 때 선택합니다. */
input:enabled + span { }/*사용 가능한 상태일 때 선택합니다. */
input:disabled + span { }/*사용 불가능한 상태일 때 선택합니다. */</code></pre>
<p>구조 가상 클래스 셀렉터</p>
<pre><code class="language-css">p:first-child { }/*p엘리먼트 중에서 첫 번째 자식 엘리먼트*/
ul &gt; li:last-child { }/*ul의 자식 엘리먼트 중에서, 마지막 자식 엘리먼트가 li인 것을 선택*/
ul &gt; li:nth-child(2n) { }section &gt; p:nth-child(2n+1) { }/* section의 자식 엘리먼트 중에서, 홀수 번째 자식 엘리먼트가 p인 것을 선택*/
ul &gt; li:first-child { }li:last-child { }div &gt; div:nth-child(4) { }/* div의 자식 엘리먼트 중에서 네 번째 자식 엘리먼트가 li인 것*/
div:nth-last-child(2) { }/* 엘리먼트가 div인 것 중 마지막에서 두 번째 자식인 것*/
section &gt; p:nth-last-child(2n + 1) { }/* section의 자식 엘리먼트 중에서, 마지막에서 홀수 번째 자식 엘리먼트가 p인 것*/
p:first-of-type { }/* p 엘리먼트의 형제 엘리먼트 중 첫 번째 p 엘리먼트를 선택 ((first-child와는 다르게 첫 번째 자식 엘리먼트가 아닌, 처음 등장하는 p를 선택) */
div:last-of-type { }/* div 엘리먼트의 형제 엘리먼트 중 마지막 div 엘리먼트를 선택 */
ul:nth-of-type(2) { }/* ul 엘리먼트의 형제 엘리먼트 중 두 번째 ul 엘리먼트를 선택 */
p:nth-last-of-type(1) { }/* p 엘리먼트의 형제 엘리먼트 중 마지막에서 두 번째 p 엘리먼트를 선택 */</code></pre>
<p>부정 셀렉터</p>
<pre><code class="language-css">input:not([type=&quot;password&quot;]) { }
div:not(:nth-of-type(2)) { }/*div 엘리먼트의 형제 엘리먼트 중 두 번째 div 엘리먼트를 제외한 모든 div 엘리먼트를 선택*/
p:not(#only) { }/*p 엘리먼트 중에서, id가 only인 엘리먼트를 제외하고 모두 선택*/</code></pre>
<p>정합성 확인 셀렉터</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[북리뷰] 고등학생의 인공지능 도서 : 만들어진 생각]]></title>
            <link>https://velog.io/@fma_/%EB%B6%81%EB%A6%AC%EB%B7%B0-%EA%B3%A0%EB%93%B1%ED%95%99%EC%83%9D%EC%9D%98-%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5-%EB%8F%84%EC%84%9C-%EB%A7%8C%EB%93%A4%EC%96%B4%EC%A7%84-%EC%83%9D%EA%B0%81</link>
            <guid>https://velog.io/@fma_/%EB%B6%81%EB%A6%AC%EB%B7%B0-%EA%B3%A0%EB%93%B1%ED%95%99%EC%83%9D%EC%9D%98-%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5-%EB%8F%84%EC%84%9C-%EB%A7%8C%EB%93%A4%EC%96%B4%EC%A7%84-%EC%83%9D%EA%B0%81</guid>
            <pubDate>Sat, 30 Mar 2024 08:21:41 GMT</pubDate>
            <description><![CDATA[<h2 id="고등학생의-열린-시각을-전하는-책">고등학생의 열린 시각을 전하는 책</h2>
<blockquote>
<p>만들어진 생각: 고등학생들이 생각하는 미래 인공지능의 발전 방향</p>
</blockquote>
<p>&#39;인공지능&#39;이라는 단어를 들으면 무엇이 생각나는가? 누군가는 사람과 대화하는 빅스비를 생각할 것이고, 이세돌 9단을 꺾으며 세계를 떠들썩하게 만들었던 알파고를 떠올리는 사람도 있을 것이다. 영화에서 무리지어 사람을 공격하는 위험한 로봇을 생각할 수도 있다. 이처럼 &#39;인공지능&#39;이라는 단어는 한 마디로 정의하기 모호한 것이다. 그 와중에 인공지능은 삶 깊숙이 스며들고 있으며, 우리는 인공지능에 점차 적응하고 있다.</p>
<p><strong>그렇다면, 도대체 인공지능이란 무엇일까? 우리 삶에는 어떤 영향을 끼칠까?</strong></p>
<p><img src="https://velog.velcdn.com/images/fma_/post/9437cff4-ac91-43f0-9794-951bf964da12/image.png" alt=""></p>
<p>이런 모호한 주제를 서술한 책 <strong>『만들어진 생각』</strong>의 저자들은 놀랍게도 고등학생이다. 학생 여덟 명이 인공지능에 관련해 각자 관심 있는 분야를 골라 인공지능의 여러 측면에 접근하고 있다. 이 분야는 인공지능의 원리와 같이 전문적인 측면부터 경제적인 측면, 그리고 사회·철학적 측면까지 다양하다.</p>
<p>초반에는 인공지능의 정의와 원리, 활용 등의 원론적인 내용을 보여 주다가 중반부에 들어가면서 공학 외의 분야와 인공지능을 연관짓기 시작한다. 인공지능을 경제적 관점에서 실업률과 관련해 분석하는가 하면, 인공지능을 철학적 관점에서 분석하기도 한다. 이는 인공지능이라는 기술 자체에 국한되지 않고 인간의 본질과 자아에 대한 궁극적인 질문을 던지면서, 인간이 인공지능 시대에서 나아가야 할 방향을 제시한다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/2cd05a5e-8a32-4932-b9f0-184695037d92/image.png" alt=""></p>
<p><strong>&quot;책의 목적은 우리 자신들을 평가받는 것이 아니라, 읽는 사람에게 찾아가 온전히 닿는 것이었습니다. 마음을 움직이던, 새로운 것을 알게 해 주던, 어떤 식으로든 읽는 사람에게 변화를 주고 싶었습니다. 또한 그것이 독자에 대한 예의임을 저희도 알았습니다.&quot;</strong></p>
<p>책의 에필로그에 쓰여 있는 문구이다. 평가받는 것에 익숙한 나이일 고등학생들이, 평가에서 벗어나 온전히 읽는 사람을 위한다는 것이 인상 깊게 다가왔다. 이런 에필로그의 말을 체감이라도 하듯 글을 읽는 내내 학생들이 정보를 좀더 쉽게 전달하고, 독자들에게 생각의 여지를 주기 위한 노력을 엿볼 수 있었다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/7c832224-9f16-4d9a-9f06-569c8a6b3662/image.png" alt=""><img src="https://velog.velcdn.com/images/fma_/post/d0b3510c-d1f7-405e-89ac-a82320dc2d5f/image.png" alt=""></p>
<p>고등학생들의 다양한 시각을 드러내는 책이지만 정보 전달 측면도 손색이 없었다. 다소 전문적이고 어려울 수 있는 내용을 최대한 이해하기 쉽게 풀어놓았다는 느낌을 받았다. 그렇다고 수박 겉 핡기 식의 내용도 아니고, 인공지능에 관련해서는 꽤나 전문적인 내용도 많이 들어가 있었다. 경제 관련 내용도 마찬가지였다. 나는 경제에 일절 배경지식이 없는 문외한이지만 어렵게나마 고개를 끄덕이면서 즐겁게 읽은 기억이 있다.</p>
<p><img src="https://velog.velcdn.com/images/fma_/post/1b2251f6-8b1a-480f-bec8-86b5915e0b0a/image.png" alt=""></p>
<p><strong>과학 연구의 이면성을 고찰</strong>한 부분도 존재한다. 과학은 기본적으로 양면성을 띤다. 이 책에서는 이를 적절한 예시를 들며 인공지능도 다르지 않다고 주장한다. 이런 악용 가능성에도 인공지능이 개발되고 있는 건 실보다 득이 많다는 과학자들의 판단으로 인한 것이지만, 인공지능으로 인한 윤리적 문제와 반사회적 영향에 대해 다시 한 번 생각해볼 필요가 있다는 글이다. 2015년에 출판된 책임에도 5년이 지난 지금도 끊임없이 회자되고 있는 부분을 정확히 짚어내었다는 게 놀라웠다. 동시에 과학의 윤리적 문제는 끝나지 않는 굴레에 갇혀있다는 생각도 들었다.</p>
<p>특히 『만들어진 생각』에서 매력적으로 다가왔던 부분은 인공지능이라는 매개체를 통해 인간의 &#39;자아&#39;에 대해 탐구하고, 더 나아가 <strong>&#39;인간&#39;자체에 관해 고찰을 시도</strong>했다는 점이었다. 단순히 과학기술의 집합체로써만 인공지능을 바라보는 것이 아닌 인간의 본질에 관해 탐구한다. 인간은 기능적인 존재가 아닌 인간 자체로서 존재한다는 말은 내가 여태까지 &#39;인간다운 삶&#39;을 살았는지 되돌아보게 하기도 한다.</p>
<p>이런 고찰은 인공지능을 종합학문의 영역으로 끌어들였다는 데 의의가 있다. 요즈음 과학기술은 단순히 기술 영역에 국한되지 않는다. 그중 인간 본질을 다루는 인공지능이야말로 공학, 사회학, 철학 등의 다양한 영역의 집합체라고 할 수 있다. 이런 점에서 과학기술자들의 인문학적 소양을 갖춰야 한다는 목소리가 커지고 있다. 수식과 코드의 늪에서 벗어나 세상을 바라보고 윤리를 사고할 때, 인공지능을 비롯한 공학사회는 바람직한 방향으로 나아갈 수 있을 것이다.</p>
<p><a href="https://search.shopping.naver.com/book/catalog/32490298711">https://search.shopping.naver.com/book/catalog/32490298711</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL 실습 3 : Aggregating Data Using Group Functions]]></title>
            <link>https://velog.io/@fma_/SQL-%EC%8B%A4%EC%8A%B5-3-Aggregating-Data-Using-Group-Functions</link>
            <guid>https://velog.io/@fma_/SQL-%EC%8B%A4%EC%8A%B5-3-Aggregating-Data-Using-Group-Functions</guid>
            <pubDate>Wed, 21 Feb 2024 05:23:47 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>LiveSQL 사용, DB : HR Object and Data</p>
</blockquote>
<blockquote>
<p>KEYWORDS : 그룹 함수, AVG와 SUM 함수, MIN과 MAX 함수, COUNT 함수, GROUP 함수, HAVING 절</p>
</blockquote>
<ol>
<li>모든 사원의 급여 최고액, 최저액, 총액 및 평균액을 표시하십시오. 열 레이블을 각각 Maximum, Minimum, Sum 및 Average로 지정하고 결과를 정수로 반올림 하십시오.</li>
</ol>
<pre><code class="language-sql">SELECT MAX(salary) Maximum, MIN(salary) Minimum, SUM(salary) Sum, ROUND(AVG(salary)) Average
FROM employees</code></pre>
<ol start="2">
<li>1번을 수정하여 각 업무 유형별로 표시하십시오.</li>
</ol>
<pre><code class="language-sql">SELECT job_id, MAX(salary) Maximum, MIN(salary) Minimum, SUM(salary) Sum, ROUND(AVG(salary)) Average
FROM employees
GROUP BY job_id</code></pre>
<ol start="3">
<li>업무가 동일한 사원 수를 표시하는 질의를 작성하십시오.</li>
</ol>
<pre><code class="language-sql">SELECT job_id, COUNT(job_id)
FROM employees
GROUP BY job_id</code></pre>
<ol start="4">
<li>관리자는 나열하지 말고 관리자 수를 확인하십시오. 열 레이블은 Number of Managers로 지정하십시오.</li>
</ol>
<pre><code class="language-sql">SELECT COUNT(manager_id) &quot;Number of Managers&quot;
FROM employees</code></pre>
<ol start="5">
<li>최고 급여와 최저 급여의 차액을 표시하는 질의를 작성하고 열 레이블을 DIFFERENCE로 지정하십시오.</li>
</ol>
<pre><code class="language-lisp">SELECT (MAX(salary) - MIN(salary)) &quot;DIFFERENCE&quot;
FROM employees</code></pre>
<ol start="6">
<li>관리자 번호 및 해당 관리자에 속한 사원의 최저 급여를 표시하십시오. 관리자를 알 수 없는 사원 및 최저 급여가 $6,000 미만인 그룹은 제외시키고 결과를 급여에 대한 내림차순으로 정렬하십시오.</li>
</ol>
<pre><code class="language-sql">SELECT manager_id, MIN(salary)
FROM employees
GROUP BY manager_id, salary
HAVING MIN(salary) &gt; 6000
ORDER BY salary</code></pre>
<ol start="7">
<li>각 부서에 대해 부서 이름, 위치, 사원 수 , 부서 내 모든 사원의 평균 급여를 표시하는 질의를 작성하고, 열 레이블을 각각 Name, Location, Number of People 및 Salary 로 지정하십시오. 평균 급여는 소수점 둘째 자리로 반올림하십시오.</li>
</ol>
<pre><code class="language-sql">select department_id &quot;Name&quot;, count(department_id) &quot;Number of People&quot;, ROUND(avg(salary),2) &quot;Salary&quot;
from employees
group by department_id</code></pre>
<ol start="8">
<li>총 사원 수 및 2005, 2006, 2007, 2008년에 입사한 사원 수를 표시하는 질의를 작성하고 적합한 열 머리글을 작성하십시오.</li>
</ol>
<pre><code class="language-sql">select count(employee_id) &quot;total&quot;,
sum(decode(to_char(hire_date, &#39;YYYY&#39;), 2005, 1, 0)) &quot;2005&quot;,
sum(decode(to_char(hire_date, &#39;YYYY&#39;), 2006, 1, 0)) &quot;2006&quot;,
sum(decode(to_char(hire_date, &#39;YYYY&#39;), 2007, 1, 0)) &quot;2007&quot;,
sum(decode(to_char(hire_date, &#39;YYYY&#39;), 2008, 1, 0)) &quot;2008&quot;
from employees</code></pre>
<ol start="9">
<li>업무를 표시한 다음 해당 업무에 대해 급여 총액과 부서 별 급여 (20, 50, 80, 90)의 총액을 각각 표시하는 형렬 질의를 작성하고 각 열에 적 합한 머리글을 지정하십시오.</li>
</ol>
<pre><code class="language-sql">select job_id &quot;job&quot;,
sum(decode(department_id, 20, salary)) &quot;Dept 20&quot;,
sum(decode(department_id, 50, salary)) &quot;Dept 50&quot;,
sum(decode(department_id, 80, salary)) &quot;Dept 80&quot;,
sum(decode(department_id, 90, salary)) &quot;Dept 90&quot;,
sum(salary) &quot;total&quot;
from employees
group by job_id</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL 실습 2 : Restricting and Sorting Data]]></title>
            <link>https://velog.io/@fma_/SQL-%EC%8B%A4%EC%8A%B5-2-Restricting-and-Sorting-Data</link>
            <guid>https://velog.io/@fma_/SQL-%EC%8B%A4%EC%8A%B5-2-Restricting-and-Sorting-Data</guid>
            <pubDate>Wed, 21 Feb 2024 05:18:48 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>LiveSQL 사용, DB : HR Object and Data</p>
</blockquote>
<ol>
<li>급여가 $12,000를 넘는 사원의 이름과 급여를 표시</li>
</ol>
<pre><code class="language-sql">SELECT first_name, salary
FROM employees
WHERE salary &gt;= 12000;</code></pre>
<ol start="2">
<li>사원 번호가 176인 사원의 이름과 부서 번호 표시</li>
</ol>
<pre><code class="language-sql">SELECT first_name, department_id
FROM employees
WHERE EMPLOYEE_ID=176;</code></pre>
<ol start="3">
<li>급여가 $5,000에서 $12,000 사이에 포함되지 않는 모든 사원의 이름과 급여를 표시</li>
</ol>
<pre><code class="language-sql">select first_name, salary
from employees
where salary not between 5000 and 12000;</code></pre>
<ol start="4">
<li>2007년 2월 20일과 2007년 5월 1일 사이에 입사한 사원의 이름, 업무 ID 및 시작일을 표시하되, 시작일을 기준으로 오름차순으로 정렬하는 질의 – 날짜는 DATE ‘2007-02-20’ 같은 형태로 표시하면 됨</li>
</ol>
<pre><code class="language-sql">select first_name, department_id, hire_date
from employees
where hire_date between to_date(&#39;2007-2-10&#39;, &#39;YYYY-MM-DD&#39;) and to_date (&#39;2007-5-1&#39;, &#39;YYYY-MM-DD&#39;)order by hire_date asc;</code></pre>
<ol start="5">
<li>부서 20 및 50에 속하는 모든 사원의 이름과 부서 번호를 이름을 기준으로 영문자순으로 표시</li>
</ol>
<pre><code class="language-sql">select first_name, department_id
from employees
where department_id = 20 or department_id = 50order by first_name asc;</code></pre>
<ol start="6">
<li>급여가 $5,000와 $12,000 사이이고 부서 번호가 20 또는 50인 사원의 이름과 급여를 나열하고, 열 레이블을 Employee와 Monthly Salary로 각각 지정</li>
</ol>
<pre><code class="language-sql">select first_name &quot;Employee&quot;, department_id &quot;Monthly Salary&quot;
from employees
where (salary between 5000 and 12000) and (department_id = 20 or department_id = 50);</code></pre>
<ol start="7">
<li>1994년에 입사한 모든 사원의 이름과 입사일을 표시</li>
</ol>
<pre><code class="language-sql">select first_name, hire_date
from employees
where hire_date between to_date(&#39;1994-1-1&#39;, &#39;YYYY-MM-DD&#39;) and to_date (&#39;1994-12-31&#39;, &#39;YYYY-MM-DD&#39;);</code></pre>
<ol start="8">
<li>관리자가 없는 모든 사원의 이름과 업무 ID를 표시</li>
</ol>
<pre><code class="language-csharp">select first_name, job_id
from employees
where manager_id is NULL;</code></pre>
<ol start="9">
<li>커미션을 받는 모든 사원의 이름, 급여 및 커미션을 급여 및 커미션을 기준으로 내림차순으로 정렬하여 표시</li>
</ol>
<pre><code class="language-sql">select first_name, salary, commission_pct
from employees
order by salary, commission_pct desc;</code></pre>
<ol start="10">
<li>이름의 세 번째 문자가 a인 모든 사원의 이름을 표시</li>
</ol>
<pre><code class="language-sql">select first_name
from employees
where first_name like &#39;__a%&#39;;</code></pre>
<ol start="11">
<li>이름에 a와 e가 있는 모든 사원의 이름을 표시</li>
</ol>
<pre><code class="language-sql">select first_name
from employees
where first_name like &#39;%a%&#39; and first_name like &#39;%e%&#39;;</code></pre>
<ol start="12">
<li>업무가 영업 사원(SA_REP) 또는 사무원(ST_CLERK)이면서 급여가 $2,500, $3,500 또는 $7,000가 아닌 모든 사원의 이름, 업무 및 급여를 표시</li>
</ol>
<pre><code class="language-sql">select first_name, job_id, salary
from employees
where (job_id = &#39;SA_REP&#39; or job_id = &#39;ST_CLERK&#39;) and salary between 2500 and 3500;</code></pre>
<ol start="13">
<li>커미션 비율이 20%인 모든 사원의 이름, 급여 및 커미션을 표시</li>
</ol>
<pre><code class="language-csharp">select first_name, salary, commission_pct
from employees
where commission_pct = 0.2</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[데이터베이스 시스템 개념정리]]></title>
            <link>https://velog.io/@fma_/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EA%B0%9C%EB%85%90%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@fma_/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EA%B0%9C%EB%85%90%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Wed, 21 Feb 2024 05:14:33 GMT</pubDate>
            <description><![CDATA[<h2 id="11-데이터베이스-시스템-개요">1.1 데이터베이스 시스템 개요</h2>
<blockquote>
<p>KEYWORD : 데이터베이스, 정보, DBMS, 데이터베이스 스키마, 데이터베이스 상태, 데이터베이스 정보, 시스템 카탈로그</p>
</blockquote>
<h3 id="1-데이터베이스의-정의"><strong>1. 데이터베이스의 정의</strong></h3>
<p>데이터베이스는 조직체의 응용 시스템들이 공유해서 사용하는 운영 데이터(operational data)들이 구조적으로 통합된 모임이다. 데이터베이스의 구조는 사용되는 데이터 모델에 의해 결정된다.</p>
<h3 id="2-데이터-vs-정보"><strong>2. 데이터 vs 정보</strong></h3>
<p>데이터 : 현실 세계에서 측정하고 수집한 사실이나 값</p>
<p>정보 : 어떠한 목적이나 의도에 맞게 데이터를 가공 처리한 것</p>
<h3 id="3-데이터베이스의-특징"><strong>3. 데이터베이스의 특징</strong></h3>
<ul>
<li>데이터의 대규모 저장소로서 여러 부서에 속하는 여러 사용자에 의해 동시에 사용됨</li>
<li>모든 데이터가 중복을 최소화하면서 통합됨</li>
<li>한 조직체의 운영 데이터뿐만 아니라 그 데이터에 관한 설명(데이터베이스 스키마 또는 메타데이터)까지 포함</li>
<li>프로그램과 데이터 간의 독립성이 제공됨</li>
<li>효율적으로 접근이 가능하고 질의를 할 수 있음</li>
</ul>
<h3 id="4-용어-정의"><strong>4. 용어 정의</strong></h3>
<p>데이터베이스 관리 시스템(DBMS) : 데이터베이스를 정의하고, 질의어를 지원하고, 리포트를 생성하는 등의 작업을 수행하는 소프트웨어</p>
<p>데이터베이스 스키마 : 전체적인 데이터베이스 구조를 뜻하며 자주 변경되지는 않음. 데이터베이스의 모든 가능한 상태를 미리 정의. 내포(intension)라고 부른다.</p>
<p>데이터베이스 상태 : 특정 시점의 데이터베이스의 내용을 의미하며, 시간이 지남에 따라 계속해서 바뀜. 외연(extension)이라고 부른다.</p>
<h3 id="5-데이터베이스-시스템dbs의-구성-요소">5<strong>. 데이터베이스 시스템(DBS)의 구성 요소</strong></h3>
<p><img src="https://velog.velcdn.com/images/fma_/post/6f048895-aa64-4c00-963d-faf7af853fa1/image.png" alt=""></p>
<ul>
<li>조직체의 응용 시스템들이 사용하는 운영 데이터들이 구조적으로 통합된 모임</li>
<li>시스템 카탈로그(또는 데이터 사전)와 저장된 데이터베이스로 구분할 수 있음</li>
<li>시스템 카탈로그(system catalog)는 데이터베이스의 스키마 정보를 유지</li>
</ul>
<p><img src="https://velog.velcdn.com/images/fma_/post/ef6284f8-21a4-4546-aeab-8a18c98e2028/image.png" alt=""></p>
<ul>
<li>DBMS<ul>
<li>사용자가 새로운 데이터베이스를 생성하고, 데이터베이스의 구조를 명시할 수 있게 하고, 사용자가 데이터를 효율적으로 질의하고 수정할 수 있도록 하며, 시스템의 고장이나 권한이 없는 사용자로부터 데이터를 안전하게 보호하며, 동시에 여러 사용자가 데이터베이스를 접근하는 것을 제어하는 소프트웨어 패키지</li>
<li>데이터베이스 언어라고 부르는 특별한 프로그래밍 언어를 한 개 이상 제공SQL은 여러 DBMS에서 제공되는 사실상의 표준 데이터베이스 언어</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/fma_/post/53d60fd4-5847-4e0f-98f7-58e5eded83a9/image.png" alt=""></p>
<ul>
<li>사용자<ul>
<li>데이터베이스 사용자는 여러 부류로 나눌 수 있음</li>
</ul>
</li>
<li>하드웨어<ul>
<li>데이터베이스는 디스크와 같은 보조 기억 장치에 저장되며, DBMS에서 원하는 정보를 찾기 위해서는 디스크의 블록들을 주기억 장치로 읽어들여야 하며, 계산이나 비교 연산들을 수행하기 위해 중앙 처리 장치가 사용됨</li>
<li>DBMS 자체도 주기억 장치에 적재되어 실행되어야 함</li>
</ul>
</li>
<li>데이터베이스 시스템의 요구사항<ul>
<li>데이터 독립성</li>
<li>효율적인 데이터 접근</li>
<li>데이터에 대한 동시 접근</li>
<li>백업과 회복</li>
<li>중복을 줄이거나 제어하며 일관성 유지</li>
<li>데이터 무결성</li>
<li>데이터 보안</li>
<li>쉬운 질의어</li>
<li>사용자 인터페이스</li>
</ul>
</li>
</ul>
<h2 id="12-화일-시스템-vs-dbms">1.2 화일 시스템 vs DBMS</h2>
<blockquote>
<p>KEYWORD : 화일 시스템, DBMS, 프로그램-데이터 독립성</p>
</blockquote>
<h3 id="1-화일-시스템을-사용한-기존의-데이터-관리"><strong>1. 화일 시스템을 사용한 기존의 데이터 관리</strong></h3>
<ul>
<li>화일 시스템은 DBMS가 등장하지 않았을 때인 1960년대부터 사용되어 왔음</li>
<li>화일의 기본적인 구성요소는 순차적인 레코드들</li>
<li>한 레코드는 연관된 필드들의 모임</li>
<li>화일을 접근하는 방식이 응용 프로그램 내에 상세하게 표현되므로 데이터에 대한 응용 프로그램의 의존도가 높음</li>
</ul>
<p><img src="https://velog.velcdn.com/images/fma_/post/cbc92f86-35d4-4873-aac1-6a2b3328e7b9/image.png" alt=""></p>
<ul>
<li>Employess 화일에 사원의 휴대폰 번호 추가하려면 : Employee 화일의 레코드를 하나씩 읽어서, 휴대폰 번호 필드를 추가한 레코드를 새로운 Employee 화일에 기록하는 프로그램을 작성 -&gt; 기존 Employee 화일을 사용하던 모든 응용 프로그램을 찾아서 휴대폰 번호 필드를 추가해야 함</li>
<li>화일 시스템의 단점</li>
<li>데이터가 많은 화일에 중복해서 저장됨</li>
<li>다수 사용자들을 위한 동시성 제어가 제공되지 않음</li>
<li>보안 조치가 미흡</li>
<li>회복 기능이 없음</li>
<li>프로그램-데이터 독립성이 없으므로 유지보수 비용이 많이 소모됨</li>
<li>화일을 검색하거나 갱신하는 절차가 상대적으로 복잡하기 때문에 프로그래머의 생산성이 낮음</li>
<li>데이터의 공유와 융통성이 부족</li>
</ul>
<h3 id="2-dbms를-사용한-데이터베이스의-관리"><strong>2. DBMS를 사용한 데이터베이스의 관리</strong></h3>
<ul>
<li>여러 사용자와 응용 프로그램들이 데이터베이스를 공유</li>
<li>사용자의 질의를 빠르게 수행할 수 있는 인덱스 등의 접근 경로를 DBMS가 자동적으로 선택하여 수행</li>
<li>권한이 없는 사용자로부터 데이터베이스를 보호</li>
<li>여러 사용자에 적합한 다양한 인터페이스를 제공</li>
<li>데이터 간의 복잡한 관계를 표현하며, 무결정 제약조건을 DBMS가 자동으로 유지</li>
<li>시스템이 고장나면 데이터베이스를 고장 전의 일관된 상태로 회복시킴</li>
<li>프로그램-데이터 독립성(program-data independence) 프로그램에 영향을 주지 않으면서 데이터베이스 구조를 변경할 수 있음</li>
</ul>
<h3 id="3-화일-시스템-vs-dbms"><strong>3. 화일 시스템 vs DBMS</strong></h3>
<table>
<thead>
<tr>
<th>화일 시스템 방식</th>
<th>DBMS 방식</th>
</tr>
</thead>
<tbody><tr>
<td>데이터에 대한 물리적 접근만 조정한다.</td>
<td>데이터에 대한 물리적 접근과 논리적인 접근을 모두 조정한다</td>
</tr>
<tr>
<td>동일한 화일을 두 개 이상의 프로그램이 동시에 접근할 수 없다.</td>
<td>동일한 데이터를 다수 사용자가 동시에 접근할 수 있다.</td>
</tr>
<tr>
<td>데이터가 비구조적이며, 중복성과 유지보수 비용이 높다.</td>
<td>데이터가 구조화되어 있으며, 중복성과 유지보수 비용이 낮다.</td>
</tr>
<tr>
<td>어떻게 프로그램이 기록한 데이터는 다른 프로그램에서 읽을 수 없는 경우가 많다.</td>
<td>접근 권한이 있는 모든 프로그램이 데이터를 공유한다.</td>
</tr>
<tr>
<td>데이터에 대한 접근은 미리 작성된 프로그램을 통해서만 가능하다.</td>
<td>질의어를 사용하여 데이터에 대한 융통성 있는 접근이 가능하다.</td>
</tr>
<tr>
<td>각 응용 프로그램마다 화일이 따로 있으므로 데이터가 통합되어 있지 않다.</td>
<td>데이터가 중복을 배제하면서 통합되어 있다.</td>
</tr>
</tbody></table>
<h3 id="4-dbms-선정시-고려-사항"><strong>4. DBMS 선정시 고려 사항</strong></h3>
<ul>
<li>기술적 요인DBMS에 사용되고 있는 데이터 모델, DBMS가 지원하는 사용자 인터페이스, 프로그래밍 언어, 응용 개발 도구, 저장 구조, 성능, 접근 방법 등</li>
<li>경제적 요인소프트웨어와 하드웨어 구입 비용, 유지 보수 비용, 직원들의 교육 지원 등</li>
</ul>
<h3 id="5-dbms의-장단점"><strong>5. DBMS의 장단점</strong></h3>
<p>장점</p>
<ul>
<li>중복성과 불일치가 감소됨</li>
<li>시스템을 개발하고 유지하는 비용이 감소됨</li>
<li>표준화를 시행하기가 용이</li>
<li>보안이 향상됨</li>
<li>무결성이 향상됨</li>
<li>조직체의 요구사항을 식별할 수 있음</li>
<li>다양한 유형의 고장으로부터 데이터베이스를 회복할 수 있음</li>
<li>데이터베이스의 공유와 동시 접근 가능</li>
</ul>
<p>단점</p>
<ul>
<li>추가적인 하드웨어 구입 비용이 들고, DBMS 자체의 구입 비용도 상당히 비쌈</li>
<li>직원들의 교육 비용도 많이 소요됨</li>
<li>비밀과 프라이버시 노출 등의 단점이 존재할 수 있음</li>
<li>초기의 투자 비용이 너무 클 때, 오버헤드가 많이 들 때, 응용이 단순하고 잘 정의되었으며 변경되지 않을 것으로 예상될 때, 엄격한 실시간 처리 요구사항이 있을 때, 데이터에 대한 다수 사용자의 접근이 필요하지 않을 때는 DBMS를 사용하지 않는 것이 바람직할 수 있음</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[SPSS t검정 정리]]></title>
            <link>https://velog.io/@fma_/SPSS-t%EA%B2%80%EC%A0%95-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@fma_/SPSS-t%EA%B2%80%EC%A0%95-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Wed, 21 Feb 2024 05:01:07 GMT</pubDate>
            <description><![CDATA[<h2 id="1-대응표본-t검정paired-saples-t-test--하나의-짝을-이룬-값의-차를-검증">1. 대응표본 t검정(Paired-Saples T-test) : 하나의 짝을 이룬 값의 차를 검증</h2>
<p><strong><a href="https://youtu.be/9Teo-PDm-eU">https://youtu.be/9Teo-PDm-eU</a></strong></p>
<p>하나의 동일 집단으로부터 두 개의 수치 차이 비교. 독립변수x, 양적인 종속변수 두 개</p>
<p>사전-사후 관계성 비교에 적합</p>
<ul>
<li>대응표본 통계량 : 차이를 보고자 한 두 변수 각각의 평균, 표본 수, 표준화 편차, 표준오차 평균</li>
<li>대응표본 상관계수 : 두 변수가 모두 양적인 종속변수이기 때문에 두 변수간의 상관계수를 보여주는 표상관계수 : 두 변량 사이의 상관관계의 정도를 나타내는 수치(계수)유의확률(p-값) : 귀무가설(의미있는 차이가 없음, 처음부터 버릴 걸 가정하는 가설)이 맞다고 가정할 때 얻은 결과보다 극단적인 결과가 실제로 관측될 확률</li>
<li>대응표본 검정표 : 실제 우리가 보고자 했던 가설을 검정해주는 결과표. 유의확률이 0.05기준으로 작게 나타남 -&gt; 귀무가설 기각, 대립가설 채택평균 : 두 종속변수 사이의 차이가 얼마나 나타났는지.</li>
</ul>
<h2 id="2-대응표본-t검정-논문-해석-방법">2. 대응표본 t검정 논문 해석 방법</h2>
<p><strong><a href="https://youtu.be/szk5PGANt4Q">https://youtu.be/szk5PGANt4Q</a></strong></p>
<h2 id="3-독립표본-t검정independent-sample-t-test">3. 독립표본 t검정(Independent-sample t-test)</h2>
<p><strong><a href="https://youtu.be/2GVLu8a4J2I">https://youtu.be/2GVLu8a4J2I</a></strong></p>
<p>서로 다른 두 집단의 평균 차이. 두 집단 간의 1:1 평균 비교</p>
<p>독립변수(원인)과 종속변수(결과)가 존재, 두 집단 모두 정규성을 만족해야 함</p>
<ul>
<li>대립가설(H1) : 두 집단의 평균이 같지 않다 = 두 집단의 평균에 차이가 있다</li>
<li>귀무가설(H0) : 두 집단의 평균이 같다 = 두 집단의 평균에 차이가 있다</li>
</ul>
<p>변수</p>
<ul>
<li>두 집단 : 독립변수(응답범주가 두 개인 명목척도) / 평균 : 종속변수(등간 또는 비율척도)</li>
<li>검정변수 칸에 종속변수, 집단변수 칸에 독립변수 넣기 -&gt; 집단 정의</li>
</ul>
<p>결과창</p>
<ul>
<li>집단통계량 : n&gt;=30 -&gt; 중심극한정리에 의해 정규성 만족.</li>
<li>독립표본 검정 : Levene의 등분산 검정 F대립가설(H1) : 등분산이 아니다대립가설(H2) : 등분산이다유의확률(p) &lt; 0.05 = 등분산을 가정하지 않음유의확률(p) &gt; 0.05 = 등분산을 가정함</li>
</ul>
<h2 id="4-독립표본-t검정-논문-해석-방법">4. 독립표본 t검정 논문 해석 방법</h2>
<p><strong><a href="https://youtu.be/I8wyP5bW2nA">https://youtu.be/I8wyP5bW2nA</a></strong></p>
]]></description>
        </item>
    </channel>
</rss>