<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>hwasowl_.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Wed, 22 Jul 2026 02:31:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>hwasowl_.log</title>
            <url>https://velog.velcdn.com/images/hwasowl_/profile/2705292a-ac8b-475c-9a5a-cf68518c7eb1/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. hwasowl_.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hwasowl_" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[루프백 4기] 사람과 지식, 그리고 이직을 얻은 10주]]></title>
            <link>https://velog.io/@hwasowl_/%EB%A3%A8%ED%94%84%EB%B0%B1-4%EA%B8%B0-%EC%82%AC%EB%9E%8C%EA%B3%BC-%EC%A7%80%EC%8B%9D-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%9D%B4%EC%A7%81%EC%9D%84-%EC%96%BB%EC%9D%80-10%EC%A3%BC</link>
            <guid>https://velog.io/@hwasowl_/%EB%A3%A8%ED%94%84%EB%B0%B1-4%EA%B8%B0-%EC%82%AC%EB%9E%8C%EA%B3%BC-%EC%A7%80%EC%8B%9D-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%9D%B4%EC%A7%81%EC%9D%84-%EC%96%BB%EC%9D%80-10%EC%A3%BC</guid>
            <pubDate>Wed, 22 Jul 2026 02:31:00 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>10주간의 루퍼스 수료 과정을 회고하며 이전과 현재를 비교한 글입니다.</p>
