<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>su-daa.log</title>
        <link>https://velog.io/</link>
        <description>아직은 감자</description>
        <lastBuildDate>Thu, 08 Jan 2026 01:22:59 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>su-daa.log</title>
            <url>https://velog.velcdn.com/images/su-daa/profile/cc7d8385-e5b2-436b-a6a6-820214a0d493/social_profile.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. su-daa.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/su-daa" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[자바 .class(클래스) 파일 디컴파일  사이트]]></title>
            <link>https://velog.io/@su-daa/%EC%9E%90%EB%B0%94-.class%ED%81%B4%EB%9E%98%EC%8A%A4-%ED%8C%8C%EC%9D%BC-%EB%94%94%EC%BB%B4%ED%8C%8C%EC%9D%BC-%EC%82%AC%EC%9D%B4%ED%8A%B8</link>
            <guid>https://velog.io/@su-daa/%EC%9E%90%EB%B0%94-.class%ED%81%B4%EB%9E%98%EC%8A%A4-%ED%8C%8C%EC%9D%BC-%EB%94%94%EC%BB%B4%ED%8C%8C%EC%9D%BC-%EC%82%AC%EC%9D%B4%ED%8A%B8</guid>
            <pubDate>Thu, 08 Jan 2026 01:22:59 GMT</pubDate>
            <description><![CDATA[<p>자바 .class 파일을 .java 로 디컴파일 해주는 온라인 웹사이트가 있습니다.</p>
<p>url: <a href="http://www.javadecompilers.com/">http://www.javadecompilers.com/</a>
<img src="https://velog.velcdn.com/images/su-daa/post/e25746ad-e97f-4877-a6ce-074015398076/image.png" alt=""></p>
<p>파일 선택 버튼을 클릭해서 파일탐색기에서 파일을 선택하거나 바로 드래그 앤 드롭으로 파일을 넣은후 
<img src="https://velog.velcdn.com/images/su-daa/post/f3f370d1-8c00-4de7-bd65-c41e4a31d9fc/image.png" alt="">
<img src="https://velog.velcdn.com/images/su-daa/post/7a88dbf6-5f84-402f-9974-7d97684f731d/image.png" alt="">
해당 버튼을 누르면 .java 로 변환된 코드를 볼 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL 기초]]></title>
            <link>https://velog.io/@su-daa/SQL-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@su-daa/SQL-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Wed, 10 Apr 2024 01:32:34 GMT</pubDate>
            <description><![CDATA[<p>🔖 데이터베이스 생성</p>
<pre><code class="language-sql">CREATE DATABASE opentutorials;</code></pre>
<p>🔖 데이터베이스 사용</p>
<pre><code class="language-sql">USE opentutorials;</code></pre>
<p>🔖 테이블 생성</p>
<pre><code class="language-sql">CREATE TABLE topic(
    -&gt; id INT(11) NOT NULL AUTO_INCREMENT,
    -&gt; title VARCHAR(100) NOT NULL,
    -&gt; description TEXT NULL,
    -&gt; created DATETIME NOT NULL,
    -&gt; author VARCHAR(30) NULL,
    -&gt; profile VARCHAR(100) NULL,
    -&gt; PRIMARY KEY(id));</code></pre>
<p>🔖 테이블 구성요소 살펴보기</p>
<pre><code class="language-sql">DESC topic;
+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| id          | int          | NO   | PRI | NULL    | auto_increment |
| title       | varchar(100) | NO   |     | NULL    |                |
| description | text         | YES  |     | NULL    |                |
| created     | datetime     | NO   |     | NULL    |                |
| author      | varchar(30)  | YES  |     | NULL    |                |
| profile     | varchar(100) | YES  |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+</code></pre>
<p>🔖 테이블에 데이터 추가</p>
<pre><code class="language-sql">INSERT INTO topic (title,description,created,author,profile) VALUES (&#39;MySQL&#39;,&#39;MySQL is ...&#39;,NOW(),&#39;egoing&#39;,&#39;developer&#39;);</code></pre>
<p>🔖 테이블 모든 데이터 읽기</p>
<pre><code class="language-sql">SELECT * FROM topic;
+----+------------+-------------------+---------------------+--------+---------------------------+
| id | title      | description       | created             | author | profile                   |
+----+------------+-------------------+---------------------+--------+---------------------------+
|  1 | MySQL      | MySQL is ...      | 2024-04-09 06:22:04 | egoing | developer                 |
|  2 | ORACLE     | ORACLE is ...     | 2024-04-09 06:23:50 | egoing | developer                 |
|  3 | SQL Server | SQL Server is ... | 2024-04-09 06:24:44 | duru   | data administrator        |
|  4 | PostgreSQL | PostgreSQL is ... | 2024-04-09 06:25:27 | taeho  | data scientist, developer |
|  5 | MongoDB    | MongoDB is ...    | 2024-04-09 06:25:57 | egoing | developer                 |
+----+------------+-------------------+---------------------+--------+---------------------------+
5 rows in set (0.00 sec)</code></pre>
<p>🔖 원하는 컬럼만 읽기</p>
<pre><code class="language-sql">SELECT id,title,author FROM topic;
+----+------------+--------+
| id | title      | author |
+----+------------+--------+
|  1 | MySQL      | egoing |
|  2 | ORACLE     | egoing |
|  3 | SQL Server | duru   |
|  4 | PostgreSQL | taeho  |
|  5 | MongoDB    | egoing |
+----+------------+--------+</code></pre>
<p>🔖 기본 조건절 사용해서 읽기</p>
<pre><code class="language-sql">SELECT id,title,author FROM topic WHERE author=&#39;egoing&#39;;
+----+---------+--------+
| id | title   | author |
+----+---------+--------+
|  1 | MySQL   | egoing |
|  2 | ORACLE  | egoing |
|  5 | MongoDB | egoing |
+----+---------+--------+</code></pre>
<p>🔖 정렬해서 읽기 (기본은 ASC=오름차순)</p>
<pre><code class="language-sql">SELECT id,title,author FROM topic WHERE author=&#39;egoing&#39; ORDER BY id DESC;
+----+---------+--------+
| id | title   | author |
+----+---------+--------+
|  5 | MongoDB | egoing |
|  2 | ORACLE  | egoing |
|  1 | MySQL   | egoing |
+----+---------+--------+</code></pre>
<p>🔖 갯수 제한해서 읽기</p>
<pre><code class="language-sql"> SELECT id,title,author FROM topic WHERE author=&#39;egoing&#39;ORDER BY id DESC LIMIT 2;
+----+---------+--------+
| id | title   | author |
+----+---------+--------+
|  5 | MongoDB | egoing |
|  2 | ORACLE  | egoing |
+----+---------+--------+</code></pre>
<p>🔖 데이터 수정하기(업데이트하기)</p>
<pre><code class="language-sql">UPDATE topic SET description=&#39;Oracle is ...&#39;, title=&#39;Oracle&#39; WHERE id=2

SELECT * FROM topic;
+----+------------+-------------------+---------------------+--------+---------------------------+
| id | title      | description       | created             | author | profile                   |
+----+------------+-------------------+---------------------+--------+---------------------------+
|  1 | MySQL      | MySQL is ...      | 2024-04-09 06:22:04 | egoing | developer                 |
|  2 | Oracle     | Oracle is ...     | 2024-04-09 06:23:50 | egoing | developer                 |
|  3 | SQL Server | SQL Server is ... | 2024-04-09 06:24:44 | duru   | data administrator        |
|  4 | PostgreSQL | PostgreSQL is ... | 2024-04-09 06:25:27 | taeho  | data scientist, developer |
|  5 | MongoDB    | MongoDB is ...    | 2024-04-09 06:25:57 | egoing | developer                 |
+----+------------+-------------------+---------------------+--------+---------------------------+</code></pre>
<p>🔖 데이터 삭제하기</p>
<pre><code class="language-sql">DELETE FROM topic WHERE id=5;

SELECT * FROM topic;
+----+------------+-------------------+---------------------+--------+---------------------------+
| id | title      | description       | created             | author | profile                   |
+----+------------+-------------------+---------------------+--------+---------------------------+
|  1 | MySQL      | MySQL is ...      | 2024-04-09 06:22:04 | egoing | developer                 |
|  2 | Oracle     | Oracle is ...     | 2024-04-09 06:23:50 | egoing | developer                 |
|  3 | SQL Server | SQL Server is ... | 2024-04-09 06:24:44 | duru   | data administrator        |
|  4 | PostgreSQL | PostgreSQL is ... | 2024-04-09 06:25:27 | taeho  | data scientist, developer |
+----+------------+-------------------+---------------------+--------+---------------------------+</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Docker로 MySQL설치하고 실행하기]]></title>
            <link>https://velog.io/@su-daa/Docker%EB%A1%9C-MySQL%EC%84%A4%EC%B9%98%ED%95%98%EA%B3%A0-%EC%8B%A4%ED%96%89%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@su-daa/Docker%EB%A1%9C-MySQL%EC%84%A4%EC%B9%98%ED%95%98%EA%B3%A0-%EC%8B%A4%ED%96%89%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 08 Apr 2024 14:44:45 GMT</pubDate>
            <description><![CDATA[<p>MySQL root 비밀번호를 까먹어서 지워버리고 새로운 마음으로 도커로 MySQL를 설치하고 사용하기로 했다!</p>
<p>💡 먼저 Docker가 설치되어있다는 전제하에</p>
<h3 id="1-mysql-이미지-다운로드">1. MySQL 이미지 다운로드</h3>
<ul>
<li>명령어로 원하는 버전의 MySQL 이미지를 다운받거나</li>
<li>docker desktop에서 직접 검색해서 다운받을수도 있다<ul>
<li>아래 캡처 사진에서 원하는 버전 선택하고 pull 누르면 이미지를 다운 받을 수 있다<pre><code class="language-bash">$ docker pull mysql:8.0.36</code></pre>
</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/su-daa/post/b255f369-fd97-48bd-ac03-fbcf6f774750/image.png" alt=""></p>
<h3 id="2-다운받은-이미지-확인">2. 다운받은 이미지 확인</h3>
<p>아래 명령어로 다운받은 이미지를 확인 할 수 있다</p>
<pre><code class="language-bash">$ docker images
REPOSITORY            TAG        IMAGE ID       CREATED         SIZE
mysql                 latest     3d6757ec48c5   13 days ago     638MB
redis                 7-alpine   0be8a78a8b83   2 months ago    46.5MB</code></pre>
<ul>
<li>mysql, redis가 있는걸 볼 수 있다</li>
</ul>
<h3 id="3-mysql-docker-컨테이너-생성">3. MySQL Docker 컨테이너 생성</h3>
<pre><code class="language-bash">$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=1234 -p 3306:3306 mysql:8.0.36</code></pre>
<p><code>mysql</code> : 원하는 컨테이너 이름 작성
MYSQL_ROOT_PASSWORD=<code>1234</code> : root 계정 비밀번호 설정
<code>3306</code>:<code>3306</code> : 외부포트:docker 내부포트 설정
<code>8.0.36</code>: 원하는 MySQL버전</p>
<h3 id="4-생성된-컨테이너-확인">4. 생성된 컨테이너 확인</h3>
<pre><code class="language-bash">$ docker ps
CONTAINER ID   IMAGE     COMMAND                   CREATED       STATUS          PORTS                               NAMES
147ac55c1fe5   mysql     &quot;docker-entrypoint.s…&quot;   3 hours ago   Up 19 minutes   0.0.0.0:3306-&gt;3306/tcp, 33060/tcp   mysql</code></pre>
<ul>
<li>ps: 실행중인 컨테이너 목록 확인</li>
<li>ps -a: 정지 되어 있는 컨테이너 까지 모든 컨테이너 목록 확인</li>
</ul>
<p><img src="https://velog.velcdn.com/images/su-daa/post/ce3c48a9-bcf0-4c0f-ae4c-0b0f38d2e3b0/image.png" alt=""></p>
<h3 id="5-컨테이너-bash-쉘-접속하기">5. 컨테이너 bash 쉘 접속하기</h3>
<p>컨테이너를 실행시킨 후 bash쉘에 접속한다</p>
<p>컨테이너 시작</p>
<pre><code>$ docker start mysql</code></pre><ul>
<li><code>mysql</code> : 컨테이너 이름</li>
</ul>
<pre><code class="language-bash">$ docker exec -it mysql bash
bash-4.4#</code></pre>
<p>접속하면 위와같이 <code>bash-4.4#</code> 가 나올 것이다</p>
<p><img src="https://velog.velcdn.com/images/su-daa/post/f0fb04df-6e6c-4ac4-8058-fd22b74c448c/image.png" alt=""></p>
<ul>
<li>docker desktop에서는 오른쪽 메뉴의 &#39;Open in terminal&#39;을 눌러도 접속할 수 있다</li>
</ul>
<h3 id="6-mysql-서버-접속">6. MySQL 서버 접속</h3>
<pre><code class="language-bash">bash-4.4# mysql -u root -p
Enter password:</code></pre>
<p><code>mysql -u root -p</code> 를 치면 위와 같이 비밀번호를 치라고 나오고 위에 설정해준 비밀번호를 치면</p>
<pre><code>Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.3.0 MySQL Community Server - GPL

Copyright (c) 2000, 2024, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type &#39;help;&#39; or &#39;\h&#39; for help. Type &#39;\c&#39; to clear the current input statement.

mysql&gt;</code></pre><p>접속완료!</p>
<hr>
<p>참고</p>
<ul>
<li><a href="https://velog.io/@hanif/%EB%8F%84%EC%BB%A4-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-%EB%8B%A4%EB%A3%A8%EA%B8%B0">https://velog.io/@hanif/%EB%8F%84%EC%BB%A4-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-%EB%8B%A4%EB%A3%A8%EA%B8%B0</a></li>
<li><a href="https://www.inflearn.com/course/%EB%8F%99%EC%8B%9C%EC%84%B1%EC%9D%B4%EC%8A%88-%EC%9E%AC%EA%B3%A0%EC%8B%9C%EC%8A%A4%ED%85%9C/dashboard">https://www.inflearn.com/course/%EB%8F%99%EC%8B%9C%EC%84%B1%EC%9D%B4%EC%8A%88-%EC%9E%AC%EA%B3%A0%EC%8B%9C%EC%8A%A4%ED%85%9C/dashboard</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[포트원(아임포트) 이용하여 결제 구현하기]]></title>
            <link>https://velog.io/@su-daa/%ED%8F%AC%ED%8A%B8%EC%9B%90%EC%95%84%EC%9E%84%ED%8F%AC%ED%8A%B8-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-%EA%B2%B0%EC%A0%9C-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@su-daa/%ED%8F%AC%ED%8A%B8%EC%9B%90%EC%95%84%EC%9E%84%ED%8F%AC%ED%8A%B8-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-%EA%B2%B0%EC%A0%9C-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 17 Mar 2024 17:45:07 GMT</pubDate>
            <description><![CDATA[<p>부트캠프의 마지막 프로젝트로 무료 취소 불가한 숙박 상품 거래 플랫폼을 만들게 되었고 그 중 결제부분을 맡게 되었다.</p>
<p>우리 서비스가 네고기능도 있고 여러가지의 상태값, 예를들어 상품상태, 네고상태, 주문상태...에 따라서 처리해야할 것들이 많아서 결제만 깔끔하게 딱 이루어진 코드는 없지만 각 상태에 따라서 결제를 어떻게 처리 했는지 기록해보려고 한다.
pg사 연동 코드를 찾는 이들에게 조금의 도움이 될까 싶어 끄적끄적 적어보았다</p>
<h3 id="erd">ERD</h3>
<p><img src="https://velog.velcdn.com/images/su-daa/post/ed2c4c44-b734-4432-8691-8068c12c06df/image.png" alt="">
프로젝트의 전체적인 erd는 위와 같고 내가 집중해서 봐야하는 쪽은 아래 확대한 부분이다
<img src="https://velog.velcdn.com/images/su-daa/post/e1543429-0e5c-48a3-939a-52c67c2e1eef/image.png" alt="">
<img src="https://velog.velcdn.com/images/su-daa/post/df0cb958-2629-42ba-bc49-a1078f3b3770/image.png" alt="">
상품 테이블: 등록된 상품에 대한 정보
주문 테이블: 결제 상세 페이지에 들어가게 되었을때 저장되는 주문 관련 정보
네고 테이블: 네고를 진행 했을시 저장되는 정보
결제 테이블: 결제 시도 후 포트원 결제 단건조회 결과를 저장
취소내역 테이블: 환불 시 저장되는 결제 관련 정보</p>
<h3 id="1-포트원-라이브러리-설정">1. 포트원 라이브러리 설정</h3>
<p>build.gradle</p>
<pre><code>repositories {
    mavenCentral()

    //iamport
    maven {
        url &#39;https://jitpack.io&#39;
    }
}

dependencies{
    //iamport
    implementation &#39;com.github.iamport:iamport-rest-client-java:0.2.23&#39;
}</code></pre><h3 id="2-config-파일-설정">2. config 파일 설정</h3>
<p>imp_key, imp_secret_key는 properties 파일에 올리고 숨겨서 사용하였다.
그리고 IamportClient를 빈으로 등록하여 사용할수 있도록 설정하였다</p>
<p>IamportApiProperty.java</p>
<pre><code class="language-java">@Getter
@Configuration
@PropertySource(&quot;classpath:/secret.properties&quot;)
public class IamportApiProperty {
    @Value(&quot;${imp_key}&quot;)
    private String impKey;
    @Value(&quot;${imp_secret}&quot;)
    private String impSecret;
}</code></pre>
<p>IamportConfig.java</p>
<pre><code class="language-java">@Configuration
@RequiredArgsConstructor
public class IamportConfig {
    private final IamportApiProperty iamportApiProperty;

    @Bean
    public IamportClient iamportClient() {
        return new IamportClient(iamportApiProperty.getImpKey(), iamportApiProperty.getImpSecret());
    }
}
</code></pre>
<h3 id="3-주문-상세-페이지">3. 주문 상세 페이지</h3>
<p>전체적인 결제 진행 과정과 상태값은 다음과 같다. </p>
<h4 id="결제-진행-과정">결제 진행 과정</h4>
<p>주문 상세 페이지 -(결제 버튼 누름)→ 사전 검증 -(사전검증 성공시)→ 프론트 측에서 pg사 결제 진행 -(결제 완료 시 결제 결과 서버측으로 넘김)→ 사후 검증 -(사후검증 완료시)→ 결제 완료</p>
<h4 id="상태값">상태값</h4>
<p><img src="https://velog.velcdn.com/images/su-daa/post/62725e26-7520-4ea0-859b-5f7c8e0dd9de/image.png" alt=""></p>
<blockquote>
<p>우리의 서비스는 네고가 만약 성공했다면 그 사람에게 해당 상품이 20분간 예약이 되고 그 시간동안에 다른사람은 해당 상품을 구매할수도, 네고할 수도 없다. 
그리고 만약 그 사람이 해당 상품을 20분 내에 구매하지 않았더라도 네고에 성공했기 때문에 그 사람은 네고를 성공한 가격에 해당 상품을 구매할 수 있도록 해야했다.
그래서 위와 같이 많은 상태값을 이용하게 되었다.</p>
</blockquote>
<p>사용자가 주문하기 버튼을 눌렀을때 주문 상세 페이지로 들어오게 되고 이때 주문 테이블에 주문 정보를 저장한다.
(최대한 결제관련해서만 적어보려고 생략한 부분이 많습니다! 자세한 코드는 아래 깃허브 링크를 참고해주세요 :-) )</p>
<p>PaymentService.java</p>
<pre><code class="language-java">public PaymentDetailResponse getPaymentDetail(Long productId,
        PrincipalDetails principalDetails) {
        User user = userService.findById(principalDetails.getUserId());

        //상품상태에 따른 처리 과정 생략

        int price = product.getGoldenPrice();

        Order order = Order.of(product.getId(), user.getId(), null, price);

        //네고 확인하는 과정 생략

        Order savedOrder = orderRepository.save(order);

        return PaymentDetailResponse.of(savedOrder.getId(), user, product, price,
            product.getYanoljaPrice());
    }</code></pre>
<h3 id="4-사전검증">4. 사전검증</h3>
<p>사전검증시 백엔드에서는 포트원측에 주문 id , 결제 금액을 저장하는 작업을 진행한다.
해당 작업이 완료되면 프론트 측으로 결제 관련 정보들을 응답으로 넘겨 주게 되고 응답으로 넘어온 데이터를 이용하여 포트원 결제를 진행하도록 하였다.</p>
<p>이때, 포트원 측에 주문 id, 결제 금액을 저장하는 이유는 넘어온 데이터를 이용하여 포트원 결제를 진행할때 포트원 측에서 저장된 데이터와 결제를 진행하는 데이터가 같은지 검증하기 위하여 다음과 같은 처리를 한다고 한다!</p>
<p>PaymentController.java</p>
<pre><code class="language-java">@PostMapping(&quot;/{orderId}/prepare&quot;)
    public ResponseEntity&lt;CommonResponse&lt;PaymentReadyResponse&gt;&gt; preparePayment(
            @PathVariable(name = &quot;orderId&quot;) final Long productId,
            @AuthenticationPrincipal PrincipalDetails principalDetails) {
        PaymentReadyResponse paymentReadyResponse = paymentService.preparePayment(productId, principalDetails);
        return ResponseEntity.ok(CommonResponse.ok(&quot;Payment ready successfully&quot;, paymentReadyResponse));
    }</code></pre>
<p>PaymentService.java</p>
<pre><code class="language-java">public PaymentReadyResponse preparePayment(Long orderId, PrincipalDetails principalDetails) {

        User user = userService.findById(principalDetails.getUserId());

        Order order = orderRepository.findById(orderId).orElseThrow(
            () -&gt; new CustomException(ErrorCode.ORDER_NOT_FOUND)
        );

        Product product = productService.getProduct(order.getProductId());
        if (product.isNotOnSale()) {
            throw new CustomException(ErrorCode.PRODUCT_NOT_ON_SALE);
        }

        //상품상태 = 예약중, 해당 경우에 본인이 네고를 진행하였고 결제 대기중인지 확인
        Optional&lt;Nego&gt; nego = negoRepository.findFirstByUser_IdAndProduct_IdOrderByCreatedAtDesc(
            user.getId(), product.getId());
        if (product.getProductStatus() == ProductStatus.RESERVED) {
            if (nego.isEmpty()) {
                throw new CustomException(ErrorCode.PRODUCT_NOT_ON_SALE);
            }
            if (nego.get().getStatus() != NegotiationStatus.PAYMENT_PENDING) {
                throw new CustomException(ErrorCode.PRODUCT_NOT_ON_SALE);
            }
        }

        //주문 상태 = 결제 대기중 으로 변경
        order.requestPayment();

        //포트원 측에 주문 id, 결제 금액을 저장 
        iamportRepository.prepare(order.getId(), BigDecimal.valueOf(order.getTotalPrice()));
        return PaymentReadyResponse.create(user, product, order);
    }</code></pre>
<h3 id="5-사후-검증">5. 사후 검증</h3>
<p>포트원 측에 저장된 실제 결제값과 우리쪽 주문 데이터베이스에 저장된 결제되어야 하는 값을 비교하는 작업을 진행한다. 
이때 우리의 결과값은 SUCCESS ,TIME_OVER, FAILED 세가지였다.
SUCCESS = 정상적으로 결제 완료된 건
TIME_OVER = 네고 성공 후 시간 초과
FAILED = 결제가 되지 않은 경우, 더 이상 살 수 없는 상품일 경우</p>
<blockquote>
<p>여기서 네고 성공한 사람이 주문 상세 페이지에 들어올때는 20분간 예약중인 시간 내에 들어왔지만 결제 완료시에 그 시간이 지났다면 해당 거래를 취소시키도록 서비스가 기획되었다.</p>
</blockquote>
<p>이때 TIME_OVER인 경우와 FAILED에서 더 이상 살 수 없는 상품일 경우에는 이미 사용자의 카드 결제가 완료 되었지만 주문을 실패처리해야하기 때문에 결제된 것을 취소처리 하는 과정을 추가하였다.</p>
<p>PaymentController.java</p>
<pre><code class="language-java">@PostMapping(&quot;/result&quot;)
    public ResponseEntity&lt;CommonResponse&lt;PaymentResponse&gt;&gt; savePayment(
            @Valid @RequestBody PaymentRequest request,
            @AuthenticationPrincipal PrincipalDetails principalDetails
    ) {
        PaymentResponse paymentResponse = paymentService.savePayment(request, principalDetails);
        return ResponseEntity.ok(CommonResponse.ok(&quot;Payment result&quot;, paymentResponse));
    }</code></pre>
<p><code>findPaymentByImpUid</code>를 이용하여 결제 내역을 조회할 수 있다.</p>
<p>PaymentService.java</p>
<pre><code class="language-java">public PaymentResponse savePayment(PaymentRequest request, PrincipalDetails principalDetails) {

        Long userId = principalDetails.getUserId();

        Payment payment = iamportRepository.findPaymentByImpUid(request.getImpUid())
            .orElseThrow(() -&gt; new CustomException(ErrorCode.PAYMENT_NOT_FOUND));

        Order order = orderRepository.findById(request.getOrderId())
            .orElseThrow(() -&gt; new CustomException(ErrorCode.ORDER_NOT_FOUND));

        Product product = productService.getProduct(order.getProductId());

        Payment savedPayment = paymentRepository.save(payment);

        if (payment.isDifferentAmount(order.getTotalPrice())) {
            throw new CustomException(ErrorCode.INVALID_PAYMENT_AMOUNT_ERROR);
        }</code></pre>
<p>이후 각 상황에 맞는 결과값을 내려준다.</p>
<pre><code class="language-java">        //결제가 되지 않은 경우
        if (savedPayment.isNotPaid()) {
            order.paymentFailed();
            return PaymentResponse.failed();
        }

        //상품상태 = 상품만료, 솔드아웃
        if (product.isNotOnSale()) {
            cancelPayment(request.getImpUid());
            return PaymentResponse.failed();
        }

        Optional&lt;Nego&gt; nego = negoRepository.findFirstByUser_IdAndProduct_IdOrderByCreatedAtDesc(
            userId, product.getId());

        //상품상태 = 예약중
        if (product.getProductStatus() == ProductStatus.RESERVED) {
            if (nego.isEmpty()) {
                cancelPayment(request.getImpUid());
                return PaymentResponse.failed();
            }
            if (nego.get().getStatus() != order.getNegoStatus()) {
                cancelPayment(request.getImpUid());
                return PaymentResponse.failed();
            }
            if (nego.get().getStatus() != NegotiationStatus.PAYMENT_PENDING) {
                cancelPayment(request.getImpUid());
                return PaymentResponse.failed();
            }
        }

        //상품상태 = 판매중
        //네고 내역 존재할 때
        if (nego.isPresent()) {
            //네고 상태: 결제 대기중 -&gt; 타임아웃 =&gt; 결제 결과 타임오버
            if (nego.get().getStatus() != order.getNegoStatus()) {
                cancelPayment(request.getImpUid());
                return PaymentResponse.timeOver();
            }
            nego.get().transferPending();
        }

        order.waitTransfer();
        product.setProductStatus(ProductStatus.RESERVED);

        // 채팅방, 알림관련 생략

        return PaymentResponse.success(chatRoomId);
    }</code></pre>
<hr>
<p>여기까지가 내가 구현한 결제부분이었다. 사실 서비스를 이해하느라 더 오랜시간이 걸렸었고 이를 정리하고 수정하고 일어날 수 있는 모든 케이스를 찾아내야만 했기 때문에 완벽한 결제 구현을 못한것이 아쉬웠다. 
하지만 이번 기회로 포트원을 사용해 볼 수 있어서 좋았고 좀 더 최적화 하는 과정을 거칠 예정이다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[포트원(아임포트) 알아보기]]></title>
            <link>https://velog.io/@su-daa/%ED%8F%AC%ED%8A%B8%EC%9B%90%EC%9C%BC%EB%A1%9C-%ED%85%8C%EC%8A%A4%ED%8A%B8%EA%B2%B0%EC%A0%9C-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@su-daa/%ED%8F%AC%ED%8A%B8%EC%9B%90%EC%9C%BC%EB%A1%9C-%ED%85%8C%EC%8A%A4%ED%8A%B8%EA%B2%B0%EC%A0%9C-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 02 Feb 2024 12:12:00 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>💡 PG사란 ?
: Payment Gateway 의 줄임말
구매자와 판매자 사이에서의 이뤄지는 결제를 안전하게 할 수 있도록 대행해주는 역할을 담당
대표적인 PG사로는 KG 이니시스, NHN, KCP, LGU+ 등이 있으며,
모바일 환경으로는 KG 모빌리언스, 다날, 카카오Pay 등이 있다 .</p>
</blockquote>
<h2 id="포트원아임포트-연동-준비">포트원(아임포트) 연동 준비</h2>
<h4 id="1-포트원-회원가입-후-테스트-결제대행사-추가">1. 포트원 회원가입 후 테스트 결제대행사 추가</h4>
<p>포트원: <a href="https://admin.portone.io/">https://admin.portone.io/</a>
위 주소로 들어가서 회원가입 후 &#39;결제연동&#39; 탭으로 이동후 원하는 결제대행사 테스트로 추가한다
나는 KG이니시스를 선택하였다
<img src="https://velog.velcdn.com/images/su-daa/post/61fadea6-a9de-4d74-90b0-648f02c042be/image.png" width="20%" align='left'>
<img src="https://velog.velcdn.com/images/su-daa/post/2448623d-d44d-4983-8468-7d665f6537f4/image.png" width="80%" align='right'></p>
<h4 id="2-결제-연동하기">2. 결제 연동하기</h4>
<p>사실 프론트의 결제 연동하는 코드는 위에 올렸던 메뉴바 가장 아래에 위치해있는 &#39;콘솔가이드&#39;에 자세히 나와있다
<a href="https://developers.portone.io/docs/ko/auth/guide/readme?v=v1">https://developers.portone.io/docs/ko/auth/guide/readme?v=v1</a></p>
<p>아래는 인증결제가 어떻게 이루어지는지 잘 설명되어있는 그림이다
<img src="https://velog.velcdn.com/images/su-daa/post/cb9e138a-b98b-4e1b-b0c0-53c87a5853ca/image.png" alt=""></p>
<p>나는 백엔드 쪽을 개발하는거라 프론트 코드는 위 사이트에 들어가서 참고하면 될것 같다.
(우리 프론트 팀원도 해당 문서에 나와있는 코드를 거의 그대로 썻다고 한다!)</p>
<h4 id="3-포트원-관련-설정">3. 포트원 관련 설정</h4>
<p>프로젝트를 시작하기 전에 실제 pg창이 뜨는지 궁금해서 간단하게 적어본 html은 아래와 같았다.</p>
<p><strong>index.html</strong></p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ko&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot;&gt;
&lt;/head&gt;
&lt;body&gt; &lt;!-- jQuery --&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;https://code.jquery.com/jquery-1.12.4.min.js&quot;&gt;&lt;/script&gt; &lt;!-- iamport.payment.js --&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;https://cdn.iamport.kr/js/iamport.payment-1.2.0.js&quot;&gt;&lt;/script&gt;
&lt;div&gt;&lt;h2&gt;IAMPORT 결제 데모&lt;/h2&gt;
    &lt;li&gt;
        &lt;button id=&quot;iamportPayment&quot; type=&quot;button&quot;&gt;결제테스트&lt;/button&gt;
    &lt;/li&gt;
&lt;/div&gt;
&lt;script&gt;
    //문서가 준비되면 제일 먼저 실행
    $(document).ready(function () {
        $(&quot;#iamportPayment&quot;).click(function () {
            proceedPay(); //버튼 클릭하면 호출
        });
    })

    function proceedPay() {
        $.ajax({
            url: &#39;/payment/proceed&#39;,
            type: &#39;POST&#39;,
            async: true,
            dataType: &quot;Json&quot;,
            data:
                $(&#39;#orderForm&#39;).serialize(),
            success: function (data) {
                if (data.cnt &gt; 0) {
                    requestPay(data)
                } else {
                    alert(data.msg)
                }
            },
            error: function (e) {
                alert(&quot;에러&quot;)
            }
        });

    }

    function requestPay(data) {
        IMP.init(&quot;가맹점 코드&quot;); // 예: imp00000000
        //IMP.request_pay(param, callback) 결제창 호출

        IMP.request_pay({ // param
            pg: &quot;html5_inicis.INIBillTst&quot;, //결제대행사 설정에 따라 다르며 공식문서 참고
            pay_method: &quot;card&quot;, //결제방법 설정에 따라 다르며 공식문서 참고
            merchant_uid: data.no, //주문(db에서 불러옴) 고유번호
            name: data.products,
            amount: data.price,
            buyer_email: &quot;&quot;,
            buyer_name: data.name,
            //buyer_tel: &quot;010-4242-4242&quot;,
            buyer_addr: data.addr,
            //buyer_postcode: &quot;01181&quot;
        }, function (rsp) { // callback
            if (rsp.success) {
                // 결제 성공 시: 결제 승인 또는 가상계좌 발급에 성공한 경우
                // jQuery로 HTTP 요청
                jQuery.ajax({
                    url: &quot;/payment/verify/&quot; + rsp.imp_uid,
                    method: &quot;POST&quot;,
                }).done(function (data) {
                    // 위의 rsp.paid_amount 와 data.response.amount를 비교한후 로직 실행 (iamport 서버검증)
                    if (rsp.paid_amount == data.response.amount) {
                        succeedPay(rsp.imp_uid, rsp.merchant_uid);
                    } else {
                        alert(&quot;결제 검증 실패&quot;);
                    }
                })
            } else {
                var msg = &#39;결제에 실패하였습니다.&#39;;
                msg += &#39;에러내용 : &#39; + rsp.error_msg;
                alert(msg);
            }
        });
    }
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>build.gradle에 포트원 관련 설정을 추가하였다.</p>
<pre><code>repositories {
    mavenCentral()

    //iamport
    maven {
        url &#39;https://jitpack.io&#39;
    }
}</code></pre><pre><code>dependencies {
    //iamport
    implementation &#39;com.github.iamport:iamport-rest-client-java:0.2.23&#39;
}</code></pre><p>추가로 아래 결제 검증을 할 때 필요한 설정 파일들을 만들어주었다. 이때 <code>impKey</code>, <code>impSecretKey</code>는 유출되면 안된다고 하여 properties 파일에 숨겨서 사용하였다.</p>
<p><strong>IamportApiProperty.java</strong></p>
<pre><code class="language-java">@Getter
@Configuration
@PropertySource(&quot;classpath:/secret.properties&quot;)
public class IamportApiProperty {
    @Value(&quot;${imp_key}&quot;)
    private String impKey;
    @Value(&quot;${imp_secret}&quot;)
    private String impSecret;
}</code></pre>
<p><strong>IamportConfig.java</strong></p>
<pre><code class="language-java">@Configuration
@RequiredArgsConstructor
public class IamportConfig {
    private final IamportApiProperty iamportApiProperty;

    @Bean
    public IamportClient iamportClient() {
        return new IamportClient(iamportApiProperty.getImpKey(), iamportApiProperty.getImpSecret());
    }
}</code></pre>
<h4 id="4-결제-검증">4. 결제 검증</h4>
<p><img src="https://velog.velcdn.com/images/su-daa/post/15cc9475-6eb8-4ddb-b34c-f39bea6cc5b8/image.png" alt="">
문서를 참고하면서 개발하다보면 결제정보를 검증하는 과정이 꼭 필요하다고 나와있었고 그 이유도 잘 나와있어서 우리도 결제정보를 검증하는 과정을 추가하게 되었다.</p>
<p>위 화면에서 보면 백엔드에서 검증은 총 2번 1. 사전검증, 2. 사후검증을 진행하도록 되어있다.</p>
<ol>
<li><p>사전검증
결제금액 사전등록 API를 요청하여 포트원 측에 주문아이디와 가격을 등록한다
<img src="https://velog.velcdn.com/images/su-daa/post/94c56abb-8305-4d25-9d35-093b0b11746f/image.png" alt=""></p>
<blockquote>
<p><a href="https://developers.portone.io/api/rest-v1/payment.validation?v=v1#post%20%2Fpayments%2Fprepare">https://developers.portone.io/api/rest-v1/payment.validation?v=v1#post%20%2Fpayments%2Fprepare</a></p>
</blockquote>
<p><strong>IamportRepository.java</strong></p>
<pre><code class="language-java">public void prepare(Long orderId, BigDecimal price) {
       try {
           iamportClient.postPrepare(new PrepareData(String.valueOf(orderId), price));
       } catch (Exception e) {
           throw new CustomException(ErrorCode.IAMPORT_ERROR);
       }
   }</code></pre>
</li>
<li><p>사후 검증</p>
<ol>
<li>사전 검증 이후에 프론트 측에서 결제를 끝내고 나면 받게되는 포트원 결제고유번호(imp_uid), 가맹점 주문번호(merchant_uid)를 프론트엔드로부터 수신<ol start="2">
<li>결제 상세내역 조회를 위해 포트원 결제 단건 조회 API 요청</li>
<li>응답받은 내용을 바탕으로 실 결제 금액과 결제요청금액(가맹점 자체 데이터베이스)을 비교
사후 검증은 결제가 이루어지고 난 다음에 우리의 데이터베이스에 저장된것과 비교하여 결제가 잘 이루어 진게 맞는지 검증하는 과정이라 위 절차를 순서대로 진행하면 된다.</li>
</ol>
</li>
</ol>
<p>나는 <code>PaymentRequest</code>의 결제고유번호(imp_uid), 가맹점 주문번호(merchant_uid)를 받고, 포트원 결제 단건 조회 API 요청하여 주문테이블에 저장되어있는 정보와 비교하여 정상적인 결제가 이루어졌다고 생각하면 결제테이블에 단건 조회 결과 = 결제 정보 를 저장하고 있다.(우리의 서비스가 복잡하여 실제로는 상태값들을 조회하는 과정이 많이 포함되어 있어서 실제 저장하고 있는 코드는 다른 글에서 다룰 예정이다!)</p>
<p><strong>IamportRepository.java</strong></p>
<pre><code class="language-java">public Optional&lt;Payment&gt; findPaymentByImpUid(String impUid) {
       try {
           IamportResponse&lt;com.siot.IamportRestClient.response.Payment&gt; response =
                   iamportClient.paymentByImpUid(impUid);
           return Optional.ofNullable(paymentMapper.mapFrom(response.getResponse()));
       } catch (Exception e) {
           throw new CustomException(ErrorCode.IAMPORT_ERROR);
       }
   }</code></pre>
</li>
</ol>
<p>이렇게 하면 간단한 결제 구현은 할 수 있다 😉</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[운영체제] 프로세스 관리]]></title>
            <link>https://velog.io/@su-daa/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EA%B4%80%EB%A6%AC</link>
            <guid>https://velog.io/@su-daa/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EA%B4%80%EB%A6%AC</guid>
            <pubDate>Fri, 28 Jul 2023 03:50:58 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>반효경 교수님의 운영체제 수업을 정리한 내용입니다</p>
</blockquote>
<h2 id="프로세스란">프로세스란</h2>
<p>실행 중인 프로그램을 프로세스라고 이야기 한다</p>
<h3 id="프로세스의-문맥">프로세스의 문맥</h3>
<p>프로세스의 현재 상태를 나타내는것</p>
<ul>
<li>CPU 수행 상태를 나타내는 하드웨어 문맥<ul>
<li>각종 레지스터</li>
<li>Program Counter</li>
</ul>
</li>
<li>프로세스의 주소 공간<ul>
<li>code, data, stack</li>
</ul>
</li>
<li>프로세스 관련 커널 자료 구조<ul>
<li>Kernel 스택</li>
<li>PCB</li>
</ul>
</li>
</ul>
<br> 


<h3 id="프로세스의-상태">프로세스의 상태</h3>
<p><img src="https://velog.velcdn.com/images/su-daa/post/4731ea38-50cc-46d8-904c-cdabb4d074b1/image.png" alt="">
<img src="https://velog.velcdn.com/images/su-daa/post/0098e15b-4d1d-4995-a18f-a4e32570ce62/image.png" alt=""></p>
<p>크게 세가지로 나눈다</p>
<ol>
<li>Running(실행): CPU를 가지고 수행중인 상태</li>
<li>Ready(준비): CPU를 기다리는 상태(1개 밖에 없으니까)</li>
<li>Blocked(대기): CPU를 줘도 당장 수행할 수 없는 상태, 자신이 요청한 이벤트(예:입출력)이 즉시 만족되지 않아 이를 기다리는 상태</li>
</ol>
<p>-&gt; PCB를 통하여 해당 상태를 알 수 있다</p>
<h2 id="pcbprocess-control-block-프로세스-제어-블록">PCB(Process Control Block) 프로세스 제어 블록</h2>
<p>운영체제가 각 프로세스를 관리하기 위해 프로세스당 유지하는 정보
운영체제 커널의 주소공간에서 프로세스 마다 PCB를 가지고 있다</p>
<ul>
<li>구성요소 네가지</li>
</ul>
<ol>
<li>OS가 관리상 사용하는 정보</li>
<li>CPU 수행 관련 하드웨어 값</li>
<li>메모리 관련</li>
<li>파일 관련</li>
</ol>
<p>왜 커널의 메모리 공간에 저장되어 있는가? 
CPU에서 뺏기기 전에 어디까지 실행 되었는지와 같은 정보를 저장하고 가지고 있어야 하기 때문에</p>
<h4 id="문맥-교환">문맥 교환</h4>
<p>CPU를 한 프로세스에서 다른 프로세스로 넘겨주는 과정</p>
<ul>
<li>CPU를 내어주는 프로세스의 상태를 그 프로세스의 PCB에 저장</li>
<li>CPU를 얻는 프로세스의 상태를 그 프로세스의 PCB에서 읽어옴</li>
</ul>
<h4 id="프로세스를-스케줄링하기-위한-큐">프로세스를 스케줄링하기 위한 큐</h4>
<p>Job Queue
현재 시스템 내에 있는 모든 프로세스의 집합
Ready Queue
현재 메모리 내에 있으면서 CPU를 잡아서 실행되기를 기다리는 프로세스의 집합
Device Queue
I/O device의 처리를 기다리는 프로세스의 집합</p>
<p>-&gt;프로세스들은 각 큐들을 오가며 수행된다. (PCB를 그 포인터를 사용해 연결 해놓는다)</p>
<h2 id="스케줄러">스케줄러</h2>
<p><strong>1. Long-term scheduler(장기 스케줄러 or job scheduler)</strong>
시작 프로세스 중(new상태) 어떤 것들을 ready queue로 보낼지 결정(메모리를 줘야 Ready로 올라감)
프로세스에 메모리 및 각종자원을 주는 문제
Degree of Multiprogramming(메모리에 올라갈 프로그램의 갯수)을 제어
시분할 system에는 보통 장기 스케줄러가 없음(무조건 Ready)</p>
<p><strong>2. Short-term scheduler(단기 스케줄러 or CPU scheduler)</strong>
어떤 프로세스를 다음번에 running시킬지 결정
프로세스에 CPU를 주는 문제
충분히 빨라야 함(millisecond 단위)</p>
<p><strong>3. Medium-Term Scheduler(중기 스케줄러 or Swapper)</strong>
→ 이 스케쥴러의 도입으로 Process의 Suspended상태 개념이 추가됨
여유 공간 마련을 위해 프로세스를 통째로 메모리에서 디스크로 쫓아냄
프로세스에게서 메모리를 뺐는 문제
Degree of Multiprogramming을 제어</p>
<h4 id="중기-스케줄러가-도입-된-후의-프로세스의-상태">중기 스케줄러가 도입 된 후의 프로세스의 상태</h4>
<p><img src="https://velog.velcdn.com/images/su-daa/post/cb360fb4-e62c-476a-b05f-38407d33bb67/image.png" alt=""></p>
<ol>
<li>Running(실행): CPU를 가지고 수행중인 상태</li>
<li>Ready(준비): CPU를 기다리는 상태(1개 밖에 없으니까)</li>
<li>Blocked(대기): CPU를 줘도 당장 수행할 수 없는 상태, 자신이 요청한 이벤트(예:입출력)이 즉시 만족되지 않아 이를 기다리는 상태</li>
<li>Suspended: 외부적인 이유로 프로세스의 수행이 정지된 상태, 프로세스는 통째로 디스크에 swap out된다</li>
</ol>
<p>-&gt; Blocked와 Suspended의 차이: Blocked는 프로세스의 수행이 정지되어 있지는 않다</p>
<h2 id="thread-스레드">Thread 스레드</h2>
<p>: 프로세스 중에서 CPU 수행 단위
<img src="https://velog.velcdn.com/images/su-daa/post/ecff6c30-cad5-4b47-a70c-1b9f801533cc/image.png" alt="">
<strong>Thread의 구성</strong>
Program Counter
Register Set
Stack Space</p>
<p><strong>Thread가 동료 Thread와 공유하는 부분(=Task)</strong>
Code Section
Data Section
OS Section</p>
<h3 id="스레드의-장점">스레드의 장점</h3>
<ol>
<li>빠른 응답성: 멀티 스레드 웹</li>
<li>자원 공유: code, data, resource 를 공유 가능</li>
<li>경제적 : 프로세스 하나를 만드는것에 비해서 스레드 하나를 만드는 것이 더 경제적</li>
</ol>
<h2 id="프로세스의-관리">프로세스의 관리</h2>
<h3 id="프로세스-생성">프로세스 생성</h3>
<p>부모 프로세스가 자식 프로세스를 생성
-&gt; 그럼 어떻게 내용을 다르게 구성하나요? : fork로 새 프로세스를 복사한 후에 exec로 기존 프로세스를 새로운 프로세스로 전환한다</p>
<p>프로세스의 트리(계층 구조) 형성</p>
<p>프로세스는 자원을 필요로 함</p>
<ul>
<li>운영체제로부터 받는다.</li>
<li>부모와 공유한다</li>
</ul>
<p>자원의 공유</p>
<ul>
<li>부모와 자식이 모든 자원을 공유하는 모델</li>
<li>일부를 공유하는 모델</li>
<li>전혀 공유하지 않는 모델</li>
</ul>
<p>수행(Execution)</p>
<ul>
<li>부모와 자식은 공존하며 수행되는 모델</li>
<li>자식이 종료(terminate)될 때까지 부모가 기다리는(wait=blocked) 모델</li>
</ul>
<h4 id="fork-시스템-콜">fork() 시스템 콜</h4>
<p><img src="https://velog.velcdn.com/images/su-daa/post/f70b8603-ff3b-4b79-bcc3-0d6ceadadb00/image.png" alt=""></p>
<p>실행 중인 프로세스로부터 새로운 프로세스를 복사하는 함수. 이를 사용하면 실행중인 프로세스와 똑같은 프로세스가 하나 더 만들어 진다.</p>
<ul>
<li>부모 프로세스: 복사되는 프로세스 </li>
<li>자식 프로세스: 복사된 프로세스
   -부모프로세스와 자식프로세스를 어떻게 구별할까? → 부모프로세스는 자식프로세스의 ID(PID)가 양수로 나오고 자식프로세스는 0이 나옴</li>
</ul>
<p>동작 과정</p>
<ul>
<li>PID가 바뀐다.</li>
<li>서로 차지하는 메모리 위치가 다르므로 메모리 관련 정보가 바뀐다.</li>
</ul>
<h4 id="exec-시스템-콜">exec() 시스템 콜</h4>
<p><img src="https://velog.velcdn.com/images/su-daa/post/7e098901-b911-42c4-b8a2-66cc14697573/image.png" alt=""></p>
<p>기존 프로세스를 새로운 프로세스로 전환하는 함수. 이미 만들어진 프로세스의 구조를 재활용 하는 것이다.</p>
<p>동작 과정</p>
<ul>
<li>코드 영역에 있는 기존 내용이 지워지고 새로운 코드로 바뀐다.</li>
<li>데이터 영역이 새로운 변수로 채워지고 스택 영역이 리셋된다</li>
</ul>
<h3 id="프로세스-종료">프로세스 종료</h3>
<p>프로세스가 마지막 명령을 수행한 후 운영체제에게 이를 알려줌(exit)</p>
<ul>
<li>자식이 부모에게 output data를 보냄(via wait)</li>
<li>프로세스의 각종 자원들이 운영체제에게 반납됨</li>
</ul>
<p>부모 프로세스가 자식의 수행을 종료시킴(abort)</p>
<ul>
<li>자식이 할당 자원의 한계치를 넘어섬</li>
<li>자식에게 할당된 태스크가 더 이상 필요하지 않음</li>
<li>부모가 종료(exit)하는 경우<ul>
<li>운영체제는 부모 프로세스가 종료되는 경우 자식이 더 이상 수행되도록 두지 않는다.</li>
<li>단계적인 종료 -&gt; 프로세스의 계층 구조가 있을 때 가장 말단에 있는 프로세스부터 먼저 종료시킨다</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[컴퓨터네트워크]어플리케이션 계층]]></title>
            <link>https://velog.io/@su-daa/%EC%BB%B4%ED%93%A8%ED%84%B0%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC%EC%96%B4%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EA%B3%84%EC%B8%B5</link>
            <guid>https://velog.io/@su-daa/%EC%BB%B4%ED%93%A8%ED%84%B0%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC%EC%96%B4%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EA%B3%84%EC%B8%B5</guid>
            <pubDate>Mon, 24 Jul 2023 01:41:52 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><a href="http://www.kocw.net/home/cview.do?cid=6b984f376cfb8f70">http://www.kocw.net/home/cview.do?cid=6b984f376cfb8f70</a>
이석복 교수님의 컴퓨터네트워크 수업을 정리한 내용입니다</p>
</blockquote>
<p>계층화 된 네트워크 계층 중, 가장 상위계층인 어플리케이션 계층에 대해서 먼저 다룬다.</p>
<p><img src="https://velog.velcdn.com/images/su-daa/post/c876f941-65ed-4b1b-9a72-b1359e3cfd6f/image.png" alt=""></p>
<h3 id="서버-클라이언트">서버-클라이언트</h3>
<p>서버</p>
<ul>
<li>IP주소 고정</li>
<li>항상 열려있다</li>
</ul>
<p>클라이언트</p>
<ul>
<li>서버와 상호작용</li>
<li>동적인 IP주소를 가지고 있다</li>
</ul>
<h3 id="전송-프로토콜-서비스">전송 프로토콜 서비스</h3>
<h4 id="tcp">TCP</h4>
<p>(전송 제어 프로토콜) 연결 지향 프로토콜</p>
<h4 id="udp">UDP</h4>
<p>(사용자 데이터그램 프로토콜) 연결 없는 프로토콜</p>
<h3 id="소켓-socket">소켓 Socket</h3>
<p><img src="https://velog.velcdn.com/images/su-daa/post/5567cdc7-c045-4151-8e86-b808e1cf43db/image.png" alt=""></p>
<ul>
<li>프로세스는 <strong>소켓</strong>을 이용하여 메세지를 송수신 한다</li>
<li>소켓은 일종의 통신 엔드포인트로서, 특정 IP 주소와 포트 번호를 바인딩하여 네트워크 상에서 식별된다</li>
</ul>
<h3 id="http">HTTP</h3>
<p><strong>HTTP: hypertext transfer protocol</strong></p>
<ul>
<li>하이퍼텍스트를 전송하는 프로토콜
( 프로토콜이란? 컴퓨터 네트워크나 통신에서 사용되는 규칙과 규약의 모음 )</li>
<li>웹은 HTTP의 별칭</li>
<li>HTTP는 TCP를 사용한다</li>
<li>클라이언트에 대한 정보를 저장해 놓지 않는다 -&gt; Stateless하다</li>
<li>80번 port 사용</li>
</ul>
<h4 id="http-연결-두가지-방식">HTTP 연결 두가지 방식</h4>
<ol>
<li>non-persistent HTTP(지속적이지 않은 HTTP)
매번 TCP연결을 새로 맺는다
응답시간이 persistent방식 보다 오래 걸린다</li>
<li>persistent HTTP(지속적인 HTTP)
TCP Connection을 재사용 한다 -&gt; 하나의 TCP Connection으로 여러개의 HTTP 송수신을 수행한다</li>
</ol>
<h3 id="쿠키-cookies">쿠키 Cookies</h3>
<ul>
<li>HTTP의 stateless를 보완하기 위해
웹 서버가 클라이언트에게 정보를 저장하고 추적하는데 사용</li>
<li>사용자 식별 가능</li>
</ul>
<h3 id="웹-캐시-web-cachesproxy-server">웹 캐시 Web Caches(Proxy server)</h3>
<ul>
<li>origin server에 HTTP 요청을 하는 대신 proxy 서버에 HTTP 요청</li>
<li>사용자에 의해 빈번하게 요청되는 데이터를 사용자와 가까운 웹개시 서버에 보관하여 빠른 서비스를 제공한다</li>
<li>장점<ul>
<li>응답 시간을 줄일 수 있다</li>
<li>웹 트래픽을 줄일 수 있다</li>
</ul>
</li>
</ul>
<h4 id="conditional-get">Conditional GET</h4>
<ul>
<li>조건이 맞을때만 GET을 하겠다</li>
<li>Proxy server에서 생기는 일관성 문제를 해결하기 위해 사용
(일관성 문제: Cache에 저장된 데이터가 최신이 아닐 수 있음)</li>
</ul>
<h3 id="dnsdomain-name-system">DNS(Domain Name System)</h3>
<ul>
<li>전화번호부 라고 생각</li>
<li>hostname 를 IP 주소로 해석.
(<a href="http://www.naver.com">www.naver.com</a> -&gt; 125.209.222.141)</li>
<li>IP, Port 번호를 일일이 다 기억하기 힘드니, 도메인 이름으로 접속할 수 있도록 한 시스템</li>
<li>분산화, 계층화 시켜놨다
<img src="https://velog.velcdn.com/images/su-daa/post/80817a6b-de84-49aa-bce6-0e5f6df392e4/image.png" alt=""></li>
</ul>
<h4 id="dns-구조">DNS 구조</h4>
<ul>
<li>최상위 DNS 서버: 루트 네임 서버</li>
<li>아래 DNS 서버: TLD(Top Level Domain) 네임 서버</li>
<li>그 아래 실제 IP주소를 가지고 있는 DNS서버: Authoritative name 서버</li>
</ul>
<p>-&gt; 특정 DNS 서버의 하위 DNS 서버는 해당하는 상위 DNS서버가 모두 관리</p>
<h4 id="dns-동작-과정">DNS 동작 과정</h4>
<ol>
<li>Iterative query
<img src="https://velog.velcdn.com/images/su-daa/post/dc33bd27-6b09-4d68-b05d-e228692763a1/image.png" alt="">
 1) 사용자가 특정 호스트 이름의 IP 주소를 요청하는 쿼리를 날리면, Local DNS 서버가 먼저 받는다.
 2) Local DNS 서버는 루트 네임 서버에게 쿼리를 날리고, 루트 네임 서버는 .edu에 해당하는 TLD를 알려준다.
 3) Local DNS 서버는 edu에 해당하는 TLD에게 쿼리를 날리고, TLD는 umass.edu에 해당하는 DNS 서버를 알려준다.
 4) Local DNS 서버는 umass.edu에 해당하는 DNS 서버에게 쿼리를 날리고, 해당 DNS 서버는 gaia.cs.umass.edu에 해당하는 IP 주소를 알려준다. 즉, umass.edu를 책임지는 DNS 서버가 authoritative name 서버인 것이다.
 5) 마지막으로 Local DNS 서버가 사용자에게 IP 주소를 전달한다.</li>