</blockquote>
<p>개발자가 이직을 준비한다면 어떤 것부터 준비할까?
이전 회사에서 작업한 프로젝트를 복기하고 이력서를 다듬거나, 기술 면접을 준비할 것이다.</p>
<p>하지만 모의 면접을 준비하거나 이력서를 준비하면서 스스로에 대한 부족함을 느끼고 맞는 방향으로 가는지 모르겠으며, 회사에서 동기부여를 얻기 어려운 분들이 있을 것이다.</p>
<p>나는 맨 마지막. <strong>회사에서 동기부여를 얻기 어려워서</strong> <a href="https://www.loopers.im/education">루프백 과정</a>을 신청했다. 그리고 이 10주간의 과정에서 얻어간 점을 정리해보려고 한다.</p>
<h3 id="1-생각하는-힘">1. 생각하는 힘</h3>
<p>먼저 기술적인 측면과 생각하는 힘이 많이 늘었다고 느꼈다.</p>
<p>지금은 빅테크에서 다루던 기술과 트레이드 오프를 기술 블로그나 AI를 통해 쉽게 얻어낼 수 있는 시대라고 생각한다. 다만 단순히 글을 읽음으로써 얻어갈 수 있는 건 한계가 있다고 느낀다. 대개 과정이 생략되어 있거나 직접 해보지 않으면 공감하기 어려운 부분도 존재하기 때문이다.</p>
<p>이 가려운 지점을 루프백에서 긁어볼 수 있었다.</p>
<hr>
<p><img src="https://velog.velcdn.com/images/hwasowl_/post/3ffb9869-f24e-49e0-9140-92af1d01927c/image.png" alt="설계문서"></p>
<p><img src="https://velog.velcdn.com/images/hwasowl_/post/a98f6a47-fc56-4fab-8fbb-97dbc2cb5f60/image.png" alt="채점방식"></p>
<p><strong>루프백 과정에서는 개발대신 설계 문서를 기반으로 채점해주신다.</strong> 설계 문서를 잘 작성했다면 구현 산출물도 적절하게 나오기 때문이다. </p>
<p>이제 구현은 AI에게 위임하는 시대이다. 그래서 차별점이 될 수 있는, 시장에서 팔릴 수 있는 개발자가 되려면 <strong>생각하는 힘이 있는 개발자</strong>가 되어야 한다고 생각한다.</p>
<p>네카라쿠배같은 메이저 기업에서 수십년 간 업무를 해오신 멘토님이 내가 작성한 설계 문서를 읽고 잘한 점과 놓친 부분을 언급해주는 경험이 가장 좋았다. 칭찬 받으면 자신감이 오르고 놓친 부분을 언급받으면 한없이 위축되기도 했다. 다만 면접장에서, 그리고 이력서에서 부족한 점을 지적받아 떨어지는 것 보다 배우는 자리에서 혼나는 것이 백배 천배 좋다고 생각한다 ㅎㅎ..</p>
<h3 id="2-동기부여">2. 동기부여</h3>
<p>진짜 대단하다. 잠을 안잔다.</p>
<p>나는 6시에 퇴근하고 집에오면 7시.. 그리고 밥먹고 준비하면 8시에 힘이 다 빠진 상태로 공부를 했던 것 같은데, 이 사람들은 새벽 3-4시까지 공부하고 이력서를 고치고 있다.</p>
<p><img src="https://velog.velcdn.com/images/hwasowl_/post/f04bab3e-38a4-4ea3-bead-201a7f7df57a/image.png" alt=""></p>
<p>심지어 나쁜 기업을 다니는 것도 아니다. 대기업급의 메이저 기업을 다님에도 저렇게 열심히 한다는 것에 내 마음 속의 불꽃을 타오르게 했다. <del><em><strong>저런 대단한 사람들도 하는데 내가 뭐 된다고 안해?</strong></em></del></p>
<h3 id="3-이직에-성공하다">3. 이직에 성공하다</h3>
<p>결론적으로는 100명대 벤처기업에서 매출 1조원의 중견기업 ERP 직무에 합격해 점프할 수 있게 되었다.</p>
<p>한번에 합격할 수 있었던 건 아니고 많이 떨어지고 좌절도 했었다. 내가 잘 준비하고 있는지도 몰랐고 시장에서의 내 가치도 잘 몰랐다. 심지어 나는 학교도 다니고 있었던 터라 누가 날 뽑아주겠어? 지금 다니는 곳도 기적인데? 라고 생각했다.</p>
<p><img src="https://velog.velcdn.com/images/hwasowl_/post/78af313d-533d-44b8-9b03-c38767aa7ccb/image.png" alt=""></p>
<p>다만 좋은 기회로 많은 사람들의 이력서를 열람하고 써야할 것과 덜어내야 할 것을 판단할 수 있게 되었다. 그리고 많은 사람들 앞에서 이력서를 공개하며 메이저 기업에 재직하시는 분들의 피드백을 받아보니 자신감이 생겨 적극적으로 서류를 넣어봤던 것 같다.</p>
<p>면접에서는 ERP 직무 특성상 쿼리 관련 질문이 많았는데 그 중 인덱스의 작동 방식, <a href="https://velog.io/@hwasowl_/MySQL-InnoDB%EC%9D%98-%EB%8F%99%EC%8B%9C%EC%84%B1-%EB%AC%B8%EC%A0%9C-%EA%B9%8A%EA%B2%8C-%ED%8C%8C%EB%B3%B4%EA%B8%B0-with.-JPA">DBMS들의 격리 수준과 발생할 수 있는 문제</a> 등이 나왔고 루프백에서 배운 내용을 토대로 성실히 답해 좋은 결과를 얻었다. </p>
<h3 id="끝으로">끝으로</h3>
<p>이후에도 가능하다면 스터디와 친목 등을 통해 친해지려고 노력할 예정이다.
열정있는 사람들과 10주를 무한으로 즐기고 싶다면 루프백을 추천한다.
대신 하는 만큼 얻어가는 과정이기에, 온전히 집중할 수 있는 분에게 추천드리고 싶다! <em>화이팅!</em></p>
<hr>
<p>입력 시 20만원 할인을 받으실 수 있습니다..! 저도 혜택을 받아요 ㅎㅎ</p>
<p><strong>추천인 코드: DCINI</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[MySQL InnoDB의 동시성 문제 깊게 파보기 (with. JPA)]]></title>
            <link>https://velog.io/@hwasowl_/MySQL-InnoDB%EC%9D%98-%EB%8F%99%EC%8B%9C%EC%84%B1-%EB%AC%B8%EC%A0%9C-%EA%B9%8A%EA%B2%8C-%ED%8C%8C%EB%B3%B4%EA%B8%B0-with.-JPA</link>
            <guid>https://velog.io/@hwasowl_/MySQL-InnoDB%EC%9D%98-%EB%8F%99%EC%8B%9C%EC%84%B1-%EB%AC%B8%EC%A0%9C-%EA%B9%8A%EA%B2%8C-%ED%8C%8C%EB%B3%B4%EA%B8%B0-with.-JPA</guid>
            <pubDate>Tue, 09 Jun 2026 05:24:29 GMT</pubDate>
            <description><![CDATA[<p>MySQL의 격리 수준이 Repeatable Read면 Phantom Read 문제가 발생해야될 것 같은데, 방지해준다고 한다.</p>
<p>해당 이유와 InnoDB에서 발생하는 동시성 문제를 해결하며 해결 방안에 대해 다뤄보겠다.</p>
<p>_이번 딥다이브는 필자가 자주 사용하고, 익숙한 MySQL + InnoDB 기준으로 진행한다.
_</p>
<hr>
<h3 id="1-격리수준">1. 격리수준</h3>
<p>MySQL InnoDB의 격리수준은 Repeatale Read이다.
Repeatale Read 격리수준은 Dirty-Read와 Non-Repeatable Read가 발생하지 않음을 보장하지만 Phantom Read 문제가 발생할 수 있다.</p>
<p>이 격리수준을 다루기 전, 앞서 말한 3가지 문제점들에 대해 간략하게 다뤄보겠다.</p>
<ol>
<li><p><strong>Dirty-Read</strong> <em>(다른 트랜잭션의 커밋 이전 데이터 읽기)</em>
 말 그대로 더러운 읽기이다. 다른 트랜잭션의 커밋 이전의 데이터를 읽어올 수 있기 때문에 들숙날숙한 정보 조회 문제가 발생한다. 대부분의 DBMS들은 이 Dirty-Read 문제 해결을 보장한다.</p>
</li>
<li><p><strong>Non-Repeatable Read</strong> (<em>트랜잭션 내 데이터의 값 변경이 발생한다.</em>)
 tx1에서 A=10을 읽었다. 그 도중 tx2에서 A=10을 동일하게 읽고 A+=10 처리 후 commit했다. tx1에서 다시 A를 읽어오면 A=20을 읽게 된다.</p>
</li>
<li><p><strong>Phantom Read</strong> (<em>트랜잭션 내 데이터가 생성이 반영된다.</em>)
 tx1에서 목록 조회로 2개의 값을 얻었다. tx2도 동일하게 조회한 후 값을 1개 추가하고 commit했다. tx1에서 다시 목록 조회를 하면 값이 1개 추가되어 3이 조회된다.</p>
</li>
</ol>
<hr>
<h3 id="2-격리-수준이-repeatable-read이지만-phantom-read는-거의-안생겨요">2. 격리 수준이 Repeatable Read이지만 Phantom Read는 거의? 안생겨요</h3>
<p>읽으면서 모순인데? 싶을 수 있다. </p>
<p>앞서 Repeatable Read 격리 수준에서는 Phantom Read가 발생한다고 했는데, 왜 MySQL에는 안생긴다고 하는걸까? <strong>그 이유는 MySQL의 InnoDB의 작동 방식에 있다.</strong></p>
<p>InnoDB는 MVCC(Multi-Version Concurrency Control)를 통해 동시성을 관리한다.</p>
<p>MVCC는 데이터베이스에서 동시성을 관리하는 메커니즘으로 Undo Log를 통해 이전 데이터 버전을 관리한다. </p>
<p><img src="https://velog.velcdn.com/images/hwasowl_/post/1505e25d-8419-413f-87ca-2c9464599c7e/image.png" alt=""></p>
<p>따라서 InnoDB의 트랜잭션은 미리 읽은 Undo Log 공간 내에서 처리가 이뤄지기 때문에 row 추가로 영향받는 Phantom Read 문제는 발생하지 않는다.</p>
<hr>
<h3 id="3-근데-거의-안생긴다는건-뭐에요">3. 근데 거의? 안생긴다는건 뭐에요?</h3>
<p>앞서 MVVC 방식을 통해 Undo Log내에서 처리가 이뤄진다고 했는데 어떻게 Phantom Read가 발생할 수 있는 것일까?</p>
<p>앞서 MVCC로 스냅샷 안에서 읽기 때문에 팬텀이 안 생긴다고 했다. 그런데 여기엔 슬쩍 숨겨둔 전제가 하나 있다. <strong>&quot;Undo Log에서 읽는 건 일반 SELECT뿐&quot;</strong>이라는 것</p>
<pre><code>[세션 A] BEGIN; SELECT * FROM t WHERE amount &gt; 10000;      -- 2건 (여기서 스냅샷 고정)
[세션 B] INSERT INTO t VALUES (..., 20000); COMMIT;        -- 새 행 커밋
[세션 A] SELECT * FROM t WHERE amount &gt; 10000;             -- 여전히 2건 (스냅샷이 숨김)
[세션 A] SELECT * FROM t WHERE amount &gt; 10000 FOR UPDATE;  -- 3건! 새 행 등장 = 팬텀</code></pre><p><strong>FOR UPDATE 연산</strong>을 위해 데이터베이스에 물리적 조회가 발생하는 순간 Undo Log를 조회하는 것이 아닌 데이터베이스를 새롭게 조회하게 되므로 팬텀 리드 문제가 발생한다.</p>
<p>즉 MySQL의 &quot;거의 안 생긴다&quot;는 두 읽기 모드를 한 트랜잭션에 섞을 때 깨질 수 있다는 뜻이다.</p>
<hr>
<h3 id="4-그럼-어떻게-막아요">4. 그럼 어떻게 막아요?</h3>
<p>팬텀이 &quot;빈 공간에 새 row가 INSERT되는 것&quot; 때문이라면, 그 빈 공간을 미리 잠가버리면 된다. InnoDB는 바로 이 일을 하는 락을 갖고 있다.</p>
<ul>
<li><p><strong>Record Lock</strong>: 인덱스 레코드(행) 하나를 잠근다.</p>
</li>
<li><p><strong>Gap Lock</strong>: 레코드와 레코드 사이의 빈 공간을 잠근다. 행을 잠그는 게 아니라 그 구간에 INSERT 하는 걸 막는다.</p>
</li>
<li><p><strong>Next-Key Lock</strong>: Record Lock + Gap Lock. (이전 레코드, 현재 레코드] 범위를 통째로 잠근다. InnoDB가 범위 스캔에서 기본으로 쓰는 잠금 단위다.</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hwasowl_/post/b99b288e-b876-45b4-8a80-66b1f45e840f/image.png" alt=""></p>
<p>팬텀의 정체가 &quot;범위로의 INSERT&quot;였으니, 범인을 잡는 건 Gap Lock이다. 그리고 이 잠금은 SELECT ... FOR UPDATE로 발동한다. 아까 그 예시를, 이번엔 <strong>처음부터 FOR UPDATE</strong>로 바꿔보자.</p>
<pre><code>[세션 A] BEGIN; SELECT * FROM t WHERE amount &gt; 10000 FOR UPDATE;  -- 범위 전체에 Next-Key Lock
[세션 B] INSERT INTO t VALUES (..., 20000);                       -- 갭락에 걸려 &#39;대기&#39;
[세션 A] SELECT * FROM t WHERE amount &gt; 10000 FOR UPDATE;         -- 그대로 2건
[세션 A] COMMIT;                                                  -- 이제서야 세션 B의 INSERT가 진행</code></pre><p>세션 B의 INSERT는 세션 A가 잡은 갭락 때문에 세션 A가 커밋할 때까지 대기한다. 끼어들 틈 자체가 사라지니 팬텀이 발생할 수 없다. </p>
<p>즉 팬텀을 반드시 막아야 한다면 첫 읽기부터 일관되게 FOR UPDATE로 범위를 잠그면 된다. (중간에 끼워넣으면 늦는다. 갭락은 거는 순간부터 INSERT를 막는 거라 타이밍이 중요하다.)</p>
<h3 id="5-그래서-jpa에서는-어떻게-써요">5. 그래서 JPA에서는 어떻게 써요?</h3>
<p>결론부터. JPA에서 <code>FOR UPDATE</code>를 걸려면 <strong>읽는 메서드에 명시적으로 <code>@Lock</code>을 붙여 줘야</strong> 한다.</p>
<pre><code class="language-java">public interface StockRepository extends JpaRepository&lt;Stock, Long&gt; {

    // PESSIMISTIC_WRITE → InnoDB에서 SELECT ... FOR UPDATE 로 나간다
    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @Query(&quot;select s from Stock s where s.id = :id&quot;)
    Optional&lt;Stock&gt; findByIdForUpdate(@Param(&quot;id&quot;) Long id);
}</code></pre>
<pre><code class="language-java">@Transactional
public void reserve(Long stockId) {
    Stock stock = stockRepository.findByIdForUpdate(stockId)   // 여기서 FOR UPDATE 발동
            .orElseThrow(() -&gt; new IllegalStateException(&quot;재고 없음&quot;));

    stock.decrease(1);   // 더티 체킹으로 트랜잭션 커밋 시 UPDATE
}</code></pre>
<p>기본 findById는 일반 SELECT로 나간다. 앞 절에서 봤듯이 첫 읽기가 범위를 잠그지 않으면 그 사이 INSERT나 변경이 끼어들 여지가 있다. 그래서 동시성 보호가 필요한 흐름이라면 진입 시점부터 <strong>findByIdForUpdate</strong> 같은 잠금 메서드로 읽는 편이 안전하다. <em>&quot;트랜잭션 안에서 읽었으니 안전하겠지&quot;라고 생각하기 쉽지만, 꼭 그렇지는 않다.</em></p>
<p>여기에 알아두면 좋은 위험이 둘 더 있다.</p>
<p><strong>락 보유 시간 = 트랜잭션 시간</strong>
잡은 락은 메서드가 끝나(=커밋되)기 전까지 유지된다. 그래서 락을 쥔 트랜잭션 안에서 외부 API 호출이나 무거운 계산 같은 느린 작업을 하면, 그동안 다른 트랜잭션이 대기하게 된다. </p>
<p><code>innodb_lock_wait_timeout</code>(기본 50초)을 넘기면 대기하던 쪽이 에러로 끝나고, 서로 물리면 데드락으로 한쪽이 롤백될 수 있다. 가능하면 <strong>느린 작업은 락 범위 밖으로 빼고, 락을 쥔 트랜잭션은 짧게 가져가는 게 좋다.</strong></p>
<hr>
<p><strong>영속성 컨텍스트(1차 캐시)</strong>
JPA는 DB의 MVCC 위에 1차 캐시가 한 겹 더 있다. <strong>findByIdForUpdate로</strong> 가져온 엔티티는 영속 상태로 캐시에 올라가서, 같은 트랜잭션에서 같은 ID를 findById로 다시 읽으면 DB를 거치지 않고 캐시 것을 돌려주는 경우가 많다. &quot;다시 조회했는데 왜 값이 그대로지?&quot;의 원인이 보통 이거다. </p>
<p>DB를 다시 읽어야 한다면 <code>entityManager.refresh()</code>로 강제할 수 있다. <em>(다만 락을 쥐고 있는 동안엔 남이 못 바꾸니, 대개는 신경 쓸 일이 없다.)</em></p>
<p>정리하면, JPA에서 동시성을 지킬 때는 대략 이렇게 가져가면 무난하다.</p>
<ul>
<li><strong>진입 시점부터</strong> <code>@Lock(LockModeType.PESSIMISTIC_WRITE)</code> 메서드로 읽기 (일반 findById는 잠그지 않는다).</li>
<li>락을 쥔 <strong>트랜잭션은 짧게</strong>, 느린 작업은 가급적 락 범위 밖으로</li>
<li>1차 캐시 때문에 <strong>재조회가 최신이 아닐 수 있다</strong>는 점 염두에 두기</li>
</ul>
<hr>
<p>격리수준은 깔려 있는 기본 방어선에 가깝고, 그 위에서 벌어지는 동시성은 결국 락을 어디서부터 얼마나 거느냐에 따라 달라지는 경우가 많다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[잘 읽히는 다이어그램 만들기]]></title>
            <link>https://velog.io/@hwasowl_/%EC%9E%98-%EC%9D%BD%ED%9E%88%EB%8A%94-%EB%8B%A4%EC%9D%B4%EC%96%B4%EA%B7%B8%EB%9E%A8-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@hwasowl_/%EC%9E%98-%EC%9D%BD%ED%9E%88%EB%8A%94-%EB%8B%A4%EC%9D%B4%EC%96%B4%EA%B7%B8%EB%9E%A8-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Thu, 21 May 2026 06:46:21 GMT</pubDate>
            <description><![CDATA[<p><strong>TL;DR</strong> <em>오히려 정보를 덜어내는 것이 효과적일 수 있다.</em></p>
<hr>
<h2 id="서론">서론</h2>
<p>다이어그램은 <strong>협업을 위해 명세서를 시각화한 도표</strong>이다. 즉 <strong>효과적인 이해와 의사소통을 위해 작성하는 문서</strong>이다. 따라서 많은 정보를 담고 있을수록, 이해가 어려워지며 설명하는 사람도, 이해하는 사람도 서로 힘들어질 수 있다.</p>
<p><em>따라서 <strong>잘 읽히는 다이어그램</strong>을 작성하기 위해 고민했던 내용들을 공유해보고자 한다.</em></p>
<hr>
<h2 id="다이어그램-선정">다이어그램 선정</h2>
<p>먼저 <strong>필요한 상황</strong>에 맞게 다이어그램을 선택해야한다. </p>
<p>UML 2.5 Diagram 기준으로 존재하는 다이어그램은 다음과 같다.
(<a href="https://www.uml-diagrams.org/uml-25-diagrams.html">https://www.uml-diagrams.org/uml-25-diagrams.html</a>)</p>
<p><strong>CI/CD 환경을 설계</strong>할 때에는 <strong>배포 다이어그램</strong>을 작성하거나, <strong>사용자의 관점을 표현</strong>하고 싶다면 <strong>유스케이스 다이어그램</strong>을 작성하는 등의 선택을 할 수 있다.</p>
<p><em>이번에 내가 고민한건 <strong>요구사항에 대한 흐름도 설계</strong>를 그려내는 과정이였기에 <strong>시퀀스 다이어그램</strong>을 작성해 표현해보겠다.</em></p>
<hr>
<h2 id="시퀀스-다이어그램이란">시퀀스 다이어그램이란</h2>
<h3 id="정의">정의</h3>
<blockquote>
<p>_Sequence diagram is the most common kind of interaction diagram, which focuses on the message interchange between a number of lifelines. _
(<a href="https://www.uml-diagrams.org/sequence-diagrams.html">https://www.uml-diagrams.org/sequence-diagrams.html</a>)</p>
</blockquote>
<p>직역해보면 시퀀스 다이어그램은 가장 일반적인 형태의 상호작용 다이어그램이며, 여러 생명선들이 서로 주고받는 메시지를 중심으로 보여준다고 한다. </p>
<p>즉 상호작용을 표현하기 위한 도표이다.</p>
<hr>
<h3 id="효과적인-표현-방법">효과적인 표현 방법</h3>
<p>시퀀스 다이어그램의 모든 구성요소를 작성하지 않아도 된다. 필요한 상황에 맞게 변형해도 된다. 그저 목적인 <strong>&quot;효과적인 의사소통/이해/협업&quot;</strong>에 집중할 수 있도록 표현하면 된다.</p>
<p>예시로 토스페이먼츠의 결제연동 가이드의 시퀀스 다이어그램을 보자.
<img src="https://velog.velcdn.com/images/hwasowl_/post/7bfbe3a8-3b43-4c13-aaef-fdaaeadf8d2c/image.png" alt=""></p>
<p>슥 읽혀서 놓칠 수 있지만, 디테일하게 보면 다음과 같은 부분을 눈치챌 수 있다.
<em>1. 인증에 대한 내용이 없다.
2. 결제 실패에 대한 내용이 없다.</em></p>
<p>이 시퀀스 다이어그램은 연동을 원하는 개발자의 입장에서 작성된 문서이기에, <strong>인증은 토스페이먼츠 내부의 역할</strong>이고, <strong>결제 실패에 대한 처리도 토스페이먼츠 내부의 역할</strong>이다. 연동을 원하는 개발자는 토스페이먼츠의 API 스펙과 동작에 집중해야 하지 내부적인 처리 방법까지 이해할 필요가 없다고 판단해 상당한 정보를 생략한 걸 볼 수 있다.</p>
<p>이런 디테일한 부분 때문인지, 연동하는 개발자의 입장에서는 필요한 부분만 빠르게 파악하고 작업에 들어갈 수 있다. </p>
<p><em>어쩌면 생략이 도움이 될 수 있다는걸 알 수 있는 지점인 것 같다.</em></p>
<hr>
<h3 id="추상화의-단계">추상화의 단계</h3>
<p>시퀀스 다이어그램을 작성하다보면, 요소들이 많아져 스케일이 커질 때가 있다. </p>
<p><strong>이럴 때에는 추상화의 단계를 높여 분리</strong>를 해보는걸 추천한다. 컨트롤러, 서비스같이 레이어드 아키텍처 단위가 아니라, 주문/제품/재고/결제 같은 도메인 단위로 나눠보는 것이다.</p>
<p>예시로 주문 생성 API를 설계하고 방향성에 대해 평가받아야 되는 상황이라고 가정해보자.</p>
<p><img src="https://velog.velcdn.com/images/hwasowl_/post/c5f50529-a56b-4a41-9ddf-003facd68495/image.png" alt=""></p>
<p>_Order, Product, Stock, Payment_등 다양한 레이어드 아키텍처들이 상호작용 과정을 표현하고 있다. 그리고 호출되는 메서드들과, 쿼리를 담아내며 디테일하게 설명하고 있다.</p>
<p>*<em>하지만 이 정보가 과연 효과적인 의사소통을 하는데 도움이 될 지는 잘 모르겠다. *</em></p>
<p><em>만약 디테일한 로직 설명이 필요하다면 <strong>별도의 시퀀스 다이어그램으로 분리</strong>해 디테일한 정보가 필요한 사람에게 보여주면 되는 것 아닌가? 이런 생각을 했다.</em></p>
<p>그래서 핵심적인 부분만 담고 요소들이 많으니 파악하기 어렵다고 느껴져 도메인 단위로 분리해 다이어그램을 다시 그려봤다.</p>
<p><img src="https://velog.velcdn.com/images/hwasowl_/post/97a28e70-a70e-4149-a7f9-8257f71817d0/image.png" alt=""></p>
<p><strong>이제는 읽히지 않는가?</strong> 유저가 주문 요청을 하면 상품 조회와 차감이 이뤄지고, 결제를 요청해 마무리하는 플로우가 한눈에 들어온다. 추상화 레벨을 도메인 단위로 올려 효과적으로 이해할 수 있도록 한 것이다.</p>
<p>만약 개발자 혹은 그외 다른 직업을 가진 사람들과 의사소통이 필요할 때에는 대화 주제, 상황에 알맞게 추상화 레벨을 높이고, 정보를 생략하며 조율한다면 앞서 말한 _잘 읽히는 다이어그램_으로써 작동할 것이다.</p>
<hr>
<h3 id="추상화---주의해야할-점">추상화 - 주의해야할 점</h3>
<p>이때 주의할 점은 추상화 단계를 올린만큼 다른 요소들의 단계도 같이 올려서 일관성을 맞춰야한다. 도메인 단위로 추상화 단계를 올렸지만, 서비스와 레포지토리가 등장한다면 읽는 사람의 입장에서는 의문을 가질 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/hwasowl_/post/c91ffa7d-bedf-44c7-a864-48d34a7e4ec7/image.png" alt=""></p>
<p>위 예시와 같이 주문 도메인에서 갑자기 레포와 DB, 외부PG등 추상화 단계가 맞지 않는다면 이해를 위해 추가적인 시간이 요소되기 때문이다.</p>
<hr>
<h2 id="마무리하며">마무리하며</h2>
<p>처음에는 디테일한 정보를 모두 다 담아두면, 좋은 것 아닌가? 라는 막연한 생각을 가졌지만 읽는 사람의 입장을 생각했을 때 이해하지 못한다면 공을 들여서 쓴 문서는 이면지와 다름 없겠구나 같은 생각을 했던 것 같다.</p>
<p>회의나 API 연동 문서 등 상황에 맞게 정보 생략과 추상화의 레벨을 맞춘다면 가독성이 훨신 좋아질 수 있으니, 다이어그램 작성 전 누가 읽는 것인지 고민을 해보는 걸 추천한다.</p>
<hr>
<h4 id="참고사이트">참고사이트</h4>
<p><a href="https://www.uml-diagrams.org/uml-25-diagrams.html">https://www.uml-diagrams.org/uml-25-diagrams.html</a>
<a href="https://docs.tosspayments.com/guides/v2/payment-window/integration">https://docs.tosspayments.com/guides/v2/payment-window/integration</a>
<a href="https://wikidocs.net/220975">https://wikidocs.net/220975</a></p>
]]></description>
        </item>
    </channel>
</rss>