</ol>
<p>=&gt; 최종 IP 주소를 받을 때까지 요청 &amp;응답을 계속해서 local name server가 반복</p>
<ol start="2">
<li>Recursive query
<img src="https://velog.velcdn.com/images/su-daa/post/02827a9d-b97e-466f-8e30-b441c3a74bf0/image.png" alt="">
 1) 사용자가 특정 호스트 이름의 IP 주소를 요청하는 쿼리를 날리면, Local DNS 서버가 먼저 받는다.
 2) Local DNS 서버는 루트 네임 서버에게 쿼리를 날리고, 루트 네임 서버는 .edu에 해당하는 TLD 서버에게 쿼리를 날린다.
 3) edu에 해당하는 TLD 서버는 umass.edu에 해당하는 DNS 서버에게 쿼리를 날린다.
 4) umass.edu에 해당하는 DNS 서버는 gaia.cs.umass.edu에 해당하는 IP 주소를 TLD 서버에게 알려준다. 즉, umass.edu를 책임지는 DNS 서버가 authoritative name 서버인 것이다.
 5) TLD 서버는 루트 네임 서버에게 IP 주소를 알려준다.
 6) 루트 네임 서버는 Local DNS 서버에게 IP 주소를 알려준다.
 7) 마지막으로 Local DNS 서버가 사용자에게 IP 주소를 전달한다.</li>
</ol>
<p>=&gt; recursive하게 실제 domain name을 가지고 있는 server까지 query가 이동하여 IP 주소를 얻는 방법</p>
<p>TTL-&gt; 캐시 문제 때문에 시간 정해놓고 레코드 없에기</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[운영체제] 컴퓨터 시스템의 구조]]></title>
            <link>https://velog.io/@su-daa/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%98-%EA%B5%AC%EC%A1%B0</link>
            <guid>https://velog.io/@su-daa/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%98-%EA%B5%AC%EC%A1%B0</guid>
            <pubDate>Tue, 18 Jul 2023 07:43:04 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>반효경 교수님의 운영체제 수업을 정리한 내용입니다</p>
</blockquote>
<h2 id="운영체제란">운영체제란?</h2>
<p> 컴퓨터 하드웨어 바로 위에 설치되어 사용자 및 다른 모든 소프트웨어와 하드웨어를 연결하는 소프트웨어 계층</p>
<ul>
<li>좁은 의미
운영체제의 핵심 부분으로 메모리에 상주하는 부분</li>
<li>넓은 의미
커널 뿐 아니라 각종 주변 시스템 유틸리티를 포함</li>
</ul>
<br>

<h3 id="운영체제의-목적">운영체제의 목적</h3>
<p>컴퓨터 시스템의 자원을 효율적으로 관리</p>
<h3 id="운영체제의-분류">운영체제의 분류</h3>
<ol>
<li>동시 작업 가능 여부</li>
<li>사용자의 수<ul>
<li>단일 사용자: MS-DOS, MS Windows</li>
<li>다중 사용자: UNIX</li>
</ul>
</li>
<li>처리 방식<ul>
<li>일괄 처리(batch processing)</li>
<li>시분할(time sharing)</li>
<li>실시간(realtime OS)</li>
</ul>
</li>
</ol>
<p><strong>용어</strong>
멀티태스킹: 컴퓨터 시스템이 동시에 여러 작업을 수행할 수 있는 능력. 여러 프로그램이 동시에 실행되는 것처럼 보이도록 하는 기술</p>
<p>멀티프로그래밍: 컴퓨터 시스템이 동시에 여러 프로그램을 메모리에 올려놓고 실행하는 기술</p>
<p>멀티 프로세스: 컴퓨터 시스템이 동시에 여러 개의 독립적인 프로세스를 실행하는 기술. 각 프로세스는 운영 체제로부터 독립적인 메모리 공간과 자원을 할당받아 실행된다</p>
<p>시분할: CPU의 시간을 분할하여 나누어 쓴다는 의미를 강조</p>
<p>-&gt; 위 4개의 용어들은 비슷한 의미로 혼용됨</p>
<h3 id="컴퓨터-시스템-구조">컴퓨터 시스템 구조</h3>
<p><img src="https://velog.velcdn.com/images/su-daa/post/0e0cf534-55c5-436e-9e84-a0478f126669/image.png" alt=""></p>
<ul>
<li>CPU: 컴퓨터 시스템에서 중앙 처리 장치로서, 프로그램의 명령어를 해석하고 실행하는 역할을 수행</li>
<li>Memory: 컴퓨터에서 프로그램과 데이터를 저장하는 공간. 주기억장치는 CPU가 직접 접근하여 데이터를 읽고 쓸 수 있는 고속의 저장장치로, RAM(Random Access Memory)과 ROM(Read-Only Memory)으로 나뉜다</li>
<li>Disk: 컴퓨터에서 대용량의 데이터를 영구적으로 저장하는 보조기억장치</li>
<li>I/O 입출력장치: 컴퓨터 시스템과 외부 환경 간의 데이터 흐름을 관리하는 장치</li>
</ul>
<p>시스템콜: 사용자 프로그램이 커널 함수를 호출하는것</p>
<p>인터럽트</p>
<ul>
<li>컴퓨터 시스템에서 발생하는 이벤트나 신호로 인해 CPU의 정상적인 실행 흐름이 중단되고, 운영체제 또는 하드웨어의 특정 처리루틴이 실행</li>
<li>넓은 의미: 하드웨어가 발생시킨 인터럽트</li>
</ul>
<p>Trap: 소프트웨어 인터럽트</p>
<ul>
<li>Exception: 프로그램이 오류를 범한 경우</li>
<li>시스템 콜: 프로그램이 커널 함수를 호출하는 경우</li>
</ul>
<p>Device Controller
: 컴퓨터 시스템에서 하드웨어 장치(입출력 장치 등)를 제어하고 관리하는 부분. 해당 장치의 동작과 상호작용을 담당하여, 컴퓨터 시스템과 장치 간의 데이터 흐름을 조절</p>
<br>
동기식 입출력
: I/O 요청 후 입출력 작업이 완료된 후에야 제어가 사용자 프로그램에 넘어감
비동기식 입출력
: I/O가 시작된 후 입출력 작업이 끝나기를 기다리지 않고 제어가 사용자 프로그램에 즉시 넘어감

<p>-&gt; 두 경우 모두 I/O완료는 인터럽트로 알려줌</p>
<p><strong>DMA(Direct Memomy Access) 직접 메모리 접근</strong>
:컴퓨터 시스템에서 메모리 전송을 위해 사용되는 기술로써 CPU의 개입 없이 주변장치와 메모리 간의 데이터 전송을 수행
-&gt; 기본적으로, CPU는 데이터를 입출력 장치와 주변장치 간에 전달하기 위해 관여해야 하는데 이러한 CPU 대신 DMA 컨트롤러(DMA Controller)가 데이터 전송을 관리하고, CPU는 다른 작업을 수행할 수 있다. </p>
<p>저장장치 계층 구조
: 속도가 빠르고 값 비싼 저장장치를 CPU가까이 두고, 값 싸고 용량 큰 저장장치를 반대쪽에 배치</p>
<p><img src="https://velog.velcdn.com/images/su-daa/post/bbb4607e-6b64-495b-90b6-bbced3a6a99c/image.png" alt=""></p>
<p>프로그램의 가상 메모리 공간 구성: code, data, stack</p>
<ul>
<li>code: cpu에서 수행할 기계어들이 위치</li>
<li>data: 전역 변수, 프로그램이 시작될 때 부터 종료될 때 까지 남아있는 데이터들</li>
<li>stack: 함수 호출, 리턴과 관련된 데이터들</li>
</ul>
<p>사용자 프로그램이 사용하는 함수</p>
<ol>
<li>사용자 정의 함수: 자신의 프로그램에서 정의한 함수</li>
<li>라이브러리 함수: 자신의 프로그램에서 정의하지 않고 가져다 쓴 함수</li>
<li>커널 함수: 운영체제 프로그램의 함수</li>
</ol>
<p>-&gt; 커널 함수의 호출 = 시스템 콜</p>
]]></description>
        </item>
    </channel>
</rss>