<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>IT, I Think </title>
    <link>https://cholol.tistory.com/</link>
    <description>안녕하세요. IT왕이 될 남자입니다. 
</description>
    <language>ko</language>
    <pubDate>Sat, 30 May 2026 10:59:31 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>마이쮸(mychew__)</managingEditor>
    <image>
      <title>IT, I Think </title>
      <url>https://tistory1.daumcdn.net/tistory/1643904/attach/6ac3500cc5c146678e99ee3f14946706</url>
      <link>https://cholol.tistory.com</link>
    </image>
    <item>
      <title>0 - 개발자가 Claude Code를 진지하게 써봤다 &amp;mdash; Flutter + Django편</title>
      <link>https://cholol.tistory.com/617</link>
      <description>&lt;div class=&quot;index_toc&quot;&gt;
&lt;p class=&quot;toc_title&quot; data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;26년이 되어서 클로드 코드가 핫하다. 얼마나 핫하냐면 보수적인 회사에서조차 AI사용을 검토해 볼 정도로..?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바이브 코딩이 나오고 코드를 AI가 만들어주면서 개발자가 아닌 사람도 개발자처럼 코딩을 할 수 있는 시대가 되었다. 작년까지만 해도 뭐 얼마나 잘하겠어? 했지만, 클로드 코드의 퍼포먼스를 보면 '어? 좀 하는데?'라는 말이 나온다 ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 본격적으로 클로드 코드가 얼마나 대단하고 어디까지 할 수 있는지를 확인하고, 정리해보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;‼️ 갑자기 클로드 코드를?&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잠깐 쉬고 있던 블로그 활동에 갑자기 클로드 코드로 글을 쓰는 이유는 간단하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 이 시기가 &lt;b&gt;기회&lt;/b&gt;라고 생각했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 코딩 시대 이전에는 개발자는 단순히 개발 관련 능력만 높으면 일을 잘하는 개발자였다. '개발자는 코드로 말한다' 느낌이랄까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 AI가 발전하고 gpt, copilot, 커서 ai, 클로드 코드와 같은 AI 툴이 나오면서, 시대가 변하고 있는 것이 느껴졌다. 개발은 AI가 할 거니 AI를 잘 이용하는 능력이 중요해졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 AI를 잘 이용하는 능력은 무엇일까? 현재 우리가 사용하는 AI는 LLM 방식으로 학습된 모델과 대화하면서 사용하는 방식이다. 즉 '대화'를 잘해야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 대부분의 개발자들이 커뮤니케이션 능력이 부족하고, 문서작업능력 역시 떨어진다고 생각한다. 이건 모두가 공감하는 개발자의 특성이 아닐까 싶다. (물론 예외도 있지만 ^~^)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 기존 개발자들은 아마 LLM 방식의 AI를 잘 활용하지 못할 것이라고 예상한다. 실제로 주변 시니어 개발자들이 AI툴 활용을 어려워하는 것을 몸소 느끼고 있다. 하지만 시니어 중에서도 꾸준히 학습하고 노력하는 사람들은 AI를 사용하면서 보다 높은 퍼포먼스를 내고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 개발자로서의 능력을 어느 정도 갖추고 있으며, 자기 계발과 학습을 꾸준히 하며, 커뮤니케이션과 문서작업과 같은 인문학적인 능력도 갖춘 사람이라면 지금 이 시대에 &lt;b&gt;AI를 활용한 개발을 가장 잘하는 사람&lt;/b&gt;이지 않을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 가설을 증명하기 위해 클로드 코드를 활용해서 이것, 저것 해보면서 내 능력이 어디까지 올라가는지 시험해보려고 한다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;⚙️ 클로드 코드 환경구성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클로드 코드는 cli 환경으로 터미널에서 명령을 실행하는 구조이다. 개발자들은 환영할 ux이긴 한데.. ㅋㅋ&amp;nbsp;&lt;br /&gt;개발자가 아닌 사람들은 살짝 불편하지 않을까?라는 생각.. 물론 다른 UI 툴을 이용하면 좀 편하게 쓸 수 있게 해 주겠지?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1772972554988&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;curl -fsSL https://claude.ai/install.sh | bash&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mac에서는 brew로 설치할 수도 있지만, native install로 해야지 최신 버전 자동 업데이트가 된다고 해서 위에 curl 명령어로 설치함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 후 claude 입력하면 실행됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2414&quot; data-origin-height=&quot;1748&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnWo6X/dJMcagkmKEL/KG6RrhEvCj6LbmZtrkDAdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnWo6X/dJMcagkmKEL/KG6RrhEvCj6LbmZtrkDAdk/img.png&quot; data-alt=&quot;익숙한 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnWo6X/dJMcagkmKEL/KG6RrhEvCj6LbmZtrkDAdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnWo6X%2FdJMcagkmKEL%2FKG6RrhEvCj6LbmZtrkDAdk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2414&quot; height=&quot;1748&quot; data-origin-width=&quot;2414&quot; data-origin-height=&quot;1748&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;익숙한 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것저것 기본 세팅을 하면 클로드 메인 화면이 뜬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2380&quot; data-origin-height=&quot;766&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzft55/dJMcadA7fLH/AfwJjE71eKkvb698ZGdDgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzft55/dJMcadA7fLH/AfwJjE71eKkvb698ZGdDgk/img.png&quot; data-alt=&quot;이것이 메인화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzft55/dJMcadA7fLH/AfwJjE71eKkvb698ZGdDgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbzft55%2FdJMcadA7fLH%2FAfwJjE71eKkvb698ZGdDgk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2380&quot; height=&quot;766&quot; data-origin-width=&quot;2380&quot; data-origin-height=&quot;766&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이것이 메인화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 메인화면 뜨고 나서. 응...? 그래서 뭐 어쩌라는 거지? 생각이 먼저 듬 ㅋㅋㅋㅋㅋ 첨부터 힘들구먼&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  프로젝트 구성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 클로드 코드는 프로젝트의 루트 경로에서 실행하는 게 정석인 것 같다. 그리고 실행되는 폴더에 읽기 쓰기 권한을 획득한 후 이것저것 알아서 실행해 주는 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 나는 이번에 프론트와 백엔드를 동시에 만들 것이기 때문에 프로젝트 폴더가 2개가 생길 텐데, 이럴 경우에는 최상위에 폴더 하나를 두고, 그 안에 두 프로젝트 폴더를 배치하면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1772984578214&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;my_project/
├── CLAUDE.md                # 프로젝트 전체 컨텍스트 (핵심!)
├── frontend/                # Flutter 앱
│   ├── CLAUDE.md
│   └── lib/
│       ├── core/            # API 클라이언트, 공통 유틸
│       └── features/        # 기능별 모듈 (auth, home 등)
├── backend/                 # Django 앱
│   ├── CLAUDE.md
│   ├── config/              # settings, urls, wsgi
│   ├── apps/                # Django 앱들
│   └── requirements/        # dev/prod 분리
├── docs/
│   └── api/                 # OpenAPI 명세
└── docker-compose.yml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 CLAUDE.md파일은 클로드에게 기본적인 가이드를 내려주는 파일이다. 이 CLAUDE.md파일에 대해서 어떻게 작성해야 되는지 논란이 많긴 한데, 기본적으로는 클로드 코드에서 /init이라는 명령어를 사용하면 자동으로 작성해 주는 파일이다. 논란인 이유는 CLAUDE.md파일이 클로드 코드의 성능을 떨어뜨린다!라는 논문 때문인데, 실제로 논문의 내용은 &lt;b&gt;'쓸데없는 글이 적힌 CLAUDE.md파일은 클로드 코드의 성능을 떨어뜨린다'&lt;/b&gt; 이기 때문에 잘 적기만 한다면 CLAUDE.md는 아주 유용하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;* 번외&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클로드 코드를 구독을 하면 내가 얼마나 사용했는지 확인이 필요한 경우가 있는데, 이럴 경우에 ccusage cli를 사용하면 얼마나 사용했는지 알 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터가 좀 불친절하게 나오기 때문에 claude-monitor를 사용하면 이쁘게 나오기는 하는데, 이게 터미널을 하나 새로 띄워놓고 할게 아니라면 생각보다 불편해서, claude code 아래 상태표시줄에 내 사용량을 측정해 주는 값을 넣을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1578&quot; data-origin-height=&quot;256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6FFO1/dJMcacbftyw/KPSL2kbrtwdesgD0alxCZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6FFO1/dJMcacbftyw/KPSL2kbrtwdesgD0alxCZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6FFO1/dJMcacbftyw/KPSL2kbrtwdesgD0alxCZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6FFO1%2FdJMcacbftyw%2FKPSL2kbrtwdesgD0alxCZ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1578&quot; height=&quot;256&quot; data-origin-width=&quot;1578&quot; data-origin-height=&quot;256&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 상태창에 넣기 완료. 넣는 방법은 claude code를 시키면 된다. ㅋㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령어는 /statusline이고 명령어치고 원하는 데이터를 넣으면 클로드가 알아서 착착 넣어준다. (완벽하게 알아서 넣어주지는 않고 몇 번 try 끝에 저 모냥이 됨... ㅋㅋ)&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재는 위에 폴더 구조에서 CLAUDE.md와 백엔드, 프론트 프로젝트 폴더 기초적인 것을 만들어 놓은 상태.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CLAUDE.md에는 다음 내용이 적혀있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1773296671395&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## 프로젝트 구조

Django 백엔드 + Flutter 웹 프론트엔드 풀스택 프로젝트.

```
claudecode_project/
├── backend/    # Django 6.0 (Python) &amp;mdash; API 서버
└── frontend/   # Flutter (Dart) &amp;mdash; 웹 전용
```

각 프로젝트의 상세 가이드는 해당 폴더의 `CLAUDE.md` 참고.

## 개발 서버 실행 (동시)

```bash
# 백엔드 (터미널 1)
cd backend &amp;amp;&amp;amp; source .venv/bin/activate &amp;amp;&amp;amp; python manage.py runserver

# 프론트엔드 (터미널 2)
cd frontend &amp;amp;&amp;amp; flutter run -d chrome
```

## 연동 구조

- Flutter 웹 &amp;rarr; Django REST API 호출
- CORS: 백엔드에 `django-cors-headers` 설정 필요
- 기본 포트: Django `8000`, Flutter 웹 `기본 랜덤` (고정 시 `--web-port 3000`)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;flutter를 웹으로 사용할 것이라는 설정만 넣고, 나머지는 아무것도 적지 않았다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대신 백엔드랑 프론트를 기본 장고앱, 플러터앱으로 세팅해 놨기 때문에 클로드가 알아서 어떤 프레임워크인지 인식해서 써준 듯하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 이제 바로 클로드한테 만들어달라고 해보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt; ️ 로드맵 작성하기&amp;nbsp;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2214&quot; data-origin-height=&quot;166&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/swjxf/dJMcaiisxi3/RdXq26q7kjiZ77sWCIhw9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/swjxf/dJMcaiisxi3/RdXq26q7kjiZ77sWCIhw9k/img.png&quot; data-alt=&quot;로드맵 작성 요청하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/swjxf/dJMcaiisxi3/RdXq26q7kjiZ77sWCIhw9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fswjxf%2FdJMcaiisxi3%2FRdXq26q7kjiZ77sWCIhw9k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2214&quot; height=&quot;166&quot; data-origin-width=&quot;2214&quot; data-origin-height=&quot;166&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;로드맵 작성 요청하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무작정 만들어 달라고 해도 잘 만들어주지만, 클로드 코드의 작업을 사람이 트랙킹하기 편하려면 '로드맵'을 작성하는 게 편하다. 클로드 코드가 어떤 순서로 어떤 작업을 할지 계획을 세워주는 단계라고 생각하면 된다. 위처럼 '로드맵을 만들어줘'라고 부탁하면 알아서 로드맵 md파일을 만들어준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1350&quot; data-origin-height=&quot;894&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QIAvx/dJMcagdTL7P/kb1DPVFmx2K8QDXXMiM4p1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QIAvx/dJMcagdTL7P/kb1DPVFmx2K8QDXXMiM4p1/img.png&quot; data-alt=&quot;Phase 별로 계획을 세워줌&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QIAvx/dJMcagdTL7P/kb1DPVFmx2K8QDXXMiM4p1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQIAvx%2FdJMcagdTL7P%2Fkb1DPVFmx2K8QDXXMiM4p1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1350&quot; height=&quot;894&quot; data-origin-width=&quot;1350&quot; data-origin-height=&quot;894&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Phase 별로 계획을 세워줌&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 단계별로 계획을 세우고, 로드맵대로 작업을 실행할까요? 하면 알아서 실행해 줌 ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델은 sonet을 사용했는데도, 생각보다 개발을 잘해주었다. 물론 돌아가는지는 잘 모르겠으니 한번 실행을 해볼까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1764&quot; data-origin-height=&quot;1498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lFZ1P/dJMcahw6PFp/ATBefylzG8MdEPA68Ukaw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lFZ1P/dJMcahw6PFp/ATBefylzG8MdEPA68Ukaw1/img.png&quot; data-alt=&quot;구현 완료&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lFZ1P/dJMcahw6PFp/ATBefylzG8MdEPA68Ukaw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlFZ1P%2FdJMcahw6PFp%2FATBefylzG8MdEPA68Ukaw1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1764&quot; height=&quot;1498&quot; data-origin-width=&quot;1764&quot; data-origin-height=&quot;1498&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;구현 완료&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;▶️ 서비스 실행해 보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발을 완료하기는 했는데, 프론트와 백엔드를 동시에 띄우기 위해 docker-compose를 사용하는 것은 적용이 안 된 상태이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백엔드 프론트 각각 실행하면 되긴 하는데, 한 번에 실행하는 게 좋으니 docker compose로 만들어달라고 요청했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1774785050747&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;❯ 백엔드랑 프론트 동시에 실행할 수 있게 docker compose로 만들어줘&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만드는데 1분 33초 걸렸네요. 음.. 이 정도는 사람이 만드는 속도랑 비슷할 수도..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 docker compose 지식이 없다면 오래 걸릴 텐데 클로드가 잘해줬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만들어진 docker-compose.yaml 파일은 아래 참고&lt;/p&gt;
&lt;pre id=&quot;code_1774785146365&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;services:
  backend:
    build:
      context: ./backend
    ports:
      - &quot;8000:8000&quot;
    volumes:
      - ./backend:/app
    environment:
      - PYTHONUNBUFFERED=1
      - DJANGO_SETTINGS_MODULE=backend.settings
    restart: unless-stopped
    healthcheck:
      test: [&quot;CMD&quot;, &quot;python&quot;, &quot;-c&quot;, &quot;import urllib.request; urllib.request.urlopen('http://localhost:8000/admin/')&quot;]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 15s

  frontend:
    build:
      context: ./frontend
    ports:
      - &quot;3000:80&quot;
    depends_on:
      backend:
        condition: service_healthy
    restart: unless-stopped&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 그대로 docker compose 실행하니까 에러가 남 ㅋㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래라면 에러 메시지 보고 어디가 문제인지 고민했겠지만, 클로드에게 맞겨본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1624&quot; data-origin-height=&quot;896&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vp4u2/dJMcafTADFL/ZCV224j5RMeCERPEVBKCM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vp4u2/dJMcafTADFL/ZCV224j5RMeCERPEVBKCM0/img.png&quot; data-alt=&quot;자기가 알아서 수정함&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vp4u2/dJMcafTADFL/ZCV224j5RMeCERPEVBKCM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fvp4u2%2FdJMcafTADFL%2FZCV224j5RMeCERPEVBKCM0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1624&quot; height=&quot;896&quot; data-origin-width=&quot;1624&quot; data-origin-height=&quot;896&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;자기가 알아서 수정함&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자기가 직접 돌려보면서 에러메시지를 보고, 다시 수정해서 돌리고 에러 있나 체크하고 쿵짝쿵짝함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 다시 돌리니까 되네?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 docker-compose.yaml이 에러가 아니라 flutter 쪽 dockerfile에 패키지 다운로드하는 부분이 권한이 없어서, ghcr -&amp;gt; debian으로 바꾼 듯하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 실행하니 다음과 같은 프론트 화면이 뜬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1512&quot; data-origin-height=&quot;1292&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bD0LtT/dJMcahjAUw3/meqq14PEUauvGVar3Kp4a0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bD0LtT/dJMcahjAUw3/meqq14PEUauvGVar3Kp4a0/img.png&quot; data-alt=&quot;보드게임 앱 완성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bD0LtT/dJMcahjAUw3/meqq14PEUauvGVar3Kp4a0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbD0LtT%2FdJMcahjAUw3%2Fmeqq14PEUauvGVar3Kp4a0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;513&quot; data-origin-width=&quot;1512&quot; data-origin-height=&quot;1292&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;보드게임 앱 완성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디자인이 좀 구린데..?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 따로 가이드를 안 해서 그런지, sonet 모델이라서 그런지 생각보다 디자인은 구렸다 ㅋㅋㅋ flutter 기본 디자인을 쓴 것 같음. 뭐 가이드를 주면 이건 이쁘게 해 줄 거니까, 그냥 무시하고 어떤 기능들이 되는지 테스트해 봤다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;로그인 가능 (어드민에서 유저 만들어야 함)&lt;/li&gt;
&lt;li&gt;모임 생성, 참여, 삭제 가능&lt;/li&gt;
&lt;li&gt;보드게임 관리기능 먹통...&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보드게임은 추가 버튼을 눌렀더니 흰 화면만 나오고 먹통이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클로드에게 이 기능이 안 된다고 고쳐달라고 요청했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2492&quot; data-origin-height=&quot;1092&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oCABX/dJMcahjAUG8/IeUXjB6W2mZfhDjTywAYd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oCABX/dJMcahjAUG8/IeUXjB6W2mZfhDjTywAYd1/img.png&quot; data-alt=&quot;알아서 다 해주죠?&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oCABX/dJMcahjAUG8/IeUXjB6W2mZfhDjTywAYd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoCABX%2FdJMcahjAUG8%2FIeUXjB6W2mZfhDjTywAYd1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2492&quot; height=&quot;1092&quot; data-origin-width=&quot;2492&quot; data-origin-height=&quot;1092&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;알아서 다 해주죠?&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자동으로 배포까지 해주기 때문에 새로고침 한번 하고 하니까 잘됨!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1068&quot; data-origin-height=&quot;1656&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUh6Os/dJMcabjm2H0/Q1VxRJTz1L5GCGTidpWK91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUh6Os/dJMcabjm2H0/Q1VxRJTz1L5GCGTidpWK91/img.png&quot; data-alt=&quot;추가 창&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUh6Os/dJMcabjm2H0/Q1VxRJTz1L5GCGTidpWK91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUh6Os%2FdJMcabjm2H0%2FQ1VxRJTz1L5GCGTidpWK91%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;930&quot; data-origin-width=&quot;1068&quot; data-origin-height=&quot;1656&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;추가 창&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 추가할 때 이미지랑 BGG ID 있길래 여기에 넣으면 자동으로 링크를 해주거나, 이미지를 추가해 주는 줄 알았는데 아무것도 안 함 ㅋㅋㅋ&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1076&quot; data-origin-height=&quot;792&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dMThlb/dJMcaduDb7j/3LOCMpKiyHV3yRMVqatTi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dMThlb/dJMcaduDb7j/3LOCMpKiyHV3yRMVqatTi1/img.png&quot; data-alt=&quot;왜 추가한건데 ㅋㅋㅋ&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dMThlb/dJMcaduDb7j/3LOCMpKiyHV3yRMVqatTi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdMThlb%2FdJMcaduDb7j%2F3LOCMpKiyHV3yRMVqatTi1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;294&quot; data-origin-width=&quot;1076&quot; data-origin-height=&quot;792&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;왜 추가한건데 ㅋㅋㅋ&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것도 한번 부탁해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지가 안 나온다고 하니 이것저것 하길래 그래도 안된다고 해서 3번에 씨름만에 드디어 완성 ㅋㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1078&quot; data-origin-height=&quot;1322&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpVSuC/dJMcaiiszcg/OAqMQ4Q2L0vzfv350txrc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpVSuC/dJMcaiiszcg/OAqMQ4Q2L0vzfv350txrc1/img.png&quot; data-alt=&quot;와우 굳&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpVSuC/dJMcaiiszcg/OAqMQ4Q2L0vzfv350txrc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcpVSuC%2FdJMcaiiszcg%2FOAqMQ4Q2L0vzfv350txrc1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;491&quot; data-origin-width=&quot;1078&quot; data-origin-height=&quot;1322&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;와우 굳&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt; &amp;zwj;  디자인 입혀보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자가 1인 개발에서 가장 어려운 건 디자인이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공대 감성은 어쩔 수 없달까? ㅋㅋㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클로드 코드한테 한번 보드게임 앱답게 디자인을 바꿔달라고 해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1770&quot; data-origin-height=&quot;1448&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r63Wj/dJMcahjAVxE/2aE2RWKme9WFyJCOP5pfJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r63Wj/dJMcahjAVxE/2aE2RWKme9WFyJCOP5pfJk/img.png&quot; data-alt=&quot;오 ?&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r63Wj/dJMcahjAVxE/2aE2RWKme9WFyJCOP5pfJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr63Wj%2FdJMcahjAVxE%2F2aE2RWKme9WFyJCOP5pfJk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1770&quot; height=&quot;1448&quot; data-origin-width=&quot;1770&quot; data-origin-height=&quot;1448&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;오 ?&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많이 바꿨다고 한다. 한번 실행해 볼까?&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1072&quot; data-origin-height=&quot;1490&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nX3ux/dJMcaaSionT/uY6GrRy28o2XhdNly6Ohuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nX3ux/dJMcaaSionT/uY6GrRy28o2XhdNly6Ohuk/img.png&quot; data-alt=&quot;오 .. ? ㅋㅋㅋ&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nX3ux/dJMcaaSionT/uY6GrRy28o2XhdNly6Ohuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnX3ux%2FdJMcaaSionT%2FuY6GrRy28o2XhdNly6Ohuk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;556&quot; data-origin-width=&quot;1072&quot; data-origin-height=&quot;1490&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;오 .. ? ㅋㅋㅋ&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테마나 레이아웃을 뭔가 요즘(?)스럽게 바꿨다. 아까보다는 좋은 듯? ㅋㅋㅋㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt; &amp;zwj;  기능을 추가하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에 만들어 달라고 했던 기능은 어느 정도 나온 것 같은데, 만들다 보니 새로운 기능이 필요해 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음부터 만드는 것도 잘했으니, 새로 기능 추가도 잘하겠지?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 내 정보를 수정할 수 있게 해 보자. 비밀번호 수정이라던지, 프로필 사진 추가라던지, 내가 참여한 모임 보기 기능 이런 것들?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1774789511881&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;❯ 새로운 기능을 추가하고 싶어. 로드맵에 추가해줘.

회원의 개인 정보를 수정하는 기능이 필요해. 비밀번호를 변경하거나 프로필 사진을 변경하고 싶어. 변경한 프로필
사진은 참여한 모임이나 내 이름이 들어가는 곳에 동그랗게 표시하고 싶어.

보드게임 관리에서는 특정 보드게임을 즐겨찾기 할 수 있는 기능을 넣고 싶어. 물론 내가 즐겨찾기한 보드게임을
모아보는 화면도 만들어줘.

보드게임을 새로 추가할 때 BGG ID를 입력하면 BGG 홈페이지에서 정보를 읽어와서 자동으로 추가하게 해줘.
보드게임에 대한 평가점수나 난이도, 게임 인원 등 추가 정보도 더 많이 표기하고 싶어.

일단 로드맵을 만들고 기존 파일에 추가해줘&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상당히 자세하게 요청했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 것을 요청하기 위해서는 어느 정도 기획능력이 필요한데, 이래서 개발자보다는 기획자가 클로드 코드를 사용한 바이브 코딩에 유리한 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1574&quot; data-origin-height=&quot;1328&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LcJlX/dJMcadg9EzH/7534GbrXtwdiXRbytzI5ik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LcJlX/dJMcadg9EzH/7534GbrXtwdiXRbytzI5ik/img.png&quot; data-alt=&quot;새로 로드맵을 만들어줌&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LcJlX/dJMcadg9EzH/7534GbrXtwdiXRbytzI5ik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLcJlX%2FdJMcadg9EzH%2F7534GbrXtwdiXRbytzI5ik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1574&quot; height=&quot;1328&quot; data-origin-width=&quot;1574&quot; data-origin-height=&quot;1328&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;새로 로드맵을 만들어줌&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 이제 만들어진 새로운 로드맵으로 작업을 해달라고 요청해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1750&quot; data-origin-height=&quot;976&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNDMQW/dJMcafe023M/D15ksq8joeHbIGLj1U0yR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNDMQW/dJMcafe023M/D15ksq8joeHbIGLj1U0yR1/img.png&quot; data-alt=&quot;오호... 총 8분이 걸렸다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNDMQW/dJMcafe023M/D15ksq8joeHbIGLj1U0yR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNDMQW%2FdJMcafe023M%2FD15ksq8joeHbIGLj1U0yR1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1750&quot; height=&quot;976&quot; data-origin-width=&quot;1750&quot; data-origin-height=&quot;976&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;오호... 총 8분이 걸렸다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 어디 얼마나 잘했는지 한번 실행해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1076&quot; data-origin-height=&quot;1494&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHwcdv/dJMcafzil7e/qgG2Q1NC7LshAaayBc8FQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHwcdv/dJMcafzil7e/qgG2Q1NC7LshAaayBc8FQk/img.png&quot; data-alt=&quot;프로필 메뉴 생김&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHwcdv/dJMcafzil7e/qgG2Q1NC7LshAaayBc8FQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHwcdv%2FdJMcafzil7e%2FqgG2Q1NC7LshAaayBc8FQk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;555&quot; data-origin-width=&quot;1076&quot; data-origin-height=&quot;1494&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로필 메뉴 생김&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;1482&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/begRDe/dJMcaiCKAqq/5mdgOgZM5itiaCOuzQmvok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/begRDe/dJMcaiCKAqq/5mdgOgZM5itiaCOuzQmvok/img.png&quot; data-alt=&quot;프로필 사진 넣었을 때 ㅋㅋ&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/begRDe/dJMcaiCKAqq/5mdgOgZM5itiaCOuzQmvok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbegRDe%2FdJMcaiCKAqq%2F5mdgOgZM5itiaCOuzQmvok%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;560&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;1482&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로필 사진 넣었을 때 ㅋㅋ&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인 정보 수정은 완벽한 것 같다. 사진 변경도 잘 됨 ^~^&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1068&quot; data-origin-height=&quot;1498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOKG4r/dJMcabDEDFR/hOzk7AQZUnvTbtwDpVPl30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOKG4r/dJMcabDEDFR/hOzk7AQZUnvTbtwDpVPl30/img.png&quot; data-alt=&quot;가장 중요한 BGG ID 가져오기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOKG4r/dJMcabDEDFR/hOzk7AQZUnvTbtwDpVPl30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOKG4r%2FdJMcabDEDFR%2FhOzk7AQZUnvTbtwDpVPl30%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;561&quot; data-origin-width=&quot;1068&quot; data-origin-height=&quot;1498&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가장 중요한 BGG ID 가져오기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음엔 BGG ID를 입력해도 작동이 안 되었는데, 클로드에게 물어보니 BGG에서 제공하는 API를 이용해서 만들려고 하고 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 API를 이용하자니 oauth연동을 해야 할 것이고, 실제로 API를 제공하는지도 모르겠고 ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 스크래핑으로 만들어줘!라고 했더니 BGG에서 가져오기를 누르면 BGG홈페이지가 잠깐 뜨고, 새로 추가되는 것을 확인할 수 있었다. 굳..&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1406&quot; data-origin-height=&quot;1654&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l2drx/dJMcadIbzYX/aZVQSkXZBoHrmcRnagf8K1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l2drx/dJMcadIbzYX/aZVQSkXZBoHrmcRnagf8K1/img.png&quot; data-alt=&quot;자동으로 값 입력 완료&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l2drx/dJMcadIbzYX/aZVQSkXZBoHrmcRnagf8K1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl2drx%2FdJMcadIbzYX%2FaZVQSkXZBoHrmcRnagf8K1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;471&quot; data-origin-width=&quot;1406&quot; data-origin-height=&quot;1654&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;자동으로 값 입력 완료&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1394&quot; data-origin-height=&quot;1602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cd5Orj/dJMcagkDxv9/MZNWqbL2ddApnCJK7FXDO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cd5Orj/dJMcagkDxv9/MZNWqbL2ddApnCJK7FXDO0/img.png&quot; data-alt=&quot;목록에도 이쁘게 나옴&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cd5Orj/dJMcagkDxv9/MZNWqbL2ddApnCJK7FXDO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcd5Orj%2FdJMcagkDxv9%2FMZNWqbL2ddApnCJK7FXDO0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;460&quot; data-origin-width=&quot;1394&quot; data-origin-height=&quot;1602&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;목록에도 이쁘게 나옴&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1396&quot; data-origin-height=&quot;1638&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UQvY5/dJMcahDP8nJ/OlFx8GB8izhkSGIdU6kwvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UQvY5/dJMcahDP8nJ/OlFx8GB8izhkSGIdU6kwvk/img.png&quot; data-alt=&quot;상세화면 너무 잘 만들죠?&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UQvY5/dJMcahDP8nJ/OlFx8GB8izhkSGIdU6kwvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUQvY5%2FdJMcahDP8nJ%2FOlFx8GB8izhkSGIdU6kwvk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;469&quot; data-origin-width=&quot;1396&quot; data-origin-height=&quot;1638&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;상세화면 너무 잘 만들죠?&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아니 너무 잘 만들어주잖아?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  정리하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에 클로드 코드를 이용해서 보드게임 동호회 서비스 프로토타입을 만들어보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 내가 개발을 해서 만들었으면 1달 정도 걸렸을 것 같은데, 클로드를 이용해서 한 5~6시간 만에 만든 것 같다. (블로그 쓰는 거 제외하면 2~3시간?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트는 역시나 잘해주었고, 백엔드도 생각했던 것보다 너무 퀄리티 있게 뽑아주었다. 특히 에러난 부분을 스스로 테스트해 가면서 고치는 게 너무 좋은 듯?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 1인 개발자로 일하게 된다면 항상 아쉬웠던 디자인 부분도 클로드가 잘 만들어주니, 상용화된 서비스도 만들 수 있을 것 같은데?라는 생각이 들었다. 물론 인프라적인 내용까지 클로드가 해주지는 못할 것 같긴 한데(AWS나 domain 등록 등...) 이 정도는 사람이 해야지 ^~^&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스팅에서는 단일 에이전트로 작업을 진행했는데, 최근에 에이전트 팀 모드를 사용해 보니 단일로 사용할 때보다 속도가 더 빨랐다. (물론 토큰을 그만큼 많이 사용해서 돈이 많이 나감.. ㅎ)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에 만든 동호회 서비스를 개선하거나, 다른 일을 하면서 클로드 코드를 어떻게 써야 효과적으로 쓸지 연구해 볼 생각이다. (요즘엔 이런 걸 AX - AI Transformation이라고 부르는 것 같다.)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/617</guid>
      <comments>https://cholol.tistory.com/617#entry617comment</comments>
      <pubDate>Sun, 29 Mar 2026 23:24:23 +0900</pubDate>
    </item>
    <item>
      <title>개발자 이직 면접, 저주 좀 풀고 가세요 !! 이직 면접에서 이것만은 피하자~!</title>
      <link>https://cholol.tistory.com/614</link>
      <description>&lt;div class=&quot;index_toc&quot;&gt;
&lt;p class=&quot;toc_title&quot; data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q9vUG/btsPDVHlSl4/5ds6kkkQWQtrNlZrdTk9k0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q9vUG/btsPDVHlSl4/5ds6kkkQWQtrNlZrdTk9k0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q9vUG/btsPDVHlSl4/5ds6kkkQWQtrNlZrdTk9k0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq9vUG%2FbtsPDVHlSl4%2F5ds6kkkQWQtrNlZrdTk9k0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;600&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  머리말&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자 이직 면접에 대해서 예전부터 하고 싶은 말이 많았는데, 드디어 씀!!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연차가 어느 정도 쌓이다 보면 면접관을 많이 하게 되는데, 정말 누가 봐도 대단하다고 생각되는 지원자 분을 만나거나, 엄청난 고스펙 이력서 대비 실제 면접에서 생각보다 별로였던 지원자 분도 있었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 면접을 잘 보는 방법(?) 같은 정석은 없는 것 같다. 회사에서 원하는 인재도 다르고, 해당 팀에서 원하는 사람도 다르고, 누가 면접에 들어가느냐, 그날 기분이 어떻냐, 질문이 어떻냐 등등 너무 많은 변수가 존재하기 때문에, 이 변수를 다 이길만한 슈퍼 전략 같은 건 없을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 잘하는 법 말고, 못하지 않는 법(?)은 몇 가지 있다. 나와 같이 참여했던 면접관들이 공통적으로 느끼는, 면접자에 실수들에 대해 말해보려고 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 포스팅에서는 이것을 '저주'라고 쓰겠다. 왜 저주인지는 아래 보면 나옴!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  지식의 저주&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지식의 저주(Curse of knowledge)라는 단어를 들어본 적이 있다면, 아마 커뮤니케이션 스킬에 대해서 어느 정도 신경 쓰고 있는 사람일 것이다. 나는 남들 앞에서 프레젠테이션 하는 것을 좋아하고 의사소통 하는 것을 좋아해서 대화의 스킬이나 심리학 등을 따로 많이 공부했었는데, 그중에서 가장 기억에 남는 단어가 바로 지식의 저주이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;지식의 저주&lt;/b&gt;란, 쉽게 설명하면 &lt;b&gt;내가 아는 것을 남도 알 것이다라고&lt;/b&gt; 추측하는 것이다. 예를 들어 보면, 최근에 개봉한 'F1'영화를 상대방도 봤을 거라 추측하고 영화의 나오는 대사나 장면을 인용하여 말한다면, 영화를 보지 않은 상대방은 '이 사람이 무슨 소리를 하는 거지?'라고 느끼게 되는 것이 당연하다. 이렇게 예를 들면 &lt;b&gt;'누가 영화 봤는지도 안 물어보고 그렇게 함?'이라고&lt;/b&gt; 할 수 있는데, 생각보다 이렇게 대화하는 사람이 많다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자의 면접은 이력서에 기술된 업무나 과제에 대해 질문과 답변을 하며 진행된다. 지원자 입장에서는 원래 회사에서 하는 업무이고, 오래 해온 일이기 때문에 면접관에 질문에 아주 쉽게 답하곤 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면접관: &quot;광고 플랫폼에 신규 프로젝트를 진행하셨는데, 어떤 일인지 설명해 주실 수 있나요?&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면접자: &quot;넵. 기존에 Oreo 서비스 안에는 CPC와 CPA가 있었는데, CPM을 추가하고, 데이터를 정리해서 Dat서버로 전달하는 기능을 추가했습니다.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 대화에서 면접자의 말을 다 알아들을 수 있는 사람은 면접자와 같은 회사에서 일하고 있는 사람들일 것이다. 면접자 입장에서는 평소에 하던 일이고, 주변에 업무 관련자들과만 얘기를 나눴기 때문에 아무런 부연 설명 없이 얘기를 했다. 하지만 면접관들은 전혀 다른 회사에 전혀 다른 업무를 하는 사람들이고, 설령 같은 업종에 일하는 사람이라고 해도 면접자가 머릿속에 생각하고 있는 것을 완벽하게 알 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따러서 위 방식대로 말하면 면접관은 하나도 못 알아듣는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면접자: &quot;넵 일단 저희가 운영 중인 광고 서비스 프로젝트 이름은 'Oreo'인데요, Oreo에서는 광고 단가 측정 방식과 관련된 서비스를 제공하고 있습니다. 광고 단가 측정방식은 여러 개가 있는데, 클릭당 단가인 CPC와 사용자 액션당 단가인 CPA를 사용 중이었습니다. 이번에 기획 요건으로 노출당 단가 CPM을 추가하고 전체 광고 데이터를 가공해서 데이터 분석팀이 운영 중인 데이터 분석 솔루션 Dat 서버로 전달하는 기능도 추가했습니다.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자세한 설명은 아니지만 처음 듣는 사람도 면접자가 어떤 업무를 한 건지 감을 잡을 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 줄 요약 - 내가 안다고 해서 모두가 아는 것은 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  우물 안 개구리 저주 (3년 차의 저주)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면접을 보다 보면 자신감이 넘쳐흘러 자만해 보이기까지 하는 지원자를 만날 수 있다. 어느 정도 자신감은 좋게 보일 수 있지만, 과다한 자신감은 면접관 머리에? 가 뜬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 회사에 입사하고 3~4년 차 정도 되면, 어느 정도 일에 익숙해지고, 협업하는 주변 동료들과 관계도 잘 형성되어 있기 때문에 일이 아주 쉬워(?) 지는 타이밍이다. 맡은 업무에 대한 대부분의 것을 알고 있기 때문에 일이 들어와도 바로바로 어떻게 해결해야 할지 머릿속에 팡팡 떠오른다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때가 위험한 순간이다. 마치 스스로가 엄청나게 대단한 사람, 기술적으로 뛰어난 사람이라는 착각을 하게 될 수 있다. 물론 모든 사람이 그런 것은 아니다 ㅎ (참고로 나는 그랬음..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 이 상태를 &lt;b&gt;'우물 안 개구리 저주'&lt;/b&gt;라고 이름 붙이기로 했다. 또 다른 이름은 &lt;b&gt;'3년 차의 저주'.&lt;/b&gt; 과거 내가 첫회사에서 3~4년 차 때 내가 정말 대단한 사람이고, 아주 어려운 문제도 빠르게 해결하는 사람인 줄 알았다. 그래서 이직을 위한 면접을 엄청 많이 봤는데, &lt;b&gt;모두 면접에서 탈락!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면접을 보면서 느낀 것은, 나는 정말 우물 안 개구리였다. 내가 잘한다고 생각했던 건 이 업무에 익숙해져서였다. &lt;b&gt;다른 특별한 건 없었다!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(지금도 면접을 보면서 당당했던 나의 태도를 생각하면서 이불킥을 하곤 한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 케이스는 면접 때 아주 자신감 있게 대답하며, &lt;u&gt;내가 한 일은 모두 대단한 일이고 옳은 일이다!라는&lt;/u&gt; 생각을 가지고 있다. 따라서 면접 도중 &lt;b&gt;'이 방법 말고 다른 방법은 없었을까요?'라는&lt;/b&gt; 질문을 받게 되면, 질문에 대한 답을 하기보다는 본인이 선택한 방법이 잘못됐다고 지적하는 것이라고 오해하기 쉬워진다. 면접관이 원한 것은 다양한 방법을 고려하고 최적의 선택 안을 찾는 스킬을 보려고 한 것인데, 전혀 엉뚱한 대답을 하곤 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자신감이 넘치게 되면 시야가 좁아진다. 그럼 질문에 대한 대답을 다양하게 하지 못하게 된다. 여러 가지 질문을 해도 본인이 경험하고 생각한 질문 한 가지로만 계속 대답을 되풀이하는 경우도 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 줄 요약 - 겸손은 최고의 미덕이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  단답의 저주&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면접이 아니라 평상시에도 이야기하다 보면 대화가 이어지지 않는 사람들이 있다. 특히 단답으로 대답하는 특성의 사람들은 대화하기가 너무 힘들다. 원래 항상 단답으로 말하는 건지, 나와 대화하기 힘들 건지 파악하기도 힘듦 ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그. 런. 데. 면접에서는 더 심하다. 면접은 면접관과 면접자가 대화를 하면서 &lt;b&gt;면접자의 성향을 파악하는 과정&lt;/b&gt;이다. 그런데 면접자가 단답으로 대답한다? 그럼 면접관 입장에서는 &lt;u&gt;&lt;b&gt;'이 사람이랑은 일하기 힘들겠는데?'&lt;/b&gt;&lt;/u&gt;라는 생각이 가장 먼저 든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 누가 면접 가서 단답으로 말할까?라고 생각하지만 생각보다 이런 케이스가 많았다. 예를 들어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면접관 - &quot;이 프로젝트라서 A라는 기술을 적용하셨는데 다른 방법에 대해 고민한 것은 없으신가요?&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면접자 - &quot; 넵 &quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면접관 - &lt;b&gt;&quot;???&quot;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 여기서 면접자는 면접관이 물어본 질문에 대해 A라는 기술을 적용했고, 다른 방법을 고민하지 않았기 때문에 그냥 '네'라고 대답했다. 문맥적으로는 이상할 것이 없는 대화이지만, 이 자리가 면접자리이기 때문에 이는 안 좋은 대답이 될 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면접에서 면접관이 하는 모든 질문의 의도는 &lt;b&gt;&quot; 자 이런 상황이야. 너의 생각을 말해봐 &quot;&lt;/b&gt;가 대부분이다. 위 질문에서는 A라는 기술을 적용했는데 왜 적용했는지, 다른 건 생각 안 해봤는지, 생각했다면 어떤 걸 비교해서 A를 적용했는지, A를 적용하면서 문제는 없었는지, 의사결정은 어떻게 됐는지 등등 모~~ 든 것이 궁금한 게 면접관 입장이다. 하지만 여기서 '넵'이라고 대화를 끝내버리면 면접관은 황당하게 된다. ㅎㅎ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 면접관으로 들어가는 경우에는, 위 같은 상황이 2번 이상 발생하면 면접관들끼리 빨리 끝내자고 합의하여 면접을 바로 종료하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 다른 회사 면접도 비슷할 듯..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면접자는 항상 면접에서 자신이 평소에 생각한 것들, 고민하고 있는 것들을 많이 보여주면 보여줄수록, 합격 확률이 높다는 것을 기억하면 좋을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;** 그런다고 너무 과한 것도 안 좋다. 한 가지 질문에 대해 너무 많은 대답. 너무 긴 대답을 하게 되면 그거대로 역효과이기 때문에, 어느 정도 어필하고 싶은 부분만 말하고 면접관이 면접을 진행할 수 있는 틈을 주는 것이 좋다. &lt;b&gt;TMI는 금지!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  정리하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하면, 면접을 보러 갈 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. &lt;b&gt;지식의 저주&lt;/b&gt; - 내가 알고 있는 것을 상대방도 알고 있다고 착각하는 저주&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. &lt;b&gt;우물 안 개구리 저주&lt;/b&gt; - 내가 대단하다는 착각에 빠져있는 저주&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. &lt;b&gt;단답 저주&lt;/b&gt; - 본인의 의견이나 생각을 어필하지 않는 저주&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 3가지 저주는 꼭 풀고 왔으면 좋겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평소에는 잘 하지만 '면접'이라는 자리가 긴장되고 부담스러워서 저주에 걸리는 사람들이 많다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면접관들이 잡아먹는 게 아니니까 편~한~ 마음으로 &lt;b&gt;평정심을 유지할 수 있는 훈련&lt;/b&gt;도 하는 게 좋을 것 같다. (&amp;lt;--- 중요 )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Blog/IT, I Think</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/614</guid>
      <comments>https://cholol.tistory.com/614#entry614comment</comments>
      <pubDate>Fri, 8 Aug 2025 19:35:05 +0900</pubDate>
    </item>
    <item>
      <title>백엔드 개발자들은 어떤 고민을 하고 있나 ? - 백엔드 개발자 모임에서 나온 개발자들의 고민들</title>
      <link>https://cholol.tistory.com/613</link>
      <description>&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;div class=&quot;index_toc&quot;&gt;
&lt;p class=&quot;toc_title&quot; data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  백엔드 개발자 모임에서 나눈 대화 정리하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난번 포스팅(&lt;a href=&quot;https://cholol.tistory.com/612&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;백엔드 개발자 놀이터 모임 준비 및 후기&lt;/a&gt;)에 이어서, 모임에서 나누었던 이야기를 정리해보려고 한다. 벌써 한 달이나 지난 일이라 가물가물한데... ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생각보다 많은 얘기를 나누었던 것 같아서 주제별로 나열해 보면서 기억하면 기억나지 않을까...? ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 백엔드 개발자 모임에서 나눌 고민 주제는 아래와 같이 요약할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; color: #333333; text-align: justify;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;&lt;b&gt;커리어 설계&lt;/b&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;&lt;b&gt;이직 준비&lt;/b&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;&lt;b&gt;일의 방식과 조직에서의 역할&lt;/b&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;&lt;b&gt;기술 스택과 성장 방향&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가적으로 이때 모인 멤버는 나까지 총 6명으로 대부분 1~5년 차 백엔드 개발자였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번부터 너무 큰 주제여서 2번 이직준비부터 대화를 진행했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*(참고) 이번 모임은 서로의 고민을 공유하고 공감하는 목적이었기 때문에 특정 고민에 대한 답을 구하는 자리는 아니었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*영상이 편하신 분들을 위한 유튜브 링크&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/IKgFvcOTsYE&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/IKgFvcOTsYE&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=IKgFvcOTsYE&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/b3byOp/hyY442PIwf/GEL9ShYKulhDipZkpCpZK1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720,https://scrap.kakaocdn.net/dn/eFGGL8/hyY37ey7nn/BpUPJxgqlTOaKGkSES3ogK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;직접 진행한 오프라인 개발자 모임 후기 !!  요즘 백엔드 개발자들은 어떤 고민을 하고 있나 ~&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/IKgFvcOTsYE&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  이직 준비&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참여자분들중에 3년 차이신 분들이 꽤 많았는데, 이 연차 때 슬슬 이직 생각을 하는 것 같다. 나도 첫회사에서 3년 차쯤~ 이직 준비를 부랴부랴 했던 것 같아서 잠깐 옛날 생각이 났었다 ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 3년차일까 생각해 보면, 3년이면 어느 정도 회사에 적응하고, 지금 하는 일에 적응하고 주어진 업무를 쉽게 처리할 능력이 되는 시기다. 그리고 3년 차면 자기가 뭔가 기술적으로나 업무적으로 성과를 내고 싶은 시기인데, 만약 회사에서 주어지는 일이 너무 쉽게 여겨지거나 도전적인 업무가 아닐 경우 (단순한 반복 업무일 경우) 매너리즘에 빠질 수 있는 때다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게다가 3년동안 개발자로 일하면 어느 정도 좋은 회사와 안 좋은 회사 필터링이 가능해지는데, IT 대기업을 가고 싶은 욕망이 뿜뿜 하는 시기다. 보통 첫회사가 IT 대기업(흔히 네카라쿠배 뭐시기..)이라면 이 시기에 이직을 덜 하는 것 같긴 하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 주제에 대해서 얘기를 나누면서 나온 고민들을 정리해 보면 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참여자 A님 (5년 차 백엔드 개발자) - 어떻게 하면 이직을 쉽게 할 수 있을까?&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 이직을 준비하는 개발자라면 누구나 하게 되는 고민이긴 한데, 고민을 공유해 주신 A님은 자기의 사례를 아주 구체적으로 말씀해 주셨다. 참여했을 당시는 이미 이직할 회사에 합격하고, 이전 회사를 그만두신 상태였는데, 이직을 하기 위해 이력서를 몇 십 군데 지원했다고 얘기하셨다. 그리고 서류 합격율이 생각보다 높으셔서 면접을 많이 봤다고 하셨다 ㅋㅋ 몇 %였는지 기억이 잘 안 나는데 25%~30% 정도였던 것 같다. 그래서 다른 참여자분들도 &quot;오 그 정도면 높은데요?!&quot;라고 부러워하셨는데... 이 바닥은 서류 합격이 힘든 게 사실인 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A님도 역시 IT 대기업을 가고 싶어 하셨는데, 합격하기 정말 힘들다고 하셨다. 면접까지는 갔는데 면접에서 자꾸 떨어진다고 ㅠㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 A님은 면접을 하면서 자기 자신의 부족한 점을 객관적으로 느끼셨다고 한다. &quot;세상에 너무 잘하는 사람이 많다&quot;라고 말하시는 겸손한 태도를 보고 언젠가 꼭 좋은 회사를 가실 수 있을 거라는 생각이 개인적으로 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이직은 3번 정도 해보고, 면접관으로 참여를 해보면서 이직은 쉽게 하는 방법에 대해서 생각해 본다면, 역시 제일 쉬운 것은 인맥이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나 역시 지금 회사에 추천으로 들어왔기 때문에 추천의 힘이 강하다는 것을 알 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사 입장에서 전혀 모르는 사람을 검증하여 뽑는 것보다는 아는 사람을 뽑는 게 더 이득이다. 이미 누군가에게 검증된 사람이기 때문이다. 이래서 레퍼체크가 중요함 ㅇㅇ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그럼 인맥은 어디서 구하는데?라고&lt;/b&gt; 질문할 수 있는데, 가장 쉬운 건 좋은 대학을 나오는 것. 스카이정도 나오면 학교 인맥으로 좋은 회사에 들어가기 쉬운 것 같다. 물론 학교 생활을 잘해서 동기나 친구들을 잘 사귀었다면 말이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 대학은 이미 과거이기 때문에, 현재에 인맥을 쌓을 수 있는 방법은 무엇일까? 네트워킹 모임을 나가면 된다. 인터넷에 개발자 모임이나 네트워킹이라고 검색하면 많은 모임이 존재한다. 개인이 주최하는 것보다 회사나 단체에서 주최하는 걸 참여하면 많은 개발자와 교류할 수 있다. 아니면 IT관련 컨퍼런스에 참여하는 것도 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 다른 방법은 회사 인맥이다. 이직을 하다 보면 전회사, 전전회사 동료를 통해 또 다른 회사로 이직할 수 있는 경우가 많다. 물론, 평소에 회사에서 좋은 인간관계를 형성해 놓아야지만 가능한 일이다 ^^&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인맥 말고 이직을 잘하는 방법은 뭐가 있을까..? 하면, 역시나 그냥 개발을 잘하는 수밖에 없다. 개발을 잘하면 딱 봐도 티가 나고 주변에서 데려가려고 아우성이다. 회사일을 잘하는 건 기본이고 오픈소스에 기여하거나 개인적인 프로젝트를 만들어서 공유하거나 하는 방식으로 잘해야 한다. 회사일만 잘해서는 눈에 띄지 않는다는 점이 중요하다. 따라서 남에 눈에 띄게 개발을 잘하려면 업무 외 시간에 개발을 많이 해야 하는데, 이렇게 되면 거~~~ 의 개인 시간이 없게 된다. 나 같은 경우 취미/특기가 개발이기 때문에 아주 운이 좋은 케이스이긴 한데, 이런 경우가 아니라면 개인의 모든 시간을 개발에 쏟아야 하기 때문에 삶이 힘들게 느껴질 수 있다. 하지만 그 정도 노력은 해야 좋은 데 가지.. 노력하지 않고 좋은 데 가려고 하는 건 너무 욕심인 것 같다. (극 T 발언..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이직/면접에 대한 마음가짐&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 그냥 이직 관련 얘기를 하다 나온 주제인데, 서류나 면접을 탈락하게 되면 심리적으로 타격이 꽤 크다. 나도 첫 이직하던 시기에는 스스로 일도 잘하고 능력이 빵빵하다고 자만할 때가 있었다. 정말 어디든 갈 수 있을 거라 생각했었는데, 맘처럼 쉽게 되지 않았다. 이곳저곳에서 탈락소식을 듣게 되면 &quot;내가 정말 잘하는 게 맞나?&quot;, &quot;나는 그냥 감자인가?&quot;, &quot;지금 회사에 익숙해진 거지 내가 잘하는 게 아니었나?&quot; 등등의 많은 생각을 하게 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 개인적으로 면접은 운 적인 요소가 많다고 생각하는데, 면접관으로 어떤 사람이 들어가냐, 그 사람의 기분은 어떠냐, 제한된 시간에 나오는 질문의 종류가 무엇이냐 등등 여러 가지 랜덤성이 있는 요소가 면접에 포함되어 있다. 따라서 면접에 떨어진다고 해서 면접자가 부족한 사람이라는 생각은 잘 안 하는 편이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 항상 말하는 것은 면접이란 면접관과 면접자가 서로 평가하는 자리로, 면접관은 면접자에 대해서 같이 일하기 좋은 사람인지 판단하고, 면접자는 면접관을 보면서 일하기 좋은 회사(or 팀)인가를 확인하는 자리다. 절대로 일방적인 평가자리가 아니라고 생각한다. 면접관을 통해 이 회사가 정말로 내가 일하기 좋은 회사인지 판단하는 것도 면접자의 일이라고 생각한다. 면접에서 좋은 결과가 있더라도, 면접관이나 면접태도 등이 마음에 들지 않는다면 가지 않는 게 좋다고 생각한다. 연차가 많을수록 이런 생각을 많이 하는지, 최종 면접까지 합격해도 회사에 오지 않는 사람이 많은 것 같다. 역시 이런 게 경험에서 나오는 지혜인가..?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;내 고민 - 면접자에 대한 배려의 선은 어디인가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 내 고민 ㅋㅋ 이직이라기보다는 면접에 대한 내용이다. 4~6년 차 개발자를 뽑기 위해 면접관으로 들어갔을 때 얘기인데, 지원자는 카카오에서 핵심 도메인을 담당하는 팀의 개발자였다. 기술적으로 특출 난 분은 아니었지만 열정이 넘치고, 대외 활동을 열심히 하시면서 개발에 대한 욕심이 많은 분이었다. 면접 진행 후 참여한 면접관끼리 면접자에 대한 판단을 내리는 시간을 가졌는데, 나는 연차대비 괜찮은 사람이라고 생각해서 'YES'로 판단했다. 같이 면접관으로 참여했단 다른 팀원은 &quot;NO&quot;로 판단했는데, 그 이유를 들어보니 &quot;우리 회사처럼 보수적인(금융회사) 회사에서는 저런 열정이 오히려 독이 될 수 있다. 하고 싶은 게 많은데 할 수 없다면 지원자분 입장에서도 장기적으로 보면 손해다&quot;였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 여기서 머리 위에??? 가 떴는데, 면접관으로 판단해야 하는 것은 면접자의 자질이지 그 사람이 회사에 들어와서 어떤 생활을 할지 미래를 평가하는 것은 아니라고 생각했기 때문이다. 그래서 지원자가 어떤 생각을 가지고 있는지도 모르고, 그런 상황에서 어떻게 대처할지도 모르고, 어떤 사람인지도 모르는데 거기까지 걱정하는 건 배려가 아니고 기만 아닌가라는 생각을 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 사례를 얘기하면서 참여자 분들에게 (마침 참여자 분들이 비슷한 연차였기 때문에) 물어보았는데, 나와 동일한 생각을 가진 분들도 있고 다른 생각을 가진 분도 있었다. 참여자 중 B님은(3년 차 백엔드 개발자) &quot;합격하게 되면 같이 일하게 될 팀원인데 그렇게 고민해 준 것에 감사하다&quot;라고 얘기해 주셔서, 그렇게 생각될 수도 있겠구나라고 고개를 끄덕였다. 그래도 만약 내가 그 지원자였으면 나에 대해서 잘 모르면서 그렇게 판단하는 건 오만이라고 화났을 것 같다. 사람의 생각이란 게 다양하는 것을 한번 더 깨닫는 중.. ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  일의 방식과 조직에서의 역할&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참여자 B님 (3년 차 백엔드 개발자) - 회의를 너무 많이 해서 제가 개발을 하는 사람인지 회의를 하는 사람인지 모르겠어요&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 고민을 들었을 때, &quot;와.. 옛날에 나도 저 고민했었는데&quot;라는 생각이 제일 먼저 들었다. 근데 옛날이라고 말한 거 보면 지금은 고민을 안 한다는 건데- ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;B님 공유해 주신 고민에 구체적인 내용은 의사 결정이 잘 안 돼서 똑같은 회의를 반복하느라 시간을 허비한다는 것이었다. 회의가 문제라기보다는 회사 문화가 문제인 것 같아 보였다. 일단 B님은 의사 결정에 권한이 없는데, 계속해서 회의를 끌려다니느라 고생하는 것 같았다. 그렇다고 안 갈 수도 없는 회의인 것 같아 무조건 가긴 가야 하는데, 회의의 결론이 잘 안 난다는 것이 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 건 답도 없는 회의라고요~!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 고민에서 어떤 회의인지 구분하는 것이 중요한데, 위처럼 답도 없는 회의면 개인이 어떻게 해결할 수 있는 문제는 아닌 것 같다 ㅋㅋ 그럼에도 불구하고 그 상황에서 내가 어떤 것을 해야 더 나은 방향으로 갈지 고민하는 것이 최선인 것 같다. 뭐 다른 의사결정자를 찾는다던지, 의사 결정자가 잘할 수 있도록 회의 시간 말고도 딱 달라붙어서 이것저것 물어보면서 준비할 사항이 있다면 준비하던지 등등..&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 그냥 개발자가 참여하는 회의가 많은 거라면 약간 다른 시선으로 바라보아야 한다. 나도 옛날에는 개발자는 회의보다는 개발을 더 많이 하는 게 좋다고 생각했다. 그런데 최근에는 개발자도 회의를 많이 해야 한다는 것을 조금씩 느끼는 중인데, 그중 하나는 영향력이다. IT회사에서는 개발자가 프로젝트에 중심에 서는 경우가 많다. 물론 리딩은 PM이 하겠지만, 특정 기능에 대한 개발 가능여부나 일정은 개발자에 더 포커싱 되어있다. 따라서 개발자가 회의에 참여하여 기능에 대한 리뷰나 일정관리등에 적극적으로 참여해야 일이 쉽게 진행된다. 전통적인 대기업 같은 경우는 수직으로 일이 할당되기 때문에 이런 일이 별로 없는데, IT기업들은 회의를 참여하는 개발자가 필요하다. 심지어 개발자들끼리 회의할 때도 많다 ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 개발자가 회의를 많이 참여하여 개발적인 생각 등을 공유하게 되고, 그 효과로 프로젝트가 잘 진행된다면 개발자로서 영향력이 쌓이게 된다. 여기서 영향력이란 쉽게 설명해서 내 말을 다른 사람들이 기꺼이 들어주게 되는 힘 같은 건데 신뢰라고 생각하면 편할 듯하다. 영향력이 높은 개발자라면 문제가 발생하거나 중요 이슈사항이 생겼을 때 사람들이 도움을 청하러 오는 경우가 많아지고, 프로젝트에 더더욱 중심에 서게 된다. 최근에 시니어 개발자의 요건 중에 이런 영향력 항목이 있는 것을 봤던 것 같은데, 회의를 많이 다니면서 자신의 개발적인 능력을 다른 동료들에게 어필하게 된다면 자연스럽게 영향력이 상승하게 되는 것 같다. 물론 개발 실력이 느는 건 아니긴 한데, 요즘은 개발 실력만 가지고 개발자를 판단하지 않으니 ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영향력 외에 또 다른 이유는 개발의 방향성을 정하기 위해서다. 회의에 참여하여 어떤 의도로 어떻게 일이 진행되고 있는지 파악해야 개발할 때 요건에 맞게 개발할 수 있게 된다. 'XX 만들어주세요'보다는 '이번에 법이 바뀌어서 새로 만들어야 하는 게 생겼는데, 기존 거에 보완해서 XX를 만들어주세요&quot;로 좀 더 구체적으로 알고 있다면, 개발하기 전에 좀 더 알맞은 설계 및 구조로 개발을 할 수 있다. 혹은 내가 개발하기 편한 방법으로 프로젝트를 드리블할 수도 있다. ^^&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 연차가 쌓일수록 개발자도 비개발적인 업무를 잘해야 편하다는 경험이 쌓이게 되면서, 회의가 많다고 불평하는 건 없어진 듯하다. 물-론!! 답 없는 회의는 너무 싫다. ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;개발자에게 조직 내 영향력이란 무엇인가?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에 주제와 연관되어서 나온 질문이었는데, 개발자의 영향력이 중요한가라는 내용이었던 것 같다. (구체적으로 어떻게 이 주제가 시작되었는지 기억 안 남.. ㅋㅋ)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 일단 '&lt;b&gt;영향력&lt;/b&gt;'이라는 단어가 나온 것에 조금 놀랐다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;놀란 이유는 최근에 회사에서 '시니어 개발자의 조건'을 한번 얘기한 적이 있는데, 시니어 개발자라면 이런 스킬이 있어야 한다!라는 느낌의 내용이었다. 시니어 개발자가 가지고 있어야 하는 역량 중에 '영향력'이 포함되어 있었다. 영향력이란 무엇인고 하니, &lt;b&gt;업무를 진행하는 데 있어서 다른 직무의 사람들이 얼마나 개발자를 의존하는가? 의사결정에 얼마나 영향을 주는가?&lt;/b&gt; 정도로 생각하면 되겠다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평소에 '영향력'이라는 것을 몸소 체험하고 있긴 하지만, 이것이 '영향력'이다!라고 정의해서 의식하고 있지는 않았는데, 시니어의 필요 요건 중에 하나라는 얘기를 들었을 때, '음 그럴 수도 있겠다~'라고 생각했다. 영향력이 없으면 개발자가 의도한 대로 개발하게 되는 경우가 적어지며 일도 힘들어지고, 구조도 복잡해질 수 있다. 물론 개발을 잘한다는 베이스가 깔려있어야 하지만 ^^ 시니어면 잘하겠지~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;암튼, 이렇게 시니어 레벨에서 고려하는 것을 이번에 모인 1~5년 차 개발자 분들이 벌써 생각하고 있는 것에 놀랐다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대체적으로, 주니어 레벨에서는 영향력을 챙기기보다는 개발 자체에 집중하는 개발자들이 많은 것 같다. 나 역시 개발만을 추구하던 때가 있었는데, 회사생활 하다 보니 개발보다 도메인이나 회의, 대인관계 등 전체적인 것이 중요하다고 느껴서 다방면으로 열심히 하려고 노력하고 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 주니어가 영향력을 갖는다는 것은 특별한 상황인 것 같다. 영향력을 갖기 위해서는 진행하는 개발업무에 대해 의사결정권이 있어야 하는데, 일반적인 회사에서는 주니어에게 그런 권한을 주지 않는다. 하지만 IT회사처럼 직급체계가 없는 개발자 중심의 회사라면 얘기가 달라진다. 이런 회사에서는 주니어라도 특정 업무를 리딩할 수 있는 기회가 주어지며, 혼자서 업무에 대한 의사결정을 할 수 있는 권한도 제한적으로 주어진다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 상황이 주어지면 어떤 개발자들은 스트레스를 받을 수도 있을 것 같다. 아직 많은 경험이 없기 때문에 의사결정 하나하나가 힘들 것이다. 차라리 개발만 하고 싶다!라는 생각이 들기도 한다. 하지만 나는 이런 상황이야 말로 개발자로서 성장할 수 있는 기회라고 생각한다. 부족한 경험을 어떻게 해서든 메꾸려는 노력을 하면서 얻는 게 많아지게 되는 시기인데, 사수나 멘토를 붙잡고 늘어지면서 자기 생각을 말하며 조언을 구하며 돌아다니는 것이다. 이때 중요한 것은 판단은 자신이 해야 한다는 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물. 론. 본인의 역량을 본인이 판단해서 &lt;b&gt;아 이 정도는 내가 할 수 있겠구나~, 이건 못하겠구나~&lt;/b&gt; 객관적인 판단을 하는 게 제일 중요하다. 시니어도 어려운 의사결정을 끙끙 앓고 있으면 역효과이기 때문이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;얘기하다 보니 이도 저도 아닌 이상한 의견(?)이 되어버렸는데 그래서 어떡하라는거냣!! ㅋㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 ^^ 이런 고민을 한다는 것 자체가 개발자로서 성장하고 있다는 증거니까,, 잘하고 있다고 얘기해주고 싶은 거다. 답은 스스로 구해야지~ ㅋㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;회사에서 요구하는 개발자, 내가 바라는 개발자&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것도 겸사겸사 나온 주제인데, 회사에서 요구하는 것과 내가 하고 싶은 것의 차이를 느낄 때 어떻게 해야 하는지에 관한 주제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 정말 어떤 회사냐, 어떤 팀이냐, 내가 어떤 생각을 가지고 있느냐에 따라 수많은 케이스가 생기는 경우라서 아마 모든 사람이 다르게 느끼는 문제가 아닐까라고 생각한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 참여자 중에 어떤 분은 회사에 조직구조가 계속해서 변하고 있어서 자신의 Role이 계속 바뀌는 것에 대해 고민이라고 말씀해 주셨다. 아직 조직이 어떤 방향으로 나아가야 할지 확실하게 정해져 있지 않아 이것저것 시도해보고 있는 것 같은데, 그 변화에 중심에 있는 것 같았다. 보통 이렇게 회사 차원에서 움직이는 거는 개인이 어떻게 해볼 도리가 없다고 생각되는데, 그렇다고 그냥 회사가 하라는 대로 따라가는 게 좋은 것인지.. 딜레마이긴 하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 일단 개인적으로는,&lt;b&gt; 내가 하고 싶은 것을 할 수 있는 곳은 내가 만든 회사&lt;/b&gt;밖에 없다고 생각한다 ㅋㅋ 아무리 개발 문화가 좋고 일하기 좋은 회사라고 해도, 이건 불변인 것 같다. 내 회사가 아닌 이상 내 맘대로 할 수 있는 건 없다. 어떤 사람은 회사에서 일할 때는 생각을 하지 말라고도 한다 ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 두 가지 사이에서 고민하는 개발자들을 보면 책임감이 매우 강한 사람들이 대부분이었다. 자신이 진행하는 업무에 대한 책임감이 강하여 잘해보려고 하는데, 회사에서 반대로 요구하거나, 전혀 다른 방향을 요구하기 때문이다. 이런 상황에서 스트레스를 받으면서 현타가 오는 분들을 많이 봤다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 일단 객관화를 매우 잘하기 때문에 회사일은 회사일이라고 생각하면서 회사에 요구사항에 최대한 맞추려는 태도를 가지고 있다. 물론 내가 원하는 방향도 있지만, 실제 책임자는 회사이고 임원이고 내 상사이기 때문에, 내가 공식적으로 책임지는 것이 아니면 웬만해서는 회사의 의견에 따르려고 한다. 이게 좋은 것은 아니지만 적어도 스트레스는 안 받는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 그렇다고 아예 순응해 버리면 안 된다. 그냥 회사와 나의 의견이 다르구나~ 정도로 다름을 인식하는 정도지, '회사가 옳다!' 이거는 아니다. 요즘 개발자는 한 곳에 오래 머무는 것도 아니고, 언제까지 회사에서 근무하는 것도 아니다. 언젠가 이직을 하고, 또 창업을 할지도 모른다. 즉, 언제까지 내가 시키는 대로만 해서 돈을 벌 수 있는 환경이 아니기 때문에 스스로 판단해 보고 의사결정 해보는 것이 중요하다. 그러므로 회사의 요구사항은 일단 그 회사에서 일하니까 받아들이고, 만약 내가 이렇게 한다면 어떨까? 상상의 나래를 펼쳐보거나 좀 더 딥하게 파고들어서 결과를 예측해 보거나, 실제 일이 끝나고 결과도 내가 원했던 방향의 결과와 비교해 보면서 최대한 얻을 수 있는 것을 얻는 게 중요하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론, 제일 좋은 건 내가 바라는 방식으로 일할 수 있는 회사를 가는 것인데, 그건 현실적으로 매우 힘들다 ^^. 하지만 언젠가 이루어질 수도 있으니 유연한 개발자가 될 수 있도록 준비하는 게 좋을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  기술 스택과 성장 방향&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;백엔드, 프론트, 풀스택&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 주제는 진짜 어느 개발자를 만나도 항상 핫한 주제가 아닐까 싶다 ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 주제의 시작은, 참가자 분들 중 본의 아니가 프론트까지 개발하고 있어서 너무 고민이라는 질문이다. 백엔드 개발자로 취업했지만, 어쩔 수 없이 프론트까지 하는 경우가 많긴 한데, 이런 경우는 어떻게 해야 하나.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 질문을 만나면 나는 일단 '회사에 얘기는 해 보았는가?'라는 질문을 가장 먼저 한다. 사실 이 질문은 어디까지 노력해 보았는가? 를 확인하기 위한 질문인데, 생각보다 많은 개발자들이 회사나 팀장, 상사에게 얘기해보지 않고 이런 불만을 갖고 있다. 즉, 본인이 어떻게 상황을 바꿔보려는 노력도 하지 않고, 그냥 불평만 하고 있는 것이다. 이런 분들을 만나면 일단 노력하고 얘기한다. 노력하지 않는데 좋은 상황을 기대하는 건 조금 욕심 아님?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 또 그렇다고, 말해서 그렇게 쉽게 바뀌는 문제는 아니다. 사람이 적은 중소기업이나 스타트업의 경우 개발자 뽑기가 힘들어서 한 사람이 두 가지 모두 하는 경우가 많은데, 회사입장에서는 아주 귀한 인재다. 이렇게 사정상 어쩔 수 없이 해야 한다면, 적어도 그 대접은 받아야 한다 라는 게 내 논리이긴 한데, 예를 들어 월급을 더 올려 받는다던지, 업무 시간을 좀 더 자유롭게 한다든지 자신이 챙길 수 있는 게 있는지 확인해서 받아내야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 하나의 방법은 그냥 즐기는 거다. 내가 이런 부류긴 한데, 나는 프론트도 잘하고 싶다 ㅋㅋㅋㅋ ㅋㅋ 프론트 잘하면 혼자 뚝딱뚝딱해서 서비스 만들 수 있자네?!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 나는 어느 정도 연차가 쌓여서 그렇게 생각하는 걸 수도? 한쪽만 해도 배울 게 많은데 두 개를 동시에 하긴 힘들 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 일단 &lt;b&gt;회사에 얘기한다 -&amp;gt; 긍정적으로 생각해 본다 -&amp;gt; 이직&lt;/b&gt; 이 순서로 해결해야 하지 않을까? 싶음 ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;깊이와 넓이 중 어디에 집중할 것인가?&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 주제도 당골이긴 한데, 깊이 vs 넓이의 싸움이다. 물 ~ 론 ~ 깊고 넓은 게 최고이긴 한데 ㅋㅋㅋ 그게 되면 그렇게 하고, 하나만 집중했을 때 어떤 걸 선택하냐~ 의 질문이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;음.. 나는 깊이가 더 좋다고 생각이 들긴 하는데, 일단 특정 기술에 대해 깊이 파고드는 노력치와 넓게 알려고 하는 능력치가 조금 다른 것 같다고 생각된다. 한 기술에 대해 깊게 파고들려면 집중력이나 이해력이 필요하다고 생각되는데, 넓게 아는 건 포용력(?) 적용력(?)이 필요하다고 생각된다. 여러 가지를 넓게 알기 위해서 제일 쉬운 방법은 원래 아는 지식과 비교해서 배우는 것. 즉 귀납법적인 사고방식이 필요하기 때문에 한 가지에 대한 전문지식을 배우는 것과는 다른 노력이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 나는 우선순위를 둘 때, '깊이'를 더 높게 두고 싶다. 한 가지 기술에 깊이 파고들 때, 그 기술에 대한 이해도만 올라가는 것이 아니라 개발 전체적으로 이해도가 올라가게 된다. 이 상태에서 다른 기술들을 접하게 되면, 내가 알던 기술에 대한 이해도 덕분에 비교하면서 더 쉽게 다가갈 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 예를 들면, C언에서의 기본 입출력은 printf, scanf인데, 이 메서드를 안다면 다른 언어-자바나 파이썬-을 공부할 때 system.out.println이나 print 등을 쉽게 이해할 수 있다. 이건 개발 도메인 한정이 아니라 모든 것이 다 그런 것 같다. 영어를 공부할 때 우리가 일일이 한국어 뜻으로 생각하면서 공부하는 이유도 이거다. 일단 한 가지 언어를 하면 그 언어와 매핑시켜서 배우면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 이건 내생각인 거고, 반대로 넓게를 먼저 알고 깊게 가는 방법도 있을 것 같다. 여러 가지를 알고 그것으로 더 깊은 지식을 찾을 수도 있으니까. 이건 그냥 사바사인 듯? 자기가 편한 대로 고르면 될 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무튼, 두 개중에 선택하는 게 아니라, 하나만 하면 다른 하나는 따라오게 되는데, 본인이 쉬운 길을 선택하면 될 것 같다는 게 내 의견~!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;기술 전환기에 겪는 어려움&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자로 살다 보면 본인이 원하지 않게 사용 중인 기술 스택이 변경되는 경우도 있고, 본인이 바꾸길 원해서 바꾸고 싶은데 그렇게 안 되는 경우가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째 경우는 그나마 나은데, 두 번째 경우가 좀 힘들 수 있다. 나도 처음에 C언어를 사용하는 회사에서 5년 있다가 다른 거 하고 싶어서 결국 이직으로 스택을 바꾸는 데 성공했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바꾸기 힘들었던 이유는 일단 C로만 개발되어 있는 회사에서 일하기 때문에 언어 바꾸기 힘듦. 그렇다고 이직을 하자니 C만 5년 했는데 C를 안 쓰는 회사에서 나를 뽑을 이유가 없음 ㅎㅎ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다행히 나는 간간히 다른 언어로 된 프로젝트를 개인적으로 진행한 것이 있고 공부를 꾸준히 해와서 이직에 성공할 수 있었다. 물론 메이저 회사로는 이직하지 못하고 도메인이 맞는 스타트업으로 이직했고, 그 후에는 이직이 조금 수월해졌다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 어떤 경우는, 본인은 계속하고 싶은데, 외부에 의해 바뀌는 경우다. java를 열심히 공부하면서 배우고 있었는데, 어느 날 갑자기 회사에서 '저희는 이제 go를 씁니다'라고 한다면..? java 공부 때려치우고 go를 해야 하나? 아니면 java를 쓰는 다른 회사를 가야 하나?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 내가 같은 경우라면 내 상황을 한번 생각해봐야 할 것 같다. 만약 내가 아직 주니어고 연차가 높지 않다면, 나는 java를 쓰는 다른 팀이나 다른 회사로 옮기는 선택을 할 것 같다. 왜냐하면 한 가지 기술에 대해 어느 정도 수준에 도달하지 않았는데, 다른 것을 하는 것은 그냥 리셋되는 것과 똑같다고 생각하기 때문이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 내가 연차가 좀 된다? 그럼 오 땡큐~ 하고 새로운 것을 받을 것 같다. 그리고 연차가 좀 돼서 개발 경력이 높다면, 금방 금방 다른 것을 할 수 있다고 생각된다. (이미 이것에 대해 깊이 vs 넓이 주제에서 얘기했다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다고 기술을 전환하는 것이 쉽다는 것은 아니다. 새로운 것을 배우는 것은 항상 어렵다. 하지만 내 상황에 따라 그것을 어떻게 받아들이는지가 차이가 있을 뿐이다. 머리 뜯어가며 이 악물고 이해해야 하는지, 아니면 조금 더 여유롭게 배우던지 차이 ㅋㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 본인이 어느 정도 노력할 수 있는지 판단하고, 최선의 선택을 하는 수밖에 없을 듯?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 제일 좋은 건 초기에 대중적인 기술을 고르고 그 기술로 어느 정도 경력을 쌓기까지 계속하는 것이다. 운이 좋아야겠지만 ^^...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt; &amp;zwj;  커리어 설계&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 커리어 설계.. ㅋㅋ 여태까지 나누었던 얘기를 총 정리하는 시간이라고 보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'나는 어떤 개발자가 되고 싶은가?'&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 대부분의 개발자가 이 고민에서는 개발을 계속할 것인지, 아니면 매니저로 빠지는 게 좋은지 선택지를 고민한다. 나도 평소에 많이 고민하는 부분인데, 사실 이건 개인의 선택보다는 외부에 의해 결정되는 경우가 많다. 개인이 할 수 있는 것은 그것을 감당할 수 있는지 정도?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 주제를 바꾸면, &lt;b&gt;매니저 하라고 하면 할래?로&lt;/b&gt; 바꿀 수 있을 것 같다 ㅋㅋ &amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 옛날에는 개발만 계속하고 싶었는데, 일을 하면서 내가 소프트 스킬이 좋다는 것을 알았고, 잘한다는 것을 알고 나서는 매니저도 할만하겠는데?라는 생각이 든다. 누군가가 개발만 계속하기 위해서는 누군가는 매니징을 해야 하기 때문에 그럴 거면 잘하는 내가 하는 게 낫지~ 이런 생각?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다고 손들고 하고 싶지는 않고 언제가 기회가 되면 하겠다는 생각정도만 하고 있다. 아직 개발이 재밌긴 해서... ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참여자분들도 대부분 이런 고민을 하고 있었지만, 아직은 그런 선택을 받게 되는 연차는 아니었다. 대부분 어떻게 하면 더 개발을 잘할까의 고민을 하고 있는 것 같았다. 스스로 생각하기에 내 성장을 막고 있는 문제점을 말하셨는데, 대부분 조직이나 팀 얘기가 많았다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 이렇게 하고 싶은데 이 팀에서는 이게 안 돼요. 그래서 이직을 준비하고 있어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 느낌?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자로 성장하기 제일 쉬운 방법은 멘토를 찾는 것 같다. 그 멘토가 같은 회사, 같은 팀에 있다면 최고다. 멘토라고 해서 뭐 대단한 사람을 말하는 게 아니다. 배울 게 있는 사람. 하나라도 그 사람에게 배울 게 있다면 멘토로 삼으면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 생각했을 때 이직 타이밍은 배울 게 없는 회사다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 회사를 이직한 이유도 이거였는데, 하루 종일 부동산 보고 있는 과장 보고 현타 와서 이직 ㅎㅎ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;훌륭한 스승을 옆에 두는 것만큼 좋은 게 없다고 생각하고, 그런 이유의 이직은 바람직하다고 생각한다. 다양한 회사와 다양한 사람을 경험해 보면 본인이 스스로 어떤 개발자가 되고 싶은지 선택의 폭이 넓어지기 때문이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 참여자 분들에게 이직은 많이 해보라고 얘기했던 것 같고, 대신 그 회사에서 얻을 수 있는 건 다 얻고 하라고 말했던 것 같다 ㅎㅎ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 정리하다 보니 '운'이라는 게 새삼 중요하다고 느꼈다. 참여자 분들 중 어떤 분은 원하지 않는데 devops영역까지 해야 하는 분이 있는가 하면, 어떤 분은 devops영역도 하고 싶은데 권한이 없어서 못한다는 분도 있었다. 코틀린을 하고 싶지만 회사에서 안 쓰는 경우도 있고, 코틀린 모르는데 코틀린을 써야 하는 경우도 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다고 운이 전부라고 생각하진 말자. 운 좋게 우리에게 기회가 왔을지 몰라도, 그 기회를 잡을 수 있는 건 우리의 노력이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;급 명언으로 마무리..  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&amp;nbsp;  마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;와.. 그때 어떤 얘기했는지 남긴 게 없어서 가물가물하면서 쓰느라 너무 힘들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 또 기록의 중요성을 느끼고... 다음부턴 무조건 적어야지. (녹음이라도)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 오랜만에 다른 개발자분들과 소통할 수 있어서 너무 재밌었고, 다음에 또 만나서 얘기를 나누고 싶다는 생각이 들었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4분기쯤에 다시 만나서 그날 이후 어떻게 지냈는지 얘기 나누는 모임을 해볼까 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그때는 꼭! 영상, 사진, 기록 남겨야지.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1354&quot; data-origin-height=&quot;1360&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dd419Y/btsOqRuBwkL/VkjSrnSBrufdgFzi9lLcL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dd419Y/btsOqRuBwkL/VkjSrnSBrufdgFzi9lLcL0/img.png&quot; data-alt=&quot;썸네일용 사진 ㅋㅋ&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dd419Y/btsOqRuBwkL/VkjSrnSBrufdgFzi9lLcL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdd419Y%2FbtsOqRuBwkL%2FVkjSrnSBrufdgFzi9lLcL0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;603&quot; data-origin-width=&quot;1354&quot; data-origin-height=&quot;1360&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;썸네일용 사진 ㅋㅋ&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Blog/IT, I Think</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/613</guid>
      <comments>https://cholol.tistory.com/613#entry613comment</comments>
      <pubDate>Sat, 7 Jun 2025 14:06:05 +0900</pubDate>
    </item>
    <item>
      <title>백엔드 개발자 놀이터 모임 준비과정 및 모임 후기 (by. 남의집)</title>
      <link>https://cholol.tistory.com/612</link>
      <description>&lt;div class=&quot;index_toc&quot;&gt;
&lt;p class=&quot;toc_title&quot; data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  모임의 시작&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3주 전에 '&lt;a href=&quot;https://cholol.tistory.com/611&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;백엔드 개발자 놀이터, 개발자 위한 오프라인 모임...'이라는&lt;/a&gt; 글을 올리면서 백엔드 개발자들을 위한 오프라인 모임을 기획했다. 유튜브로도 이것저것 많은 영상을 올리고 많은 얘기를 하고 있지만, 얼굴과 얼굴을 맞대고 진행하는 오프라인 모임의 맛(?)을 살리기는 어렵다.&amp;nbsp;작년에 개발자 커뮤니티 활동을 너무 안 한 것도 있고 해서 올해의 목표로 오프라인 모임 진행하기를 결심했고, 드디어 실행하는 날이 다가왔닼 !!~!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에 유튜브와 블로그에만 모임 홍보글을 올렸는데 3분이 신청해 주셨다. 모임을 기획할 당시에는 '한 명도 안 오면 어떡하지..?' 고민을 많이 했었는데, 많은 분들이 빠르게 신청을 해주셔서 조금 안심했다. ☺️&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러다가 좀 더 다양한 채널에서 모집해야 참여자 분들의 커리어가 다양할 것이라고 생각해서 okky 커뮤니티에도 글을 올렸다. 역시 okky를 많은 분들이 보셔서 그런지 글을 올리자마자 많은 분들이 신청해 주셨고, 초기 생각했던 마감 인원 5명까지 꽉 찼다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인원이 마감된 건 모임까지 10일 정도 남았을 때였는데, 이제 모임을 위해 이것저것 준비하는 것만 남은 상태였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  모임 준비하기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;장소&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자 모임에 어떤 걸 준비해야 할까?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 장소.. 나까지 6명의 인원이 앉아서 떠들 공간이 필요하다. 우리 집 거실은 그 역할을 하기에 충분했으나 한 가지 고민이 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;소파 vs 테이블&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;블로그1.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eoQMfC/btsNbQJe6Gl/Vu6rqaFqC7Fbev4HMFzLUk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eoQMfC/btsNbQJe6Gl/Vu6rqaFqC7Fbev4HMFzLUk/img.jpg&quot; data-alt=&quot;우리집 거실. 겨울에 찍은 거라 트리가 남아있음 ㅎ&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eoQMfC/btsNbQJe6Gl/Vu6rqaFqC7Fbev4HMFzLUk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeoQMfC%2FbtsNbQJe6Gl%2FVu6rqaFqC7Fbev4HMFzLUk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;4032&quot; height=&quot;3024&quot; data-filename=&quot;블로그1.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;우리집 거실. 겨울에 찍은 거라 트리가 남아있음 ㅎ&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;거실에 소파와 테이블이 있는데, 테이블에서 진행하면 너무 딱딱할 것 같은 느낌이 들었다. 먼가 편하게 얘기를 나누고 싶은데 회의를 진행하는 것 같은 느낌이 될까 봐 걱정,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다고 소파에서 하자니 다 같이 한쪽을 바라보면서 얘기하는 건 너무 웃길 것 같았다 ㅋㅋㅋ 반대편에는 TV가 있는데 TV 보는 것 같기도 하고...&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 방구석에 있던 빈백을 꺼내서 소파 반대편에 놓고, 쇼파 자리에 편하게 앉을 수 있도록 쇼파 위치를 조금 수정했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;블로그2.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cghDCR/btsNbddYuuX/8DTCgFf1LYKJUazauch8u0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cghDCR/btsNbddYuuX/8DTCgFf1LYKJUazauch8u0/img.jpg&quot; data-alt=&quot;빈백 놓기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cghDCR/btsNbddYuuX/8DTCgFf1LYKJUazauch8u0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcghDCR%2FbtsNbddYuuX%2F8DTCgFf1LYKJUazauch8u0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;4032&quot; height=&quot;3024&quot; data-filename=&quot;블로그2.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;빈백 놓기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소파와 빈백은 아무래도 등을 기댈 수 있어서 편한 자리라고 생각되는데, 아무래도 빈백에 앉는 건 거의 눕는 자리 다 보니까 사람들이 선뜻 안 앉을 것 같기도..?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중간에 덩그러니 있는 소파는 등받침이 없어서 조금 불편할 것 같아 내가 앉으려고 했는데, 다른 분이 먼저 앉으셨다!!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 먼가 이렇게 둥그렇게 앉으니 자연스럽게 얘기할 수 있는 분위기가 된 것 같아 이대로 진행~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;명찰&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무래도 서로 처음 보는 사람들이 모이다 보니 서로의 이름을 잘 모를 것 같다고 생각했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 컨퍼런스에 참여할 때처럼 명찰을 만들어 볼까? 생각하고 바로 행동으로 옮기기~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다이소가 아주 가까이 있기 때문에 바로 다이소를 가봤는데, 내가 생각하는 명찰은 없었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;918&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cP4J8B/btsNcTSDUnQ/SIjNR2UN6qa4qvmUITIKY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cP4J8B/btsNcTSDUnQ/SIjNR2UN6qa4qvmUITIKY0/img.png&quot; data-alt=&quot;다이소에서 파는것&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cP4J8B/btsNcTSDUnQ/SIjNR2UN6qa4qvmUITIKY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcP4J8B%2FbtsNcTSDUnQ%2FSIjNR2UN6qa4qvmUITIKY0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;306&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;918&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;다이소에서 파는것&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;약간 클립으로 된 명찰이랑, 사원증 같은 명찰만 있었다 ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사원증 뭔가 약간 당기기는 했는데, 너무 작아서 패스~!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 쿠팡에서 주문하기로...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2516&quot; data-origin-height=&quot;1264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8uXol/btsNaIFzBeH/p3giLX3SeLsHYzFnFHZ0dk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8uXol/btsNaIFzBeH/p3giLX3SeLsHYzFnFHZ0dk/img.png&quot; data-alt=&quot;이거다~!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8uXol/btsNaIFzBeH/p3giLX3SeLsHYzFnFHZ0dk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8uXol%2FbtsNaIFzBeH%2Fp3giLX3SeLsHYzFnFHZ0dk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2516&quot; height=&quot;1264&quot; data-origin-width=&quot;2516&quot; data-origin-height=&quot;1264&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이거다~!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 찾아버리기~~~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 명찰에 어떤 걸 넣어야 하나 고민했는데, 일단 이름을 넣는 것은 확실한데 뭔가 재밌게 할 수 없을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고민하다가 요즘 사진을 gpt한테 만들어 달라고 하는 게 유행이라서 나도 한 번 해봤다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하-지-만- 참여자 분들 사진이 없기 때문에, 모임 신청할 때 참여자분들이 제출한 정보를 이용해 gpt한테 알아서 만들어달라고 부탁했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1390&quot; data-origin-height=&quot;3176&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZT5dO/btsM5xP2YQk/QYUWM1jqUYZRz3B95HJlIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZT5dO/btsM5xP2YQk/QYUWM1jqUYZRz3B95HJlIK/img.png&quot; data-alt=&quot;gpt로 명찰 만들기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZT5dO/btsM5xP2YQk/QYUWM1jqUYZRz3B95HJlIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZT5dO%2FbtsM5xP2YQk%2FQYUWM1jqUYZRz3B95HJlIK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;1142&quot; data-origin-width=&quot;1390&quot; data-origin-height=&quot;3176&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;gpt로 명찰 만들기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에 갑자기 실물 사진으로 만들어줘서 당황했다 ㅋㅋㅋㅋㅋ ㅋㅋㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭔가 외형에 대한 정보 없이 신청한 정보만 넣었는데 전부 다르게 만들어줘서 신기했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇게 만들어진 사진이 바로....&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;블로그3.png&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biklGX/btsNcJJxQow/WsWkLCa2vcU4P9zfQ6eZ1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biklGX/btsNcJJxQow/WsWkLCa2vcU4P9zfQ6eZ1k/img.png&quot; data-alt=&quot;출력물&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biklGX/btsNcJJxQow/WsWkLCa2vcU4P9zfQ6eZ1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiklGX%2FbtsNcJJxQow%2FWsWkLCa2vcU4P9zfQ6eZ1k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3024&quot; height=&quot;4032&quot; data-filename=&quot;블로그3.png&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출력물&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방이 어두워서 화질이 별로 안 좋은데, 역시 잉크젯 포토 프린트.. 거의 사진급으로 나옴!! ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뒷면에는 집 구조랑 주의사항을 적은 다음에 하나씩 명함에 꼽았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;블로그4.png&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vvOOn/btsNcRnaDKf/k9bG85nw3nO4AMTeZQgsP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vvOOn/btsNcRnaDKf/k9bG85nw3nO4AMTeZQgsP0/img.png&quot; data-alt=&quot;명찰 완성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vvOOn/btsNcRnaDKf/k9bG85nw3nO4AMTeZQgsP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvvOOn%2FbtsNcRnaDKf%2Fk9bG85nw3nO4AMTeZQgsP0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;4032&quot; height=&quot;3024&quot; data-filename=&quot;블로그4.png&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;명찰 완성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 개발자는 안경을 씌우는 거냐 GPT 녀석...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각 사진마다 조금씩 개성이 있는 이름표가 완성되었다 ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;☕️ 음료 및 다과&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 마실 음료와 군것질 거리를 준비했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마실 음료는.. 음 일단 생수와 페트병으로 된 음료를 준비했는데, 역시 스타벅스 커피정도는 먹어줘야 하지 않을까? 해서 모임 당일에 스타벅스를 주문하기로 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모임 전에 카톡으로 각자 마실 음료를 결정해 달라고 요청했고, 모임 당일 배민으로 스벅을 시키려고 하는데, '아이스 슈크림 라때'는 배민에 없네!?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 그냥 직접 사이렌 오더하고 pick up 하러 가기로 했다. (스벅도 1분 거리 ^오^)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;집에서 바로 사이렌 오더가 되길래 6잔 주문하고 갔다 왔는데 10분도 안 걸림 ;;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뜨거운 음료를 주문하신 분이 계셨는데 식을까 봐 걱정했다. 너무 식으면 다시 전기포트로 끓여서 제공할 예정이었는데 다행히 따뜻했다 - (다행)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;블로그5.png&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;2532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Cp7YE/btsNcGTJZr5/Kd3tlhzwp0E4jj8i6rfFeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Cp7YE/btsNcGTJZr5/Kd3tlhzwp0E4jj8i6rfFeK/img.png&quot; data-alt=&quot;스벅~&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Cp7YE/btsNcGTJZr5/Kd3tlhzwp0E4jj8i6rfFeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCp7YE%2FbtsNcGTJZr5%2FKd3tlhzwp0E4jj8i6rfFeK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;649&quot; data-filename=&quot;블로그5.png&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;2532&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;스벅~&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과자는 어떤 걸 좋아하는지 몰라서 여러 개를 꺼내놓았는데, 대부분 남아서 내가 다 먹을 예정 ^오^&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;블로그6.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JD9ME/btsNaK4v7pH/UHH45HVANcWfQuCj4yeKN1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JD9ME/btsNaK4v7pH/UHH45HVANcWfQuCj4yeKN1/img.jpg&quot; data-alt=&quot;까까&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JD9ME/btsNaK4v7pH/UHH45HVANcWfQuCj4yeKN1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJD9ME%2FbtsNaK4v7pH%2FUHH45HVANcWfQuCj4yeKN1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;4032&quot; height=&quot;3024&quot; data-filename=&quot;블로그6.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;까까&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;음료와 과자까지 준비 완료~!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  모임 당일&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대망의 모임날, 아침부터 부랴부랴 준비하고 밥 먹고 커피 사 오고 했는데 시간이 너무 빠르다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2시 되기 전에 참여자 분들이 도착해서 문 열어주고 안내해주고 하느라 정신이 없었다. 원래는 모임을 진행하면서 영상을 찍어서 유튜브에 올리려고 했는데, 정말 하~~~ 나도 안 찍었다!!! ㅋㅋ (유일하게 현관문 찍음..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멀리서 오시는 분이 계셔서 2시 20분에 모임을 시작했는데, 이런저런 얘기를 하다 보니 어느덧 6시가 훌쩍 넘었다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무려 4시간 동안 이런저런 얘기를 했는데, 나눈 얘기를 주제별로 정리하면 아래와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;커리어 설계&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;나는 어떤 개발자가 되고 싶은가?&lt;/li&gt;
&lt;li&gt;다양한 커리어 트랙 (IC, 매니저, 스페셜리스트, 창업 등)&lt;/li&gt;
&lt;li&gt;기술 vs 도메인 vs 조직 내 영향력&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이직 준비&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;이력서, 포트폴리오, 기술 면접 준비 팁&lt;/li&gt;
&lt;li&gt;지원 전략 (스타트업/중견/대기업, 네카라쿠배 등)&lt;/li&gt;
&lt;li&gt;실패 경험 공유 &amp;amp; 다시 도전하는 방법&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;일의 방식과 조직에서의 역할&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;기획/회의 업무 비중이 늘어날 때 생기는 갈등&lt;/li&gt;
&lt;li&gt;회사에서 원하는 방식과 본인의 스타일 간 차이&lt;/li&gt;
&lt;li&gt;개발자로서의 정체성을 지키는 방법&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;기술 스택과 성장 방향&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;기술 전환기에서 겪는 어려움&lt;/li&gt;
&lt;li&gt;풀스택 &amp;rarr; 백엔드 전환 고민&lt;/li&gt;
&lt;li&gt;깊이와 넓이 중 어디에 집중할 것인가?&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참여자 분들의 연차가 1~5년으로 비슷했기 때문이었을지 몰라도 가지고 있는 고민이 비슷했다. 아마 나도 비슷한 고민을 하고 있었기 때문에 연차가 아니라 그냥 개발자가 가진 고민들이 아닐까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;얘기를 하면서 느꼈던 것은 정말 다양한 시점과 다양한 생각이 존재한다는 것이다. 정답을 찾기보다는 다양한 생각을 공유하고 공감하는 자리였다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나누었던 내용을 따로 정리하여 블로그와 유튜브 콘텐츠를 만들려고 한다. (기억날지 모르겠네..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  후기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 가장 후회되는 것은 영상과 사진을 하나도 안 찍었다는 것이다. ㅋㅋㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아니 단체샷이라도 하나 찍었어야 하는데 얘기하는데 집중해서 그만,,,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 모두 가고 남은 자리만 사진으로 남겼다.....&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;블로그7.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ta7OT/btsNc6xFDcq/gKhPFu9GJpSXheaz5edKs0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ta7OT/btsNc6xFDcq/gKhPFu9GJpSXheaz5edKs0/img.jpg&quot; data-alt=&quot;모임 후 사진 ..&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ta7OT/btsNc6xFDcq/gKhPFu9GJpSXheaz5edKs0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fta7OT%2FbtsNc6xFDcq%2FgKhPFu9GJpSXheaz5edKs0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;4032&quot; height=&quot;3024&quot; data-filename=&quot;블로그7.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모임 후 사진 ..&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정신없이 모임이 끝나고 나니 '아 이 얘기도 해볼걸!', '이것도 물어볼걸!' 하던 게 생각나서 아쉬운 마음이 너무 컸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기회가 된다면 다음 모임을 잡아봐야겠다 ^^&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;올해 목표 중에 하나인 오프라인 모임 진행하기 완료~!&lt;/p&gt;</description>
      <category>Blog/IT, I Think</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/612</guid>
      <comments>https://cholol.tistory.com/612#entry612comment</comments>
      <pubDate>Tue, 1 Apr 2025 21:11:06 +0900</pubDate>
    </item>
    <item>
      <title>백엔드 개발자 놀이터, 개발자를 위한 오프라인 모임 진행하기~! 이직 고민, 이력서 고민, 면접 고민, 커리어 고민 다 모여라~ [마감]</title>
      <link>https://cholol.tistory.com/611</link>
      <description>&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;24년을 사이드 프로젝트와 바쁜 회사 일로 불태우고, 보드게임에 빠져 허우적 대다가 이제 다시 뭔가 개발을 하고 싶은 열정이 뿜뿜 하는 시기가 되었습니다. ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;와 진짜 낮에는 회사일 밤에는 사이드 프로젝트를 하는데 매일 엄청 피곤하더라구요? 24년 10월에 서비스 런칭하고 이제 본업으로 서비스를 유지해 주실 분들을 찾아 인수인계해 주고, 저는 다시 한가로운 원잡러로 돌아왔습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유튜브도 많이 못하고, 블로그도 많이 못쓰고, IT책도 많이 못읽고, 멘토링도 못하고,,, 뭔가 뒤처진 것 같은 느낌이 스멀스멀 들기 시작하더니, 지금은 뭔가 다시 활력을 찾았습니다 ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 사이드 프로젝트하면서 이런 저런 경험이나 트러플슈팅, AWS와 씨름하면서 만들어낸 배포 자동화, 아키텍처 설계 등 좋은 경험을 많이 하긴 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 경험들을 좀 나누고 싶은데..? 여태까지 못한 멘토링이나 개발 수다도 좀 떨고 싶은데..? 해서 준비한&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;25년 4월 5일 (토) &lt;br /&gt;백엔드 개발자 오프라인 모임!!&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;566&quot; data-origin-height=&quot;770&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QYA62/btsMUqDcGsk/mstBjuGMQt8Smy3MrWSHKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QYA62/btsMUqDcGsk/mstBjuGMQt8Smy3MrWSHKk/img.png&quot; data-alt=&quot;광고 아닙니다 ㅋㅋㅋㅋㅋㅋㅋㅋ&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QYA62/btsMUqDcGsk/mstBjuGMQt8Smy3MrWSHKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQYA62%2FbtsMUqDcGsk%2FmstBjuGMQt8Smy3MrWSHKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;277&quot; height=&quot;377&quot; data-origin-width=&quot;566&quot; data-origin-height=&quot;770&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;광고 아닙니다 ㅋㅋㅋㅋㅋㅋㅋㅋ&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;남의집이라는 플랫폼을 이용해서 오프라인 모임을 진행해 보기로 했습니다. ^오^&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;거창한 건 아니고 그냥.. 백엔드 개발자 심심한 사람 모여라~ 느낌의 모임입니다 ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참여 링크: &lt;a href=&quot;https://naamezip.com/naamezip/14425?episodeId=43556&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://naamezip.com/naamezip/14425?episodeId=43556&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1742560483795&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;백엔드 개발자 놀이터&quot; data-og-description=&quot;개발자 커리어, 이직, 개발, 면접. 여기서 얘기해보자&quot; data-og-host=&quot;naamezip.com&quot; data-og-source-url=&quot;https://naamezip.com/naamezip/14425?episodeId=43556&quot; data-og-url=&quot;https://naamezip.com/naamezip/14425&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Z42T2/hyYuoODl7G/fkzLgsNZ3WGK3sigFVF8ZK/img.jpg?width=1792&amp;amp;height=1024&amp;amp;face=0_0_1792_1024,https://scrap.kakaocdn.net/dn/dDK3ia/hyYufjPMkY/Cbjc2kPEj7kqhHeSoNw2A1/img.jpg?width=1792&amp;amp;height=1024&amp;amp;face=0_0_1792_1024&quot;&gt;&lt;a href=&quot;https://naamezip.com/naamezip/14425?episodeId=43556&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://naamezip.com/naamezip/14425?episodeId=43556&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Z42T2/hyYuoODl7G/fkzLgsNZ3WGK3sigFVF8ZK/img.jpg?width=1792&amp;amp;height=1024&amp;amp;face=0_0_1792_1024,https://scrap.kakaocdn.net/dn/dDK3ia/hyYufjPMkY/Cbjc2kPEj7kqhHeSoNw2A1/img.jpg?width=1792&amp;amp;height=1024&amp;amp;face=0_0_1792_1024');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;백엔드 개발자 놀이터&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;개발자 커리어, 이직, 개발, 면접. 여기서 얘기해보자&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;naamezip.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플랫폼 특성상 참가비가 있지만.... 맛난 커피와 다과를 준비했으니, 많이 오셨으면 좋겠네요~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자로서 고민이나 커리어 고민, 이직 고민, 면접 고민, 자소서 고민, 포트폴리오 고민 등등 어떤 고민을 들고 오셔도 됩니다~!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저도 요즘 고민이 참 많은데 제 고민도 와서 들어주세요~! ㅋㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일시 : 25년 4월 5일 토요일 오후 2시 ~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장소 : 서울 신림역 도보 1분 거리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주제 : 여러분의 고민, 나의 고민, 개발자의 고민, 개발자들의 아무 말 대잔치&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상세한 일정 및 진행 내용은 위 링크에 나와있습니다~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;놀러 오셔서 같이 놀자는 의미로 백엔드 개발자 놀이터(Play Ground)라고 지어봤습니다 ㅋㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관심 있으신 분은 참가신청해 주세요~~  &amp;zwj; &amp;zwj; &lt;/p&gt;</description>
      <category>Blog/IT, I Think</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/611</guid>
      <comments>https://cholol.tistory.com/611#entry611comment</comments>
      <pubDate>Fri, 21 Mar 2025 21:42:31 +0900</pubDate>
    </item>
    <item>
      <title>Django: 실전 백엔드 구축 &amp;amp; 운영, #1 Django 프로젝트 세팅하기, 세팅이 반이다.</title>
      <link>https://cholol.tistory.com/608</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;index_toc&quot;&gt;
&lt;p class=&quot;toc_title&quot; data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  시작하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자로 일해오면서 여러 가지 언어로 수많은 프로젝트를 셋업 해봤지만, django만큼 쉽게 환경을 구성할 수 있는 언어도 없는 것 같다. 아니면 내가 너무 익숙해 진건가? ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;python의 모토가 &lt;b&gt;life is shot, I do python&lt;/b&gt; 인 것만 봐도 python 진영이 뭔가 간단함을 추구한다는 것은 알 수 있다. django도 python 진영이다 보니 그 사상을 많이 따라간 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;django를 이미 여러 번 사용해 봤다면, 이번 강의는 그냥 건너뛰어도 좋다&lt;/b&gt;&lt;/u&gt;. 이번 강의에서는 IDE 선택, python 버전 선택, django 프로젝트 시작하기에 대한 간단한 내용을 다룰 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; ️ IDE 선택하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;통합개발툴(IDE - Integrated Development Enviroment)은 개발을 쉽게 도와주는 역할을 할 뿐만 아니라 최근 copilot 같은 ai의 도입으로 개발 편의성 및 효율성을 대폭 향상해 주는 역할을 한다. 최근에는 IDE를 안 쓰는 사람을 본 적이 없긴 한대, 예전에 금융사에서 일할 때 vim을 가지고만 개발했던 기억이 새록새록하다. (라때는...)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 IDE를 선택할 때 정말 고민도 하지 않고 JetBrains의 툴을 고른다. java진영은 intelliJ, python은 PyCharm, Ruby는 RubyMine, DB는 DataGrip.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전에는 JetBrains의 툴이 편의성도 좋고 기능도 많아서 좋았는데, 최근에는 vscode도 기능이 많고 편해져서 많은 개발자들이 사용하는 것 같다. 비유하자면 윈도우 유저는 vscode, 맥 유저는 JetBrains 쓰는 느낌이랄까? ㅎㅎ 물론 개인적인 생각이긴 하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 강의 역시 JetBrains의 PyCharm Pro버전으로 진행한다. 무료 버전인 Comunity 버전도 있지만 Pro버전이 더 많은 기능을 지원하며 편의성 역시 높다. PyCharm은 무료버전이라도 있는데, DB를 조회할 때 사용하는 DataGrip은 무료버전도 없다. ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 자기가 개발에 익숙해서 자신이 사용하는 IDE로 강의를 따라갈 수 있다면 자신이 사용하던 툴을 계속 사용하는 것을 추천한다. 하지만 따로 사용하던 툴이 없거나 개발경력이 많지 않다면 JetBrains 툴을 사용하며 강의를 따라 하기를 권장한다. 기본적으로 30일 무료이기 때문에 30일 동안 강의를 완료한다는 생각으로 하는 게 좋을 것 같다. (동기부여도 될 겸) 혹은 대학생일 경우 교육 라이선스를 공짜로 받아서 쓸 수 있기 때문에 무기한으로 사용할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2632&quot; data-origin-height=&quot;1250&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l5fmA/btsJMrmXFzE/js2qR74UgWRgMl4rQCZ6K0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l5fmA/btsJMrmXFzE/js2qR74UgWRgMl4rQCZ6K0/img.png&quot; data-alt=&quot;PyCharm&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l5fmA/btsJMrmXFzE/js2qR74UgWRgMl4rQCZ6K0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl5fmA%2FbtsJMrmXFzE%2Fjs2qR74UgWRgMl4rQCZ6K0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2632&quot; height=&quot;1250&quot; data-origin-width=&quot;2632&quot; data-origin-height=&quot;1250&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;PyCharm&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2568&quot; data-origin-height=&quot;1138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brlAcV/btsJM6vRbn9/5aZPWOdiEVrvcsJGfM08pk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brlAcV/btsJM6vRbn9/5aZPWOdiEVrvcsJGfM08pk/img.png&quot; data-alt=&quot;DataGrip&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brlAcV/btsJM6vRbn9/5aZPWOdiEVrvcsJGfM08pk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrlAcV%2FbtsJM6vRbn9%2F5aZPWOdiEVrvcsJGfM08pk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2568&quot; height=&quot;1138&quot; data-origin-width=&quot;2568&quot; data-origin-height=&quot;1138&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;DataGrip&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  python 버전 정하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발을 하기 전에 사용하는 언어나 프레임워크의 버전을 정하는 일은 신중해야한다. 메이저 버전일 경우 상당히 많은 변화가 생기기 때문에 너무 오래된 버전으로 개발하면 특정 라이브러리나 코드를 사용할 수 없을 수도 있고, 보안적인 취약점이 발생할 수 있기 때문이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 우리는 상용화된 서비스를 굴리는 목적이 아닌, 교육이 목적이기 때문에 python의 최신버전을 사용할 예정이다. (이 강의가 오래되면 예전 버전이 되겠지만..) 하지만 만약 회사에서 사용할 프로젝트를 만들 것이라면, 너무 최신버전도 안정성이나 호환성 문제로 안 좋을 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 이러한 문제들은 개발하면서 마주하기 때문에 처음에 정할 수 없을지도 모르지만, 대부분의 언어나 프레임워크는 Stable버전이라고 해서 여러 사람들의 사용을 통해 안정성이 검증된 버전을 제공하고 있다. 현재 시점으로 python 공식 홈페이지에 들어가니 3.12.6 버전이 보편화된 버전인 것 같아서 3.12.6 버전으로 강의를 진행해보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1896&quot; data-origin-height=&quot;918&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HLdro/btsJObv155i/kpbUox715KYdRX5GrE8X8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HLdro/btsJObv155i/kpbUox715KYdRX5GrE8X8K/img.png&quot; data-alt=&quot;python 공식 홈페이지 (https://www.python.org/downloads/)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HLdro/btsJObv155i/kpbUox715KYdRX5GrE8X8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHLdro%2FbtsJObv155i%2FkpbUox715KYdRX5GrE8X8K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1896&quot; height=&quot;918&quot; data-origin-width=&quot;1896&quot; data-origin-height=&quot;918&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;python 공식 홈페이지 (https://www.python.org/downloads/)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  신규 프로젝트 생성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Django 신규 프로젝트를 생성하는 방법은 CLI(Command Line Interface)를 이용하는 방법과 IDE를 이용하는 방법이 있다. cli를 이용하면 아래와 같은 명령어를 치면 된다.&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot; style=&quot;color: #000000; text-align: left;&quot;&gt;&lt;code&gt;django-admin startproject mysite&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 그냥 입력하면 안된다. python이 설치되어 있어야 하고, django package가 설치되어 있어야 한다. python이 설치되어 있다면 django는 아래와 같이 설치할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1727354390492&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install django&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;python을 설치할 때 보통 pip가 같이 설치되기는 하는데, pip 명령어를 못 찾는다고 나온다면 pip도 설치해줘야 한다. 이는 운영체재마다 설치과정이 다르기 때문에 여기서는 생략하도록 하겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위처럼 cli를 이용해서 프로젝트를 시작하는 방법이 있고, IDE를 통해서 프로젝트를 시작하는 방법이 있다. PyCharm에서는 신규 프로젝트 시작하기 &amp;gt; Django 선택을 통해 아주 쉽게 신규 프로젝트를 시작할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1594&quot; data-origin-height=&quot;1352&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMB0dg/btsJNO2seGK/iFkeGhL2cVpGdI4n7zDqB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMB0dg/btsJNO2seGK/iFkeGhL2cVpGdI4n7zDqB1/img.png&quot; data-alt=&quot;신규 프로젝트 생성 by PyCharm&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMB0dg/btsJNO2seGK/iFkeGhL2cVpGdI4n7zDqB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMB0dg%2FbtsJNO2seGK%2FiFkeGhL2cVpGdI4n7zDqB1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1594&quot; height=&quot;1352&quot; data-origin-width=&quot;1594&quot; data-origin-height=&quot;1352&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;신규 프로젝트 생성 by PyCharm&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 python은 설치되어있어야 하며, 가상환경(virtual enviroment)도 자동으로 설치된다. 이런 편리함 때문에 IDE사용을 적극 권장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2772&quot; data-origin-height=&quot;1908&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ddgmy4/btsJNgynLoE/7kyytyVYKtdCH4SMkaYv30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ddgmy4/btsJNgynLoE/7kyytyVYKtdCH4SMkaYv30/img.png&quot; data-alt=&quot;프로젝트 첫 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ddgmy4/btsJNgynLoE/7kyytyVYKtdCH4SMkaYv30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fddgmy4%2FbtsJNgynLoE%2F7kyytyVYKtdCH4SMkaYv30%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2772&quot; height=&quot;1908&quot; data-origin-width=&quot;2772&quot; data-origin-height=&quot;1908&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로젝트 첫 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 생성한 프로젝트는 프로젝트 이름의 폴더, manage.py 파일, 가상환경이 적용되어있는 .venv 폴더가 기본적으로 들어있다. templates의 경우 프론트화면을 위해 생성되기는 하지만, 이번 강의에서는 사용되지 않으니 지워도 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 간단히 생성만 해도 프로젝트를 실행할 수 있는데, pycharm에서 오른쪽 위에 run 버튼(초록색 화살표 모양)을 누르면 실행이 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1444&quot; data-origin-height=&quot;386&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bX1G0c/btsJX44UGhv/lFvyit293lCPJSr9jag291/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bX1G0c/btsJX44UGhv/lFvyit293lCPJSr9jag291/img.png&quot; data-alt=&quot;실행하기 버튼&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bX1G0c/btsJX44UGhv/lFvyit293lCPJSr9jag291/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbX1G0c%2FbtsJX44UGhv%2FlFvyit293lCPJSr9jag291%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1444&quot; height=&quot;386&quot; data-origin-width=&quot;1444&quot; data-origin-height=&quot;386&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실행하기 버튼&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3368&quot; data-origin-height=&quot;636&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xgtY9/btsJW8mVzUn/QLa3tUff99FOF2X2ZqFL7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xgtY9/btsJW8mVzUn/QLa3tUff99FOF2X2ZqFL7K/img.png&quot; data-alt=&quot;실행하면 화면 하단에 나오는 문구&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xgtY9/btsJW8mVzUn/QLa3tUff99FOF2X2ZqFL7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxgtY9%2FbtsJW8mVzUn%2FQLa3tUff99FOF2X2ZqFL7K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3368&quot; height=&quot;636&quot; data-origin-width=&quot;3368&quot; data-origin-height=&quot;636&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실행하면 화면 하단에 나오는 문구&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행하게 되면 http://localhost:8000/으로 development server가 실행 중이라는 메시지를 확인할 수 있다. 실제로 해당 url로 접속해 보면 장고가 실행 중인 것을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2100&quot; data-origin-height=&quot;1494&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWlxex/btsJWWNRD9x/L1sV7UAyZodQx1DPGFIUp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWlxex/btsJWWNRD9x/L1sV7UAyZodQx1DPGFIUp0/img.png&quot; data-alt=&quot;실행 중인 장고 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWlxex/btsJWWNRD9x/L1sV7UAyZodQx1DPGFIUp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWlxex%2FbtsJWWNRD9x%2FL1sV7UAyZodQx1DPGFIUp0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2100&quot; height=&quot;1494&quot; data-origin-width=&quot;2100&quot; data-origin-height=&quot;1494&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실행 중인 장고 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728365375882&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 메시지 상세 설명 
You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
-&amp;gt; django는 orm을 지원하기 때문에 model을 만들면 migrate를 통해 DB에 테이블을 생성하게 됩니다. 
django프로젝트를 새로 만들면 기본적인 model들이 생성되는데, migrate를 아직 하지 않아서 발생하는 메시지입니다.

October 08, 2024 - 04:12:17
-&amp;gt; 실행 시간

Django version 5.1.1, using settings 'UltimateDjangoCource.settings'
-&amp;gt; django 버전, 사용한 환경설정 파일 (기본적으로 settings.py 사용)

Starting development server at http://localhost:8000/
-&amp;gt; 서버 실행 정보 

Quit the server with CONTROL-C.
-&amp;gt; 종료하기 위한 방법&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;default 설정으로 django를 실행해도 실행이 잘 되는 것을 볼 수 있다. 다음 강의부터는 여기에 하나씩 기능들을 덧붙이면서 좀 더 상용화된 프로그램으로 만들어보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;⚙️ 그 밖에 사용하면 좋은 툴&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pycham 말고도 강의를 따라가는 데 사용하면 좋은 툴들이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;DataGrip&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 위에서 언급한 DataGrip은 데이터베이스를 조회하고 저장된 데이터를 수정하거나 변경하는데 좋은 툴이다. 한 가지 흠이라면 유료인 점..? 30일 무료나 교육 라이선스를 활용해서 무료로 최대한 사용해 보고, 정 아니다 싶으면 다른 툴을 사용해도 사실 데이터베이스를 확인하는데 큰 문제는 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Postman&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API 테스트를 위해 제일 많이 사용하는 툴이다. 어떤 걸 개발해도 가장 많이 사용하는 툴이기도 하고, 한번 만들어놓으면 공유하기도 쉽고 수정하기도 쉽고 추가 및 수정하기도 쉽다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서도 많이 사용하는데, 요즘에는 QA분들도 Postman을 통해 API를 테스트를 하는 것 같다. 모두가 사용하는 툴이 되는 느낌?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 Post, Get API를 찌르기에는 UI가 좀 복잡한 면이 있긴 한데, 그만큼 다양한 기능을 제공하기 때문에 한번 익숙해지면 너무 편리하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2764&quot; data-origin-height=&quot;1374&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUFEfc/btsJYKfC6TA/PGiXfmOoefmLJV3aKghZwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUFEfc/btsJYKfC6TA/PGiXfmOoefmLJV3aKghZwk/img.png&quot; data-alt=&quot;API 테스트 툴&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUFEfc/btsJYKfC6TA/PGiXfmOoefmLJV3aKghZwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUFEfc%2FbtsJYKfC6TA%2FPGiXfmOoefmLJV3aKghZwk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2764&quot; height=&quot;1374&quot; data-origin-width=&quot;2764&quot; data-origin-height=&quot;1374&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;API 테스트 툴&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 라이트하게 사용하고 싶다면 &lt;a href=&quot;https://insomnia.rest/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;insomnia&lt;/a&gt;라는 툴을 추천한다. Postman보다 가볍고 디자인이 조금 더 이쁘다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Sublime Text&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터를 새로 세팅할 때 항상 같이 설치하는 소프트웨어다. 기능은 그냥 메모장인데, 글에 syntax나 highlight기능이 너무 좋다. 개발용 메모장이라고 해야 하나? 여러 플러그인이 있어서 실제로 sublime Text만을 이용해서 개발하는 사람도 있다. 나는 그냥 메모장 정도로만 사용한다 ㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.sublimetext.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;공식 홈페이지&lt;/a&gt;에서 무료로 받을 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2490&quot; data-origin-height=&quot;1298&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oHpyk/btsJZNbzpBX/Z2oNZimQ8VkVrKabrSBN8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oHpyk/btsJZNbzpBX/Z2oNZimQ8VkVrKabrSBN8k/img.png&quot; data-alt=&quot;개발자들의 메모장&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oHpyk/btsJZNbzpBX/Z2oNZimQ8VkVrKabrSBN8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoHpyk%2FbtsJZNbzpBX%2FZ2oNZimQ8VkVrKabrSBN8k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2490&quot; height=&quot;1298&quot; data-origin-width=&quot;2490&quot; data-origin-height=&quot;1298&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;개발자들의 메모장&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Course/django : 실전 장고 백엔드 구축 &amp;amp; 운영</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/608</guid>
      <comments>https://cholol.tistory.com/608#entry608comment</comments>
      <pubDate>Mon, 23 Sep 2024 19:51:28 +0900</pubDate>
    </item>
    <item>
      <title>Django: 실전 백엔드 구축 &amp;amp; 운영, #0 Django 백엔드 강의는 이거 하나로 종결</title>
      <link>https://cholol.tistory.com/607</link>
      <description>&lt;div class=&quot;index_toc&quot;&gt;
&lt;p class=&quot;toc_title&quot; data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btYuIv/btsJKaKs4mL/1SJvd6RsLVi0yJ9iVQbyTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btYuIv/btsJKaKs4mL/1SJvd6RsLVi0yJ9iVQbyTK/img.png&quot; data-alt=&quot;gpt한테 이거 하나면 끝장나는 강의 표지 만들어줘 했더니 만들어줌 ㅋㅋ&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btYuIv/btsJKaKs4mL/1SJvd6RsLVi0yJ9iVQbyTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtYuIv%2FbtsJKaKs4mL%2F1SJvd6RsLVi0yJ9iVQbyTK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;1024&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;gpt한테 이거 하나면 끝장나는 강의 표지 만들어줘 했더니 만들어줌 ㅋㅋ&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  시작하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 회사에서 스프링을 많이 사용하면서 잊혀지고 있던 python과 django.. 그런데 언어의 유행은 돌고 도는 건지, 최근에 회사에서도 python 프로젝트를 진행하게 되었고, 사이드 프로젝트에 백엔드를 django로 구현하게 되면서 갑자기 python과 django 사용 횟수가 급증했다. 물 들어올 때 노 저으라고, 지금이 딱 django 중급강의를 만들기에 적합한 시기가 아닐까?라고 생각해서 바로 실행에 옮기는 중이다 ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;django 강의를 만들기 전에 어떤 내용을 담을지 고민했다. 이전에 만들었던 '&lt;b&gt;Django: 제로부터 시작하는 인스타그램'&lt;/b&gt;의 경우 django를 이용해 프론트부터 백엔드까지 간단하게 구현해 본 강의였다. 프론트와 백엔드를 동시에 다루다 보니 백엔드의 내용이 살짝 부실해진 느낌이 있었는데, 이번엔 백엔드에 좀 집중해 보는 방향으로 강의를 만들고 싶다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 강의를 만들기 위해 이미 있는 django강의를 참고해보려고 했는데, 시중에 나와있는 django 유료 강의들은 대부분 퀄리티가 낮은 것 같다. 뭐라고 해야 하나.. 실무에서 사용해보지 않은 사람들의 강의 같은 느낌이랄까..? 실제로 필드에서 구르고 배운 사람들은 강의를 안 만들기도 하고.. (귀찮으니..)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 커리큘럼 자체를 기존에 django 강의를 참고하는 것보다는, 강의가 많은 Spring강의를 참고하려고 한다. 언어나 프레임워크가 다르긴 하지만 사용하는 목적이 비슷하기 때문에 어느 정도 참고가 되지 않을까 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  누가 이 강의를 들어야 하나?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백엔드 개발자가 되고 싶은 사람들이 참고하면 좋을 것 같다.  django보다 spring이 수요가 더 많긴 하지만, 백엔드 프레임워크들이 대부분 비슷한 기능을 제공하기 때문에 django를 배우고 spring을 배워도 충분하다. 혹시 좋은 spring강의나 선생님이 있다면 바로 spring을 배우는 것을 추천한다. spring을 사용하는 회사가 더 많기 때문에 직장을 구하기 위해서라면 spring이 맞다. 하지만 spring도 그냥 spring, boot, kopring, 버전별 차이점 등등을 고려하면 spring을 배웠다고 해서 회사에 가서 온전히 배운 것들을 다 쓸 수 있는 보장이 없다 ㅎㅎ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 강의 코스에서는 django에 아주 기초적인 내용들은 생략할 예정이다. 이전 강의인 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;'&lt;/span&gt;&lt;b&gt;Django: 제로부터 시작하는 인스타그램'을&lt;/b&gt; 선수강하거나, django에 대한 기초적인 내용을 알고 있어야 강의를 더 잘 따라올 수 있을 것 같다. 물론 처음 접하는 사람들도 열정만 있다면 충분히 따라올 수 있을 것이다. 요즘 GPT가 너무 잘해주기 때문에 GPT와 함께라면 쉽게 django를 마스터할 수 있을 것 같다 ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  그래서 강의 순서는?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ChatGPT한테 목차를 만들어달라고 했더니 20장이나 만들어줬다 ㅋㅋ 이렇게 많이는 필요 없는데..&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 python이나 django에 대한 기본적인 내용은 이전 강의 (Django: 인스타그램)을 수강하라고 하기로 하고, 실제로 백엔드에 기본적인 기능들을 하나하나 구현해 나가는 방법으로 진행하려고 한다. 글을 쓰는 시점에 생각한 목차로는 아래와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;로그인, 회원가입, 회원정보 다루기&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;oauth를 이용한 로그인&lt;/li&gt;
&lt;li&gt;회원 정보 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;AWS 환경 위에서 Django 프로젝트 구축
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;docker 활용한 배포&lt;/li&gt;
&lt;li&gt;github action으로 배포 자동화&lt;/li&gt;
&lt;li&gt;Route53, ALB, TargetGroup 세팅하기&lt;/li&gt;
&lt;li&gt;RDS 연결&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;피드 데이터 생성, 조회, 검색
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;피드 데이터 생성&lt;/li&gt;
&lt;li&gt;s3 이미지 업로드&lt;/li&gt;
&lt;li&gt;피드 데이터 조회&lt;/li&gt;
&lt;li&gt;피드 데이터 검색&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;캐시 데이터 활용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AWS elasticache를 이용한 캐싱&lt;/li&gt;
&lt;li&gt;피드 데이터 캐싱하기&lt;/li&gt;
&lt;li&gt;사용자 정보 캐싱하기&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;로그, 모니터링
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그라파나, 센트리, 데이터독 사용해 보기&lt;/li&gt;
&lt;li&gt;슬랙 연동&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;그 밖에 기능들 추가...&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스는 개발자를 위한 인스타그램이랄까? TIL이나 코딩하기 좋은 카페, 개발자 it템 등 다양한 사진을 올릴 수 있는 서비스를 만들어보고자 한다. 물론 Django로는 백엔드만 만드는 것으로. 프론트는 만들 수 있다면 flutter로 만들 계획이지만, Django강의와는 별개의 코스로 진행될 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 하나하나 진행하면서 목차는 변경될 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  강의를 천천히 따라 해 보자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강의는 먼저 블로그에 정리하고 그다음 youtube영상으로 만들 예정이다. 블로그에 정리하면서 어느 정도 자료가 나와야 youtube를 찍기 편했던 것 같다. 지난번 강의 영상은 총 12시간 길이였는데, 만드는데 한 달은 걸린 것 같다. 물론 한 달 동안 정리하고 나서, 영상으로는 이틀 만에 찍었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 강의는 시간이 날 때 틈틈이 만들 계획이기 때문에 빠르게 올라오지 못할 수 있다. 최근에 회사 업무나 사이드 프로젝트 등 신경 쓸 일들이 많아졌는데, 최대한 짬을 내서 올해 안에는 강의를 끝내려고 한다. 이 강의로 돈 주고 django강의를 듣는 사람들이 없어지는 것을 목표로 하고 있다.  물론 그만큼 강의 퀄리티가 좋아야 하기 때문에 많은 노력을 해야겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책을 낼 생각도 있기 때문에 블로그 글 구성은 약간 책을 읽는 느낌(?)이 들 수 있을 것 같다. 그림이나 사진 하나하나 신경 써서 정리해 두면 바로 책으로 낼 수 있지 않을까 생각된다. 아직 첫 번째 강의글도 만들지 않았지만, 앞으로 만들 강의가 많은 사람들에게 도움이 되었으면 좋겠다. 물론 나 역시도 강의를 준비하면서 많은 것을 배울 수 있길 바란다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Course/django : 실전 장고 백엔드 구축 &amp;amp; 운영</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/607</guid>
      <comments>https://cholol.tistory.com/607#entry607comment</comments>
      <pubDate>Mon, 23 Sep 2024 19:36:17 +0900</pubDate>
    </item>
    <item>
      <title>장고 프로젝트 github action으로 배포 자동화 하기 feat. github action, github package(ghcr.io), docker-compose</title>
      <link>https://cholol.tistory.com/606</link>
      <description>&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; &amp;zwj;  들어가면서&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 포스팅 중에 nginx와 django 앱을 github action을 이용해 배포하는 것을 다루었었다.&amp;nbsp;&lt;br /&gt;&lt;a href=&quot;https://cholol.tistory.com/586&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://cholol.tistory.com/586&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때는 컨테이너 환경을 사용하지 않고 EC2에 직접 nginx와 django, uwsgi를 사용해서 서버를 실행했기 때문에 배포할 때 리모트로 들어가서 서버를 껐다 켜는(?) 명령어를 실행했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 docker를 이용한 환경에서 github action을 통해 자동으로 docker image를 만들고, github package에 이미지를 업로드하고, 해당 ec2에서 만들어진 이미지를 자동으로 pull 받아서 배포가 되는 환경을 구성하려고 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사이드 프로젝트를 진행하는데 변경사항이 빈번하게 일어나고 메인 푸시, 서버 배포, 메인 푸시, 서버 배포 이런 식으로 진행하다 보니 자동화가 너무 급했다.. ㅋㅋ github action 안 쓰고 서버에 직접 들어가서 docker-compose build, up -d를 수동으로 하고 있잖아 현타가 와서...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; &amp;zwj;♂️ Github Action 만들기&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;  docker image build and push action&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;github action은 이전 CI/CD포스팅에서 사용한 것과 거의 유사하게 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 main이 push되었을 때 django 앱 초기화 및 이미지를 빌드하고, github package (ghcr)에 이미지를 업로드한다. 그다음 EC2에 리모트로 접속해서 업로드한 docker image를 pull 하고 container를 재실행한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;docker image를 저장하기 위한 저장소로 github package를 사용한 것은 단순하다. github action 쓰니까.. ㅋㅋ github package 말고 도커 이미지를 저장해서 사용할 수 있는 서비스는 많다. 어느 정도까지는 공짜이기 때문에 개인이 사용한다면 크게 무리 없이 쓸 수 있다. 가장 큰 곳은 아마 도커 허브가 아닐까?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1526&quot; data-origin-height=&quot;554&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lbDnD/btsH52OrZtr/HiYzhU5hhPlOTp081Y2t50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lbDnD/btsH52OrZtr/HiYzhU5hhPlOTp081Y2t50/img.png&quot; data-alt=&quot;github package 가격 정보&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lbDnD/btsH52OrZtr/HiYzhU5hhPlOTp081Y2t50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlbDnD%2FbtsH52OrZtr%2FHiYzhU5hhPlOTp081Y2t50%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1526&quot; height=&quot;554&quot; data-origin-width=&quot;1526&quot; data-origin-height=&quot;554&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;github package 가격 정보&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도커 패키지도 public repository에 대해서는 무료라고 한다. private나 organization에서 private한 repo를 사용할 때는 위처럼 용량 제한이 있다. 엔터프라이즈 요금도 스토리지가 생각보다 크지가 않다 ;;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 나는 github enterprise에 가입된 organization이라 50GB는 쓸 수 있는 것 같다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 main이 push 되었을 때 도커 이미지를 만들고 ghcr에 push하는 action코드를 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1718854085422&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;name: Build and Push Docker Image

on:
  push:
    branches:
      - main

jobs:
  build-and-push:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v3

    - name: Get current timestamp
      id: timestamp
      run: echo &quot;::set-output name=TIME::$(date +'%Y%m%d%H%M%S')&quot;

    - name: Log in to GitHub Container Registry
      uses: docker/login-action@v1
      with:
        registry: ghcr.io
        username: ${{ github.repository_owner }}
        password: ${{ secrets.PERSONAL_TOKEN }}

    - name: Build and push Docker image
      uses: docker/build-push-action@v6
      with:
        context: .
        file: ./Dockerfile
        push: true
        tags: |
          ghcr.io/${{ github.repository_owner }}/app-django:latest
          ghcr.io/${{ github.repository_owner }}/app-django:${{ steps.timestamp.outputs.TIME }}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;on: 에 적혀있는 내용은 언제이 &lt;b&gt;action&lt;/b&gt;이 수행되는지에 대한 내용이다. main이 push 되었을 때 자동으로 실행하도록 적혀있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;jobs: 에 적혀있는 것이 실제로 이 action이 수행하는 작업이다. 바로 애라 steps:가 일련의 작업을 절차적으로 적어놓은 코드다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;name: 해당 step의 명칭&lt;/li&gt;
&lt;li&gt;uses: 사용할 라이브러리. github action도 누군가가 만들어놓은 코드를 가져다가 쓸 수 있다. github action marketplace라는 곳에서 검색해서 자신이 원하는 것을 사용할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;with: 작업을 위한 command가 들어간다. 실제 작업되는 코드라고 보면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심이 되는 step은 맨 마지막&lt;b&gt; Build and push Docker image&lt;/b&gt;이다. 여기서 실제로 docker를 빌드하고 ghcr.io에 푸시하게 된다. dockerfile의 경로는 해당 repository를 root로 생각하고 적으면 된다. 나는 django 프로젝트 root경로에 Dockerfile을 만들어 놨기 때문에./Dockerfile로 지정했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ghcr.io에 푸시할 때 사용되는 경로는 github 계정이름인데, repository_owner를 입력하면 된다. 그 뒤에는 이미지 이름과 버전 tag를 적게 되는데 이건 원하는 값을 적으면 된다. 나는 latest와 timestamp를 이용해 태그를 달았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ghcr.io에 로그인하는 부분은 중간에 있는 &lt;b&gt;step Log in in Github Container Repository인데&lt;/b&gt; 깃헙에서 제공하는 Personal Access Token을 사용해서 접속 가능하다. github에 setting에서 secret메뉴에 보면 PAT를 생성하는 메뉴가 있다. 생성할 때 패키지 접근 권한을 체크하고 토큰을 생성하면 해당 PAT로 ghcr에 접속 가능하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;action에서 보면 secrets.XXX라는 변수를 사용하는데, 이건 github에서 제공하는 secrets에서 값을 가져오겠다는 뜻이다. github repo에서 setting에 가면 secret value를 설정할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2234&quot; data-origin-height=&quot;1404&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCS2lA/btsH42BXY2u/6JLqrb6KoObXdyPLVYjrC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCS2lA/btsH42BXY2u/6JLqrb6KoObXdyPLVYjrC1/img.png&quot; data-alt=&quot;Secret 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCS2lA/btsH42BXY2u/6JLqrb6KoObXdyPLVYjrC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCS2lA%2FbtsH42BXY2u%2F6JLqrb6KoObXdyPLVYjrC1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2234&quot; height=&quot;1404&quot; data-origin-width=&quot;2234&quot; data-origin-height=&quot;1404&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Secret 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Secret 값을 한번 설정하면 설정한 사람도 볼 수 없기 때문에 처음에 잘 설정해야 한다. (만약 값이 바뀌거나 잃어버리면 다시 생성하는 게 방법)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 만든 github action 파일은 repo에 &lt;b&gt;.github/workflows/xxx-github-action.yaml&lt;/b&gt;에 만들어놓으면 github이 자동으로 인식한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2620&quot; data-origin-height=&quot;1312&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dBYP9s/btsH6hYZuyU/FG5kJELQfkai4q9KH0kFe0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dBYP9s/btsH6hYZuyU/FG5kJELQfkai4q9KH0kFe0/img.png&quot; data-alt=&quot;github action 메뉴&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dBYP9s/btsH6hYZuyU/FG5kJELQfkai4q9KH0kFe0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdBYP9s%2FbtsH6hYZuyU%2FFG5kJELQfkai4q9KH0kFe0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2620&quot; height=&quot;1312&quot; data-origin-width=&quot;2620&quot; data-origin-height=&quot;1312&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;github action 메뉴&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 위 yaml을 추가하고 main push 하면 자동으로 github repo 페이지 action메뉴에서 job이 실행되는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;⬆️ deploy action&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deploy 액션은 build보다 간단하다. 서버에 접속해서 이전 단계에서 만들어진 docker image를 pull 하고, docker를 재시작하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1718856831969&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;name: Deploy Sandbox Django

on:
  workflow_run:
    workflows: [&quot;Build and Push Docker Image&quot;]
    types:
      - completed

jobs:
  deploy:
    runs-on: ubuntu-latest

    if: ${{ github.event.workflow_run.conclusion == 'success' }}

    steps:
    - name: remote ssh and deploy
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.SANDBOX_SERVER_IP }}
        username: ${{ secrets.SANDBOX_SERVER_USERNAME }}
        key: ${{ secrets.SANDBOX_SERVER_SSH_KEY }}
        port: 22
        script: |
          docker login ghcr.io -u {{ github.repository_owner }} -p ${{ secrets.PERSONAL_TOKEN }}
          cd /home/ubuntu/havit-backend-django
          docker-compose pull
          docker-compose build
          docker image prune -f
          docker-compose up -d&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금은 서버가 1대만 띄워져 있기 때문에 한 곳에만 접속해서 명령어를 실행하지만, 만약 서버가 여러대라면 순차적으로 접속해서 명령어를 실행하도록 하면 된다. 하지만 서버를 여러 대 띄울 정도라면 다른 배포방식을 선택했겠지 ㅎㅎ 아직은 한 대니까 그냥 쓰자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 github action을 통해서 ghcr.io를 push할 때랑 다른 점은 docker login을 통해 로그인한다는 점이다. 이전엔 github action 인스턴스에서 로그인했기 때문에 docker/login_action이라는 패키지의 도움을 받아서 로그인했지만, ec2에 remote로 접근했기 때문에 ec2인스턴스에서 ghcr에 로그인해야 한다. 이럴 때는 docker login명령어를 쓰면 로그인 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;docker-compose.yaml파일에 이미 이미지 경로를 적어놨기 때문에 그냥 단순히 docker-compose pull만 하면 이미지 다운로드가 가능하다. 참고로 이전에 올린 이미지 경로는 github package 메뉴에서 확인 가능하다. package메뉴는 repo 쪽에 있는 게 아니라 더 상위에 있다는 것을 참고하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-06-20 오후 1.23.42.png&quot; data-origin-width=&quot;2510&quot; data-origin-height=&quot;790&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BsSHT/btsH5JPhXT7/WDBTbRqG782xKTtitncFQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BsSHT/btsH5JPhXT7/WDBTbRqG782xKTtitncFQ1/img.png&quot; data-alt=&quot;packages 메뉴에서 이미지 확인 가능&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BsSHT/btsH5JPhXT7/WDBTbRqG782xKTtitncFQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBsSHT%2FbtsH5JPhXT7%2FWDBTbRqG782xKTtitncFQ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2510&quot; height=&quot;790&quot; data-filename=&quot;스크린샷 2024-06-20 오후 1.23.42.png&quot; data-origin-width=&quot;2510&quot; data-origin-height=&quot;790&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;packages 메뉴에서 이미지 확인 가능&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;docker-compose pull 후 docker-compose up 만 하면 되지만 나는 docker-compose build와 docker image prune 이라는 명령어를 추가했다. docker-compose에 django-app만 있는 게 아니라 nginx도 있기 때문에 nginx는 아직 ghcr에 올리는 것으로 만들지 않았다. 사실 별로 변동사항이 없기 때문에 굳이 ghcr에 올리지 않아도 될 것 같긴 하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;docker image prune은 ec2에 쌓여있는 이전 버전 이미지들을 삭제하기 위한 명령어다. 요걸 해주지 않으면 EC2에 이미지가 계속 쌓여서 disk 용량 부족이 발생할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt; ️ delete old image action&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;github package에서는 자동으로 옛날 이미지를 삭제해주는 옵션을 제공해주지 않는다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엔터프라이즈를 사용해도 20GB밖에 제공해주지 않기 때문에 오래 사용하다 보면 용량을 더 사용해서 추가요금을 낼 수 있다. 이럴 때는 과거 이미지를 삭제해야 하는데, github 페이지에서는 일일이 수동으로 하나하나 삭제하는 방법밖에 제공하지 않는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배포 자동화 했으니 이것도 자동화 시켜주자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1718874608201&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;name: Delete Old Docker Images

on:
  schedule:
    - cron: &quot;0 0 * * *&quot;  # Runs daily at midnight
  workflow_dispatch:  # Allows manual triggering

jobs:
  clean-ghcr:
    runs-on: ubuntu-latest

    steps:
    - name: Delete old Docker images
      uses: snok/container-retention-policy@v2
      with:
        image-names: app-django # 앱 이름
        cut-off: &quot;1 day ago UTC&quot;
        timestamp-to-use: created_at
        account-type: org
        org-name: my organization # 내 오가니제이션 이름
        keep-at-least: 1
        token: ${{ secrets.PERSONAL_TOKEN }}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 액션은 날마다 00시에 하루 지난 이미지를 삭제하는 github action이다. workflow_dispatch: 를 on:에 추가하면 github 홈페이지에서 수동으로 action을 실행시킬 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;⌚️ 마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;github에서 제공하는 무료(제한적) 기능들로 생산성을 높일 수 있는 일들은 많다. 특히 개발단계에서 CI/CD를 프로덕션 레벨로 구현하기는 힘들다. 구현이 힘든 게 아니라 계속 바뀌므로, 번거롭다고 표현하는 게 더 좋겠다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사이드 프로젝트 하면서 항상 하는 고민이 이걸 k8s로 만들어놔 말아? 인 것 같다. 미리 k8s로 구성해 놓으면 확실히 편하긴 한데, 아직 개발단계에서는 너무 이른 단계가 아닐까? 개발할 때는 조그마한 서버 하나만 있으면 돌아가기 때문에 k8s로 구성하는 것조차 너무 허들이 크다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 가장 단순하고, 쉽고, 빠르게 구현하는 것이 개발단계에서의 필요한 마음가짐이다. github action은 빠르고 간단하게 CI/CD를 만들 수 있기 때문에 아주 유용한 툴이다. 쓸 때마다 좀 헷갈리기는 하는데,, yaml 특성상 그게 그거 같단 말이지...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 github aciton으로 docker 빌드, 배포, package관리까지 끝~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 더 나아가 슬랙 빌드 완료 시 슬랙 알림도 넣으면 개꿀~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Study/IT 실전 지식</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/606</guid>
      <comments>https://cholol.tistory.com/606#entry606comment</comments>
      <pubDate>Wed, 19 Jun 2024 21:12:08 +0900</pubDate>
    </item>
    <item>
      <title>[django] 장고에 S3연결하기. 프로필 사진 업로드, 조회 기능 만들기</title>
      <link>https://cholol.tistory.com/605</link>
      <description>&lt;div class=&quot;index_toc&quot;&gt;
&lt;p class=&quot;toc_title&quot; data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  서론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;옛날이나 지금이나 파일 업로드/다운로드는 어떤 서비스를 만들던지 필요했던 기능이다. 그냥 게시판을&amp;nbsp; 만들어도 사진 업로드 기능이 필요하기 때문이다. 요즘엔 클라우드를 통해 인프라를 쉽게 구축할 수 있는 만큼 대용량의 사진들도 쉽게 서버에 업로드하여 서비스할 수 있게 되었다. AWS에 S3는 이 기능을 사용하기 적합한 클라우드 서비스 중 하나이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스팅에서는 장고에서 S3를 연동하기 위해 S3 버킷 생성부터 사진 업로드 API까지 만들어볼 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  S3 버킷 만들기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 할일은 S3 버킷을 만드는 것이다. AWS를 사용하기 위한 가입절차는 이 포스팅에서는 생략한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS 콘솔에서 S3를 검색해서 S3메뉴로 가면 버킷을 만들 수 있다. S3 버킷을 만들면서 특별한 설정을 할 게 없다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1706&quot; data-origin-height=&quot;1562&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FsEh1/btsHa2oYehP/DACsvL08tKcozGIJx3B3n1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FsEh1/btsHa2oYehP/DACsvL08tKcozGIJx3B3n1/img.png&quot; data-alt=&quot;이름 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FsEh1/btsHa2oYehP/DACsvL08tKcozGIJx3B3n1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFsEh1%2FbtsHa2oYehP%2FDACsvL08tKcozGIJx3B3n1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1706&quot; height=&quot;1562&quot; data-origin-width=&quot;1706&quot; data-origin-height=&quot;1562&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이름 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버킷의 이름을 정하고 객체 소유권은 권장 설정을 사용한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1620&quot; data-origin-height=&quot;1268&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTfNNM/btsHadSrvL0/5Wf84cYVDP5NTYYmRwhq5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTfNNM/btsHadSrvL0/5Wf84cYVDP5NTYYmRwhq5k/img.png&quot; data-alt=&quot;중요한 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTfNNM/btsHadSrvL0/5Wf84cYVDP5NTYYmRwhq5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTfNNM%2FbtsHadSrvL0%2F5Wf84cYVDP5NTYYmRwhq5k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1620&quot; height=&quot;1268&quot; data-origin-width=&quot;1620&quot; data-origin-height=&quot;1268&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;중요한 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한건 아래 있는 모든 퍼블릭 액세스 차단이다. 디폴트로 이게 켜져 있는데, 퍼블릭 차단이 켜져 있으면 외부에서 s3접근이 안된다. 즉 이미지를 올려도 사용자가 볼 수 없다는 뜻이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어차피 서버에서 사용해서 클라로 내려주는 거 아니에요?라고 생각할 수 있다. 하지만 이미지를 사용하는 대부분의 서비스는 아래와 같은 구조로 구성되어 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1320&quot; data-origin-height=&quot;826&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zngYG/btsHbO4E1DA/pVV4NCM7ZH6oNkyZyq12AK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zngYG/btsHbO4E1DA/pVV4NCM7ZH6oNkyZyq12AK/img.png&quot; data-alt=&quot;이미지 저장 서비스 FLOW&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zngYG/btsHbO4E1DA/pVV4NCM7ZH6oNkyZyq12AK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzngYG%2FbtsHbO4E1DA%2FpVV4NCM7ZH6oNkyZyq12AK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1320&quot; height=&quot;826&quot; data-origin-width=&quot;1320&quot; data-origin-height=&quot;826&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이미지 저장 서비스 FLOW&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지를 저장하는 과정은, 클라에서 이미지를 업로드하면 우선 &lt;b&gt;1. S3에 파일을 업로드 한다&lt;/b&gt;. 그 후 &lt;b&gt;2. 업로드한 파일의 경로를 별도의 DB에 저장&lt;/b&gt;한다. 파일을 저장하지 않고 경로를 저장한다는 것이 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1418&quot; data-origin-height=&quot;748&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mtDbS/btsHaR9hDOb/wxhRTf8fX2ljaEu3YhUW51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mtDbS/btsHaR9hDOb/wxhRTf8fX2ljaEu3YhUW51/img.png&quot; data-alt=&quot;이미지 사용 서비스 FLOW&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mtDbS/btsHaR9hDOb/wxhRTf8fX2ljaEu3YhUW51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmtDbS%2FbtsHaR9hDOb%2FwxhRTf8fX2ljaEu3YhUW51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1418&quot; height=&quot;748&quot; data-origin-width=&quot;1418&quot; data-origin-height=&quot;748&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이미지 사용 서비스 FLOW&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라에서 이미지를 사용할 때는 &lt;b&gt;1. 서버에 먼저 이미지의 경로&lt;/b&gt;를 물어본다. 그럼 서버는 DB에 저장된 이미지 경로를 내려주고, 클라는 &lt;b&gt;2. 이 경로를 활용하여 다시 S3에 이미지를 조회&lt;/b&gt;한다. 이때 대부분의 클라는 사용자들의 PC 거나 스마트폰이다. 따라서 어떤 IP에서 접속할지 모르고 공개된 인터넷망을 사용하기 때문에 퍼블릭망에서 접근하게 된다. 만약 우리가 S3에 퍼블릭 접근을 차단한다면, 클라에서 해당 이미지를 조회할 수 없게 되기 때문에 이미지를 볼 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1630&quot; data-origin-height=&quot;1584&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/x3nXv/btsHadSsoZf/qE6UQUkzhBVikVmdxO99MK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/x3nXv/btsHadSsoZf/qE6UQUkzhBVikVmdxO99MK/img.png&quot; data-alt=&quot;그 외 설정들&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/x3nXv/btsHadSsoZf/qE6UQUkzhBVikVmdxO99MK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fx3nXv%2FbtsHadSsoZf%2FqE6UQUkzhBVikVmdxO99MK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1630&quot; height=&quot;1584&quot; data-origin-width=&quot;1630&quot; data-origin-height=&quot;1584&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그 외 설정들&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 외 설정들은 그냥 디폴트를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3530&quot; data-origin-height=&quot;402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ld4ob/btsHaul0Siv/9uCMjnGa57BgQsD9JjdtPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ld4ob/btsHaul0Siv/9uCMjnGa57BgQsD9JjdtPK/img.png&quot; data-alt=&quot;버킷 생성 완료&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ld4ob/btsHaul0Siv/9uCMjnGa57BgQsD9JjdtPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fld4ob%2FbtsHaul0Siv%2F9uCMjnGa57BgQsD9JjdtPK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3530&quot; height=&quot;402&quot; data-origin-width=&quot;3530&quot; data-origin-height=&quot;402&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;버킷 생성 완료&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버킷 만들기를 누르면 S3에 버킷이 생성된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; &amp;zwj;  django에 s3 연결 세팅하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;django에서 s3에 연결하기 위해서는 boto3라는 패키지가 필요하다. boto3는 django에서 aws cli를 사용하기 위한 패키지이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pip install boto3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;boto3을 사용해서 aws s3에 접근하기 위한 인증방법은 여러 가지가 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. session_profile or AWS_S3_SESSION_PROFILE&lt;br /&gt;2. access_key or AWS_S3_ACCESS_KEY_ID or AWS_S3_SECRET_ACCESS_KEY&lt;br /&gt;3. secret_key or AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY&lt;br /&gt;4. The environment variables AWS_S3_ACCESS_KEY_ID and AWS_S3_SECRET_ACCESS_KEY&lt;br /&gt;5. The environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY&lt;br /&gt;6. Use Boto3&amp;rsquo;s default session&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식 문서에는 위 6가지 방법을 제시하는데, 나는 여기서 5번을 사용할 예정이다. S3에 접근하기 위한 별도의 key를 발급하는 방법이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키를 만들기 위해서 AWS 콘솔에서 IAM메뉴로 들어간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-05-03 오후 11.10.27.png&quot; data-origin-width=&quot;2126&quot; data-origin-height=&quot;1086&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YwqGQ/btsHaZza83u/U6g4J81bnpYwwawjlzONtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YwqGQ/btsHaZza83u/U6g4J81bnpYwwawjlzONtk/img.png&quot; data-alt=&quot;사용자&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YwqGQ/btsHaZza83u/U6g4J81bnpYwwawjlzONtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYwqGQ%2FbtsHaZza83u%2FU6g4J81bnpYwwawjlzONtk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2126&quot; height=&quot;1086&quot; data-filename=&quot;스크린샷 2024-05-03 오후 11.10.27.png&quot; data-origin-width=&quot;2126&quot; data-origin-height=&quot;1086&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;사용자&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왼쪽에 메뉴에서 사용자를 눌러서 신규 사용자를 추가한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-05-03 오후 11.11.25.png&quot; data-origin-width=&quot;3092&quot; data-origin-height=&quot;658&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mMS6k/btsHbTdN56X/gpefd6JwVHAamowjtKfCIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mMS6k/btsHbTdN56X/gpefd6JwVHAamowjtKfCIk/img.png&quot; data-alt=&quot;사용자 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mMS6k/btsHbTdN56X/gpefd6JwVHAamowjtKfCIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmMS6k%2FbtsHbTdN56X%2Fgpefd6JwVHAamowjtKfCIk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3092&quot; height=&quot;658&quot; data-filename=&quot;스크린샷 2024-05-03 오후 11.11.25.png&quot; data-origin-width=&quot;3092&quot; data-origin-height=&quot;658&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;사용자 생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이름을 대충 정하고 다음을 누르면 권한 설정이 나오는데, 직접 정책 연결을 누른 후 S3 FullAccess를 선택해 준다. 여기서 선택하는 권한이 이 사용자가 할 수 있는 권한이다. 우리는 S3접근이 필요한 사용자가 필요하기 때문에 이거만 선택!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-05-03 오후 11.12.53.png&quot; data-origin-width=&quot;3034&quot; data-origin-height=&quot;1186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfqOdU/btsHclVe2LU/4j2xjTe9LCyhOloLTQv1dk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfqOdU/btsHclVe2LU/4j2xjTe9LCyhOloLTQv1dk/img.png&quot; data-alt=&quot;필요한 권한만 주기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfqOdU/btsHclVe2LU/4j2xjTe9LCyhOloLTQv1dk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfqOdU%2FbtsHclVe2LU%2F4j2xjTe9LCyhOloLTQv1dk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3034&quot; height=&quot;1186&quot; data-filename=&quot;스크린샷 2024-05-03 오후 11.12.53.png&quot; data-origin-width=&quot;3034&quot; data-origin-height=&quot;1186&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;필요한 권한만 주기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음을 누르고 사용자 생성을 누르면 사용자가 만들어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-05-03 오후 11.14.03.png&quot; data-origin-width=&quot;1822&quot; data-origin-height=&quot;532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdlEGu/btsHbtGxXgq/82zimKn5gvBnFADi3TG7n1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdlEGu/btsHbtGxXgq/82zimKn5gvBnFADi3TG7n1/img.png&quot; data-alt=&quot;사용자 생성 완료&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdlEGu/btsHbtGxXgq/82zimKn5gvBnFADi3TG7n1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdlEGu%2FbtsHbtGxXgq%2F82zimKn5gvBnFADi3TG7n1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1822&quot; height=&quot;532&quot; data-filename=&quot;스크린샷 2024-05-03 오후 11.14.03.png&quot; data-origin-width=&quot;1822&quot; data-origin-height=&quot;532&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;사용자 생성 완료&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 상세 정보로 들어가서 궈보안 자격 증명을 누른 후 아래로 내려가면 액세스 키라는 메뉴가 있다. 여기서 액세스 키 만들기를 누르면 Access_key와 Secret_key를 만들어준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-05-03 오후 11.15.13.png&quot; data-origin-width=&quot;3082&quot; data-origin-height=&quot;1298&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OvV81/btsHcKAuVa5/2WEusHFWWHcMs224a6Kx5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OvV81/btsHcKAuVa5/2WEusHFWWHcMs224a6Kx5k/img.png&quot; data-alt=&quot;액세스 키 만들기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OvV81/btsHcKAuVa5/2WEusHFWWHcMs224a6Kx5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOvV81%2FbtsHcKAuVa5%2F2WEusHFWWHcMs224a6Kx5k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3082&quot; height=&quot;1298&quot; data-filename=&quot;스크린샷 2024-05-03 오후 11.15.13.png&quot; data-origin-width=&quot;3082&quot; data-origin-height=&quot;1298&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;액세스 키 만들기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-05-03 오후 11.15.50.png&quot; data-origin-width=&quot;2498&quot; data-origin-height=&quot;1554&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btJaqZ/btsHb7Xfz1Y/8Ha80sjeLPqcm8wn9MQfv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btJaqZ/btsHb7Xfz1Y/8Ha80sjeLPqcm8wn9MQfv0/img.png&quot; data-alt=&quot;CLI로 만들기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btJaqZ/btsHb7Xfz1Y/8Ha80sjeLPqcm8wn9MQfv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtJaqZ%2FbtsHb7Xfz1Y%2F8Ha80sjeLPqcm8wn9MQfv0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2498&quot; height=&quot;1554&quot; data-filename=&quot;스크린샷 2024-05-03 오후 11.15.50.png&quot; data-origin-width=&quot;2498&quot; data-origin-height=&quot;1554&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;CLI로 만들기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용은 CLI로 체크하면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그후 태그값을 정하면 Access_Key와 Secrey_Key를 얻을 수 있다. 이 값을 환경변수를 이용해 django에 세팅하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1714745873267&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# settings.py

# S3 setting
AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID', '방금 만든 access_key')
AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY', '방금 만든 secret_key')
AWS_STORAGE_BUCKET_NAME = os.environ.get('AWS_STORAGE_BUCKET_NAME', 'cholol.tistory.com')
AWS_S3_REGION_NAME = os.environ.get('AWS_S3_REGION_NAME', 'ap-northeast-2')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 이제 django에서 s3를 접근 테스트를 위해 python shell에서 아래와 같이 입력해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1714746062926&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;In [1]: import boto3

In [2]: from settings import AWS_S3_REGION_NAME, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_STORAGE_BUCKET_NAME

In [3]: s3_client = boto3.client('s3',  aws_access_key_id=AWS_ACCESS_KEY_ID, aws_secret_access_key=AWS_SECRET_ACCESS_KEY, region_name=AWS_S3_REGION_NAME)

In [4]: s3_client.list_buckets()
Out[4]: 
{'ResponseMetadata': 
...
 'Buckets': [{'Name': 'cholol.tistory.com',
   'CreationDate': datetime.datetime(2024, 5, 3, 12, 56, 42, tzinfo=tzutc())},
 'Owner': {'ID': 'xxxxx'}}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로 s3에 접근하는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  파일 업로드 코드 만들기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 업로드는 간단하게 만들 수 있다. 공통 함수로 만들어서 쉽게 쓸 수 있게 하자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1714746682358&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def s3_file_upload_by_file_data(upload_file, region_name, bucket_name, bucket_path, content_type=None, extension=None):
    bucket_name = bucket_name.replace('/', '')
    if content_type:
        content_type = content_type
    else:
        content_type = upload_file.content_type
    if extension:
        extension = extension
    else:
        extension = upload_file.name.split('.')[-1]

    now = datetime.now()
    random_str = get_random_text('A', 20)
    random_file_name = f&quot;{now}_{random_str}.{extension}&quot;
    upload_file_path_name = f&quot;{bucket_path}/{random_file_name}&quot;

    try:
        upload_file.seek(0)
    except Exception:
        pass

    s3 = boto3.resource('s3', region_name=region_name, aws_access_key_id=settings.AWS_ACCESS_KEY_ID, aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY)

    if s3.Bucket(bucket_name).put_object(Key=upload_file_path_name, Body=upload_file, ContentType=content_type, ACL='public-read') is not None:
        return f&quot;https://s3-{region_name}.amazonaws.com/{bucket_name}/{bucket_path}/{random_file_name}&quot;

    return False&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; 해당 함수에 file과 s3설정값들을 넣으면 파일을 업로드한 path를 리턴하게 된다. s3에 저장할 때 어떤 파일명으로 저장할지 정할 수 있는데 나는 20글자의 랜덤 알파벳으로 저장하게 했다. 실제로 파일에 key값은 DB에 저장하고, 그 key로 파일 경로를 찾을 것이기 때문에 사실 파일명은 의미가 없다고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 다운로드는 실제로 클라에서 하기 때문에 서버에 구현할 필요가 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;s3 사용이 이미 보편화되어서 그런지 예전에 했을 때랑 코드가 달라진 게 없다. 패키지도 많고, 찾아보면 더 편한 패키지들이 많을 것이다. 여기서 백엔드의 성능을 더 높이기 위해 s3_client를 singleton으로 만들어볼 수 있을 것 같은데, 그 정도로 많은 호출이 필요하다면 뭔가 더 체계적인 구조로 다시 만들어야 할 것 같다 ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Study/python</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/605</guid>
      <comments>https://cholol.tistory.com/605#entry605comment</comments>
      <pubDate>Fri, 3 May 2024 23:35:44 +0900</pubDate>
    </item>
    <item>
      <title>맥에서 jar 파일 디컴파일 하기</title>
      <link>https://cholol.tistory.com/604</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외부 라이브러리를 사용하기 위해 jar 파일을 사용할 때가 있다. jar에 있는 class를 사용하기 위해서는 어떤 package나 class로 되어있는지 확인이 필요한데, jar자체는 바이너리 파일이라 사람이 읽을 수 없다. 따라서 최대한 사람이 읽을 수 있는 java형태로 디컴파일(decompile)을 해야 하는데, 간단한 툴을 사용해서 디컴파일을 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;윈도에서는 exe파일로 실행 가능한 툴이 있었는데, 맥에서는 exe가 안 돌아가니, 개발자스럽게 cli를 사용해서 디컴파일 해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/java-decompiler/jd-gui/releases&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/java-decompiler/jd-gui/releases&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1713869324587&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;Releases &amp;middot; java-decompiler/jd-gui&quot; data-og-description=&quot;A standalone Java Decompiler GUI. Contribute to java-decompiler/jd-gui development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/java-decompiler/jd-gui/releases&quot; data-og-url=&quot;https://github.com/java-decompiler/jd-gui/releases&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/4gaoG/hyVVzKXWIg/mgKpgZqruEq0Ea1yGkNT21/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/java-decompiler/jd-gui/releases&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/java-decompiler/jd-gui/releases&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/4gaoG/hyVVzKXWIg/mgKpgZqruEq0Ea1yGkNT21/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Releases &amp;middot; java-decompiler/jd-gui&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A standalone Java Decompiler GUI. Contribute to java-decompiler/jd-gui development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 repo에 들어가보면 여러 형태의 파일을 받을 수 있는데, 그냥 jar파일을 받아서 java로 실행하면 된다. M 맥에서도 됨!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;986&quot; data-origin-height=&quot;974&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kJJX6/btsGRLHQhoW/Yrn0s1lbSJHLKSX6UBBx71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kJJX6/btsGRLHQhoW/Yrn0s1lbSJHLKSX6UBBx71/img.png&quot; data-alt=&quot;창이 아담하다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kJJX6/btsGRLHQhoW/Yrn0s1lbSJHLKSX6UBBx71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkJJX6%2FbtsGRLHQhoW%2FYrn0s1lbSJHLKSX6UBBx71%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;494&quot; data-origin-width=&quot;986&quot; data-origin-height=&quot;974&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;창이 아담하다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;java -jar jd-gui-*.jar 를 실행하면 커피 아이콘이 잠깐 나오고, 디컴파일 가능한 윈도가 하나 열린다. 여기에 디컴파일 하고 싶은 jar파일을 올리면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론, 요즘엔 난독화기능을 사용해서 디컴파일로 코드 확인이 불가능한 jar도 많아 상세한 코드까지는 파악이 불가능하다. 다행히 내가 하려고 한느건 패키지명이나 클래스명정도는 확인이 가능했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-04-23 오후 8.03.17.png&quot; data-origin-width=&quot;1638&quot; data-origin-height=&quot;972&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bR3piO/btsGTz8Crk8/CvZ1znT7hpbkLEJvaR6RLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bR3piO/btsGTz8Crk8/CvZ1znT7hpbkLEJvaR6RLk/img.png&quot; data-alt=&quot;jar 디컴파일&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bR3piO/btsGTz8Crk8/CvZ1znT7hpbkLEJvaR6RLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbR3piO%2FbtsGTz8Crk8%2FCvZ1znT7hpbkLEJvaR6RLk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;356&quot; data-filename=&quot;스크린샷 2024-04-23 오후 8.03.17.png&quot; data-origin-width=&quot;1638&quot; data-origin-height=&quot;972&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;jar 디컴파일&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전에 안드로이드 개발할 때도 디컴파일 많이 했던것 같은데 ㅋㅋ 요즘엔 인텔리제이나 이클립스와 같은 IDE에서도 디컴파일 기능을 제공하기 때문에 더 쉽게 코드를 까볼 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근에는 스크립트 언어를 많이 했었어서 컴파일에 대한 개념이 가물가물했었는데, jar 디컴파일 하면서 다시금 컴파일 존재에 대해 인식할 수 있는 시간이 되었다 ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Blog/IT, I Think</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/604</guid>
      <comments>https://cholol.tistory.com/604#entry604comment</comments>
      <pubDate>Thu, 25 Apr 2024 12:03:53 +0900</pubDate>
    </item>
    <item>
      <title>맥북 Python에서 Jpype 사용하기 위한 삽질</title>
      <link>https://cholol.tistory.com/603</link>
      <description>&lt;div class=&quot;index_toc&quot;&gt;
&lt;p class=&quot;toc_title&quot; data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; &amp;zwj;♂️ 사건의 시작&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나이스평가정보에서 제공하는 휴대폰본인인증을 사용하기 위해, 해당 업체로부터 라이브러리를 받았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;제공 모듈 : ASP, PHP, JSP&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아니 ㅋㅋㅋㅋ 지금 무슨 2000년대냐고요.. JSP는 인정,, ASP랑 PHP 같은 옛날 패키지 누가 쓰냐구요 ㅋㅋㅋㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 웃긴건 회사 소개 페이지에 &lt;b&gt;모든 언어 플랫폼 지원 모듈 제공!&lt;/b&gt; 이라고 광고해 놓고, 이 정도면 계약 사기 아님? ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 혹시 담당 개발자한테 전화로 &quot;다른 언어는 제공 안 하나요?&quot; 물어봤더니 &quot;네 없어요~&quot; ㅋㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;거의 일하기 싫은 공무원이 다른 부서에게 핑퐁하듯이 퉁명스러운 대답만 돌아왔다. 하- 갑자기 증권회사에서 일하던 그날들이 잠깐 스쳐 지나갔지만, 세상에 이렇게 의욕 없고 놀고먹는 개발자도 있어야지~라는 생각에 그냥 넘어가기로 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 JSP로 제공된 jar파일을 어떻게 해보는 것으로..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; &amp;zwj;  jpype사용하기&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;옛날에 자연어 처리할 때 konlpy 엄청 사용했었는데, 요 라이브러리가 jpype를 사용해서 java를 python에서 돌리던 패키지였다. 마찬가지로 jpype를 사용하면 python에서 java패키지 사용이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가벼운 마음으로 .jar파일을 프로젝트에 복사한 뒤, pip install JPype1로 jpype를 설치했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;jpype를 이용해 jvm을 시작하기 위해선 jpype.startJVM(classpath={.jar 경로})를 입력하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2882&quot; data-origin-height=&quot;1204&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PgNw7/btsGHHxHa3n/fN5uSRvriJ2R14EkIPFZT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PgNw7/btsGHHxHa3n/fN5uSRvriJ2R14EkIPFZT1/img.png&quot; data-alt=&quot;바로 에러 뜨쥬?&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PgNw7/btsGHHxHa3n/fN5uSRvriJ2R14EkIPFZT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPgNw7%2FbtsGHHxHa3n%2FfN5uSRvriJ2R14EkIPFZT1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2882&quot; height=&quot;1204&quot; data-origin-width=&quot;2882&quot; data-origin-height=&quot;1204&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;바로 에러 뜨쥬?&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 바로 에러가 뜨는데,, 검색해보면 여러 가지 문제가 있는데 맥북 M1이라서 문제라고 한다(실제로 M3사용 중이긴 하다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 살펴보니 CPU문제는 아닌것 같고 실제로 JAVA_HOME경로가 안 잡혀있다는 것을 알았는데,,,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  asdf로 설치된 java path 설정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;asdf를 이용해 java를 깔았는데 이상하네? 하고 검색해보니 asdf에서 java_home을 설정하기 위해 추가로 해줘야 하는 것이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1056&quot; data-origin-height=&quot;548&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSyp6S/btsGGXumQac/A6hhUTFaN33tUZLslykFk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSyp6S/btsGGXumQac/A6hhUTFaN33tUZLslykFk1/img.png&quot; data-alt=&quot;set-java-home을 해줘야함&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSyp6S/btsGGXumQac/A6hhUTFaN33tUZLslykFk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSyp6S%2FbtsGGXumQac%2FA6hhUTFaN33tUZLslykFk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;208&quot; data-origin-width=&quot;1056&quot; data-origin-height=&quot;548&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;set-java-home을 해줘야함&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;홈 경로에서 ~/.asdf/plugins/java에 가보면 set-java-home이라는 쉘들이 많은데, 여기서 컴퓨터에 설치된 쉘을 실행해 주면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 zsh이 설치되어있기 때문에 set-java-home.zsh에 있는 내용을 복사해서 ~/.zshrc에 붙여 넣기 해주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1118&quot; data-origin-height=&quot;506&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bso7gG/btsGG6dDMGp/rpdw3a0X27t7hFE0VKF79k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bso7gG/btsGG6dDMGp/rpdw3a0X27t7hFE0VKF79k/img.png&quot; data-alt=&quot;.zshrc 맨아래 복사&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bso7gG/btsGG6dDMGp/rpdw3a0X27t7hFE0VKF79k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbso7gG%2FbtsGG6dDMGp%2Frpdw3a0X27t7hFE0VKF79k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;181&quot; data-origin-width=&quot;1118&quot; data-origin-height=&quot;506&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;.zshrc 맨아래 복사&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 터미널이 실행될때 java_home을 알아서 지정할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt; &amp;zwj;  재도전&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JAVA_HOME 경로 확인하고 재도전..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1808&quot; data-origin-height=&quot;476&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QAKpL/btsGE5Uwwt1/sjKoalB4JS7HR5ys576AwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QAKpL/btsGE5Uwwt1/sjKoalB4JS7HR5ys576AwK/img.png&quot; data-alt=&quot;바로 실행되쥬~?&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QAKpL/btsGE5Uwwt1/sjKoalB4JS7HR5ys576AwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQAKpL%2FbtsGE5Uwwt1%2FsjKoalB4JS7HR5ys576AwK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1808&quot; height=&quot;476&quot; data-origin-width=&quot;1808&quot; data-origin-height=&quot;476&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;바로 실행되쥬~?&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 오라클 JAVA가 m1에서 잘된다고 해서 oracle java를 설치했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1246&quot; data-origin-height=&quot;122&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOOJq1/btsGGOYFkHl/qV0RKOyrSBOqs5jE5NAHh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOOJq1/btsGGOYFkHl/qV0RKOyrSBOqs5jE5NAHh0/img.png&quot; data-alt=&quot;oracle java&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOOJq1/btsGGOYFkHl/qV0RKOyrSBOqs5jE5NAHh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOOJq1%2FbtsGGOYFkHl%2FqV0RKOyrSBOqs5jE5NAHh0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1246&quot; height=&quot;122&quot; data-origin-width=&quot;1246&quot; data-origin-height=&quot;122&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;oracle java&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래는 다른 java를 쓰고 있긴 했었는데,, 이거 할 때만 이걸로 해야지 뭐  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Study/python</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/603</guid>
      <comments>https://cholol.tistory.com/603#entry603comment</comments>
      <pubDate>Wed, 17 Apr 2024 00:23:39 +0900</pubDate>
    </item>
    <item>
      <title>django에 swagger 만들기, drf-spectacular</title>
      <link>https://cholol.tistory.com/602</link>
      <description>&lt;pre id=&quot;code_1712223282372&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class KakaoAuthorize(PublicView):
    @extend_schema(
        parameters=[
            OpenApiParameter(
                name=&quot;code&quot;,
                type=OpenApiTypes.STR,
                location=OpenApiParameter.QUERY,
                description=&quot;Authorization code&quot;,
                required=True,
            )
        ],
        responses={
            status.HTTP_200_OK: LoginTokenSerializer(),
            status.HTTP_400_BAD_REQUEST: BAD_REQUEST_RESPONSE
        },
    )
    def get(self, request, *args, **kwargs):&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; API 스펙 공유를 위한 swagger&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자들에게 swagger는 아주 친숙한 이름이다. 프론트엔드와 백엔드 모두 자주 활용하는 기능인데, API 스펙에 대한 명세를 확인할 수 있는 '&lt;b&gt;공유 문서&lt;/b&gt;'라고 생각하면 된다. 웹 브라우져를 이용해 GUI형태로 제공되기 때문에 보기 편하고, 실제로 API를 호출해 볼 수 있기도 하다. (보안 때문에 실제 운영 서버에서는 swagger로 호출을 막아놓기는 한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전에 장고 프로젝트를 진행할 때는 drf-yasg를 사용했었는데, 최근에 drf-spectacular라는게 더 잘 나가는 패키지인 것 같다. 지원하는 버전이 더 높은가 보다. drf-spectacular를 사용하면서 이것저것 세팅을 좀 해보면서 사용법을 정리해 본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2706&quot; data-origin-height=&quot;1928&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nlvm8/btsGnyaCGt5/plonKJRqBPfuN3Xzs21fIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nlvm8/btsGnyaCGt5/plonKJRqBPfuN3Xzs21fIk/img.png&quot; data-alt=&quot;swagger 실행 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nlvm8/btsGnyaCGt5/plonKJRqBPfuN3Xzs21fIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fnlvm8%2FbtsGnyaCGt5%2FplonKJRqBPfuN3Xzs21fIk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2706&quot; height=&quot;1928&quot; data-origin-width=&quot;2706&quot; data-origin-height=&quot;1928&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;swagger 실행 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;⬇️ 설치하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 패키지를 설치해야한다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712220579839&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install drf-spectacular&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재기준 0.27.1버전이 최신버전인데, 계속해서 버전 업되고 있는 모양이다. 깃헙링크 : &lt;a href=&quot;https://github.com/tfranzel/drf-spectacular&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/tfranzel/drf-spectacular&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패키지를 설치하고 몇가지 세팅이 필요한데, 일단 settings.py에 아래와 같은 코드를 추가해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712220753077&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# settings.py

INSTALLED_APPS = [
    ...
    'drf_spectacular',   # installed_app에 추가
    ...
]

REST_FRAMEWORK = {
    'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
}



SPECTACULAR_SETTINGS = {
    # General schema metadata. Refer to spec for valid inputs
    # https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md#openapi-object
    'TITLE': 'drf-spectacular API Document',
    'DESCRIPTION': 'drf-specatular 를 사용해서 만든 API 문서입니다.',
    'SWAGGER_UI_SETTINGS': {
        'dom_id': '#swagger-ui',
        'layout': 'BaseLayout', 
        'deepLinking': True,  
        'displayOperationId': True,
        'filter': True,
    },
   
    'LICENSE': {
        'name': 'MIT License',
    },
    'VERSION': '1.0.0',
    'SERVE_INCLUDE_SCHEMA': False,

    'SWAGGER_UI_DIST': '//unpkg.com/swagger-ui-dist@3.38.0',
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SPECTACULAR_SETTINGS가 실제로 swagger화면에 이것저것 옵션을 넣는 설정인데, 자세한 설정값들은 &lt;a href=&quot;https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;요기&lt;/a&gt;를 가면 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 다음으로 urls.py를 수정하면 스웨거 화면을 띄울 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712222679445&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# urls.py
from drf_spectacular.views import SpectacularJSONAPIView, SpectacularYAMLAPIView, SpectacularSwaggerView, \
    SpectacularRedocView

urlpatterns = [
    path(&quot;swagger.json/&quot;, SpectacularJSONAPIView.as_view(), name=&quot;schema-json&quot;),
    path(&quot;swagger.yaml/&quot;, SpectacularYAMLAPIView.as_view(), name=&quot;swagger-yaml&quot;),
    path(&quot;swagger/&quot;, SpectacularSwaggerView.as_view(url_name=&quot;schema-json&quot;), name=&quot;swagger-ui&quot;, ),
    path(&quot;redoc/&quot;, SpectacularRedocView.as_view(url_name=&quot;schema-json&quot;), name=&quot;redoc&quot;, ),
    ...
]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 url path는 ~/swagger 지만 json이나 yaml형태로 데이터를 받고 싶은 클라이언트가 있기 때문에 swagger.json, swagger.yaml도 추가했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 django 프로젝트를 실행하면 swagger화면이 뜨는것을 확인할 수 있다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; &amp;zwj;  커스터마이징&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위처럼 설치만 하고 swagger를 띄우면 단순히 API 리스트만 나오고 다른 정보들은 표기되지 않는다. 이런 것들까지 자동으로 찾아서 보여준다면 아주 좋겠지만, 각 API마다 request나 response type을 일일이 지정해 줘야 좀 더 swagger를 잘 활용할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 카카오 인증을 하는 API에 대해 parameter를 세팅한 예시이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712223324993&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class KakaoAuthorize(PublicView):
    @extend_schema(
        parameters=[
            OpenApiParameter(
                name=&quot;code&quot;,
                type=OpenApiTypes.STR,
                location=OpenApiParameter.QUERY,
                description=&quot;Authorization code&quot;,
                required=True,
            )
        ],
        responses={
            status.HTTP_200_OK: LoginTokenSerializer(),
            status.HTTP_400_BAD_REQUEST: BAD_REQUEST_RESPONSE
        },
    )
    def get(self, request, *args, **kwargs):
        ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 parameters, request, responses 3개만 잘 세팅하면 된다. parameters는 헤더나 path에 세팅되는 값, request는 body에 세팅되는 값, response는 응답값이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;parameters같은 경우 OpenApiParameter를 사용해 표기할 수 있고, request와 response는 serializer로 표현할 수 있는데, serializer로 표현하면 어떤 타입의 field인지만 보여줄 수 있다. drf-spectacular에서 제공하는 OpenApiRequest와 OpenApiResponse를 활용하면 serializer정보 + 예제 요청/응답과 같은 추가적인 정보를 세팅할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에 responses에서 200인경우는 LoginTokenSerializer라는 serializer정보를 내려주고, 400 응답일 경우 BAD_REQUEST_RESPONSE라는 OpenApiResponse 클래스를 내려주는데, 각 클래스 구현은 아래와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712223686136&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class LoginTokenSerializer(serializers.ModelSerializer):
    class Meta:
        model = LoginToken
        depth = 1
        fields = ['access_token', 'refresh_token', 'expires_in', 'refresh_token_expires_in', 'secret_key']



class BadRequestResponse(OpenApiResponse):
    def __init__(self):
        super().__init__(
            inline_serializer(
                name=&quot;BadRequest&quot;,
                fields={
                    &quot;error_code&quot;: serializers.CharField(),
                    &quot;message&quot;: serializers.CharField(),
                    &quot;display_type&quot;: serializers.CharField(),
                },
                allow_null=True,
            ),
            description=&quot;Bad request&quot;,
            examples=[
                OpenApiExample(
                    name=&quot;Bad JSON passed in&quot;,
                    value={
                        &quot;error_code&quot;: &quot;notification&quot;,
                        &quot;message&quot;: &quot;&quot;,
                        &quot;display_type&quot;: &quot;event_type and event_parameters fields are required&quot;,
                    },
                    status_codes=[&quot;400&quot;],
                ),
                OpenApiExample(
                    name=&quot;Not good JSON&quot;,
                    value={
                        &quot;detail&quot;: &quot;JSON parse error - Expecting ':' delimiter: line 2 column 17 (char 18)&quot;
                    },
                    status_codes=[&quot;400&quot;],
                ),
            ],
        )&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드가 swagger에서 표현되는 화면은 아래와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2618&quot; data-origin-height=&quot;1188&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cygPMd/btsGn14ABcD/AmXxCrEVBdQNp8fZy9Npa1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cygPMd/btsGn14ABcD/AmXxCrEVBdQNp8fZy9Npa1/img.png&quot; data-alt=&quot;실제로 노출되는 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cygPMd/btsGn14ABcD/AmXxCrEVBdQNp8fZy9Npa1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcygPMd%2FbtsGn14ABcD%2FAmXxCrEVBdQNp8fZy9Npa1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2618&quot; height=&quot;1188&quot; data-origin-width=&quot;2618&quot; data-origin-height=&quot;1188&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실제로 노출되는 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;200이 serializer, 400이 OpenApiResponse를 사용한 항목이다. serializer의 경우 각 field와 type이 적혀있긴 하지만, 구체적으로 어떤 값이 나오는지는 확인할 수 없다. (사실 이 정도만 해도...)&amp;nbsp; &amp;nbsp;400의 경우는 실제로 field에 어떤 값이 들어갈지 세팅할 수 있어서 개발할 때 더 효과적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정말 완벽하게 swagger를 사용하기 위해서는 OpenApiResponse를 각 API마다 만들어주는게 좋겠지만, 대충 어느 type인지만 알아도 개발이 가능하기 때문에 고민해 볼 필요가 있다. 개발 팀의 커뮤니케이션 빈도가 높다면 굳이 swagger에 모든 정보를 노출하는 것보다는, 딱 필요정보만 보여주고 다른 건 다른 의사소통 채널을 통해 진행하는 게 더 좋을 수 있다. 반대로 회의 Cost가 높다고 생각한다면 (물리적인 위치가 멀어서 ?) 완벽한 Swagger문서를 공유하는 것이 더 바람직할 수 있다. 진리의 케바케&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  마치며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 사용했던 drf-yasg와 사용하는 방법에는 큰 차이가 없다. 하지만 OpenApi 3.0 스펙을 제공하는 것은 drf-spectacular만 제공하며, drf-yasg문서에는 drf-spectacular를 사용하라고 적혀있다 ㅎㅎ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;swagger를 사용하는 이유는 개발 편의이기 때문에, swagger를 사용하면서 개발일정이 길어진다거나 작업이 어려운 경우 사용하지 않는 게 바람직하다. 일을 위한 일을 하지 않는 것이 제일 좋다고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 특정 클라이언트들은 swagger를 보고 자동으로 API 호출 코드를 생성하는 라이브러리를 사용하기도 한다. 따라서 꼭 필요하거나, 개발 생산성이 높아진다면 무조건 사용하는게 이득이라고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/602</guid>
      <comments>https://cholol.tistory.com/602#entry602comment</comments>
      <pubDate>Thu, 4 Apr 2024 22:00:53 +0900</pubDate>
    </item>
    <item>
      <title>KB증권, 인범 TV 시스템 오류 사태, 무엇이 문제였을까~? 개발자의 시선</title>
      <link>https://cholol.tistory.com/601</link>
      <description>&lt;div class=&quot;index_toc&quot;&gt;
&lt;p class=&quot;toc_title&quot; data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;서론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유튜브 알고리즘에 의해 어쩌다가 인범 TV 쇼츠가 떴는데, 내용이 KB증권 고소한다는 내용이었다. 무슨 내용인가 영상을 시청했는데, 3월 1일 23시 59분경에 해외선물 주문을 냈는데 '시스템 작업으로 인하여 업무가 잠시 중단되고 있습니다.' 에러가 발생한 것이다. 그 에러를 딱 봤을 때, &quot;와 개발자 X 됐다..&quot;라고 생각이 들었다. ㅋㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 문제는 23시 59분이 점검시간도 아니었고, 점검공지도 없었고, 거래가능시간이었다는 것이다. 거래가능 시간에 떡하니 오류가 나버리니, 이건 금감원에서 가만히 않있을것같은데..?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 오류가 왜 났는지 나름 증권사 개발자 출신으로서 상황을 파악해 본것을 정리해 본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;오류가 난 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 오류가 난 이유는 정확하지 않으나, 메시지를 보면 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;'시스템 작업으로 인하여 업무가 잠시 중단되고 있습니다.'라고 나오기 때문에, 시스템 작업에 의한 오류라고 확인할 수 있다. 사실 명확히 따지면 오류는 아니고 시스템 점검 중이니 아무것도 하지 말라는 &lt;b&gt;예외&lt;/b&gt;이다. 그럼 이 예외처리를 고객한테 알려야 하는 의무가 있는데 하지 않은 걸 보면, &lt;u&gt;해외선물 주문 서비스가 의도하지 않게 이 점검시간에 걸리게 된 것&lt;/u&gt;이라고 추측된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;923&quot; data-origin-height=&quot;565&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brX2Ng/btsFPbaoCe0/u3zmrBkb5OwwBjzgvR5XeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brX2Ng/btsFPbaoCe0/u3zmrBkb5OwwBjzgvR5XeK/img.png&quot; data-alt=&quot;????&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brX2Ng/btsFPbaoCe0/u3zmrBkb5OwwBjzgvR5XeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrX2Ng%2FbtsFPbaoCe0%2Fu3zmrBkb5OwwBjzgvR5XeK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;306&quot; data-origin-width=&quot;923&quot; data-origin-height=&quot;565&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;????&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 이 메시지가 어디서 온 것일까? 어떤 시스템 오류인 걸까?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 가장 처음 생각했던 오류는 HTS 클라이언트 문제이다. (즉 설치돼있는 HTS가 뭔가 오류로 인해 에러를 뱉었다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;가능성 1. HTS 클라이언트가 오작동&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터에 설치된 HTS클라이언트의 오류라고 생각한 이유는 3월 5일 인범 TV에 올라온 KB증권 차장과의 통화 내용 때문이다. 거기서 KB증권 차장은 아래와 같이 말했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1716&quot; data-origin-height=&quot;408&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dVKgIQ/btsFOgiFyba/lkUNdKHw7cByxafrc6FUtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dVKgIQ/btsFOgiFyba/lkUNdKHw7cByxafrc6FUtk/img.png&quot; data-alt=&quot;통화내용&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dVKgIQ/btsFOgiFyba/lkUNdKHw7cByxafrc6FUtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdVKgIQ%2FbtsFOgiFyba%2FlkUNdKHw7cByxafrc6FUtk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1716&quot; height=&quot;408&quot; data-origin-width=&quot;1716&quot; data-origin-height=&quot;408&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;통화내용&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 그 해당 주문 창에 있어서 그게 뭐라고 해야 할까요? 그.. &lt;u&gt;일자 확인을 하는 그런.. 프로세스, 절차&lt;/u&gt;가 있습니다. 물론 CME거래소는 영업일이 뭐라고 해야.. 거래일이 오전 6시 이런 식으로 미국을 따라가지 않습니까? 아무래도 &lt;u&gt;한국매체 같은 경우 한국시간&lt;/u&gt;을 따라가게 되거든요. 네 근데 아마 그 시간대 그 주문창이 &lt;u&gt;주문과는 상관없이 그런 일자를 이식하는 그런 전산작업&lt;/u&gt;이 뒤따르면서 돌았던 것 같아요...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;증권사 프로그램의 경우 각 프로그램 상에서 현재시간을 체크해서 장시간을 계산하는 로직이 담겨있다. 통화내용에서 '&lt;u&gt;일자 확인을 하는 그런.. 프로세스, 절차&lt;/u&gt;'가 바로 그것이다. 장시간이 거의 매일 동일한 시간이기는 하나, 휴장일도 있고 순연돼서 1시간 빨라지거나 1시간 느려지거나 하는 경우도 있기 때문에, HTS에서는 장시간을 정확히 알기 위해 서버에 장시간을 조회해서 내려받게 된다. 이 작업이 보통 한국 같은 경우 장시작 전 (새벽 5~6시)에 하게 되는데&lt;b&gt;&lt;u&gt; 이걸 00시 전에 하도록 프로그래밍되어있는 건가?라는&lt;/u&gt;&lt;/b&gt; 추측도 든다. 만약 이 작업이 실행되면 찰나의 순간(프로그램에 서버에서 받은 장시간을 업데이트하는 순간)에 장시간을 확인할 수 없어 주문이 나가지 않는 에러가 발생할 수 있기 때문이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 오류가 발생할 수 있는 이유도 통화내용에 나오는데, '한국매체의 경우 한국시간을 &lt;u&gt;따른다'라는&lt;/u&gt; 내용은 한국에서 HTS를 이용하면 PC시간도 한국이고 하다 보니 컴퓨터에 시간을 이용해 주문시간을 체크하는 경우도 있는데, 이때 뭔가 로직이 꼬여서 잠깐의 주문이 들어갈 수 없는 시간이 될 수 있다. 이렇게 장시간을 계산하는 작업을 통화에서는&amp;nbsp;'&lt;u&gt;주문과는 상관없이 그런 일자를 이식하는 그런 전산작업&lt;/u&gt;'이라고 표현한 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요약하면 &lt;b&gt;&quot;해외시장이지만 HTS가 한국시간으로 장시간을 인지하다 보니 주문가능한 시간을 계산하다가 버그로 인해 주문이 안 나갔다&quot;라는&lt;/b&gt; 의미다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 요약한다고 이게 충분히 발생가능한, 막지 못하는 타당한 오류라는 건 아니다. 이건 그냥 잘 못 만든 거다 ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 증권사 앱의 경우 시간계산을 PC나 스마트폰 시간을 쓰지 않고 서버에서 내려주는 시간을 사용하게 만들기 때문에 HTS자체적으로 시간을 잘 못 계산할 수는 없을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 뭔가 HTS의 문제로 에러가 발생했다고 생각했는데 인범 TV에 올라온 로그파일을 보니 생각이 또 바뀌게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;가능성 2. 주문은 서버까지 들어갔고, 서버에서 오류가 났다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인범 TV KB증권 답변 쇼츠를 보면 KB증권 측에서 제공한 로그가 있는데, TR로그라고 해서 증권사에서 많이 사용하는 익숙한 로그 형태이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;959&quot; data-origin-height=&quot;919&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rCvKa/btsFOhPqkfn/4fh8UqSXsaB8j38k4kKSS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rCvKa/btsFOhPqkfn/4fh8UqSXsaB8j38k4kKSS1/img.png&quot; data-alt=&quot;익숙한 증권사 로그&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rCvKa/btsFOhPqkfn/4fh8UqSXsaB8j38k4kKSS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrCvKa%2FbtsFOhPqkfn%2F4fh8UqSXsaB8j38k4kKSS1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;479&quot; data-origin-width=&quot;959&quot; data-origin-height=&quot;919&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;익숙한 증권사 로그&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 이렇게 로그파일을 보냈다는 건 &lt;b&gt;3월 5일 통화내용 중 매체에서 시간을 잘못 계산했다는 내용은 구라라는 것&lt;/b&gt;이 된다. 매체에서 주문시간을 잘 못 계산했다면 아예 서버로 주문을 보내지 않았기 때문에 로그가 남으면 안 된다. 시스템에 대해 잘 알지 못하면 로그를 보낸다고 해서 예전에 했던 얘기가 거짓말이라고 판단할 수 없으니 그냥 로그를 보내준 것 같다 ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그를 보면 '로그일시', 'TR서비스명', 'IO' 3가지로 분류된다. IO라는 건 Input/Output이라고 해서 HTS에서 서버로 전송한 데이터(Input)와 서버에서 HTS로 전송한 데이터(Output)이다. 데이터를 가린 건 저기에 계좌번호나 id 같은 개인정보, 매매가 등 개인정보들이 담겨있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 봐야 하는 건 IO인데, &quot;시스템 작업으로 인하여 업무가 잠시 중단..&quot;이 있는 거 보면 서버에서 HTS로 에러메시지를 보내주고 HTS는 그냥 팝업만 띄웠다는 것이다. 즉 HTS가 시간 계산 잘못한 게 아니라 서버에서 애초에 해당 시간에 주문을 처리 못하고 있다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요약하면, HTS에서는 정상적으로 주문을 냈고, 받아주는 서버에서 처리하지 못하고 에러가 발생한 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;흔적이 있다 없다~? 밝혀지는 의문점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;KB증권과 인범 TV 통화내용을 보면 몇 가지 의문점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 인범 TV가 사고 발생 직후 KB증권에 전화했을 때는 &quot;스탑주문을 내신 흔적이 없다&quot;라고 말했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;574&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GWM5f/btsFRb0YEex/Ued8XHn3TJFxHQ7roQeldk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GWM5f/btsFRb0YEex/Ued8XHn3TJFxHQ7roQeldk/img.png&quot; data-alt=&quot;흔적이 없어서..&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GWM5f/btsFRb0YEex/Ued8XHn3TJFxHQ7roQeldk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGWM5f%2FbtsFRb0YEex%2FUed8XHn3TJFxHQ7roQeldk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;235&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;574&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;흔적이 없어서..&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그가 남아있다고 했는데 흔적이 없다는 건 무슨 말일까~? 이건 KB증권과 통화내용 중 더 자세한 내용을 들을 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;529&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQNeox/btsFRBFbzLL/oRi7Spe8ar0A89YA8rzH4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQNeox/btsFRBFbzLL/oRi7Spe8ar0A89YA8rzH4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQNeox/btsFRBFbzLL/oRi7Spe8ar0A89YA8rzH4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQNeox%2FbtsFRBFbzLL%2FoRi7Spe8ar0A89YA8rzH4K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;220&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;529&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;972&quot; data-origin-height=&quot;937&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckMAXX/btsFPHmysDr/39Qp93mS2kNEBGBPyeYUVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckMAXX/btsFPHmysDr/39Qp93mS2kNEBGBPyeYUVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckMAXX/btsFPHmysDr/39Qp93mS2kNEBGBPyeYUVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckMAXX%2FbtsFPHmysDr%2F39Qp93mS2kNEBGBPyeYUVk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;386&quot; data-origin-width=&quot;972&quot; data-origin-height=&quot;937&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;통화내용을 보면 로그가 별도로 2가지 존재하고, 프론트 데스크 직원이 볼 수 있는 로그와 볼 수 없는 로그라고 말한다. 아마도 프론트 데스크 직원이 볼 수 있는 로그는 '&lt;b&gt;주문을 처리한 로그&lt;/b&gt;' 일 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 로그파일을 보면 응답으로 &quot;시스템 작업으로 인하여 업무가 잠시 중단..&quot;이라는 에러가 나갔다. 즉 주문 처리를 하다가 중간에 멈추고 에러를 발생했다는 소리다. 이 경우 주문은 성공도 취소도 아닌 에러상태이기 때문에 '&lt;u&gt;&lt;b&gt;주문을 처리한 로그&lt;/b&gt;&lt;/u&gt;'에는 남지 않는다. 그래서 고객센터나 프론트 데스크 직원들은 아무리 검색해도 주문을 한 흔적이 보이지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 다른 로그는 무엇인가? 바로 '&lt;b&gt;전체 로그&lt;/b&gt;'다. 전체 로그는 성공이든 실패든 에러든 모든 걸 남긴다. 보통 개발자들이 많이 보는데 네트워크 에러나 데이터 에러로 인해 발생하는 것들은 굳이 업무용 화면에 노출할 필요가 없으니 생략하게 된다. 이번 경우도 굳이 에러가 난 로그까지 '주문 처리 로그'에 담지 않았기 때문에 고객센터나 프론트 데스크에서 확인하는 업무용 프로그램에서는 조회가 안 됐던 것 같다. 따라서 담당자한테 전화 걸어도 '주문 없는데요~?'라는 반응이 오게 된 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;근데 왜 이런 에러가 났을까? 이번에만 발생한 걸까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생각해 보면 이상한 게, 23시 59분부터 1분간 점검시간이 원래 있었다면, 더 많은 사람들이 피해를 보지 않았을까?라는 의문점이다. 여기에는 몇 가지 추측이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;추측 1. 오픈한 지 별로 안돼서&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색해 보면 해외선물 서버 조건 등록(해외선물 클릭주문) 서비스는 24년 1월에 오픈했다. 따라서 오픈한 지 약 2개월밖에 안됬기 때문에 원래도 해당 시간 점검이 있었는데, 어쩌다가 인범 tv에 걸려서 이슈가 된 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;추측 2. 다른 기능 적용하다가 오류가 나서&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성능개선이나 다른 추가기능을 적용하기 위해서 해당 서비스를 수정하다가, 모르고 다른 서비스 점검시간을 체크하는 코드를 사용해서 일시적으로 오류가 발생한 것이다. 1~2월에는 잘 되다가 3월에 뭔가 개선하려고 업데이트했는데, 하필이면 버그가 있는 코드를 추가해 가지고 잠깐만 에러가 발생한 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;추측 3. 장시간 운영 실수해서&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 사건이 일어난 일이 3월 1일 (휴일)이라는 점을 생각했을 때, 한국은 휴장일이지만 미장은 휴장일이 아닌데 운영하는 사람이 장 운영시간 세팅을 잘못해서 발생한 해프닝일 수 있다. 실제로 증권사는 장운영 시간을 수동으로 관리하는데, 매년 선거일이나 수능일과 같은 장시간 변동을 입력해 놓고 해당 스케줄로 시스템이 운영된다. 3월 1일이 한국만 휴장일인걸 고려했을 때 충분히 실수가 발생할 수 있는 날이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실수든, 기술적 오류든, 원래 시스템이 그랬던 것이든 증권이 사용자에게 불편함을 준 것은 변함없다. 이제 적절하게 대응하는 것만 남아있는데, 소비자 입장에서 가장 깔끔해 보이는 건 증권사 측에서 해당 서비스 오픈 후 해당 에러가 발생한 건들을 모두 모아서 보상하는 게 가장 좋아 보이기는 한다. 증권사 입장에서는 굳이 민원 들어온 것도 아닌 것들에 대해 먼저 보상해 준다는 게 손해를 보는 것이긴 하나, 기업 이미지가 안 좋아 보이는 것보다는 좋지 않을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;KB증권 담당자분이 통화하는 것을 보니, 증권사에 있을 때 일하던 기억이 새록새록 나서 좀 안쓰럽다. 해당 기능 개발한 개발자들도 ㅎㄷㄷ 하고 있을 것을 생각하니,, 금융권 개발자는 역시 힘든 것 같다.&lt;/p&gt;</description>
      <category>Blog/잡다</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/601</guid>
      <comments>https://cholol.tistory.com/601#entry601comment</comments>
      <pubDate>Sat, 16 Mar 2024 14:16:37 +0900</pubDate>
    </item>
    <item>
      <title>AWS Route 53 외부 도메인 연결하기, Squarespace 도메인 연결</title>
      <link>https://cholol.tistory.com/600</link>
      <description>&lt;div class=&quot;index_toc&quot;&gt;
&lt;p class=&quot;toc_title&quot; data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt; &amp;zwj;  외부도메인 AWS 연결&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;평소에는 route 53에서 도메인을 구매하고 사용했었는데, 이미 구매한 외부 도메인을 aws에 연결해야 하는 일이 생겼다. route 53에서 사면 aws console에서 뚝딱뚝딱 설정하면 되는데, 외부 도메인을 사용해야하니 어쩔수 없이 뭔가 따로 설정을 해줘야 하는 상황이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;기존 route 53을 할 때도 sub domain생성하거나 하면 lb나 ec2와 연결시켜주는 일을 하나하나 해줬어야 하는데, 외부 도메인을 연결할 때는 어떻게 해야하는지 정리할 겸 블로그에 남겨둔다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;연결할 외부 도메인은 squarespace라는 도메인 서비스를 제공하는 곳이다. 검색해보니 2023년만 해도 google domain이었는데, 팔린것 같다. 그래서 구글 로그인해서 도메인을 살 수 있나보다 ㅎㅎ&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt; route 53 설정&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;외부 도메인이 이미 만들어진 상태라면 특정 도메인에 대한 소유권을 가지고 있을 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-13 오후 12.48.41.png&quot; data-origin-width=&quot;2032&quot; data-origin-height=&quot;990&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZ1i9b/btsFK9PReU4/xsh7aiMUKy6yfgOw4kn8tk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZ1i9b/btsFK9PReU4/xsh7aiMUKy6yfgOw4kn8tk/img.png&quot; data-alt=&quot;squarespace에 등록한 도메인 정보&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZ1i9b/btsFK9PReU4/xsh7aiMUKy6yfgOw4kn8tk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZ1i9b%2FbtsFK9PReU4%2Fxsh7aiMUKy6yfgOw4kn8tk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2032&quot; height=&quot;990&quot; data-filename=&quot;스크린샷 2024-03-13 오후 12.48.41.png&quot; data-origin-width=&quot;2032&quot; data-origin-height=&quot;990&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;squarespace에 등록한 도메인 정보&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 해당 도메인 주소로 route53에 등록한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1648&quot; data-origin-height=&quot;1236&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BmF9d/btsFKQJMQmn/d9nIEp5IdroJaKriQBwOQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BmF9d/btsFKQJMQmn/d9nIEp5IdroJaKriQBwOQk/img.png&quot; data-alt=&quot;호스팅 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BmF9d/btsFKQJMQmn/d9nIEp5IdroJaKriQBwOQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBmF9d%2FbtsFKQJMQmn%2Fd9nIEp5IdroJaKriQBwOQk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1648&quot; height=&quot;1236&quot; data-origin-width=&quot;1648&quot; data-origin-height=&quot;1236&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;호스팅 생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;읭? 밑도끝도 없이 생성해? 라고 생각할 수 있는데 그냥 일단 생성한다 ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성하고 나면 레코드가 2개가 생기는데 이걸 외부 도메인 서비스에 등록하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-13 오후 12.54.12.png&quot; data-origin-width=&quot;2228&quot; data-origin-height=&quot;392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0BhBG/btsFI5A9mK6/FcBGCZ6E3nSIrYDNFPk2YK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0BhBG/btsFI5A9mK6/FcBGCZ6E3nSIrYDNFPk2YK/img.png&quot; data-alt=&quot;생성된 레코드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0BhBG/btsFI5A9mK6/FcBGCZ6E3nSIrYDNFPk2YK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0BhBG%2FbtsFI5A9mK6%2FFcBGCZ6E3nSIrYDNFPk2YK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2228&quot; height=&quot;392&quot; data-filename=&quot;스크린샷 2024-03-13 오후 12.54.12.png&quot; data-origin-width=&quot;2228&quot; data-origin-height=&quot;392&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;생성된 레코드&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;등록해야하는 값은 값/트래픽 라우팅 대상에 적혀있는 값들이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외부 도메인 서비스로 가면 네임서버 세팅 (Nameservers Settings)라는 메뉴가 있을 텐데, 여기 들어가면 위 값을 입력할 수 있는 창이 뜬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-13 오후 12.56.13.png&quot; data-origin-width=&quot;764&quot; data-origin-height=&quot;1118&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEt0Ui/btsFLu7kh1a/y3slZdUZDCpL4z3jx6de70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEt0Ui/btsFLu7kh1a/y3slZdUZDCpL4z3jx6de70/img.png&quot; data-alt=&quot;하나씩 입력한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEt0Ui/btsFLu7kh1a/y3slZdUZDCpL4z3jx6de70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEt0Ui%2FbtsFLu7kh1a%2Fy3slZdUZDCpL4z3jx6de70%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;585&quot; data-filename=&quot;스크린샷 2024-03-13 오후 12.56.13.png&quot; data-origin-width=&quot;764&quot; data-origin-height=&quot;1118&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;하나씩 입력한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Route 53에는 맨 뒤에 .이 있는데, 실제로 입력할 때는 .을 빼고 입력해주어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에는 Use Squarespace nameservers로 세팅되어 있는데, custom nameserver를 눌러줘야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것만 등록하면 이제 추가적인 sub domain은 route53에서 생성 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 외부도메인 서버와 연동에서 딜레이가 좀 있어서.. AWS 쓸거면 가급적이면 AWS도메인을 쓰는게 속 편할 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Study/서버</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/600</guid>
      <comments>https://cholol.tistory.com/600#entry600comment</comments>
      <pubDate>Wed, 13 Mar 2024 13:29:56 +0900</pubDate>
    </item>
    <item>
      <title>사용자가 늘어나면서 서비스 구조는 어떻게 바뀌게 되는가? / 대규모 트래픽을 받기위해 서버를 어떻게 구성해야하는가? / feat. 가상 면접 사례로 배우는 대규모 시스템 설계 기초</title>
      <link>https://cholol.tistory.com/599</link>
      <description>&lt;div class=&quot;index_toc&quot;&gt;
&lt;p class=&quot;toc_title&quot; data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;들어가기 전에&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;23년에 회사에서 다양한 IT책으로 스터디를 진행했다. 스터디한 책중에는 &quot;가상 면접 사례로 배우는 대규모 시스템 설계 기초&quot;라는 책이 있었다. 이 책에선 면접에 나올만한 주제로 다양한 IT 지식을 논의하는데, 그중 1장 &quot;사용자 수에 따른 규모 확장성&quot; 내용이 아주 재밌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재밌다고 생각한 이유는 단일 서버에서 사용자가 늘어남에 따라 서버 구조를 어떻게 바꿔야 하는지, 바꾸면서 해결할 수 있는 문제는 무엇인지 단계적으로 설명해 준다. 결론적으로는 대규모 트래픽을 받을 수 있는 서비스 구조를 만들게 되는데, 아마 큰 회사에서 사용하는 서비스 구조가 아닐까 생각된다. (일단 우리 회사랑은 비슷함 ㅇㅇ)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 채용페이지를 보면 개발자 지원자격에 항상 이런 말이 적혀있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;대규모 트래픽을 경험 또는 운영해본 개발자&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경력이 없는 개발자들은 도대채 어디서 대규모 트래픽을 경험한단 말인가?! 참 아이러니한 문구라고 생각된다. 그렇다고 면접에서 이렇게 말할 수는 없으니 우리는 간접경험이라도 해야 한다. 그 간접경험을 가장 기가 막히게 해 주는 게 이 책이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;서비스의 진화과정&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 단일 서버&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 이제 우리가 서비스를 하나 런칭한 스타트업이라고 생각해 보자. 아니 스타트업도 좀 커 보이니까 주변 지인들과 사이드프로젝트로 작은 서비스를 런칭했다. 프론트와 서버가 하나씩 존재하는 아주 간단한 서비스다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;940&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/O3avc/btsDbcVqRib/WYyaQTLX0MEjwEEsoalFa0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/O3avc/btsDbcVqRib/WYyaQTLX0MEjwEEsoalFa0/img.png&quot; data-alt=&quot;1단계 단일 서버 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/O3avc/btsDbcVqRib/WYyaQTLX0MEjwEEsoalFa0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FO3avc%2FbtsDbcVqRib%2FWYyaQTLX0MEjwEEsoalFa0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;533&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;940&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;1단계 단일 서버 구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앱으로만 서비스한다면 AWS EC2의 public IP만으로 서비스가 가능하다. 하지만 웹 서비스도 사용한다면 도메인 서비스가 필요할 수 있다. AWS에서는 도메인 서비스를 위한 Route 53도 제공하니 이것도 추가해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;902&quot; data-origin-height=&quot;926&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCw8Oo/btsC6TihDpA/0RfMkSzRIivTvSv8IxULy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCw8Oo/btsC6TihDpA/0RfMkSzRIivTvSv8IxULy0/img.png&quot; data-alt=&quot;1단계 단일 서버 구조 (+ DNS를 위한 Route 53 추가 )&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCw8Oo/btsC6TihDpA/0RfMkSzRIivTvSv8IxULy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCw8Oo%2FbtsC6TihDpA%2F0RfMkSzRIivTvSv8IxULy0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;513&quot; data-origin-width=&quot;902&quot; data-origin-height=&quot;926&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;1단계 단일 서버 구조 (+ DNS를 위한 Route 53 추가 )&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 클라이언트에서 www.example.com과 같은 도메인을 입력해도 route53이 해당 도메인의 경로를 찾아 올바른 서버 주소를 알려준다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 데이터베이스 추가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 정보를 보여주는 서비스의 경우 데이터를 저장할 필요가 없지만, 사용자가 이전에 한 행위나 사용자의 정보, 서비스의 정보 등을 저장하기 위해서는 데이터저장소가 필요하다. 작은 서비스의 경우 로컬  저장소를 이용해 구현할 수 있겠지만, 이것도 사용자가 많아지면 부족하게 된다. 이때 필요한 것이 바로 데이터베이스이다. AWS에서 제공하는 RDS를 이용해 데이터베이스를 연결한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1266&quot; data-origin-height=&quot;932&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biTrTu/btsC89rmaSu/BkjbwoSygTMtdN6ZgDlaZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biTrTu/btsC89rmaSu/BkjbwoSygTMtdN6ZgDlaZK/img.png&quot; data-alt=&quot;2단계 데이터베이스 추가&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biTrTu/btsC89rmaSu/BkjbwoSygTMtdN6ZgDlaZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiTrTu%2FbtsC89rmaSu%2FBkjbwoSygTMtdN6ZgDlaZK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;442&quot; data-origin-width=&quot;1266&quot; data-origin-height=&quot;932&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;2단계 데이터베이스 추가&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 서비스에 필요한 데이터를 데이터베이스에 저장할 수 있다. 기존에 클라이언트에서 API를 요청하면 EC2에서 데이터를 처리해서 응답을 내려주었지만, 이제 특정 데이터가 필요하면 데이터베이스(RDS)를 조회해 필요한 데이터를 찾아 응답하게 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스는 다양한 종류가 있다. 우리가 많이 알고 있고 사용하고 있는 RDBMS의 mysql, oracle 등이 있고, 비관계형 데이터베이스인 NoSql의 mongo, dynamoDB 등이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 데이터베이스를 사용하는지는 데이터의 성격에 따라 다르다. 데이터가 비정형인지, 응답속도가 빨라야 하는지, 데이터의 양이 큰지 등을 고려하여 알맞은 데이터베이스를 선택하면 된다. 일반적인 서비스에서는 관계형 데이터베이스를 선택하는 것이 무난하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 스케일 아웃&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 늘어나서 API요청이 늘어나면 EC2의 성능을 올려 동시처리량을 증가시킬 수 있다. 이렇게 단일 서버의 성능을 올리는 방식을 스케일-업(scale-up)이라고 표현한다. 하지만 CPU나 메모리 등을 무한정으로 올릴 수는 없다. 이럴 경우 병렬로 서버를 늘려 API요청을 분산처리하는 방법이 있다. 이를 스케일-아웃(scale-out)이라고 표현한다. EC2앞에 로드밸런서(Load Balancer)를 추가하여 스케일 아웃을 적용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;1022&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qVJd4/btsC7sksB5W/0yD2k6GTclvgIOGRieNoyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qVJd4/btsC7sksB5W/0yD2k6GTclvgIOGRieNoyk/img.png&quot; data-alt=&quot;3단계 로드밸런서 추가&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qVJd4/btsC7sksB5W/0yD2k6GTclvgIOGRieNoyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqVJd4%2FbtsC7sksB5W%2F0yD2k6GTclvgIOGRieNoyk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;512&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;1022&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;3단계 로드밸런서 추가&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS에서 제공하는 로드밸런서를 EC2 앞에 추가한다. 로드밸런서는 들어온 요청을 로드밸런서에 등록된 EC2에 고르게 분배한다. 기존에 하나의 EC2에서 서비스하는 것보다 EC2의 개수만큼 처리할 수 있는 양이 늘어나게 된다. AWS에서는 Auto Scale기능도 지원하기 때문에 특정지표(클라 요청수나 EC2의 CPU사용률 등)를 기준으로 EC2를 자동으로 늘리거나 줄일 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 사용자의 요청이 늘어나면 EC2를 늘려서 대응할 수 있게 되었다. 하지만 데이터베이스는 아직도 하나다!! 요청이 몰리면 데이터베이스가 느려질 수 있다. 대부분의 데이터베이스 시스템은 다중화를 제공한다. AWS에서는 Read Replica를 제공해 주는데, 같은 데이터베이스를 1개의 Master DB와 여러 개의 Slave DB로 나눌 수 있다. Slave DB는 Read만 가능하며 Write 쿼리는 모두 Master DB로 보내야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1232&quot; data-origin-height=&quot;1068&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3NT4Z/btsC9aKA0d2/efJ1DiU1sGyLsfUSh7MNJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3NT4Z/btsC9aKA0d2/efJ1DiU1sGyLsfUSh7MNJK/img.png&quot; data-alt=&quot;3단계 데이터베이스 다중화&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3NT4Z/btsC9aKA0d2/efJ1DiU1sGyLsfUSh7MNJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3NT4Z%2FbtsC9aKA0d2%2FefJ1DiU1sGyLsfUSh7MNJK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;520&quot; data-origin-width=&quot;1232&quot; data-origin-height=&quot;1068&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;3단계 데이터베이스 다중화&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 마스터 DB에서도 데이터조회가 가능하다. 마스터 DB에 쓰기 작업을 하게 되면 해당 작업은 read replica들에게 전달되며 자동으로 동기화된다. 따라서 데이터가 전달되는 시간 동안 약간의 데이터 정합성이 깨지는 경우(replica lag)가 발생하는데, AWS에서는 이 시간은 일반적으로 0.1초 이내라고 얘기하고 있다. 시간에 매우 민감한 데이터가 아니라면 0.1초는 무의미하기 때문에 read replica를 사용하면 되지만, 시간에 민감한 데이터라면 조회 역시 master DB에서 조회하면 delay를 줄일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 캐시정책 적용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스를 좀 더 효율적으로 사용하기 위해서는 데이터베이스 앞에 캐시(Cache)를 두는 것을 고려할 수 있다. 데이터베이스는 기본적으로 Disk기반이라 읽고 쓰는 연산이 메모리에 비해 느리다. 데이터베이스 앞에 메모리 기반 캐시를 두게 되면 시스템 성능을 향상할 수 있다. AWS에서는 ElasticCache라는 서비스로 캐시서비스를 제공하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1050&quot; data-origin-height=&quot;1140&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nrUZg/btsC4Fx6FMw/roK30JZzGnLOtTkUKc8DUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nrUZg/btsC4Fx6FMw/roK30JZzGnLOtTkUKc8DUK/img.png&quot; data-alt=&quot;4단계 레디스 캐시 등록&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nrUZg/btsC4Fx6FMw/roK30JZzGnLOtTkUKc8DUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnrUZg%2FbtsC4Fx6FMw%2FroK30JZzGnLOtTkUKc8DUK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;760&quot; data-origin-width=&quot;1050&quot; data-origin-height=&quot;1140&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;4단계 레디스 캐시 등록&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EC2는 사용자의 요청을 바로 RDS에서 조회하지 않고 캐시를 먼저 확인한다. 만약 원하는 데이터가 캐시에 있다면(cache hit) 클라이언트에 바로 데이터를 내려준다. 만약 찾는 데이터가 없다면 데이터베이스에서 조회하고 캐시에 해당 데이터를 업데이트한다. 이렇게 되면 다음에 같은 데이터를 조회할 때 캐시를 사용할 수 있게 되므로 데이터베이스의 부하를 줄일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐시를 사용할 때는 데이터의 성격을 잘 알아야 한다. 데이터가 매우 빠르게 변한다면 캐시 사용은 무용지물일 수 있다.(오히려 독일수도 있다.) 데이터가 빠르게 변한다면 캐싱된 데이터와 데이터베이스의 데이터가 틀어질 수 있기 때문이다. 따라서 데이터의 변화 주기를 고려해 캐시 할 데이터를 정해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. CDN 적용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정적인 데이터를 캐싱하기 위해서는 CDN서비스를 사용할 수 있다. (동적인 데이터 캐싱도 지원하긴 한다!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글로벌 서비스는 유튜브를 생각해 보면, 하나의 동영상이 한국에서도 재생되고 미국에서도 재생되고 유럽에서도 재생된다. 이렇게 물리적으로 떨어진 곳에 데이터를 빠르게 전달하기 위해서는 어떻게 해야 할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1030&quot; data-origin-height=&quot;1140&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2A7l6/btsC8SXvnZ0/OUJVqFDU4diWcER3t7AZG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2A7l6/btsC8SXvnZ0/OUJVqFDU4diWcER3t7AZG1/img.png&quot; data-alt=&quot;5단계 CDN 적용&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2A7l6/btsC8SXvnZ0/OUJVqFDU4diWcER3t7AZG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2A7l6%2FbtsC8SXvnZ0%2FOUJVqFDU4diWcER3t7AZG1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1030&quot; height=&quot;1140&quot; data-origin-width=&quot;1030&quot; data-origin-height=&quot;1140&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;5단계 CDN 적용&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS에서는 CloudFront라는 서비스를 통해 CDN서비스를 제공하고 있다. CloudFront를 클라이언트와 서버 사이에 두면 클라이언트에서 동영상이나 이미지를 조회할 때 CDN(CloudFront)를 먼저 조회한다. 만약 CDN에 데이터가 없다면 원본 저장소에서 데이터를 가져온다. CDN 사업자들은 CDN서버를 전국 곳곳에 관리하고 있기 때문에 사용자에게 최대한 가까운 CDN서버에서 응답이 내려가도록 보장하고 있다. 유튜브가 하나의 동영상을 끊김 없이 글로벌하게 제공할 수 있는 이유 중 하나이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. 데이터센터 다중화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 물리적인 관점으로 다가가보자. 서버들이 모여있는 데이터센터에 불이 나면 어떻게 될까? 아마 모든 서버들이 작동을 중단하게 되고, 서비스가 중단될 것이다. 이를 위해 우리 서버들을 2개 이상의 데이터 센터에 분배할 필요가 있다. 다행히도, AWS를 사용하면 AvailableZone을 이용해 물리적 이중화를 구현할 수 있다. AWS에서 제공하는 각각의 서비스에 옵션으로 AZ(AvailbleZone)을 선택하면 되는데, 요즘에는 AZ를 2개 이상 선택해야 하는 게 디폴트라 아마 대부분 2개 이상으로 설정되어 있을 것이다. AWS 서울리전에는 a~d까지 총 4개의 AvailableZone을 운영하고 있기 때문에 원하는 AZ를 선택하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AZ 다중화로도 만족하지 못하는 경우 Cloud 다중화를 고려할 수 있다. 실제로 카카오에서 일할 때 AWS 전체 서비스가 무너지면 어떻게 하나?라는 고민을 했었다.(너무 오버하는 것 같기도 하지만..) 실제로 한국에서 AWS장애로 여러 서비스가 먹통이 되는 사건이 간간히 발생했다. 장애가 긴 시간 지속된 것은 아니었지만, 무중단 서비스를 위해서는 Cloud 자체 다중화를 고려해야 할 수도 있다. AWS에 구축한 서비스를 고대로 구글 클라우드나 네이버 클라우드에 구축하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1832&quot; data-origin-height=&quot;1156&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b32Yrd/btsC5YRKTCr/FvYpQk2joFoyPQvRvOvzf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b32Yrd/btsC5YRKTCr/FvYpQk2joFoyPQvRvOvzf1/img.png&quot; data-alt=&quot;6단계 클라우드 서비스 다중화&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b32Yrd/btsC5YRKTCr/FvYpQk2joFoyPQvRvOvzf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb32Yrd%2FbtsC5YRKTCr%2FFvYpQk2joFoyPQvRvOvzf1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1832&quot; height=&quot;1156&quot; data-origin-width=&quot;1832&quot; data-origin-height=&quot;1156&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;6단계 클라우드 서비스 다중화&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 그냥 똑같이 복사 붙여 넣기 한다고 되는 것이 아니다. DB의 경우 각 클라우드에 저장되는 데이터가 다르기 때문에 어디든 메인으로 사용할 데이터베이스가 있어야 한다. 메인이 아닌 데이터베이스가 있는 클라우드의 경우 CDC와 같은 솔루션을 통해 데이터베이스를 지속적으로 동기화하다가, 메인 데이터베이스가 있는 클라우드가 서비스 중지될 경우 메인으로 승격하여 사용될 수 있도록 되어야 한다. 그 밖에도 양쪽 클라우드를 어떤 클라이언트가 어떤 조건일 때 호출해야 하는지도 결정해야 하고, 그 결정은 어떤 클라우드(혹은 on-premise) 서버에서 할지도 결정해야 하기 대문에 상당~~히 복잡한 구조가 만들어진다. 일반적인 회사에서 클라우드까지 다중화하는 경우는 거의 없을 것 같다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;7. 데이터베이스 샤딩&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Read Replica와 Cache를 이용해 데이터베이스의 부하를 줄이기는 했지만, 쓰기 작업에 대해서는 DB 부하가 높을 수 있다. 이를 해결하기 위해 데이터베이스 샤딩을 하게 되는데, 데이터를 특정 키를 기준으로 나누어 저장하는 것이다. 이전 회사에서는 회원의 계좌정보를 홀짝으로 구분해, 홀수 계좌번호는 데이터베이스 1번, 짝수 계좌번호는 데이터베이스 2번을 사용했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1176&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tiBbU/btsC6xTUaAN/aavSDlIKoWOoAGEt3i8Mz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tiBbU/btsC6xTUaAN/aavSDlIKoWOoAGEt3i8Mz0/img.png&quot; data-alt=&quot;7단계 데이터베이스 샤딩&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tiBbU/btsC6xTUaAN/aavSDlIKoWOoAGEt3i8Mz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtiBbU%2FbtsC6xTUaAN%2FaavSDlIKoWOoAGEt3i8Mz0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;784&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1176&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;7단계 데이터베이스 샤딩&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;홀수/짝수로 나뉘게 되면 2개의 마스터 DB가 생기게 되기 때문에 쓰기 작업을 2등분 할 수 있다. 더 분할하고 싶다면 샤닝수를 늘리면 된다. 샤딩을 하게 되면 데이터가 분할되어 저장되기 때문에 동시에 여러 개의 데이터를 조회해야 하는 비즈니스에는 부적합할 수 있다. 이런 비즈니스가 있다면 샤딩된 데이터를 한 번에 저장하는 데이터마트를 구성하거나, 분산된 데이터를 한 번에 조회할 수 있는 서비스를 만들어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;8. 메시지 큐 활용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스가 커지고 복잡해지면서 서버 간 의존성이 높아지고, 작업을 처리하는 시간이 많아지는 이슈가 생길 수 있다. 이때 적용할 수 있는 솔루션으로는 메시지 큐가 있다. 메시지큐를 사용하면 서비스, 서버 간 관계가 느슨해지면서 확장에 용이한 서비스 구조가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;918&quot; data-origin-height=&quot;1162&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/doKTEn/btsC4f7ujxA/TZG62NIfIOxgkwKsYNgZ91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/doKTEn/btsC4f7ujxA/TZG62NIfIOxgkwKsYNgZ91/img.png&quot; data-alt=&quot;8단계 메시지 큐 적용&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/doKTEn/btsC4f7ujxA/TZG62NIfIOxgkwKsYNgZ91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdoKTEn%2FbtsC4f7ujxA%2FTZG62NIfIOxgkwKsYNgZ91%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;886&quot; data-origin-width=&quot;918&quot; data-origin-height=&quot;1162&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;8단계 메시지 큐 적용&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기적으로 처리해야 하는 비즈니스인 경우 서버에서 메시지 큐를 발행하여 비동기 요청을 보내고, 서버는 다른 일을 할 수 있다. 따라서 동시에 처리할 수 있는 처리량이 늘어나게 된다. 보통 사용자에게 Push를 보내거나 백그라운드로 동작해도 되는 비즈니스의 경우가 이에 해당된다. 동시에 여러 서버에 데이터를 보내야 할 때도 메시지 큐의 Pub/Sub 구조를 이용해 데이터를 전달할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;9. 서비스 모니터링&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구조가 복잡해지고 커질수록 모니터링 기능이 필수가 된다. 어떤 서버에 어떤 문제가 발생하는지 실시간으로 확인하는 것은 중요하다. AWS에서는 기본적으로 CloudWatch를 통해 각 서버들의 상태를 파악할 수 있게 되어있다. 어플리케이션 서버 레벨에서의 상태를 확인하기 위해 별도의 3rd party 모니터링 툴을 도입할 수 있다. 메시지큐를 이용해 각 서버에서 발생하는 로그를 수집해 grafana나 datadog 같은 모니터링 툴로 전송하여 대시보드 형태로 볼 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;898&quot; data-origin-height=&quot;1166&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cV2II5/btsC6yrKna1/jcOaSyWkdu1eAofbbD1x0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cV2II5/btsC6yrKna1/jcOaSyWkdu1eAofbbD1x0K/img.png&quot; data-alt=&quot;9단계 모니터링 추가&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cV2II5/btsC6yrKna1/jcOaSyWkdu1eAofbbD1x0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcV2II5%2FbtsC6yrKna1%2FjcOaSyWkdu1eAofbbD1x0K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;898&quot; height=&quot;1166&quot; data-origin-width=&quot;898&quot; data-origin-height=&quot;1166&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;9단계 모니터링 추가&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모니터링 지표를 통해 서버 상태를 확인할 수 있을 뿐만 아니라, 지표를 이용해 자동으로 서버를 늘리고 줄이는 자동화(auto scailing)를 할 수 있다. ReadReplica의 CPU가 증가하는 경우 ReadReplica DB의 수를 늘릴 수 있고, EC2의 CPU가 올라간다면 EC2를 여러 대 더 생성할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;끝없는 구조 개선&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단일 서버에서 시작한 서비스 구조가 큰 규모의 트래픽을 받을 수 있는 대규모 서비스로 진화했다. 더 많은 트래픽을 받기 위해서는 꾸준한 관리가 필요하다. 각각의 서비스를 쪼개서 단일 서버로 만드는 과정(MSA), 빈번히 조회되는 데이터 캐싱, 쓰기 작업이 많은 데이터 샤딩, 무거운 작업 비동기처리 등 지속적인 개선을 통해 서비스 구조는 계속 커질 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 대부분의 IT서비스 기업들은 위와 비슷한 구조로 서비스를 운영하고 있을 것이다. 아직 취업하지 않았거나 작은 회사에서 일하고 있다면 이 글로 조금이나마 서비스 구조에 대해 이해했으면 좋겠다. 앞서 설명한 것처럼 이 내용은 책 &quot;가상 면접 사례로 배우는 대규모 시스템 설계 실습&quot; 1장에 소개되어 있다. 이 책에는 이 내용 말고도 많은 실전 내용이 담겨 있기 때문에 면접을 보기 전이나 IT관련 지식을 공부할 때 한 번쯤 읽어볼 만한 책인 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 글을 쓰는 시점에는 책 2편이 나왔다.!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Study/IT 실전 지식</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/599</guid>
      <comments>https://cholol.tistory.com/599#entry599comment</comments>
      <pubDate>Sun, 7 Jan 2024 18:02:22 +0900</pubDate>
    </item>
    <item>
      <title>기획하는 개발자, 개발공부하는 기획자</title>
      <link>https://cholol.tistory.com/598</link>
      <description>&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;div class=&quot;index_toc&quot;&gt;
&lt;p class=&quot;toc_title&quot; data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; &amp;zwj; 개발자가 바라보는 기획, 기획자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 첫 번째 회사(지금 이름은 &lt;b&gt;한화 시스템&lt;/b&gt;)는 대기업 IT계열사이다. 대기업 계열사에서 IT를 담당하고 있는 회사들은 다른 계열사에 IT 시스템을 유지보수하는 업무를 주로 하게 된다. 나는 '&lt;b&gt;한화투자증권&lt;/b&gt;'에 증권 서비스를 담당했었다. (이게 내 금융 IT 커리어의 시작..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 대기업 IT 계열사들의 특징은 하청느낌으로 일을 한다는 것이다. 다른 계열사들이 '갑'이 되고 개발을 진행하는 계열사는 '을'이 된다. 나의 경우 한화투자증권 직원들이 '갑'이었고, 한화 시스템에서 한화투자증권 관련 서비스를 유지보수하는 팀이 '을'인 것이다. 따라서 대부분의 업무는 '갑'쪽의 기획 인력들이 요구사항을 전달하면, 그것을 만들어주거나, 서비스가 이상 없이 동작하는 것을 모니터링 및 유지보수하는 방식으로 진행된다. 이때는 기획자가 개발 지식이 필요하다고 느끼지 못했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 두 번째 회사는 작은 스타트업이다. 10명 이하의 직원이 있었고, 개발자 3명, 마케팅 3명, 디자이너 1명, 기획/운영 1명 구성으로 꾸려진 회사다. 여기서는 따로 정해진 기획자가 없다. 누구나 앱에 대한 의견을 낼 수 있었고, 원하면 기획을 할 수 있었다. 빠르게 의사결정해서 피쳐를 내야 하기 때문에 개발자들은 모든 회의에 들어갔고, 자연스럽게 비 개발자들과 개발자들은 많은 시간을 같이 얘기하면서 보낼 수 있었다. 그 결과 모든 사람들이 개발적인 지식을 가지게 되었다. 아니 사실 가지게 된 건지는 모르겠지만, 된다 안된다 소리를 많이 들으니까 이제 뭐가 되고 안되는지 아는 수준까지 도달했다 ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 번째 회사는 카카오 계열사였다. 카카오페이증권에서 초기 증권시스템 구축일을 하게 되었다. 팀구조는 사실 첫회사와 비슷했지만, '카카오' 계열사 특성상 개발자들도 기획에 많이 참여하게 되었고, 오히려 기획자보다 개발자의 의견이 더 존중되는 회사였다. 개발자가 의견을 더 많이 제시하고, 기획자는 컨펌하는 느낌? 사실 기획자라는 포지션보다 PM이라는 포지션이 카카오에 더 잘 어울린다고 생각한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 지금 다니는 회사는, 가파르게 성장한 회사다. 2022년 1월 입사했을 때 200명 정도였던 회사는 2023년 10월 기준 600명이 넘는다. 스타트업 형태로 시작한 회사가 점점 대기업스러워지고 있는 상황이다. 그래서 그런지 여기는 아직 문화가 정착되지 않았다. IT기반 스타트업으로 시작했기 때문에 오래된 사람들 중에는 개발자가 많고, 그렇게 때문에 도메인도 개발자들이 더 많이 알고 있다. 개발자들이 더 잘 알기 때문에 개발자들이 힘이 센 구조다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 회사에서 경력으로 온 기획자들은 이 문화에 잘 적응하지 못하는 것 같다. 특정 서비스를 만들 때 기획자가 준비해 온 기획안에 대해서 신랄하게 비판하는 개발자들이 있기 때문이다. 물론 우리 팀 개발자들도 예외는 아니다 ㅋㅋ 어떤 기획자가 일하기 좋은지, 어떤 기획자랑은 일하기 너무 싫은지는 항상 우리의 재밌는 이야깃거리가 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 팀원들은 '개발 지식이 어느 정도 있는' 기획자를 원한다. 아마 말은 이렇게 하지만 실제로 원하는 건 '말이 통하는' 기획자일 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; &amp;zwj;♀️ &amp;zwj;♂️언제부터 기획자가 개발 지식을 알아야 했을까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2015년 첫회사에 있을 때만 해도 기획자의 기본 소양중 '개발 지식'은 포함되지 않았다. 하지만 어느 세부 터인가? '오늘도 개발자가 안된다고 말했다.', '기획자를 위한 개발지식', '개발자와 협업을 위한 개발지식' 등과 같은 책들이 출간되기 시작했고, 개발 지식이 없는 기획자들을 무시하는(?) 사람들도 등장하기 시작했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;778&quot; data-origin-height=&quot;1194&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bk2qbs/btszNQuPqgd/cJA2lS3W6MDxbwvu5ul4N0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bk2qbs/btszNQuPqgd/cJA2lS3W6MDxbwvu5ul4N0/img.png&quot; data-alt=&quot;오늘도 개발자가 안 된다고 말했다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bk2qbs/btszNQuPqgd/cJA2lS3W6MDxbwvu5ul4N0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbk2qbs%2FbtszNQuPqgd%2FcJA2lS3W6MDxbwvu5ul4N0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;767&quot; data-origin-width=&quot;778&quot; data-origin-height=&quot;1194&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;오늘도 개발자가 안 된다고 말했다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과연 언제부터 기획자가 개발지식까지 알아야 하는 시대가 온 것인가!?!?!?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 아무래도 개발자와 기획자라는 직업의 위치와 관련이 있을 것 같다. 옛날만 해도 개발자는 아주 고달픈 직업이라는 인식이 강했다. 시키대로 하는 직업, 밤새 야근하는 직업, 주말 작업하는 직업이라는 느낌이 강했었는데, 한때 IT 개발 열풍이 불면서 개발자들 연봉이 올라가더니, 개발자라는 직업 자체의 위치가 수직상승하게 되었다. 물론 아무 이유 없이 수직상승한 것은 아니다. 스마트 기기가 널리 보급되고, 인터넷을 접속할 수 있는 인프라가 발달하면서 요즘에는 IT관련 서비스가 아니어도 IT 인프라가 필요하다. 예를 들어 커피점을 한다고 해도, 쿠폰시스템이나 주문시스템이 필요하기 때문에 개발자가 필요하다. 거기에 IT기반 기업들 (흔히 네카라쿠배....라고 말하는) 대거 등장하면서 IT개발자의 필요성이 증가되면서 기획자보다는 개발자가 더 중요한 직업이 되어버렸다. 한마디로 개발자만 있어도 서비스를 만들 수 있는 시대가 온 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 그렇다고 기획자가 필요 없는 것은 아니다. 단지 개발자들끼리 어느 정도 돌아가는 서비스를 만들 수 있다는 소리다. 사용자가 많기 전까지는 기획은 큰 의미를 갖지 못한다. 일단 돌아가는 서비스를 만들고, 그 후 가다듬으면 된다. 따라서 작은 기업이나 스타트업들은 기획자보다는 개발자 비중이 높다. 초기단계에서는 개발자는 필수지만 기획자는 옵션인 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  기획자님 이게 더 좋을 것 같은데요?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 개발자들끼리 개발도 하고 기획도 하다가, 추후 회사가 커지고 기획자가 충원되면 이런 상황이 자주 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;기획자님 이거 사용자한테는 이게 더 좋지 않을까요?&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경력으로 들어온 기획자 입장에서는 어리둥절할지도 모른다. 열심히 기획해서 준비해 온 문서를 개발자들이 평가한다? 어떻게 보면 선 넘은 것처럼 보인다. 이런 상황이 발생하는 이유는 개발자들이 도메인지식이 더 많기 때문이다. 우리 회사가 제공하는 서비스에 대한 이해도가 처음부터 만든 사람과, 중간에 들어온 사람을 비교해 보면 당연히 처음부터 만든 사람이 더 많은 지식을 가지고 있을 것이다. 개발자들은 흔히 '내가 만든 내 새끼'라는 생각(or 오너쉽)을 가지고 있기 때문에 내가 만든 서비스가 잘 되길 바라고 있으며, 자신의 사상과 의견을 넣으려고 한다. 하지만 기획자는 객관적인 시장 평가나 사용자 경험을 토대로 서비스를 수정하려고 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러다 보니 서비스의 방향을 정하기 위한 회의가 많아지고, 개발자와 기획자 간의 의사소통 기회가 많아진다. 하지만 여기에 한 가지 문제가 있다. 서비스에 대한 이해도는 개발자와 기획자 둘 다 비슷하다. 개발자 역시 초기부터 서비스를 개발해 왔기 때문에 서비스에 대한 이해도가 높으며, 기획자는 본업이기 때문에 이해도가 높다. 하지만 개발 지식이 추가되면 어떨 까? 변경되는 화면 구성에 대해 개발적으로 가능한지, 불가능한지를 판단하기 위해서는 개발지식이 필요하다. 개발자 본업이 개발이다 보니 되고 안되고 가 바로 보인다. 하지만 개발지식이 없는 기획자 입장에서는 가능 여부를 알 수 없기 때문에 개발자에게 물어볼 수밖에 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기획자: &quot;이거 돼요?&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자: &quot;음... 안 돼요&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기획자: &quot;이거는요?&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자: &quot;이거는 당연히 안되죠&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기획자: &quot;힝구 ㅠ&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt; &amp;zwj;  개발공부를 하는 기획자들&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자와 기획자의 불편한(?) 불균형에 대해 알아보았다. 기획은 직업에 상관없이 누구나 할 수 있는 제네럴 한 스킬이다. 반면 개발자는 전공지식이 있어야만 가능하다. 따라서 기획자가 개발자들과 동등한 위치에 있기 위해선 여태까지 몰랐단 개발지식이 필요하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;965&quot; data-origin-height=&quot;715&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmXHXp/btszK84bSR9/11D2XSPTGCdthK15alIql0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmXHXp/btszK84bSR9/11D2XSPTGCdthK15alIql0/img.png&quot; data-alt=&quot;냥냥 개발공부다냥&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmXHXp/btszK84bSR9/11D2XSPTGCdthK15alIql0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmXHXp%2FbtszK84bSR9%2F11D2XSPTGCdthK15alIql0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;296&quot; data-origin-width=&quot;965&quot; data-origin-height=&quot;715&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;냥냥 개발공부다냥&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 최근에는 개발지식도 제네럴의 영역에 들어오고 있다. 초등학교 과목에 코딩이 들어갈 정도로 한국에서는 개발이 교양이 되고 있다. 따라서 새롭게 기획자로 발을 들이는 주니어 기획자들은 어느 정도 개발지식이 있을 것이라고 생각된다. 하지만 연차가 있는 기획자는 따로 시간을 내어 공부해야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  이게 맞나?&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기획에 관여하는 개발자, 개발공부를 하는 기획자. 과연 이게 맞는 것일까? 스타트업과 같은 특별한 상황에서 기획은 하는 개발자는 아주 필요하다. 그리고 그런 개발자들과 협업하기 위해서는 개발지식이 있는 기획자 역시 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;하지만 우리는 모두 스타트업이 아니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람은 변화를 싫어한다. 개발지식이 있는 기획자들과 협업한 경험이 많은 개발자들은 항상 개발지식이 있는 기획자를 원하며, 개발지식이 없는 기획자를 꺼려한다. 실제로 우리 팀 사람들은 회사규모가 작을 때부터 일했던 사람들인데, 그때 기획자는 개발자들과 딱 달라붙어서 일을 진행했다고 한다. 그래서 그때 기획자들은 개발지식이 빠삭하다. 하지만 최근 경력 기획자들이 들어오면서 우리 팀의 불만은 자연스럽게 기획자들의 '능력부족'을 지적한다. 기획자의 기획능력이 아닌 개발능력을 말이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난주에 사내 어드민을 만들기 위한 API 만들 때 변수명을 정할일이 있었다. '소수점 고정자리'와 '고정 수수료'라는 두 가지 필드가 필요했는데, 서버 코딩상 둘 다 Fixed라는 필드를 사용했다. (소수점 고정자리 = A모델. Fixed, 고정 수수료 = B모델. Fixed)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에 만드는 사내 어드민은 사용자가 직접 API를 불러와서 화면을 구성할 수 있는 유연한 시스템이다. 따라서 필드명에 의미를 담아야 사용자가 화면을 구성하는데 편리하게 된다. 따라서 나는 소수점 고정자리는 &lt;span style=&quot;background-color: #fdfdfd; color: #000000; text-align: start;&quot;&gt;decimal_place, 고정 수수료는 fixed_fee라고 지을 예정이다. 하지만 옆에 있던 팀원은 이렇게 말했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000; text-align: start;&quot;&gt;팀원: &quot;저라면 A_Fixed, B_Fixed라고 지을 것 같아요. 다른 개발자가 이 코드를 봤을 때 파악하기 쉽게요&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000; text-align: start;&quot;&gt;나: &quot;그건 개발자 입장이고 사용하는 입장에서는 모르지 않을까요? 명확하게 변수명으로 나타내는 게 좋을 것 같은데, &quot;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000; text-align: start;&quot;&gt;팀원: &quot;이거 쓰는 사람이 누군데요?&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000; text-align: start;&quot;&gt;나: &quot;어드민 쓰는 운영팀?&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000; text-align: start;&quot;&gt;팀원: &quot;그분들은 이거 다 알아요.&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd;&quot;&gt;대화를 하면서??? 가 많이 생겼다. 이 팀원은 사용자를 이미 특정 대상으로 좁히고, 그 사용자를 위해서만 서비스를 만들고 있다. 물론 정확하게 특정 사용자만 사용한다면 올바른 방향일 수도 있다. 하지만 회사에서도 인력 순환이 되고, 모든 사용자를 확실하게 알지 못하는 한 사용자가 명확하게 알 수 있도록 만드는 것이 좋다고 생각한다. 이 팀원은 왜 이런 생각을 하게 됐을까?&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd;&quot;&gt;그 팀원은 회사에 오래 일하면서 운영팀과 잦은 커뮤니케이션을 해왔다. 함께 일하면서 자신이 알고 있는 도메인을 많이 고 융해 줬다고 생각하기 때문에 당연히 이거는 알 거다라는 고정관념이 박혀있다. 아마 그 팀원은 모든 협업을 그런 식으로 했을 것이다. 자신이 알고 있는 용어를 쓰고 그 용어를 모르면 도메인을 공유하면서 알려줬을 것이다. 물론 이 방법은 좋은 방법이다. 하지만 그 팀원이 회사의 모든 사람에게 지식을 공유할 수는 없다. 신규 입사자도 있을 것이고, 다른 팀에서 넘어온 사람도 있을 것이다. 매번 이런 설명을 하기는 힘들기 때문에 '이미 알고 있는' 직원들과 일하기를 선호할 것이다. 그 팀원의 말버릇은 이거다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd;&quot;&gt;&quot;아 왜 이걸 하는지 모르겠네, &quot;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 주변에, 기획자에 개발능력에 불만을 느끼는 개발자들은 대부분 같은 생각을 가지고 있었다. 다들 자신이 생각하는 방향이 있고, 그렇게 되지 않으면 불만을 느끼고 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; 우리는 어떤 자세를 취해야 하나&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나의 개인적인 생각은, &quot;기획자가 개발지식을 알면 편하지만 몰라도 된다&quot;라고 생각하는 쪽이다. 더 정확히 말하면, &quot;기획자가 개발지식을 안다면 편할 것이고, 모르면 내가 더 노력하면 되지~&quot;라는 생각이다. 개발 지식을 모르면 더 쉽게 설명하면 된다. 개발용어를 굳이 석어 가면서, DB 필드니 락이니 하는 개발 용어를 굳이 쓰지 않아도 기획자와 의사소통을 할 수 있어야 한다고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 내 주변 몇몇 개발자들은 기획자랑 이야기할 때도 서슴없이 개발용어를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;해당 오류가 발생한 이유는 XXX모델에 콜백으로 YYY가 실행됐기 때문입니다&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에 나는 너무 당황했다. 저런 얘기를 기획자에게 한다고? 물론 개발지식이 있는 기획자에게는 아주 빠르고 쉽게 내용을 전달할 수 있다. 하지만 모두가 개발지식이 있지는 않다. 이게 회사에서 개발자들에게 커뮤니케이션 능력을 요구하는 이유 중에 하나다. 개발자는 누구에게나 쉽게 자신이 만든 코드를 설명할 수 있는 능력이 요구된다. 기획자에게 개발지식을 요구하는 것은, 다르게 표현하면 &quot;나는 그것을 설명할 능력이 안된다&quot;라고 보일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 상대방이 어느 정도의 이해력이 있는지를 항상 체크한다. 현재 업무에 대한 이해도나 배경지식, 용어에 대한 이해력 등을 판단하여 어떻게 설명해야 내 말이 잘 전달될지를 생각하고 말하는 편이다. 이건 내가 어렸을 때부터 발표하는 것을 좋아해서 쌓인 버릇 같은 것이다. 커뮤니케이션 능력이 부족한 개발자들은 이런 것에 약하다. 그들은 대부분 자신들이 알고 있는 것을 다른 사람도 알기를 원한고, 내가 아는 것을 상대방도 알고 있을 거라는 기대를 가지며 대화를 한다. 마치 '&lt;b&gt;지식의 저주&lt;/b&gt;'에 걸린 것처럼 말이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; &lt;a href=&quot;https://cholol.tistory.com/590&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;지식의 저주에 대한&lt;/a&gt; 지난 포스팅&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기획자든 개발자든 서로의 영역을 알면 협업하기 편하다. 이건 기획자와 개발자에 국한된 것이 아니다. 협업을 하는 카운터 파트너에 대한 이해도는 항상 일 진행을 수월하게 만들어준다. 기획자에게만 개발 지식을 강요하는 것은 너무 이기적인 생각은 아닐까?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 개발자도 UI/UX에 대한 공부나 마케팅과 같은 기획적인 요소를 공부하는 것을 추천한다. 나 역시 UI/UX에 대한 책이나 글들을 많이 찾아보는 편이다. 즉, 기획자에게 개발적인 지식을 요구하기 전에 우리도 기획적인 지식을 쌓자는 소리다. 가장 좋은 것은 양쪽 다 서로의 지식을 공부하는 것이지만, 상대가 못할 경우 내가 준비하면 된다는 마인드를 갖자.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 가장 중요한 것은 유연함, 진리의 케바케다. 어떤 회사에서는 개발자는 개발만 하고, 기획자는 기획만 하고 있을 수 있다. 또 어디에서는 기획자들이 개발을 관여하고 있을 수 있고, 어디는 개발자가 기획과 개발을 동시에 하고 있을 수 있다. 세상은 다양하다. 내가 속한 조직에 알맞은 방향을 찾아 적용하는 유연성을 기르자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Blog/IT, I Think</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/598</guid>
      <comments>https://cholol.tistory.com/598#entry598comment</comments>
      <pubDate>Sun, 5 Nov 2023 20:18:33 +0900</pubDate>
    </item>
    <item>
      <title>IT회사 팀사람들과 스터디 하기 5차, 이펙티브 소프트웨어 테스팅, 사례 중심으로 배우는 실전 소프트웨어 테스트 가이드</title>
      <link>https://cholol.tistory.com/596</link>
      <description>&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot; _스터디의_시작&quot; style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size26&quot;&gt;  스터디의 시작&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2023년이 반정도 지난 지금, 회사에서 5번째 스터디를 진행했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 테스트 관련된 스터디로 회사에서 테스트 코드를 많이 작성하기 때문에 스터디 주제로 선정하게 되었다 ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근에 테스트 시 사용하는 mock과 stub에 차이에 대해서 팀 사람들과 논의한 적이 있었는데, 사용법은 비슷하지만 차이가 있는 것들이었다. 이번에 공부한 책에서 mock, stub, spy에 대해 나온 챕터가 있기 때문에 자세한 설명은 아래를 참고하길 바란다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난번 스터디였던 몽고 DB는 회사에서 사용하고 있지 않아서 뭔가 설렁설렁 진행한 감이 없지 않아 있었는데, 이번 주제는 어느 정도 업무와 관련이 있다 보니 좀 더 의미 있는 스터디가 되었던 것 같다.&lt;/p&gt;
&lt;h2 style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size26&quot;&gt;  책 소개&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1030&quot; data-origin-height=&quot;1336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czztXI/btsqHSvxGUG/jVW8E711CUmtSYHUNYoSJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czztXI/btsqHSvxGUG/jVW8E711CUmtSYHUNYoSJ0/img.png&quot; data-alt=&quot;이펙티브 소프트웨어 테스팅&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czztXI/btsqHSvxGUG/jVW8E711CUmtSYHUNYoSJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FczztXI%2FbtsqHSvxGUG%2FjVW8E711CUmtSYHUNYoSJ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1030&quot; height=&quot;1336&quot; data-origin-width=&quot;1030&quot; data-origin-height=&quot;1336&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이펙티브 소프트웨어 테스팅&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용한 책은 '&lt;b&gt;이펙티브 소프트웨어 테스팅 - 사례 중심으로 배우는 실전 소프트웨어 테스트 가이드'이다.&lt;/b&gt; 테스트 관련 책들이 많지는 않기 때문에 아마 아는 사람이 많을 것 같고, 관련해서 외부 스터디도 나름 활발한 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;목차&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 효율적이고 체계적인 소프트웨어 테스트&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 명세 기반 테스트&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 구조적 테스트와 코드 커버리지&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 계약 설계&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5. 속성 기반 테스트&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6. 테스트 더블과 모의 객체&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;7. 테스트 가능성을 위한 설계&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;8. 테스트 주도 개발&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;9. 대규모 테스트 작성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;10. 테스트 코드 품질&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;11. 마무리&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 350페이지 정도 되며 1주에 2~3 챕터씩 뽀개기로 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size26&quot;&gt;  어떤 것을 배웠나? (기억나는 내용 위주)&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 효율적이고 체계적인 소프트웨어 테스트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 제일 재미있었던 챕터. ( 역시 챕터 1은 재미있다 ㅋㅋ )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트에 대한 기본적인 개념이나 왜 써야하는지에 대해서 재미있는 예시를 통해서 알려준다. 테스트코드를 자주 사용하는 개발자와 그렇지 않은 개발자의 업무 스타일을 비교하면서 테스트 코드의 장점을 설명했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 명세 기반 테스트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;번역이 조금 이상하긴 한데, 테스트도 요구사항 정의를 잘해야 한다는 말을 하고 있다. 또 요구사항 정의를 잘하려면 해당 도메인을 잘 알아야 한다는 말도,,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역시 개발자는 개발만 잘하면 되는게 아니라 업무 도메인도 잘 알아야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 구조적 코드 테스트와 코드 커버리지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 코드를 작성할 때 케이스를 이것저것 생각하면서 짜게 된다. 짝수일 때? 홀수일 때? 값이 길 때? 널 일 때? 등등 다양한 케이스를 생각하게 되는데, 이 중에서 대표적인 케이스 그룹을 나누고, 해당 그룹을 대표하는 값(경계값)으로 테스트를 작성하게 된다. 예를 들어 5보다 큰 경우와 5 이하일 경우 다르게 동작하는 코드를 테스트하기 위해, 테스트 케이스에 5일 경우와 6일 경우를 추가한다. 여태까지 이렇게 하는 게 그냥 자연스럽게 생각하는 대로 짜는 거였는데, 이것도 나름 전략이 있는 방법이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전략이름은 MC/DC(Modified Condition / Decision Coverage)로 아무 조건 없이 테스트 케이스를 많이 하면 테스트 코드가 무분별하게 많아지니, 모든 코드에 대한 코드 커버리지를 만족할 수 있는 핵심 테스트 케이스만 선정하여 테스트 코드를 작성하는 것이다. 사실 당연히 이렇게 해야 한다고 생각만 하고 있었는데, 따로 용어로 정의되어 있다니, 앞으로는 &quot;&lt;b&gt;테스트 어떻게 작성하세요?&quot;라고&lt;/b&gt; 물으면 &quot;&lt;b&gt;MC/DC를 적용해서 테스트 코드를 작성합니다.&quot;라고&lt;/b&gt; 대답하면 되겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 계약 설계&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사전 검수와 사후 검수라는 단어를 처음 봤다. 사전 검수는 특정 클래스에서 들어온 인자값에 대한 valid체크를 하는 것을 말하고, 사후 검수는 return해주는 값에 대한 valid체크를 말한다. 이런 사전 검수, 사후 검수를 잘 짜야 테스트가 편하다는 게 내용이었는데 코드를 짜는 걸 기억해 보면 사전 검수는 많이 적용했는데, 사후 검수를 적용한 적은 거의 없는 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;들어온 값은 class에서 확인하는 게 맞는 것 같은데 return까지 검수해야 하나? 왜냐하면 바로 위에서 내가 짠 코드인데 이게 실패할 수가 있나.? 외부 호출이 있는 경우에는 할 수 도 있을 것 같은데, 외부 호출할 때 호출하는 외부 클래스에서는 사전 검수를 하니까 내가 안 해도 되지 않나?라는 꼬리를 무는 질문에 팀원들과 얘기해 봤더니 다들 사후 검수는 갸우뚱한 것 같다. 글쓴이가 좀 과한 듯...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. 테스트 더블과 모의 객체&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dummy, fake, stub, mock, spy와 같이 테스트에 사용하는 비슷비슷한 것들이지만 쓰임세가 다 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- dummy: 테스트에 사용하지 않는 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- fake: 실제와 동일한 동작을 하는 다른 객체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- stub: 실제 호출 시 미리 정의해 둔 데이터를 응답하도록 하는 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- mock: stub + 호출 행위 자체를 검증&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- spy: 실체 호출 행위를 기록하는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대충 책에는 이렇게 쓰여있는데, 구분해서 사용하지 않아서 그런지,, 느낌만 가져가는 걸로.. ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;10. 테스트 코드 품질&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 코드 작성할 때 유의점을 모아놨다. 이 챕터의 내용을 요약하면&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;테스트는 빠르고, 응집력 있고, 독립적이고, 존재 이유가 있어야 하고, 반복가능해야 하고, 안정적이어야 하며, 탄탄해야 하고, 행위가 변경될 경우 깨져야 하고, 명확한 이유로 실패해야 하고, 작성하기 쉬워야 하고, 읽기도 쉬워야 한다. + 유지보수도 쉬워야 한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot; _스터디_후기&quot; style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size26&quot;&gt;  스터디 후기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 때 TDD가 엄청 유행이었다. 너도 나도 TDD를 외치던 시절이었는데, 그때도 나는 TDD에 대해 부정적이었던 것 같다. 이 책을 읽으면서도 역시 TDD는 개발 방법 중에 하나일 뿐이지 MUST는 아니라는 생각이 든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책에서 보면 TDD의 목적은 테스트가 아니다. 코드의 품질을 높이는 것이 목표다. 테스트를 짜면서 내 코드의 퀄리티를 높이는 것이 TDD의 목적이다. 하지만 코드의 품질을 높이는 방법이 TDD만 있는 것이 아니다. 숙련된 개발자는 테스트코드를 짜지 않아도 에러가 발생할 엣지 케이스나 비즈니스 요건등을 확실히 파악하여 정확한 코드를 짤 수 있다. 사람의 말을 듣고 잘 기억하는 사람이 있는 반면, 메모하면서 기억하는 사람이 있듯이, 바로 코드를 개발해도 잘하는 사람이 있고 테스트코드를 짜면서 개발해야 잘하는 사람이 있다. 이런 건 방법일 뿐이지 목적이 아니다. 따라서 TDD를 하고 안 하고는 개인의 선택인 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 테스트 코드를 짜는 것은 찬성하지만, TDD는 개인의 취향이라고 생각한다. 내가 해야 한다고 해서 남한테 권하지 말고, 남이 한다고 해서 내가 하지는 말자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀 사람들 의견도 대~충 비슷했다.&lt;/p&gt;</description>
      <category>Study/회사 팀스터디</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/596</guid>
      <comments>https://cholol.tistory.com/596#entry596comment</comments>
      <pubDate>Wed, 9 Aug 2023 20:32:15 +0900</pubDate>
    </item>
    <item>
      <title>[flutter] 플러터 웹뷰 3.xx -&amp;gt; 4.xx 변경점, webview_flutter 최신화, 코드팩토리의 플러터 프로그래밍</title>
      <link>https://cholol.tistory.com/595</link>
      <description>&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드팩토리의 플러터 프로그래밍책을 보다가 webview_flutter package를 이용하는 게 있는데, 책에서 사용한 3.04와 현재 최신인 4.xx버전이 사용방법이 많이 달라진 것 같다. 이런 패키지가 버전이 달라진다고 사용방법이 자주 바뀌지는 않는데, 아무래도 메이저 버전이 업데이트되었으니 변경된 것 같다. 아니면 네이티브 진영(안드나 아이폰)에서 뭔가 설정이 바뀌어서 업데이트가 됐나?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무튼 책을 그대로 따라 하면 안 되길래 4.xx대로 webview를 써보자. 옛날 거로 쓰긴 싫으니 ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드팩토리의 플러터 책은 강의도 그렇지만 참 설명이 짧다. 이런 거는 패키지 버전 다르면 사용법이 다를 수 있다고 명시를 좀 해줘야 할 텐데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 pub.dev에 가보면 현재 버전은 4.2.2가 최신이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://pub.dev/packages/webview_flutter&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://pub.dev/packages/webview_flutter&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1690472963969&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;webview_flutter | Flutter Package&quot; data-og-description=&quot;A Flutter plugin that provides a WebView widget on Android and iOS.&quot; data-og-host=&quot;pub.dev&quot; data-og-source-url=&quot;https://pub.dev/packages/webview_flutter&quot; data-og-url=&quot;https://pub.dev/packages/webview_flutter&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/B4fFZ/hyTrJjsilu/sKEP4yXq7MwTOmyoe3Ln81/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/bVxVpC/hyTrJ4PfFm/bFkHSSIFXCa7MFJQ58G72k/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640&quot;&gt;&lt;a href=&quot;https://pub.dev/packages/webview_flutter&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://pub.dev/packages/webview_flutter&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/B4fFZ/hyTrJjsilu/sKEP4yXq7MwTOmyoe3Ln81/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/bVxVpC/hyTrJ4PfFm/bFkHSSIFXCa7MFJQ58G72k/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;webview_flutter | Flutter Package&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A Flutter plugin that provides a WebView widget on Android and iOS.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;pub.dev&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금은 이게 최신인데 아마 나중에 도 업그레이드 되면서 스펙이 달라질 수 있다. 그럴 땐 최신버전에 대한 샘플코드를 보면서 또 변경해야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 지금은 4.2.2인데 책에서 설명하는 3.0.4와 차이점이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 3.0.4는 그냥 WebView라는 클래스를 사용해서 바로 웹뷰를 표기할 수 있었다. (아주 편했었는 듯?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 4.2.2는 WebViewController를 만들어서 넘겨줘야 실행이 되게 바뀌었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1532&quot; data-origin-height=&quot;920&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOI38j/btspeJsP435/BKtwxVWZk13B3ZYQ8qrX1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOI38j/btspeJsP435/BKtwxVWZk13B3ZYQ8qrX1k/img.png&quot; data-alt=&quot;3.0.4&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOI38j/btspeJsP435/BKtwxVWZk13B3ZYQ8qrX1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOI38j%2FbtspeJsP435%2FBKtwxVWZk13B3ZYQ8qrX1k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1532&quot; height=&quot;920&quot; data-origin-width=&quot;1532&quot; data-origin-height=&quot;920&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;3.0.4&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1604&quot; data-origin-height=&quot;1356&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XpI4Y/btso7Rlu4GG/s0OkKVoBznwE8ezOXLRLdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XpI4Y/btso7Rlu4GG/s0OkKVoBznwE8ezOXLRLdk/img.png&quot; data-alt=&quot;4.2.2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XpI4Y/btso7Rlu4GG/s0OkKVoBznwE8ezOXLRLdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXpI4Y%2Fbtso7Rlu4GG%2Fs0OkKVoBznwE8ezOXLRLdk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1604&quot; height=&quot;1356&quot; data-origin-width=&quot;1604&quot; data-origin-height=&quot;1356&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;4.2.2&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 기존에는 아래 코드로도 웹뷰가 떴는데, 지금은 안된다는 소리.&lt;/p&gt;
&lt;pre id=&quot;code_1690473216714&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';


class WebViewWidget extends StatelessWidget {
  const WebViewWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: WebView(
        initialUrl: 'https://cholol.tistory.com/',
        javascriptMode: JavascriptMode.unrestricted,
      ),
    );
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4.2.2 버전으로 해보자면 아래와 같다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1690479026609&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import 'package:flutter/material.dart';

import 'package:webview_flutter/webview_flutter.dart';

class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});

  @override
  State&amp;lt;WebViewApp&amp;gt; createState() =&amp;gt; _WebViewAppState();
}

class _WebViewAppState extends State&amp;lt;WebViewApp&amp;gt; {
  late final WebViewController controller;

  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://google.com'),
      );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1902&quot; data-origin-height=&quot;2060&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2aA3w/btso8yMOujj/ei45tEp9jr7MbtfcEBilnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2aA3w/btso8yMOujj/ei45tEp9jr7MbtfcEBilnk/img.png&quot; data-alt=&quot;됨&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2aA3w/btso8yMOujj/ei45tEp9jr7MbtfcEBilnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2aA3w%2Fbtso8yMOujj%2Fei45tEp9jr7MbtfcEBilnk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1902&quot; height=&quot;2060&quot; data-origin-width=&quot;1902&quot; data-origin-height=&quot;2060&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;됨&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 어디 웹페이지를 선택하냐에 따라서 ssl연결이 잘 안 돼서 웹뷰가 로딩이 안될 수 있다. naver.com으로 했는데 안 돼서 google.com으로 바꾸니까 잘됨 ;;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저 컨트롤러에는 이것저것 옵션을 넣을 수 있는것 같다. 내가 만든 코드는 아주 기본적인 웹뷰만 딱 띄우는 거고 이것저것 옵션을 넣으면 앱에 있는 브라우저랑 흡사하게 사용할 수 있는 모양이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 배경색 옵션을 주면 아래와 같이 색이 변한다.&lt;/p&gt;
&lt;pre id=&quot;code_1690481351962&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    controller = WebViewController()
      ..setBackgroundColor(Colors.black)
      ..loadRequest(
        Uri.parse('https://google.com'),
      );&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;1296&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0lmPL/btspeHBPqYy/RUXw1pKuQEs2uwEwKY8451/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0lmPL/btspeHBPqYy/RUXw1pKuQEs2uwEwKY8451/img.png&quot; data-alt=&quot;백그라운드 색 변경&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0lmPL/btspeHBPqYy/RUXw1pKuQEs2uwEwKY8451/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0lmPL%2FbtspeHBPqYy%2FRUXw1pKuQEs2uwEwKY8451%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;549&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;1296&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;백그라운드 색 변경&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹뷰는 거의 화면은 다 차지하고 있으니 배경색은 좀 의미가 없는듯... ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;navigationDelegate를 추가하면 웹뷰 내에서 페이지를 이동하는 것을 트래킹 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1690483472819&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;controller = WebViewController()
      ..setBackgroundColor(Colors.black)
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..loadRequest(
        Uri.parse(url),
      )
      ..setNavigationDelegate(
        NavigationDelegate(
          onNavigationRequest: (request) {
            return NavigationDecision.navigate;
          },
          onUrlChange: (UrlChange change) {
            debugPrint('url change to ${change.url}');
          },
          onPageFinished: (String url) {
            debugPrint('page finished loading: $url');
          },
        )
      );&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;onNavigationRequest에서 요청한 request.url을 가지고 특정 페이지에는 링크가 되고 안되고를 정할 수 있다. return으로 NavigationDecision.navigate를 하면 허용이고, prevent를 하면 막는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 막 눌러보니 대부분의 페이지는 잘 안들어가지는데 (ssl이슈인가 에뮬레이터 이슈인가..) 구글이나 링크드인은 접속이 된다. 이동할 때마다 아래와 같이 로그가 찍힌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2508&quot; data-origin-height=&quot;708&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dBdt4F/btspd3kOxRf/cmSkJlKEe18VFH6vUtriCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dBdt4F/btspd3kOxRf/cmSkJlKEe18VFH6vUtriCk/img.png&quot; data-alt=&quot;로그&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dBdt4F/btspd3kOxRf/cmSkJlKEe18VFH6vUtriCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdBdt4F%2Fbtspd3kOxRf%2FcmSkJlKEe18VFH6vUtriCk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2508&quot; height=&quot;708&quot; data-origin-width=&quot;2508&quot; data-origin-height=&quot;708&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;로그&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앱에서 웹뷰를 띄울때 앱에서 제공하는 브라우저처럼 서핑기능을 제공하기 위해 만드는 경우는 없을 거다. 아마 특정 페이지를 띄우는 용도니까 사실 어디로 이동하는 기능은 필요 없겠지. 강제로 이동하는 거만 잘 막으면 될 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹뷰로 웹용으로 빌드된 코드를 쓴다던지, 앱 카메라 같은거 사용할 수는 있을것 같은데.. 나중에 기회되면 앱에 카메라 쪽도 한번 건들 기회가 있으면 좋겠다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Study/FrontEnd</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/595</guid>
      <comments>https://cholol.tistory.com/595#entry595comment</comments>
      <pubDate>Fri, 28 Jul 2023 03:48:41 +0900</pubDate>
    </item>
    <item>
      <title>flutter : 제로부터 시작하는 인스타그램 클론코딩 - #0 마음에 드는 플러터 강의가 없어서 직접 만들는 강의</title>
      <link>https://cholol.tistory.com/594</link>
      <description>&lt;div class=&quot;index_toc&quot;&gt;
&lt;p class=&quot;toc_title&quot; data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;플러터 강의를 시작하는 목적&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 백엔드개발자로 일하고 있지만, 아주 초기에는 안드로이드 개발자였습니다 ㅋㅋ 물론 취업하기 전이었고, 학부와 대학원 시절에 안드로이드가 주력이었기 때문에 그렇게 말하고 있지만, 지금 와서 생각해 보니 &lt;b&gt;안드로이드 개발자라고 말할 수 있나?&lt;/b&gt; 라는 의문이 들긴 하지만요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백엔드 개발을 하면서 계속 아쉬운 점은 사용할 수 있는 화면, 즉 UI를 만들 수 없다는 점입니다. 물론 간단한 화면정도는 제공하는 프레임워크가 있긴 하지만 상용화가 가능한 클라이언트를 만들고 싶은 욕심은 항상 있습니다. 예를 들어 특정 서비스를 만들고 싶은데 백엔드 만드는 건 문제가 아닌데 앱이나 웹을 만드는 건 문제가 됩니다. 가장 좋은 방법은 근처에 프론트를 맡아줄 사람이 있는 건데, 이게 쉽지 않잖아요? 서로 스케줄도 맞아야 되고 지속적으로 개발하기 위한 노력도 필요합니다. 그래서 가장 쉬운 건 &lt;b&gt;내가 둘다 하자!입니다&lt;/b&gt; ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;올해 들어서 플러터 강의나 책을 많이 보면서 공부하고 있는데 생각보다 국내에 좋은 강의나 책이 없습니다. 그나마 최근 코드팩토리라는 저자가 쓴 플러터 강의를 봤는데, 가격 치고는 너무 별로더군요. 플러터를 배운다기보다는 앱을 찍어내는 방법을 배우는 느낌이었습니다. 그래서 이럴 바에 그냥 &lt;u&gt;&lt;b&gt;내가 딥하게 공부하면서 강의를 만들어보자!&lt;/b&gt;&lt;/u&gt; 해서 시작하게 되었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;강의 진행 방향&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 기존에 제가 만든 &lt;b&gt;django : 제로부터 시작하는 인스타그램 클론코딩&lt;/b&gt;을 기반으로 flutter로 인스타그램을 구현해 볼 생각입니다. 다른 점은 django로 할 때는 프론트와 백엔드 모두 django로 만들었지만, flutter 강의에서는 프론트엔드는 flutter, 백엔드는 기존에 django 백엔드를 사용할 예정입니다. 물론 기존에 django 인스타그램 코드를 완전히 재사용하지는 못하고 조금 바꿔야겠지만요.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 강의를 따라하는 사용자분들을 위해 django 코드는 도커 이미지로 제공할 예정입니다. 여러분들 컴퓨터에서 도커로 django 프로젝트를 실행시켜서 백엔드 코드를 돌아가게 만들고, 그 위에서 flutter로 프론트엔드를 만드는 방식이죠. 이건 이전 블로그 글 중에 서버개발자가 되는 방법에서 한번 써먹었던 건데, 그때는 react를 docker로 제공하고 백엔드를 django로 만드는 방식이었지만요.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 django 강의를 보신 분이라면 직접 django 코드를 수정해서도 가능할겁니다. ㅎㅎ 물론 프론트와 백엔드를 동시에 하고 싶은 욕심쟁이들만 이렇게 하겠지요 ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 기존에 django로 만든 인스타그램 프로젝트를 백엔드 api로 사용하는 flutter 앱(웹)을 만드는게 목적입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;flutter에서 사용하는 언어는 dart이기 때문에 아주 생소한데요, C기반이기 때문에 C언어를 5년동안 사용했던 제 입장에서는 코드가 아주 익숙해서 좋습니다 ㅎㅎ 대신 flutter에서 사용되는 위젯이나 프론트엔드용 코딩스타일이 저한테 생소해서 아마 만들면서 이것저것 많이 분석해 보고 찾아보고 하느라 시간이 오래 걸리지 않을까 싶네요. &lt;s&gt;사실 강의라기보다는 그냥 공부하는걸 공유한다고 해야 하나...&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강의는 일단 블로그를 쓰면서 만들어보고 어느 정도 만들어지면 유튜브로 만들 계획입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;최종 계획&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 생각하고 있는 계획은 아래와 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 기존에 만들어놓은 django 백엔드 코드를 활용해 flutter 인스타그램 클론코딩 완성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. flutter 인스타그램 클론코딩 완성 후 이 프로젝트를 기반으로 springboot 백엔드 강의 진행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. flutter, springboot로 각각 프론트 백엔드 구성 후 개발자 커뮤니티 같은 웹 서비스 개발.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최종적으로는 flutter + springboot의 서비스를 만들 계획이죠. 그럼 처음부터 springboot 쓰면 편하긴 할 텐데, 이미 만들어놓은 django프로젝트가 있기도 하고, 아직은 django가 저에게 생산성이 더 높습니다 ㅋㅋ springboot로 또다시 만들려면 너무 오래 걸릴 것 같아요. (배우면서 해야 하니)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Course/flutter : 제로부터 시작하는 인스타그램</category>
      <category>인스타그램</category>
      <category>클론코딩</category>
      <category>플러터</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/594</guid>
      <comments>https://cholol.tistory.com/594#entry594comment</comments>
      <pubDate>Wed, 26 Jul 2023 19:23:02 +0900</pubDate>
    </item>
    <item>
      <title>토스는 일하기 좋은 회사일까? 블라인드에서 Hot했던 토린이 일기를 보고 느낀 생각들..</title>
      <link>https://cholol.tistory.com/593</link>
      <description>&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근에 블라인드(직장인 익명 커뮤니티)에서 핫했던 '&lt;b&gt;토린이의 일기&lt;/b&gt;'.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금은 블라인드에서 지워졌지만 총 4편까지 연재되었던 핫한글이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금도 인터넷 검색하면 1편과 2편은 나오는데 3편과 4편은 찾을 수가 없다. (누가 캡처 안 해놨나요!!?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토린이는 토스 + 어린이로, 토스에 갓 입사한 글쓴이가 토스에서 일하는 내용을 적은 것인데, 내용이 참 재밌다. ㅋㅋㅋ 일단 아래 1편과 2편을 잠깐 봐보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;# 토린이 일기 1편&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;output_3846654528.jpg&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1542&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciQi8p/btsn7vi4uJW/htDQhNFCGKY1n0BeZcjVp0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciQi8p/btsn7vi4uJW/htDQhNFCGKY1n0BeZcjVp0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciQi8p/btsn7vi4uJW/htDQhNFCGKY1n0BeZcjVp0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FciQi8p%2Fbtsn7vi4uJW%2FhtDQhNFCGKY1n0BeZcjVp0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;900&quot; height=&quot;1542&quot; data-filename=&quot;output_3846654528.jpg&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1542&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;output_3705133031.jpg&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1508&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lyFCr/btsn9UCaymr/l1XMttxPr3iTnj4S4PNfF0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lyFCr/btsn9UCaymr/l1XMttxPr3iTnj4S4PNfF0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lyFCr/btsn9UCaymr/l1XMttxPr3iTnj4S4PNfF0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlyFCr%2Fbtsn9UCaymr%2Fl1XMttxPr3iTnj4S4PNfF0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;900&quot; height=&quot;1508&quot; data-filename=&quot;output_3705133031.jpg&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1508&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;output_210937079.jpg&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;672&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xnBVU/btsn9KsO6ds/bkjRSfKv4teTUFmBPrnKKk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xnBVU/btsn9KsO6ds/bkjRSfKv4teTUFmBPrnKKk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xnBVU/btsn9KsO6ds/bkjRSfKv4teTUFmBPrnKKk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxnBVU%2Fbtsn9KsO6ds%2FbkjRSfKv4teTUFmBPrnKKk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;900&quot; height=&quot;672&quot; data-filename=&quot;output_210937079.jpg&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;672&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;# 토린이 일기 2편&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;output_3695624938.jpg&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1554&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/spT9g/btsoeAXtJau/2Y5L1SmxDuE7nAtKzqLD2k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/spT9g/btsoeAXtJau/2Y5L1SmxDuE7nAtKzqLD2k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/spT9g/btsoeAXtJau/2Y5L1SmxDuE7nAtKzqLD2k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FspT9g%2FbtsoeAXtJau%2F2Y5L1SmxDuE7nAtKzqLD2k%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;900&quot; height=&quot;1554&quot; data-filename=&quot;output_3695624938.jpg&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1554&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;output_1907488419.jpg&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1584&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRQxKO/btsn7sfBBws/rIEDQf5KQJZ9sOgIla9Il0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRQxKO/btsn7sfBBws/rIEDQf5KQJZ9sOgIla9Il0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRQxKO/btsn7sfBBws/rIEDQf5KQJZ9sOgIla9Il0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRQxKO%2Fbtsn7sfBBws%2FrIEDQf5KQJZ9sOgIla9Il0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;900&quot; height=&quot;1584&quot; data-filename=&quot;output_1907488419.jpg&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1584&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;output_708624996.jpg&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1584&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/T6tYU/btsn14fxleC/5oisHBk41vJJT9lG1e97x1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/T6tYU/btsn14fxleC/5oisHBk41vJJT9lG1e97x1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/T6tYU/btsn14fxleC/5oisHBk41vJJT9lG1e97x1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FT6tYU%2Fbtsn14fxleC%2F5oisHBk41vJJT9lG1e97x1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;900&quot; height=&quot;1584&quot; data-filename=&quot;output_708624996.jpg&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1584&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;output_612363876.jpg&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;866&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVwS9r/btsn7uqXMsX/JqCcGrwGqNeKFu8HFZ7FQ1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVwS9r/btsn7uqXMsX/JqCcGrwGqNeKFu8HFZ7FQ1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVwS9r/btsn7uqXMsX/JqCcGrwGqNeKFu8HFZ7FQ1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVwS9r%2Fbtsn7uqXMsX%2FJqCcGrwGqNeKFu8HFZ7FQ1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;900&quot; height=&quot;866&quot; data-filename=&quot;output_612363876.jpg&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;866&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3편은 아마 '래디컬 캔도어'에 관련한 내용이었던 것 같고, 4편은 특별한 내용은 없고, &quot;여태까지의 글은 사실이 아닙니다. 관심 가져주셔서 감사합니다&quot;라는 내용이었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글을 보면 생소한 단어들이 많이 나오는데, 특히 포커스 온 임팩트에 아주 꽂혀있는 것처럼 보인다 ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토스(회사명 : 비바퍼블리카)는 생기고 나서부터 회사문화가 아주 유명했었는데, 사람을 뽑아서 믹서기로 갈아버릴 정도로 업무강도가 높다고 유명하다. 요즘에는 뉴스에 나올 정도로 사내 문화에 대한 이슈가 많은데, 뉴스들 내용이 죄다 부정적이다. ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;썩은 사과 사건&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토스의 가장 유명한 사건중 하나는 썩은 사과 사건이다. 토스 채용 공고페이지에 '썩은 사과'라는 단어를 쓴 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1156&quot; data-origin-height=&quot;1264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6nzFS/btsn7ymIjSA/2ntxL9nmnmaIpnkrBq7gik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6nzFS/btsn7ymIjSA/2ntxL9nmnmaIpnkrBq7gik/img.png&quot; data-alt=&quot;썩은 사과는 없애야한다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6nzFS/btsn7ymIjSA/2ntxL9nmnmaIpnkrBq7gik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6nzFS%2Fbtsn7ymIjSA%2F2ntxL9nmnmaIpnkrBq7gik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;437&quot; data-origin-width=&quot;1156&quot; data-origin-height=&quot;1264&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;썩은 사과는 없애야한다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심가치에 부합하지 않는 팀원을 &quot;썩은 사과&quot;에 비유해서 제거 대상이라고 표시하고 있다. 이게 한창 논란이 돼서 지금은 글을 삭제했지만, 저런 글이 잠깐이나마 채용 홈페이지에 노출이 되었다는 게 놀랍다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 객관적으로 생각해 보면 맞는 말이긴 하다. 흔히 말하는 버스 타는 직원을 없애겠다는 소리. 누가 같이 일하는 사람 중에 무임승차하는 사람들을 좋아할까? 잘하는 사람들끼리 일하면 일이 잘되는 건 당연하다 ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 이 말에 공감하는 이유는 저 글이 올라왔을 당시 나는 대기업 증권사에 있었는데, 주변에 직급이 높은 월급루팡들이 많았다. 출근해서 하루종일 부동산만 보는 과장도 있었고, 매일 전날 술 먹고 출근해서 엎드려서 자는 과장도 있었다. 이렇게 무능력한 월급루팡들이랑 함께 일하는 게 너무 싫어서 이직을 결심했었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 만약 내가 토스였다면 저런 사람들은 &quot;썩은 사과&quot; 취급을 당해 제거되었을 것이다. 그리고는 열심히 일하는 사람만 남았겠지. 그렇게 생각하면 좋은 문화 아닌가?라는 생각도 든다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이건 내 생각이고, 누구에게는 저 &quot;썩은 사과&quot;라는 단어가 다르게 받아들여질지도 모른다. 특히 &quot;썩은 사과&quot;는 너무 상대적인 개념이다. 모두가 균등하게 일을 잘하는 이상적인 상황은 존재하지 않는다. 상대적으로 일을 못하는 사람이 발생하게 되는데, 그 사람은 억울하게 &quot;썩은 사과&quot;가 될 수 있다. 언젠가 내가 &quot;썩은 사과&quot;가 될 수 있다는 걱정을 하며 회사를 다니는 건 조금 무서울 지도..?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;동료 평가, 삼진아웃 제도&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토스는 또 동료평가제도가 쌔다고 유명하다. 같이 일하는 동료끼리 평가를 아주 신랄하게 한다는 소리 ㅋㅋ 그리고 동료 평가가 안 좋으면 회사에서 경고를 주고 경고가 3번 싸이게 되면 삼진아웃으로 퇴사를 '권고'한다고 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 이렇게 퇴사를 '권고'하는 건 노동법 상 불법이다. 토스 회사 측에서는 '퇴사를 권고'한 게 아니라고 말하긴 하는데, 실제 퇴사당한 사람들 말을 들어보면 거의 '강제 퇴사'당하는 것이라고 한다. 예를 들어 이상한 팀으로 보내거나, 일을 안 주거나, 모욕감을 주거나 등등..&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근에는 삼진 아웃 제도를 없앴다고 하긴 하는데, 뉴스를 보면 아직도 '권고사직'은 존재하는 것 같다. 회사는 계속 아니라고 하긴 하지만 뭐가 진실인지..?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블라인드에서도 이런 제도는 말이 많긴 한대, 나는 역시 여기서도 중립기어를 넣겠다. 뉴스나 커뮤니티에는 실제로 퇴사를 당한 사람들에 인터뷰들이 있긴 한데, 회사의 입장, 같은 팀원들의 입장도 들어봐야 하기 때문이다.&amp;nbsp;&lt;s&gt;진짜 일을 못하는 또라이 일수도 있으니&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사 입장에서는 일 잘하는 사람들을 대우해 주고, 일 못하는 사람들을 내쫓는 건 당연하다. 회사의 이익을 추구해야 하니까. 어떻게 보면 당연한 일인데 이게 왜 논란이 되는 걸까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 생각에는 이런 평가들이 객관적이지 않게 진행되기 때문이라고 생각한다. 토스도 생각보다 오래되지 않은 서비스이고, 회사도 오래되지 않았다. 스타트업으로 시작해 급작스럽게 성장한 기업인데, 이런 기업에는 항상 &quot;텃세&quot;가 있다. 예를 들면 토스 설립부터 있던 직원들(우리는 흔히 고인물이라고 부른다)은 서로 아주 친하다. 그러다가 마음에 안 드는 직원이 들어오면 친한 직원들끼리 그 사람을 까 내린다. 실제로 그 사람을 싫어하진 않지만, 고인물 무리에 끼고 싶어서 어쩔 수 없이 그 사람을 까 내리는 사람도 있을 수 있다. 이렇게 특정 그룹으로 인해 의사결정이 진행되는 경우는 모든 기업에서 빈번하게 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대기업, 스타트업, 카카오계열사, 현재 두나무에서 일하고 있는 나도, 모든 회사에서 이런 문화를 경험해 보았다. 물론 회사에서 모든 팀이, 모든 사람들이 이런 건 아니다. 진리의 팀바팀, 사바사.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 이런 사건에 휘말리지 않으려면 두 가지 방법이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 사회생활 만렙 (눈치고수, 샤뱌샤뱌 고수)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 그것을 뛰어넘을 정도로 일을 개 잘함 (핵심 인력 되기)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 남한테 샤뱌샤뱌 하는 게 싫기 때문에 2번을 선호한다. (그래서 이직하고 나면 악착같이 해당 회사의 서비스를 파악하려고 노력한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;토스 개발자들은 어떨까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 &quot;경력직 이직 경험&quot;이라는 유튜브 콘텐츠에서 토스증권 면접에 대한 썰을 푼 적이 있다. 내 면접에 들어온 면접관들(토스증권 서버개발자 2명)은 모두 금융권 출신이 아니었다. 토스 개발자들은 대부분 금융권 개발자 출신이 아니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면접을 보면서 내가 느꼈던 점은, 그들은 자신들의 금융권 출신이 아닌데 금융 서비스를 만든다는 거에 상당한 자부심을 느끼고 있다는 점이다. 면접을 진행하면서 &quot;저희는 기존 금융회사와 개발문화가 다르다&quot;라는 말을 수시로 했다. 내가 면접 본 게 2년 전이었는데, 그렇게 금융권 출신이 아닌 개발자들이 만든 토스 증권 서비스는 최근 버그가 너무 많이 발생해서 차세대를 한다고 한다.. ㅋㅋㅋㅋ 실제로 블라인드나 뉴스에 토스 버그 제보들이 많이 올라오고 있다고,,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제는 토스와 토스증권이 분리되어 있기 때문에 토스 전체 개발자 문화는 알지 못한다. 하지만 내가 면접 봤을 때는 아직 토스 증권이라는 회사로 분리되기 전이라서, 토스 개발문화에 대해 살짝이나마 맛을 본 느낌이다. 물론 팀바팀 사바사이기 때문에 나를 면접본 면접관들만 그런 사람이었을 수 있다. 토스에도 괜찮은 개발자들이 많겠지. 하지만 면접을 본 입장에서 토스는 가기 싫은 회사라는 인상을 너무 강하게 주었다. ㅋㅋㅋㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 나는 토스 개발자들의 생각에 어느 정도 공감은 한다. 토스 개발자들이 왜 금융권 출신이 아니라는 점을 강조하는지,, 실제로 금융권 개발자들 중에 개발을 잘하는 사람은 드물다. 금융권 개발자들은 개발보다는 복잡한 비즈니스 로직(흔히 업무 도메인이라고 부름)에 더 특화되어 있다. 그들은 개발 용어는 잘 모르지만, 어려운 금융 용어는 꿰뚫고 있다. 그러다 보니 대기업 증권사에서 일할 때 같이 일하는 개발자들과 의사소통이 안됬던 적이 한두 번이 아니다. 기본적인 개발 용어를 모른다고 하니까 ㅋㅋㅋ 그리고 이런 개발자들 특징은, 자신들이 개발을 못한다는 걸 당당하게 생각한다는 것이다. &quot;우리는 개발보다는 업무에 포커스를 두고 있기 때문이다!!&quot;라고 당당하게 말하고 다닌다. 아니 개발도 잘하고 업무도 잘할 수 있잖아? 꼭 둘 중 택일이어야 하니? ㅋㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 어느 정도, 토스 개발자들의 생각도 이해가 간다. 마치 &quot;우리는 타 금융 개발자들과 다르다!!&quot;라는 걸 말하고 싶은 걸 수도..&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;결론&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론적으로 토스가 일하기 좋은 회사일까?라는 질문에는, &quot;나는 토스에서 일해보고 싶다&quot;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 토스가 객관적으로 사람을 평가한다면 내가 토스에서 일할 때 어떤 평가를 받는지도 궁금하다. 나는 회사 프로덕트에 대한 책임감도 가지고 일을 하고 개발하는 것을 좋아하는 워커홀릭이기 때문에 토스에 적합한 사람일지도..?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 정말 토스의 문화가 위와 같다면 거기는 다 일 잘하는 사람만 있는 거자나? ㄱㅇㄷ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 업무에 대한 가치관이 모두 나 같지는 않으니, 토스에 맞는 사람이 있고 아닌 사람이 있을 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 내가 어떤 사람인가를 잘 알고 토스에 들어가야 하는 게 정답일 듯. 워라밸 중시하고 업무보다는 내 개인 삶을 중요시하는 사람이 토스에 들어가서 불평하는 건,, 그 사람이 잘 못 선택한 게 아닐까 싶다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요약 - 일에 미친 사람은 좋은 회사일 듯? 아니라면 별-루-&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Blog/IT, I Think</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/593</guid>
      <comments>https://cholol.tistory.com/593#entry593comment</comments>
      <pubDate>Wed, 19 Jul 2023 13:45:59 +0900</pubDate>
    </item>
    <item>
      <title>IT회사 팀사람들과 스터디 하기 4차, 몽고DB, mongo DB</title>
      <link>https://cholol.tistory.com/592</link>
      <description>&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;div class=&quot;index_toc&quot;&gt;
&lt;p class=&quot;toc_title&quot; data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot; _스터디의_시작&quot; style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size26&quot;&gt;  스터디의 시작&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어느덧 2023년 4번째 스터디까지 오게 됐다. ( 실제로 글을 쓰는 시점에는 5번째를 하고 있지만.. ㅋㅋㅋ )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4번째는 NoSQL DB를 선택했는데, NoSQL DB 중에 어떤 걸 할지 고르다가 가장 많이 들어본 몽고 DB를 선택하게 되었다. 대학생들이나 취준생들 멘토링을 하다 보면 대부분 몽고 DB를 사용했다는 걸 많이 볼 수 있었는데, 그때마다 왜 mysql을 안 하고 몽고 DB를 했을까?라는 생각이 많이 들었다. 이번 기회에 알게 되었는데 그건 아래에 설명... ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 NoSQL에 대해서 난 그냥 '노 에스큐엘'이라고 읽었는데 팀원 중에 한 명이 '노시클'이라고 읽어서 간지나 보였다.   우리 모두 노시클이라고 발음하도록 하자.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot; _책_소개&quot; style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  책 소개&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책은 한빛미디어에서 나온 &lt;b&gt;몽고DB 완벽 가이드이다.&lt;/b&gt; &lt;s&gt;개인적으로 한빛미디어 책을 싫어한다&lt;/s&gt;.. 책이 너무 딱딱하고 지루해,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1274&quot; data-origin-height=&quot;1580&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLfnO0/btskuOGavyG/WcnKsnGWOgT3hQgszV9Ujk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLfnO0/btskuOGavyG/WcnKsnGWOgT3hQgszV9Ujk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLfnO0/btskuOGavyG/WcnKsnGWOgT3hQgszV9Ujk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLfnO0%2FbtskuOGavyG%2FWcnKsnGWOgT3hQgszV9Ujk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;744&quot; data-origin-width=&quot;1274&quot; data-origin-height=&quot;1580&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목차는 너무너무 길어서 큰제목만 적었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;PART I 몽고DB 시작&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CHAPTER 1 몽고DB 소개&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 2 몽고DB 기본&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 3 도큐먼트 생성, 갱신, 삭제&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 4 쿼리&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;PART II 몽고DB 개발&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CHAPTER 5 인덱싱&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 6 특수 인덱스와 컬렉션 유형&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 7 집계 프레임워크&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 8 트랜잭션&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 9 애플리케이션 설계&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;/b&gt;&lt;b&gt;PART III 복제&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 10 복제 셋 설정&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 11 복제 셋 구성 요소&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 12 애플리케이션에서 복제 셋 연결&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 13 관리&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;PART IV 샤딩&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 14 샤딩 소개&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 15 샤딩 구성&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 16 샤드 키 선정&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 17 샤딩 관리&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;PART V 애플리케이션 관리&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 18 애플리케이션 작업 확인&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 19 몽고DB 보안 소개&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 20 영속성&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;PART VI 서버 관리&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 21 몽고DB 시작과 중지&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 22 몽고DB 모니터링&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 23 백업&lt;/b&gt;&lt;br /&gt;&lt;b&gt;CHAPTER 24 몽고DB 배포&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지수도 거의 600페이지가 넘는다!! 하지만 역시나 우리는 필요한 챕터만 골라빼 먹기를 하기 때문에 총 4주에 걸쳐 끝내기로 했다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot; _어떤_것을_배웠나?_(기억나는_내용_위주)&quot; style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  어떤 것을 배웠나? (기억나는 내용 위주)&lt;/h2&gt;
&lt;h3 id=&quot;1장_사용자_수에_따른_규모_확장성&quot; style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;1장 몽고DB 소개&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몽고 DB란 무엇인가, 도큐먼트 DB란 무엇인가 라는 내용이다. RDB에 너무 익숙해져서 도큐먼트 DB에 대한 이미지가 확실히 떠오르지 않는다. 그냥 머릿속에 두 개의 칼럼이 있고 하나는 id, 하나는 아무거나 들어가는 TEXT인 것 같은 RDB 같은데 말이지... ㅋㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;1장_사용자_수에_따른_규모_확장성&quot; style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;2장 몽고DB 기본&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mongo shell이라는 cli툴을 제공해 줘서 생각보다 쉽게 테스트해 볼 수 있다. mysql cli랑 비슷한데 더 유저 친화적인 느낌이랄까..?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;1장_사용자_수에_따른_규모_확장성&quot; style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;5장 인덱스&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몽고 DB에 쿼리를 날리면 어떤 index를 선택할지 정하는 방법이 흥미로웠다. 가지고 있는 인덱스 중에 쿼리문에 맞는 거 다 골라서 경합을 시키고 거기서 최고의 결과를 내는 것을 선택한다고 한다. ㅋㅋㅋ 즉 아무리 쿼리랑 잘 매칭이 되어도 속도가 안 나오는 인덱스는 탈락이라는 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 인덱스와 실제 서비스에서 사용하는 쿼리가 항상 일치된다는 보장이 없기 때문에 괜찮은 방법인 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;1장_사용자_수에_따른_규모_확장성&quot; style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;6장 특수 인덱스와 컬렉션 유형&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공간정보를 저장하는 인덱스를 제공한다는 것에 놀람.. 옛날에 대학원시절 수자원 연구소 쪽이랑 좌표나 시계열 관련 데이터를 추출해서 관리하는 작업을 했었는데, 이때 몽고 DB를 쓰면 효율적으로 데이터를 적재할 수 있지 않을까?라는 생각이 문득,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;1장_사용자_수에_따른_규모_확장성&quot; style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;8장 트랜잭션&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DB 하면 트랜잭션이 가장 중요하긴 한데, 대규모의 형식이 없는 데이터베이스인 몽고 DB에서 트랜잭션을 찾으면 안 될 것 같다는 개인적인 생각... 물론 몽고 DB에서 트랜잭션을 지원하긴 하는데, 스펙상 지원할 뿐 성능이나 안정성이 높진 않은 것 같다. 트랜잭션이 필요하면 다른 DB를 쓰는 게 좋을 것 같다. 몽고 DB는 조회를 많이 하는 서비스에 좋아 보임&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;1장_사용자_수에_따른_규모_확장성&quot; style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;15장 샤딩&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;15장 이후 샤딩에 관한 내용이 나온다. 너무 이론적인 내용이라 그런가 보다~하고 봤음. 몽고 DB는 편하게 아주 자동으로 샤딩을 지원하는데 '자동 샤딩'이라는 걸 지원한다고 한다. 알아서 분배해 줌 ㅋㅋ. 근데 중간중간 예외상황이 있어 수동으로 데이터를 이동해줘야 하는 경우가 있다고 한다. 믿을만한 건가... ㅋㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot; _스터디_후기&quot; style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size26&quot;&gt;  스터디 후기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이름만 들어본 몽고 DB에 대해서 책을 읽고 나니 뭔가 이해가 많이 된 느낌이다. 몽고 DB를 왜 주니어가 많이 쓰는지 알게 되었다. 이게 아주 쓰기 편하다. 마치 튜토리얼처럼 그냥 설치만 하면 바로 쓸 수 있고, RDB처럼 컬럼이나 초기 세팅이 필요 없다. 왜냐면 '노시클'이기 때문에. 아무거나 그냥 넣으면 들어간다 ㅋㅋㅋ 그렇기 때문에 RDB에 익숙하지 않은 사람들이 쓰기 쉽고 알려주기도 쉽다. 국비교육이나 학원에서 몽고 DB를 알려주는 이유는 그냥 알려주기 귀찮아서인 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대규모 데이터를 적재하는데 아주 도움이 될 것 같고, 시계열 데이터를 저장하고 조회하는 효과적인 방법이나 인덱스를 활용하면 내가 사이드프로젝트로 진행하고 있는 타이머앱에도 적용할 수 있을 것 같다. 사용자의 공부시간등을 한 번에 내려줄 때 DB를 어떻게 설계할까 고민했었는데 '노시클' DB를 활용하면 row 하나를 조회해서 다 내려줄 수 있을 것 같다. 대신 메인 DB로 사용하진 않고 서브 DB로 활용하면서 기존 RDB에 쌓인 내용을 가공하여 몽고 DB에 적재하는 프로그램이 있어야 하겠지. 하지만 애플리케이션 성능은 대폭 오르고 메인 DB인 RDB에도 부하가 줄어들 태니 괜찮은 방법인 듯? 나중에 시간 나면 적용해 봐야겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS에서도 document DB라는 몽고 DB 비슷한 서비스가 있는데 실제 몽고 DB와 100% 일치하지 않는다고 한다. 쿼리를 돌리면 두 개의 결과가 다르다고,,, 이가 빠진 서비스인 듯 ㅋㅋ 실제로 쓰려면 그냥 on-premise로 쓰지 않을까? 싶다. docker에 보니까 몽고 DB + ui 제공해주는 이미지가 있던데 star가 많은걸 보니 사람들이 많이 쓰는듯?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론 : 몽고DB 쓰려면 조회용으로, docker로 사용하기.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Study/회사 팀스터디</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/592</guid>
      <comments>https://cholol.tistory.com/592#entry592comment</comments>
      <pubDate>Mon, 19 Jun 2023 15:10:13 +0900</pubDate>
    </item>
    <item>
      <title>IT회사 팀사람들과 스터디 하기 3차, 가상 면접 사례로 배우는 대규모 시스템 설계 기초</title>
      <link>https://cholol.tistory.com/591</link>
      <description>&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;div class=&quot;index_toc&quot;&gt;
&lt;p class=&quot;toc_title&quot; data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  스터디의 시작&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어느덧, 스터디 2회 차가 끝나고 3회 차에 접어들었다. 기존에 약간 프로그램 언어에 관한 것이었다면, 이번엔 이론? 설계? 에 관한 스터디를 하고 싶어 했다. 너무 코드를 많이 읽어서 그런지 그냥 쉽게 읽히면서 쉬어가는 스터디 시간? 을 갖기 위함이었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇게 선택된 책은 &lt;b&gt;가상 면접 사례로 배우는 대규모 시스템 설계 기초&lt;/b&gt;라는 책이다. 생각보다 이곳저곳에서 이 책을 가지고 스터디를 많이 하는 것 같았다. 배민에서 진행하는 우아한 스터디에도 이 책을 가지고 스터디하는 게 있어서 나름 유명한 책인가 보다~ 생각했고, 출판일도 나름 최신이라서 최근 트렌드를 배우는데 도움이 될 것 같았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;830&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLerAc/btsh2NWmIiA/6kXBtOAmTnnPbn6qW5kE51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLerAc/btsh2NWmIiA/6kXBtOAmTnnPbn6qW5kE51/img.png&quot; data-alt=&quot;책 표지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLerAc/btsh2NWmIiA/6kXBtOAmTnnPbn6qW5kE51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLerAc%2Fbtsh2NWmIiA%2F6kXBtOAmTnnPbn6qW5kE51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;651&quot; data-origin-width=&quot;830&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;책 표지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  책 소개&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애초에 책을 먼저 선택하고 시작한 스터디이기 때문에 책선정은 따로 없었다. 해당 책은 여러 가지 시스템을 챕터별로 나눠서 설명하는 구성이다. 챕터는 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: justify;&quot;&gt;1장 사용자 수에 따른 규모 확장성&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: justify;&quot;&gt;2장 개략적인 규모 추정&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: justify;&quot;&gt;3장 시스템 설계 면접 공략법&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: justify;&quot;&gt;4장 처리율 제한 장치의 설계&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: justify;&quot;&gt;5장 안정 해시 설계&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: justify;&quot;&gt;6장 키-값 저장소 설계&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: justify;&quot;&gt;7장 분산 시스템을 위한 유일 ID 생성기 설계&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: justify;&quot;&gt;8장 URL 단축기 설계&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: justify;&quot;&gt;9장 웹 크롤러 설계&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: justify;&quot;&gt;10장 알림 시스템 설계&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: justify;&quot;&gt;11장 뉴스 피드 시스템 설계&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: justify;&quot;&gt;12장 채팅 시스템 설계&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: justify;&quot;&gt;13장 검색어 자동완성 시스템&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: justify;&quot;&gt;14장 유튜브 설계&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: justify;&quot;&gt;15장 구글 드라이브 설계&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: justify;&quot;&gt;16장 배움은 계속된다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 16장으로 구성되어 있어서 우리는 일주일에 4챕터씩 4주로 진행하기로 했다. 각 챕터가 생각보다 재밌는 내용을 다루고 있었기 때문에 앞으로 스터디가 재미있어질 것 같았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  어떤 것을 배웠나? (기억나는 내용 위주)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1장 사용자 수에 따른 규모 확장성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 1장이 제일 재미있었다. 원래 문제집 풀 때도 1장은 열심히 하는 게 국룰이니까&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1장은 서비스가 커지면서 시스템 구조가 어떻게 바뀌는지를 시간의 흐름으로 보여주었다. 처음에는 아주 작은 시스템이었는데, 사용자가 많아지면서 시스템이 확장되었다. 그때그때 사용되는 기술이나 설계방법 등을 보여주었는데, 현업 경험이 없는 주니어들이 보면 좋을 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리 팀에서 현재 회사가 첫 회사인 팀원이 있는데, 그 팀원은 당연히 이렇게 구성해야 하는 거 아닌가?라고 생각하는 내용이 책에 적혀있었다고 했다. 아무래도 처음부터 대규모 시스템을 만졌기 때문에 시스템 구조가 당연하다고 생각했다고 한다. 하지만 작은 회사나 스타트업은 결코 완벽한 시스템이 구성되어있지 않다. 따라서 아주 작은 소규모 시스템으로 부터 확장하게 되는데, 이렇게 대규모 시스템에 대한 경험이 없는 개발자들에게 아주 좋은 내용이 될 것 같다. 안 그래도 채용 조건에 '대규모 시스템 운용 경험'이라는 게 항상 있는데, 입사를 시켜줘야 대규모 시스템을 운용하지 ㅋㅋㅋ 이 책이라도 읽고 간접 경험을 하면 면접 때 정말 도움이 될 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5장 안정 해시 설계&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평소에 해시함수를 아주 많이 사용하지만, 실제로 안정 해시라는 개념을 책에서 처음 봤다. 해싱을 균등하게 하기 위해 해시 링을 사용하여 분배하는 방법이 아주 신선했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안정 해시 챕터가 기억에 남는 이유는 최근에 레디스 클러스터를 사용하면서, 어떤 데이터가 어떤 클러스터에 들어가는지 어떻게 계산하는가?를 디깅 했었는데, 스프링에서 자체 라이브러리가 레디스에 데이터를 넣을 때 키를 해싱해서, 해싱된 데이터를 가지고 어떤 클러스터에 들어갈지 정하게 된다. 레디스 클러스터들에게 골고루 데이터를 분산시키기 위해서는 안정 해시를 사용해서 분배한다고 한다. 이게 생각보다 복잡한 이유가 클러스터가 추가되거나 제거될 경우에도 기존 데이터를 클러스터들이 골고루 나누어 가져야 하는데, 요것을 해결하는 방법이 생각보다 재밌다. 여기에 적기에는 너무 복잡하기 때문에 궁금하면 책을 읽어보는 걸로,,,, ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;8장 URL 단축기 설계&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 스타트업에서 일할 때 긴 URL을 짧게 줄여주는 서비스를 이용했었는데, 이 서비스가 유료 서비스였다고 한다. 무료로도 사용 가능하긴 한데, 유료로 쓰면 추가 기능들이 있다나,,,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 URL 단축 서비스를 설계하는 방법이 이 챕터에 나온다. 생각보다 단순.. 어떻게 URL을 단축시킬지, DB를 쓸지? 안 겹치게 어떻게 할지? 등등의 내용이 나오는데 이런 서비스 만들어서 광고 달면 돈이 되려나?라는 생각이 더 많이 들었던 것 같다 ㅋㅋㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;14장 유튜브 설계&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전에 BTS동영상이 유튜브에 업로드 된지 1시간 만에 수백만 뷰가 찍혀서 유튜브가 어떻게 이게 가능한가에 대한 아티클을 본 것 같다. CDN을 아주 잘 활용했다는 게 주 내용이었는데, 이 챕터에서도 비슷한 내용이 나온다. 유튜브에서 어떻게 동영상을 끊임없이 스트리밍 하는가? 가 주 내용이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근에 누가 email로 비슷한 질문을 물어봐서 아주 타이밍 좋게 대답을 해줄 수 있었던 기억이 난다. ㅋㅋㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유튜브 같은 시스템을 만들고 싶지만, CDN비용이 매우 매우 비싸기 때문에 적자일 것 같다. 그냥 서비스 이용하는 게 개 꿀~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  스터디 후기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책 초반은 재밌게 읽었는데, 후반으로 갈 수록 내가 지친 건지, 책 내용이 지루한 건지 재미가 없었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 챕터 1의 내용은 정말 좋기 때문에 나중에 따로 유튜브로 만들어보면 좋을 것 같다는 생각이 든다. 간단하게 5분 정도? 하면 취준생분들이나 면접 준비자들한테 아주 좋은 내용이 될 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책의 전체적인 내용은 가상 면접을 통해 진행되긴하는데, 우리나라 회사들 중에 이렇게 높은 퀄리티의 면접을 보는 회사가 있을까?라는 생각도 들었다. ㅋㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실리콘 밸리 정도는 되야 이런 수준의 면접을 진행하지 않을까....&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Study/회사 팀스터디</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/591</guid>
      <comments>https://cholol.tistory.com/591#entry591comment</comments>
      <pubDate>Tue, 30 May 2023 15:45:50 +0900</pubDate>
    </item>
    <item>
      <title>개발자에게 필요한 소프트 스킬이란 무엇인가? 센스있게 일하는 방법은 무엇인가?</title>
      <link>https://cholol.tistory.com/590</link>
      <description>&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;div class=&quot;index_toc&quot;&gt;
&lt;p class=&quot;toc_title&quot; data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근에 기술 문서 작성을 위해 문서작성과 관련된 도서가 없는지 찾다가 'Doc for Developers'라는 책을 구매하게 되었다. 아직 다 읽지는 못했는데, 첫 페이지에 '&lt;b&gt;지식의 저주&lt;/b&gt;'라는 단어가 나온다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;지식의 저주&lt;br /&gt;(curse of knowledge)란 어떤 개인이 다른 사람들과 의사소통을 할 때 다른 사람도 이해할 수 있는 배경을 가지고 있다고 자신도 모르게 추측하여 발생하는 인식적 편견이다&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러다가 문득 최근에 개발자와 기획자 간에 의사소통, 혹은 개발 팀원들끼리의 의사소통에 문제가 있는 사례들을 생각해 보며 과연 개발자에게 필요한 소프트 스킬이란 무엇인가?라는 고민을 해보게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  소프트 스킬이란 무엇인가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주니어 개발자나 개발자를 준비하는 사람들과 이야기를 나눌 때, 나는 항상 '소프트 스킬'의 중요성을 이야기한다. 개발자에게 중요한 것은 개발하는 실력뿐만 아니라 협업하는 능력, 대화하는 능력, 이해하는 능력 등 다양한 소프트 스킬이 필요하다. 물론! 소프트 스킬은 협업을 하는 집단에서 일을 하는 사람이라면 누구나 필요한 것이라고 생각한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데, 많은 글들이나 인터뷰에서 소프트 스킬을 강조하지만, 정작 그게 무엇인지 구체적인 예나 사례, 어떻게 키우는지 등을 알려주지 않는다. 마치 수능 1등이 '교과서 위주로 공부했어요'라고 말하는 느낌이다. ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;nbsp;소프트 스킬이 중요하다고 말하지만, &lt;br /&gt;정작 소프트 스킬이 무엇인지 알려주지 않는다.  &lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 소프트스킬이 흔히 말하는 센스와 비슷하다고 생각한다. 우리는 일상에서 '어 저사람 센스 있네~', '오~ 센스~!'라는 말을 가끔 하게 된다. 친구들과 커피를 마시러 가서 커피를 주문하고 자리에 앉았는데, 빨대를 가져오는 것을 까먹었다. 하지만 옆에 앉은 친구가 내 빨대까지 챙겨 왔을 때 우리는 '오 이 친구 센스 있네~'라고 생각할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 상황에서 센스는 '상대방이 겪을 문제나 상황등을 고려하고 더 나아가 그것을 해결해 주기 위해 노력하는 행위'라고 정의해 볼 수 있다. 자 그럼 이걸 일과 연결시켜 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 회사생활을 하면서 많은 갈등 문제들을 만나왔다. 그게 팀 동료의 문제일 수도 있고, 저기 멀리 다른 팀의 문제를 블라인드나 소문으로 들은 것일 수도 있다. 혹은 친구한테 들은 친구 회사 이야기일 수도?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면에 나는 이런 갈등을 잘 회피하고 있다. 나는 어느 회사에 가도 '회의를 잘하는 개발자', '기획자와 이야기를 잘하는 개발자'라는 이미지가 찍힌다. 자랑으로 들릴 수 있을 것 같은데, &lt;u&gt;&lt;b&gt;그&lt;/b&gt;&lt;b&gt;렇게 생각하면 님말이 맞음&lt;/b&gt;&lt;/u&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;센스 있게, 혹은 일을 잘하는 사람, 으로 일하는 나만의 방법을 고민하면서 정리해 보니 &lt;u&gt;2가지&lt;/u&gt;가 있는 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; &amp;zwj;  센스 있게 일하기 첫 번째, &quot;지난번에 어디까지 했죠?&quot; 히스토리 파악하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째는 히스토리 파악이다. 우리는 개발을 하다가 특정 코드가 왜 이렇게 개발되었는지 파악할 때 '히스토리를 파악한다'라는 말을 많이 사용한다. git commit log나 회의록등을 찾아보며 코드가 왜 이렇게 작성되었는지 이유를 찾는 과정이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 이런 히스토리 파악이 코드만 대상으로 할게 아니라 더 확장할 필요가 있다고 생각한다. 간단한 예로 점심, &lt;b&gt;저녁 메뉴에 대한 히스토리&lt;/b&gt;다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 재택을 많이 하긴 하지만 출근도 가끔 하는데, 출근할 때 팀원들끼리 저녁을 먹으로 나간다. 하지만 우리는 1층에서 3~5분 정도 소요한다. 바로 메뉴를 고르기 위해서다. (K-직장인 국룰)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 메뉴를 정하는 방법은 간단하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;1. &amp;nbsp;누군가 먹고 싶은 게 있다? -&amp;gt; 2번으로 이동&lt;br /&gt;2. 그 메뉴를 최근에 먹었나? -&amp;gt; Yes: 1번으로 이동, No: 3번으로 이동&lt;br /&gt;3. 못 먹는 사람이 있나? -&amp;gt; Yes: 1번으로 이동, No: 메뉴 선택!&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 대부분 비슷하지 않을까 싶다. 1번에서 멤버 전부 먹고 싶은 게 없다면 가장 먹은 지 오래된 것을 먹기도 한다. ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 이제 기억을 더듬어보자. 메뉴를 고를 때 항상 이렇게 말하는 사람이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&quot;어제 뭐 먹었지?&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 말하는 사람은 메뉴에 대한 히스토리 관리를 안 하는 사람이거나 먹는 거에 관심이 없는 사람이다. 하지만 히스토리 관리를 하거나 먹는 것에 관심이 있는 사람은 바로 기억한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&quot;어제 부대찌개~&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;히스토리 관리는 이런 거다. 코드뿐만 아니라 사소한 것에도 히스토리 관리가 필요하다. 만약 아무도 메뉴에 대한 히스토리를 기억 못 한다면 최악의 경우 매일 같은 음식만 먹어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 이제 약간 업무의 영역으로 들어와 보자. 우리는 일주일에 적게는 1~2회, 많게는 수십 회의 회의를 진행한다. 회의는 일회성인 경우도 있고 반복되는 경우도 있다. 정기적인 회의가 있다면, 회의를 시작할 때 가장 먼저 무엇을 하는가? 바로 '지난 회의 때 어디까지 했지?'이다. 만약 회의록이 있다면 지난 회의록을 간단하게 리뷰하고 다시 회의를 진행하면 된다. 하지만 이렇게 리뷰하더라고 개개인마다 지난 회의에 대해 기억하는 정도가 다르다. 따라서 회의를 진행하면서 '지난번에 이렇게 정했잖아요~'라는 말을 많이 하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 회의에 참여한 사람 모두가 지난 회의에 대한 기억을 다 하고 있다면, 즉 히스토리를 다 알고 있는 사람이라면 어떨까? 그럼 지난 회의에 대한 리뷰를 하지 않아도 모두가 똑같은 이해 수준으로 회의를 진행할 수 있다. 이게 포인트다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대기업에서 일을 할 때, 회의시간의 대부분 '상사에게 일을 설명'하는 시간이었다. 부장이나 팀장이 들어간 회의는 최소 30분은 기존 히스토리에 대해 설명하는 시간이었으며, 한 사람이 설명하면 다른 사람들은 상사가 이해하기까지 앉아서 기다리는 시간이다. 지금 생각해도 아주 비효율적이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'아마존에서는 이렇게 일한다'라는 책에는 아마존의 회의방법이 나온다. 아마존에서는 회의를 소집한 사람이 회의를 소집한 이유나 아젠다 등을 1장으로 요약해서 회의시작하면 모든 사람한테 나눠준다. 회의에 참여한 사람들은 3~5분 정도 나눠준 종이를 읽으면 회의를 진행하게 된다. 이 회의방식은 모든 사람의 눈높이를 맞추는 효과가 있으며 히스토리 파악도 가능하게 한다. 대신 내용을 1장으로 요약을 잘해야 모든 사람들이 쉽게 이해하기 때문에 1장을 잘 요약하는 일이 가장 어렵다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마존의 기업문화를 모방할 수 있다면 가장 베스트겠지만, 문화를 도입하는 것은 개인이 노력해서 되는 게 아니기 때문에 힘들 수 있다. 우리가 할 수 있는 건, 최대한 회의에 대한 히스토리를 가지고 있는 것이다. 개발자인 내가 생각했을 때 일을 잘하는 기획자는 무엇인가 지난 일을 설명하지 않아도 알고 있다. 이상적인 회의에서는 대명사 가지고도 회의가 끝나기도 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;나: &quot;그거 그렇게&amp;nbsp;하는 거&amp;nbsp;변한 거&amp;nbsp;없죠?&quot;&lt;br /&gt;기획자: &quot;네, 그거 저번에&amp;nbsp;그렇게 안 하고&amp;nbsp;반대로 하려고&amp;nbsp;했던 거&amp;nbsp;캔슬돼서&amp;nbsp;그냥 원래대로 하시면&amp;nbsp;돼요~&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 대화를 히스토리가 전혀 없는 사람이 들으면 뭐지? 하겠지만, 지난 회의에 히스토리를 다 알고 있다면 아주 명확한 대화가 된다. 이렇게 히스토리를 잘 알고 있다면 &lt;b&gt;커뮤니케이션에 대한 코스트&lt;/b&gt;가 확 줄어든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size16&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;히스토리를 파악하면 커뮤니케이션이 쉬워진다.&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;히스토리 파악에 대해 회의에 대해서만 언급했지만, 개인에 대해 대상이 될 수도 있다. 우리 주변에는 꼭 같은 얘기를 반복하는 사람이 한 두 명쯤은 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;'나 저번에 핸드폰 잃어버려서 바꿨잖아~!'&lt;br /&gt;'응 벌써 3번째 들었어'&lt;br /&gt;'아? 내가 얘기했나?'&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반복적인 얘기를 하는 사람은, 내가 누구에게 무슨 얘기를 했는지 히스토리를 기억하지 않는 사람이다. 이런 사람들은 내가 누구와 어디까지 얘기했는지 기억하는 것에 관심이 없기 때문에 대화를 이어나가기 힘들다. 항상 이전 이야기를 다시 해주고 본론으로 넘어가야 하기 때문에&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커뮤니케이션 코스트가 높아진다. 반면 이전 이야기를 잘 기억하는 사람들은 얘기하기가 쉽다. 이전 설명 없이 새로운 얘기를 바로 하면 되기 때문이다. 혹시라도 '&lt;b&gt;대화하기 편한 상대'&lt;/b&gt;라는 이미지를 갖고 싶다면, 주변인들과 나눈 대화의 히스토리를 잘 기억해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt; &amp;zwj;  센스 있게 일하기 두 번째, &quot;왜 저럴까?&quot; 고민하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째는 상대방이 왜 저러는지 고민하는 것이다. 표현이 좀 이상하긴 한대, 간단히 말하면 상대방에 입장에서 고민해 보라는 거다. 주변 기획자분들이 'XXX 개발자랑은 일하기가 너무 불편해'라고 했을 때 10중에 8이 대부분 상대방 입장을 고려 안 하는 개발자다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 기획자, 아니 대부분의 사람이 무언가 말을 하면, '왜 저렇게 말하지?'라는 고민을 먼저 하게 된다. 글 처음에 언급한 지식의 저주에 현혹되지 않기 위해서다. 사람들은 대부분 나와 같은 생각을 다른 사람도 하고 있다고 생각한다. 따라서 내가 생각하는 것과 다르게 말하면 그 사람이 틀리다고 생각하고 멍청하다고 생각하게 된다. 하지만 대부분의 경우에는, 상대방과 내가 아는 상황이 다른 경우라는 것을 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근에 서비스 사용자가 늘어나서 앱이 느려지는 이슈가 생겼다. 이슈를 해결하기 위해 개발자와 기획자가 모여서 회의를 진행했다. 이슈를 해결하기 위해서는 서버를 늘리던지, 사용자에게 보이는 화면에 데이터를 줄여서 앱 성능을 향상하는 방법이 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;기획자 A: &quot;기존 화면을 건드리면 UX가 바뀌니 서버를 늘리는 방향으로 가시죠?&quot;&lt;br /&gt;개발자 B: &quot;굳이 서버를 늘려야 하나요? 코드로 바꿀 수 있을 것 같은데?&quot;&amp;nbsp;&lt;br /&gt;기획자 A: &quot;아까 말했다시피 UX가 바뀌면 사용자가 불편할 수도 있으니까요&quot;&lt;br /&gt;개발자 B: &quot;자주 사용하는 화면도 아니고 별 이슈 없을 것 같은데요?&quot;&lt;br /&gt;...&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 대화는 끝이 없을지도 모른다. 우리는 이렇게 정답이 없는 회의를 많이 경험해 보았을 것이다. 그럼 여기서 &quot;왜 저럴까?&quot;라는 것을 넣으면 어떻게 될까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;기획자 A: &quot;기존 화면을 건드리면 UX가 바뀌니 서버를 늘리는 방향으로 가시죠?&quot;&lt;br /&gt;개발자 B: &quot;굳이 서버를 늘려야 하나요? 코드로 바꿀 수 있을 것 같은데?&quot;&amp;nbsp;&lt;br /&gt;기획자 A: &quot;혹시 서버를 늘리면 다른 이슈가 발생하는 걸까요?&quot;&lt;br /&gt;개발자 B: &quot;네 저희가 사용하는 서버는 사용 비용이 높은 서버로 늘리게 되면 월 서버 비용이 1.5배 오를 수 있습니다.&quot;&lt;br /&gt;기획자 A: &quot;그렇군요. 그럼 사용자가 어느 정도 불편할지 예상해 보고 양자택일을 해야겠네요.&quot;&lt;br /&gt;개발자 B: &quot;해당 화면에 진입하는 유저는 전체 5% 정도로 집계됩니다. 의사결정할 때 참고하세요&quot;&lt;br /&gt;...&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;너무 극적으로 화목해지긴 했지만, 기획자 A가 먼저 개발자 B에 대답을 듣고 고민을 한 흔적이 보인다. &quot;서버를 늘리지 않기를 바라는 것 같은데 왜 그럴까? 서버를 늘리면 다른 문제가 생기는 건가?&quot;라는 고민을 해봄으로써 왜 개발자가 서버를 늘리는 것보다 화면을 고치는 게 더 좋겠다고 말한 지 이해할 수 있다. 이처럼 상대방이 왜 그렇게 말했는지 조금만 고민해 본다면, 일을 좀 더 쉽게 진행할 수 있게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 이런 상황을 가장 많이 느끼는 건 클라이언트 개발자와 협업을 하는 경우다. 내 업무가 백엔드다 보니 클라이언트 개발자와 협업할 때가 많은데, 대부분의 개발자들은 자기의 영역에 대한 지식만 가지고 있는 경우가 많다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;클라이언트 개발자: 응답에서 is_used라는 변수가 안 내려오는데 확인해 주실 수 있나요?&lt;br /&gt;백엔드 개발자: 아 그거 안 내려갈 수도 있어요.&lt;br /&gt;클라이언트&amp;nbsp;개발자: 필수 값인데 안 내려온다고요?&lt;br /&gt;백엔드 개발자: 넵 서버가 그렇게 만들어져 있어요.&lt;br /&gt;클라이언트&amp;nbsp;개발자: 넣어주실 수 있나요?&lt;br /&gt;백엔드 개발자: 왜 넣어야 하죠??&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적절한 예를 생각하다가 이런 대화를 생각했는데, 적절하지 않을 수 있다 ㅋㅋ 일단 두 개발자는 서로의 개발 영역이 어떻게 개발되었는지 모른다. 클라이언트에서 특정 라이브러리가 항상 json 필수값을 받아야 하는 것이라면 값을 추가해 주는 게 맞을 거다. 하지만 백엔드 개발자 입장에서 값이 없으면 생략하는 라이브러리를 사용했고, 예전에도 그렇게 잘 사용하고 있었기 때문에 이해가 안 가는 상황이다. 백엔드 개발자 입장에서 안 내려가는 게 당연한데, 그걸 묻는 클라이언트개발자가 이상했을 것이다. 하. 지. 만, '왜 저럴까?'생각을 한번 해본다면 대화가 조금 달라질 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;클라이언트 개발자:&amp;nbsp;응답에서 is_used라는 변수가 안 내려오는데 확인해 주실 수 있나요?&lt;br /&gt;백엔드 개발자: 어, 그거 안 내려갈 수도 있는데 항상 필요한 건가요?&lt;br /&gt;클라이언트 개발자: 네, 이거 공통모듈에서 처리하는데 이번에 업데이트돼서 값이 없으면 에러가 나더라고요&lt;br /&gt;백엔드 개발자: 아 이번에 변경되었군요. 기존에는 없으면 안 내려주는 방식이었는데, 바꿀 수 있는지 확인해 볼게요&lt;br /&gt;...&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역시나 극적으로 화목해졌다. 이렇게 상대방이 왜 그렇게 얘기하는지, 혹은 왜 그렇게 얘기할 수밖에 없는지 이해하려고 한다면, 커뮤니케이션 코스트는 줄어들고 더 빠르게 이슈를 확인할 수 있을뿐더러 &lt;b&gt;일을 잘하는 인상&lt;/b&gt;까지 줄 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*(위 예제가 적절하지 않은 이유는 Json 스펙상 boolean값이 false인 경우 필드가 없는 게 룰이다. 즉 is_used가 응답에 없다면 false로 인식해야 하는 게 정답. 이건 사용하는 라이브러리의 옵션으로 false여도 내려줄 수 있게 바꿀 수는 있을 거다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 쓰려고 했는데 예시까지 들면서 본격적으로 쓰게 되었다. 최근 주변에서 커뮤니케이션에 어려움을 겪는 사람들을 많이 보기도 하고, 내가 어려움을 겪기도 한다. 그럴 때마다 나는 최대한 상대방을 이해하려고 노력하고, 내가 문제일 것이다라는 생각도 적극적으로 하고 있다. 이건 누구의 잘못인지 찾는 문제가 아니라 어떻게 하면 효율적으로 이 상황을 개선할 수 있을까의 문제이기 때문이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글을 읽는다고 당장 소프트 스킬이 늘거나 센스 있는 직장인이 되지는 않겠지만, 앞으로 여러분들이 일을 하는 데 있어 도움이 됐으면 하는 바람이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Blog/IT, I Think</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/590</guid>
      <comments>https://cholol.tistory.com/590#entry590comment</comments>
      <pubDate>Sat, 27 May 2023 15:51:19 +0900</pubDate>
    </item>
    <item>
      <title>IT회사 팀사람들과 스터디 하기 2탄, graphql 스터디</title>
      <link>https://cholol.tistory.com/588</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;index_toc&quot;&gt;
&lt;p class=&quot;toc_title&quot; data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;graphql 스터디의 시작&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;DDD 스터디를 진행하고, 그 기세를 모아 바로 다음 스터디 시작~!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;어떤 스터디를 할까 후보에 이것저것 올라왔는데, 그중에서 무난했던 graphql이 선택되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;후보 리스트:&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;스프링 (코틀린)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;카프카&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;클린 아키텍처 : 지금 할 만함&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;클린 코드 : 지금 할만함&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Google RPC : 독학이 더 좋음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;graphQL : 지금 할 만함&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;디자인패턴 : 지금 할 만함&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;리팩토링&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;http http/2.0&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;database&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;생각보다 많은 후보군이 있었는데 ㅋㅋ 코딩하는 건 뭔가 독학이 더 효율적일 것 같고, 5주간 DDD를 했더니, 너무 범위가 커서 오래 걸릴 것 같은 스터디는 피했다. 그래서 선택된 것이 graphQL!!  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;graphQL은 사이드 프로젝트로 진행한 경험이 있기 때문에 나에게 아주 익숙한 프레임워크다.  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;사이드 프로젝트는 django를 이용해 graphQL을 구현했었는데, 패키지중에 grapene라는 패키지를 사용했다. 장고에서 제공하는 ORM과 연동이 너무 쉬워서 편안하게 진행했던 것 같다. 근데 이번 공부를 하면서 내가 사용하지 않은 graphQL에 기능들이 엄청 많다는 것을 깨달았다!!! &amp;zwj; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;역시 책이나 공식 문서를 참고하며 개발해야 뭔가 숨겨진 기능, 더 편리한 기능들을 많이 사용할 수 있는것 같다. 추가로 올바른 사용은 덤!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size16&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;공식 문서나 책을 참고하는 것은 항상 옳다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;사용한 책&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1328&quot; data-origin-height=&quot;1698&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tDUuV/btsdpbbBoh9/VfxlqnJsVKuB5sd6jcW670/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tDUuV/btsdpbbBoh9/VfxlqnJsVKuB5sd6jcW670/img.png&quot; data-alt=&quot;사용한 책&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tDUuV/btsdpbbBoh9/VfxlqnJsVKuB5sd6jcW670/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtDUuV%2FbtsdpbbBoh9%2FVfxlqnJsVKuB5sd6jcW670%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;767&quot; data-origin-width=&quot;1328&quot; data-origin-height=&quot;1698&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;사용한 책&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;스터디에서 사용한 책은 웹 앱 API 개발을 위한 GraphQL이다. 생각보다 아주 얇다 ㅋㅋ&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;GraphQL in action도 후보에 있었는데, in action시리즈는 워낙 두껍고 방대해서,, 가볍게 찍먹 하기 위해서 얇은 책을 골랐다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이 책에 목차는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;1장 GraphQL에 오신 것을 환영합니다&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;2장 그래프 이론&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;3장 GraphQL 쿼리어&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;4장 스키마 설계하기&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;5장 GraphQL API 만들기&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;6장 GraphQL 클라이언트&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;7장 실제 제품을 위한 GraphQL&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;책도 얇고 한 챕터당 30페이지 정도라서 1~4장을 1주 차에 보고 5~7장을 2주 차에 봐서 2주 만에 끝내는 일정으로 진행했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;어떤 것을 배웠나?&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1장 ~ 2장&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;일단,, graphQL의 장단점이라고 해야 하나? 이것저것 많이 설명을 해준다. 사실 GraphQL의 장단점이라기보다는 REST와 비교했을 때의 장단점이라고 해야 맞을 것 같다. 그만큼 REST가 거의 표준이니까 ㅋㅋ&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;내가 사용했을 때의 장점은, 서버와 클라이언트가 어느 정도 API 스펙을 맞출 수 있다는 점이다. 사람이 맞추는 게 아니라 프로그램이 맞춘다. 즉 서로 회의해서 정하는 게 아니라 Instropection이라는 기능을 제공해 줘서 클라이언트가 최초에 서버에 조회해서 사용할 수 있는 API스펙을 긁어간다 ㅋㅋ 따라서 아폴로와 같은 라이브러리를 쓰면 클라이언트도 알아서 API 응답에 대한 모델을 자동으로 만들어준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;또 다른 장점은, 여러 가지 상황에 대한 응답값 커스터마이징을 안 해줘도 된다는 점이다. 화면마다 응답값이 조금씩 다른데 사용하는 모델이 같은 경우, REST의 경우 각각 따로 만들어줘야 했지만, GraphQL의 경우 클라이언트가 알아서 응답값을 정해서 조회할 수 있기 때문에 작업이 매우 편하다. 하지만 특정 값에 대한 특정 계산식이 들어가야 하는 경우는 REST와 마찬가지로 API를 분리해서 만들어줘야 하는 건 동일하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;단점은,, 음 binary를 이용한 업로드가 불편하다. 쉽게 말하면 파일 업로드가 불편하다. 그리고 인증도 불편했는데, 기존에 사용하던 oauth방식을 그대로 사용하기 위해 이것저것 설정해야 하는 게 맞다. 이건 사실 인증 문제라기보다는 개발자의 접근성? 문제인 것 같다. 많이 안 써봤으니 어려운 게 당연하지 ㅋㅋ&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;그 밖에도 REST에 비해 빈약한 커뮤니티가 있다. 문제가 생겼을 때 검색을 해도 잘 안 나온다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3장 ~ 4장&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GraphQL에 대한 문법이다 설계방법 등이 나온다. GraphQL에는 조회를 위한 기능 Query, 수정 업데이트를 위한 기능 Mutation을 제공한다. CRUD에서 R과 CUD를 따로 분리해서 Query와 Mutation으로 나눴다고 생각하면 편하다. 사이드 프로젝트를 할 때 이 두 가지 기능만 생각하고 만들었는데, 책을 보니 다른 기능들도 제공하고 있었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Subscription - 구독하는 기능. 이 Subscription이 있었다면 클라이언트에서 polling 하는 구조로 만들지 않았을 텐데 ㅋㅋ 자체적으로 아마 웹소켓을 구현해서 서버에서 클라이언트로 푸시하는 기능을 제공하고 있다. 대단..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Instrospection - 위에서 말했듯이 GraphQL에서 제공하는 API 스펙을 조회할 수 있는 기능이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5장 ~ 7장&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 GraphQL로 API를 만드는 내용을 다루고 있다. 꽤 실무적이긴 한데 너무 간단한(?) 예제라서 지루하다. ㅎㅎ 회사에서는 아주 복잡한 비즈니스 모델을 다룬다고!!  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;스터디 후기&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;2주 만에 후딱 끝낸 스터디라서 후기가 쓸게 없다 ㅋㅋ &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;팀원들 모두 간단하게 아~ 이런 게 있구나~ 하고 넘어간 느낌? 특히나 GraphQL에 대한 경험이 없는 팀원들은 그냥 쓰-윽- 하고 책을 읽은 느낌이라고 한다. 이런 프레임워크는 실습이 중요하기 때문에 뭔가 만들어보면서 하는 게 좋은데, 직장인이라 시간이 없잖아!?!  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;그래도 평일 짬시간과 주말을 노려서 각자 어느 정도 GraphQL을 이용한 API를 만들어보긴 했다. 어느 정도 짬이 있으면 간단한 API는 금방 만드니까 ㅎㅎ&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;GraphQL을 배우고 가장 큰 수확은 Query와 Mutation 말고 다양한 방법이 있다랄까? REST에 비해 코드를 적게 써도 돼서 생산성이 높게 보일 수 있는데, 이것도 제대로 쓰려면 REST와 비슷하게 이것저것 설정해줘야 할게 많고 최적화를 위해 이것저것 해줘야 할 것 같다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;우리 팀에서 내린 결론은 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;조회가 많은 서비스에는 용이하지만 CUD가 많은 서비스에는 글쎄?&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Study/회사 팀스터디</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/588</guid>
      <comments>https://cholol.tistory.com/588#entry588comment</comments>
      <pubDate>Tue, 2 May 2023 16:43:30 +0900</pubDate>
    </item>
    <item>
      <title>Django:제로부터 시작하는 인스타그램 만들기 - DevOps #5 - SSL 적용하기, AWS ALB  + ROUTE53 이용하기</title>
      <link>https://cholol.tistory.com/587</link>
      <description>&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://cholol.tistory.com/550&quot; target=&quot;_self&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #337ab7;&quot;&gt;2021.09.15 - [Course/django : 제로부터 시작하는 인스타그램] - Django:제로부터 시작하는 인스타그램 만들기 - clone instagram 목차&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;유튜브 버전 - &lt;a href=&quot;https://youtu.be/DKDod2Nl_Ww&quot; target=&quot;_blank&quot;&gt;&lt;span&gt;https://youtu.be/DKDod2Nl_Ww&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=DKDod2Nl_Ww&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/bfSe3g/hySozWtlfG/Hs1roFGYLSvt4wEVEfMqzK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-origin-width=&quot;1280&quot; data-video-origin-height=&quot;720&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/DKDod2Nl_Ww&quot; width=&quot;300&quot; height=&quot;225&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;시작하기 전에&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: center;&quot;&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&lt;b&gt;이 강의는 ROUTE53을 이용해 도메인을 발급받아야 SSL인증서를 발급받을 수 있습니다. AWS에서 ROUTE53을 이용한 도메인 발급 비용은 보통 1년에 만원정도 합니다. 발급하지 못하면 SSL적용이 힘드니 참고해 주세요~&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: center;&quot;&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;SSL(Secure Sockets Layer)이라는 말을 많이 들어보았을 겁니다. 약간 연차가 있는 분들은 TLS라고 부르기도 하는데 같은 말입니다. ㅎㅎ&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;HTTP통신에 암호화를 추가해 보안성을 높여 HTTPS 통신으로 만들어주는 게 바로 SSL입니다. 아마 여러분들 웹 서핑을 할 때 어떤 페이지는 HTTP고 어떤 페이지는 HTTPS였던 걸 기억하실 겁니다. 큰 웹사이트는 대부분 HTTPS지만, 개인 웹사이트나 작은 웹은 아직도 HTTP를 사용하는 곳이 많습니다. 요즘엔 브라우저가 HTTP 웹사이트에 들어가면 경고를 띄워주더라고요.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;HTTPS가 HTTP와 다른 점은 간단합니다. 서로 통신을 할 때 암호화를 하냐 안 하냐 차이입니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1498&quot; data-origin-height=&quot;1069&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VGsxD/btsb1RRC07v/3P4S2CcYKjCBKLJNi9xhck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VGsxD/btsb1RRC07v/3P4S2CcYKjCBKLJNi9xhck/img.png&quot; data-alt=&quot;HTTP VS HTTPS&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VGsxD/btsb1RRC07v/3P4S2CcYKjCBKLJNi9xhck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVGsxD%2Fbtsb1RRC07v%2F3P4S2CcYKjCBKLJNi9xhck%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1498&quot; height=&quot;1069&quot; data-origin-width=&quot;1498&quot; data-origin-height=&quot;1069&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;HTTP VS HTTPS&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;ROUTE53 도메인 발급하기&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;SSL을 적요하려면 도메인이 필요하기 때문에 우선 도메인 발급부터 진행하겠습니다. AWS에서 ROUTE53이라는 서비스를 이용해 도메인을 발급할 수 있습니다. (유료!! )&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1845&quot; data-origin-height=&quot;453&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4u4hO/btscfAIrRSk/QY0dx2D3kTbv9uMiZppbkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4u4hO/btscfAIrRSk/QY0dx2D3kTbv9uMiZppbkK/img.png&quot; data-alt=&quot;route 53&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4u4hO/btscfAIrRSk/QY0dx2D3kTbv9uMiZppbkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4u4hO%2FbtscfAIrRSk%2FQY0dx2D3kTbv9uMiZppbkK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1845&quot; height=&quot;453&quot; data-origin-width=&quot;1845&quot; data-origin-height=&quot;453&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;route 53&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2498&quot; data-origin-height=&quot;1198&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/B2z1q/btsb5lyjbgm/VMG1ziw8ynHx2oDYkMYDIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/B2z1q/btsb5lyjbgm/VMG1ziw8ynHx2oDYkMYDIK/img.png&quot; data-alt=&quot;도메인 등록&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/B2z1q/btsb5lyjbgm/VMG1ziw8ynHx2oDYkMYDIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB2z1q%2Fbtsb5lyjbgm%2FVMG1ziw8ynHx2oDYkMYDIK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2498&quot; height=&quot;1198&quot; data-origin-width=&quot;2498&quot; data-origin-height=&quot;1198&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;도메인 등록&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ROUTE53에서 왼쪽에 등록된 도메인을 누르면 도메인을 등록할 수 있습니다. 도메인 등록 버튼을 누르면 도메인 이름을 정할 수 있습니다. 이미 있는 도메인은 안됩니다 ㅎㅎ 이미 있으면 다른 도메인을 추천해 줍니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2329&quot; data-origin-height=&quot;1263&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/W7zXC/btscmMhtDba/mqK8NPDtd0AIOIBY6KraT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/W7zXC/btscmMhtDba/mqK8NPDtd0AIOIBY6KraT0/img.png&quot; data-alt=&quot;django-zero라고 입력&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/W7zXC/btscmMhtDba/mqK8NPDtd0AIOIBY6KraT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FW7zXC%2FbtscmMhtDba%2FmqK8NPDtd0AIOIBY6KraT0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2329&quot; height=&quot;1263&quot; data-origin-width=&quot;2329&quot; data-origin-height=&quot;1263&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;django-zero라고 입력&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가격이 아주 비싸졌네요,, 작년엔 5달러짜리도 있었는데 ㅠㅠ&lt;br&gt;&amp;nbsp;&lt;br&gt;가장 저렵한 도메인을 선택하고 장바구니에 담으면 결제화면으로 넘어갑니다. 결제화면에서 개인정보들을 입력하면 구매 완료!!&lt;br&gt;&amp;nbsp;&lt;br&gt;시간이 어느 정도 지나면 구매가 확정되고 도메인을 사용할 수 있게 됩니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;저는 이미 &lt;b&gt;nullnullstudio.co라는 도메인을&lt;/b&gt; 사용하고 있기 때문에 해당 도메인으로 포스팅을 진행하도록 하겠습니다.&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;HTTPS의 상세 과정&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;HTTPS의 과정을 다음과 같이 진행됩니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;&lt;li&gt;클라이언트와 서버 간에 &lt;b&gt;랜덤 값(서버와 클라이언트 각각 생성)&lt;/b&gt; 교환 (이때 서버에서는 &lt;b&gt;인증서&lt;/b&gt;도 함께 전송)&lt;/li&gt;&lt;li&gt;클라이언트에서는 수신된 &lt;b&gt;인증서&lt;/b&gt; 검증 (인증 기관을 통해서 검증)&lt;/li&gt;&lt;li&gt;클라이언트는 &lt;u&gt;서버와 클라이언트가 생성한 랜덤값을 섞어서&lt;/u&gt; &lt;b&gt;pre-master secret&lt;/b&gt;을 생성 후, &lt;b&gt;인증서의 공개키(인증서에 포함되어 있음)&lt;/b&gt;로 암호화하여 서버로 전송&lt;/li&gt;&lt;li&gt;서버는 &lt;b&gt;인증서의 개인키(서버만 가지고 있음)&lt;/b&gt;를 사용해 &lt;b&gt;pre-master secret&lt;/b&gt;을 복호화합니다.&lt;/li&gt;&lt;li&gt;서버와 클라이언트 각각 정해진 암호화 방식을 사용하여 &lt;b&gt;pre-master secret&lt;/b&gt;을 암호화하고, 해시 함수를 통해 해싱합니다. 이때 나온 결과값이 &lt;b&gt;master secret&lt;/b&gt;입니다.&lt;/li&gt;&lt;li&gt;이제 서버와 클라이언트 모두 동일한 &lt;b&gt;master secret&lt;/b&gt; 값을 가지고 있으므로, 이 값을 이용해 통신할 때 전송하는 데이터를 암호화/복호화합니다.&lt;/li&gt;&lt;/ol&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;글로 열심히 적어보았는데, 풀어서 설명을 해 볼까요? 일단 1번에서 클라이언트가 먼저 서버에 랜덤 한 값을 전송합니다. 추가로 어떤 master secret을 만들 때 클라이언트가 사용 가능한 암호화 방법들을 전달합니다. 서버는 요청을 받으면 역시 랜덤 한 값을 클라이언트에게 전달하고, 클라이언트가 전달한 암호화 방법들 중에 가장 안전한 방법을 고릅니다.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;아래 그림은 클라이언트에서 &quot;mychew&quot;라는 랜덤 값과 [&quot;AES&quot;, &quot;3DES&quot;..]로 암호화 방법들을 리스트 형태로 전달하는 모습입니다. 서버는 마찬가지로 &quot;youtube&quot;라는 랜덤 값을 전달했고, 암호화 방법들 중에 &quot;AES&quot;를 선택했습니다. 그리고 제일 중요한 &quot;&lt;b&gt;인증서&lt;/b&gt;&quot;를 보냅니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1713&quot; data-origin-height=&quot;688&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6Sj7m/btsbVcBU54r/FNtq1QronKkyUDbnjLHUhK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6Sj7m/btsbVcBU54r/FNtq1QronKkyUDbnjLHUhK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6Sj7m/btsbVcBU54r/FNtq1QronKkyUDbnjLHUhK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6Sj7m%2FbtsbVcBU54r%2FFNtq1QronKkyUDbnjLHUhK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1713&quot; height=&quot;688&quot; data-origin-width=&quot;1713&quot; data-origin-height=&quot;688&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;이렇게 인증서를 전달받은 클라이언트는 해당 인증서가 신뢰할 수 있는 인증서인지 검증합니다. 해당 인증서에는 인증서 발급기관과 공개키 등의 정보가 있는데, 인증서 발급기관(CA)이 신뢰할 수 있는 발급기관인지 확인합니다. 여기서 이제 어떻게 신뢰할 수 있을까?라는 고민을 할 수 있는데, 보통 웹 브라우저나 OS는 신뢰할 수 있는 인증기관 목록을 가지고 있기 때문에 해당 인증서가 목록에 있는지 검사하게 됩니다. 만약 목록에 없는 인증서 발급기관이라면, 함께 온 공개키를 이용해 서명검증을 하게 됩니다. 이때 서명검증을 해서 인증서가 유효한지는 확인할 수 있지만, 신뢰할 수 있는 인증기관은 아니기 때문에 주의해야 합니다. 가끔 웹페이지 들어갔을 때 신뢰할 수 없는 인증서!!라고 빨갛게 뜨는 사이트가 있는데, 사설 인증서를 사용하면 요롷게 뜹니다 ㅎㅎ.&lt;br&gt;&amp;nbsp;&lt;br&gt;인증서확인이 끝나면 클라이언트는, 서버와 클라이언트가 각각 생성한 랜덤값을 가지고 공개키로 암호화합니다. 이 값이 pre-master secret 값입니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1575&quot; data-origin-height=&quot;578&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qtQXl/btsca0f8Fbt/TCeKuxRTzvuOK4XiYVLXMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qtQXl/btsca0f8Fbt/TCeKuxRTzvuOK4XiYVLXMK/img.png&quot; data-alt=&quot;pre-master secret&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qtQXl/btsca0f8Fbt/TCeKuxRTzvuOK4XiYVLXMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqtQXl%2Fbtsca0f8Fbt%2FTCeKuxRTzvuOK4XiYVLXMK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1575&quot; height=&quot;578&quot; data-origin-width=&quot;1575&quot; data-origin-height=&quot;578&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;pre-master secret&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 클라이언트와 서버가 모두 pre-master secret값을 가지고 있습니다. 이제 앞서 정의한 암호화 방식을 통해 이 값을 암호화하고 해싱함수를 통해 해시하면 master secret값이 나오게 됩니다. 지원하는 암호화 방식이나 해시방식은 TLS 스펙에 따라 다릅니다. (보통 라이브러리가 알아서 정해주니,,,)&lt;br&gt;&amp;nbsp;&lt;br&gt;이렇게 양쪽에 master secret이 생겼으니, 이 값으로 이제 암호화해서 데이터를 전달하면 됩니다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1589&quot; data-origin-height=&quot;487&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VIWIR/btsbTV8yfs9/SzzUCx7T79Sh4R1mfQR7ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VIWIR/btsbTV8yfs9/SzzUCx7T79Sh4R1mfQR7ck/img.png&quot; data-alt=&quot;master secret으로 암호화하여 전달&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VIWIR/btsbTV8yfs9/SzzUCx7T79Sh4R1mfQR7ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVIWIR%2FbtsbTV8yfs9%2FSzzUCx7T79Sh4R1mfQR7ck%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1589&quot; height=&quot;487&quot; data-origin-width=&quot;1589&quot; data-origin-height=&quot;487&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;master secret으로 암호화하여 전달&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;master secret은 대칭키이기 때문에 암호화 한 데이터를 복호화하기 위해서 그대로 master secret을 사용하면 됩니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;우리 서버에 SSL 적용하기&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;자 이제 이론을 알았으니 적용을 해볼까요? SSL을 적용하는 방법은 여러 가지가 있는데, AWS인증서를 사용해서 AWS ALB(Application Load Balancer)를 이용해 적용하는 방법이 있고, 사설 인증서를 만든 다음 NGINX에 적용하는 선택지가 있습니다. 양쪽 다 SSL을 이용하는 건 동일한데 한 가지 고려해야 할 점이 있습니다. 바로 '어디서 암호화/복호화를 하느냐'인데요,&lt;br&gt;&amp;nbsp;&lt;br&gt;NGINX에 인증서를 등록해서 암/복호화를 한다면 EC2에서 암복호화가 진행됩니다. 그럼 저희 EC2의 CPU와 메모리가 소모됩니다. 하지만 AWS에 ALB에 인증서 등록하고 사용하면 암복호화를 ALB가 대신해 주게 됩니다. 그 후 ALB와 EC2사이의 통신은 HTTP로 이루어지기 때문에 EC2에서는 암복호화를 신경 쓰지 않아도 됩니다. 암복호화를 보통 SSL 터미네이션이라고 하는데, SSL 터미네이션을 어느 구간에서 하는지가 서버 성능에 영향을 미치기 때문에 대용량 서비스를 구축할 때는 신중해야 합니다. 물론 저희는 상관없지만요  &amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;아 그리고 ALB에서 SSL 터미네이션을 한다고 해서 서버가 무조건 좋은 건 아닙니다. ALB도 사용 가능한 자원이 있기 때문에 많은 요청이 들어오면 힘들어합니다. AWS의 ALB는 요청에 따라 자동으로 서버가 늘어나고 줄어드는 auto scale이 되기 때문에 그나마 EC2보다는 설정이 간단합니다. (EC2도 auto scale 되지만,,, ㅎㅎ)&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;자 그럼 AWS에 ALB를 이용해 SSL통신을 적용해 볼까요?&amp;nbsp; (&lt;s&gt;생각보다 간단함 주의&lt;/s&gt;)&lt;br&gt;&amp;nbsp;&lt;br&gt;일단 ALB를 만들어야 하는데 ALB는 EC2 대시보드에서 생성할 수 있습니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3620&quot; data-origin-height=&quot;1692&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPuq15/btsbT2zICTH/2XS637SkZviCJI1vlKCro0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPuq15/btsbT2zICTH/2XS637SkZviCJI1vlKCro0/img.png&quot; data-alt=&quot;로드 밸런서 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPuq15/btsbT2zICTH/2XS637SkZviCJI1vlKCro0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPuq15%2FbtsbT2zICTH%2F2XS637SkZviCJI1vlKCro0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3620&quot; height=&quot;1692&quot; data-origin-width=&quot;3620&quot; data-origin-height=&quot;1692&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;로드 밸런서 생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성하기에 들어가면 ALB, NLB, GLB 등을 선택하는 화면이 나옵니다. 저희는 ALB를 생성합니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2146&quot; data-origin-height=&quot;1660&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1eE47/btscfzQcP5D/v0SLWZK84mUsKNxpn7h6Yk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1eE47/btscfzQcP5D/v0SLWZK84mUsKNxpn7h6Yk/img.png&quot; data-alt=&quot;ALB 선택&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1eE47/btscfzQcP5D/v0SLWZK84mUsKNxpn7h6Yk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1eE47%2FbtscfzQcP5D%2Fv0SLWZK84mUsKNxpn7h6Yk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2146&quot; height=&quot;1660&quot; data-origin-width=&quot;2146&quot; data-origin-height=&quot;1660&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ALB 선택&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;그럼 이제 상세 설정화면이 나오는데요, 일단 Load Balancer name을 정합니다. 저희는 django_zero_alb라고 할게요.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2132&quot; data-origin-height=&quot;384&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tK10g/btsca1lXYkI/o8OlWKvKg0gEh4BkGL5eik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tK10g/btsca1lXYkI/o8OlWKvKg0gEh4BkGL5eik/img.png&quot; data-alt=&quot;이름 정하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tK10g/btsca1lXYkI/o8OlWKvKg0gEh4BkGL5eik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtK10g%2Fbtsca1lXYkI%2Fo8OlWKvKg0gEh4BkGL5eik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2132&quot; height=&quot;384&quot; data-origin-width=&quot;2132&quot; data-origin-height=&quot;384&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이름 정하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;그리고 아래 VPC는 아마 디폴트로 하나가 되어있을 겁니다. 그냥 건들지 않으면 되고, 아래 mappings에서 AZ 두 개를 골라야 합니다. 이전에 말했다시피 고가용성을 지원하기 위해 AZ는 2개 이상으로 골라야 합니다. 여기서는 우리의 EC2가 어디에 위치에 있는지 확인하고 골라야 합니다. 제 EC2는 a존에 있기 때문에 a와 c를 고르겠습니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2970&quot; data-origin-height=&quot;162&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Du3n6/btscjkekpWy/ALRkViVF2jbp0w6D1dHxCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Du3n6/btscjkekpWy/ALRkViVF2jbp0w6D1dHxCk/img.png&quot; data-alt=&quot;가용 영역 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Du3n6/btscjkekpWy/ALRkViVF2jbp0w6D1dHxCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDu3n6%2FbtscjkekpWy%2FALRkViVF2jbp0w6D1dHxCk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2970&quot; height=&quot;162&quot; data-origin-width=&quot;2970&quot; data-origin-height=&quot;162&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가용 영역 확인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2112&quot; data-origin-height=&quot;834&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCOY9w/btsbVeGxuhU/iJD09nd8PkO2kSbR1yZkkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCOY9w/btsbVeGxuhU/iJD09nd8PkO2kSbR1yZkkk/img.png&quot; data-alt=&quot;https 선택&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCOY9w/btsbVeGxuhU/iJD09nd8PkO2kSbR1yZkkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCOY9w%2FbtsbVeGxuhU%2FiJD09nd8PkO2kSbR1yZkkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2112&quot; height=&quot;834&quot; data-origin-width=&quot;2112&quot; data-origin-height=&quot;834&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https 선택&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 아래 보안그룹(security group)은 디폴트로 설정하고, 제일 중요한 Listeners and routing 박스를 봅시다. 여기에서 프로토콜을 선택할 수 있는데, 우리는 ssl을 사용하기 때문에 https를 선택해 줍니다. 그럼 포트번호가 443으로 변경됩니다. 옆에는 타겟 그룹(target group)을 정하라는 창이 있는데 타겟 그룹이란 ALB가 바라보는 ec2 그룹입니다.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1203&quot; data-origin-height=&quot;1031&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mODAL/btsbSKNb5Ip/pFNnJ3ijAEMtWepHT9GaQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mODAL/btsbSKNb5Ip/pFNnJ3ijAEMtWepHT9GaQK/img.png&quot; data-alt=&quot;타겟 그룹&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mODAL/btsbSKNb5Ip/pFNnJ3ijAEMtWepHT9GaQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmODAL%2FbtsbSKNb5Ip%2FpFNnJ3ijAEMtWepHT9GaQK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;343&quot; data-origin-width=&quot;1203&quot; data-origin-height=&quot;1031&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;타겟 그룹&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 타겟 그룹을 정하게 되면 ALB는 타겟 그룹안에 있는 EC2에 들어온 요청을 골고루 분배하게됩니다. 하지만 저희는 EC2가 한대니까 ALB로 들어온 요청은 모두 하나의 EC2로 가게되겠죠? ㅎㅎ 그래서 사실 EC2가 하나면 필요가 없긴한데,, SSL를 적용하기 위해서 ALB를 사용하는 겁니다. 참고로 이런 ALB의 로드밸런싱 기능은 NGINX에서도 가능합니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1048&quot; data-origin-height=&quot;635&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q4UsC/btscjjT5jgI/vEnkyGFuZatbRpt0TJezXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q4UsC/btscjjT5jgI/vEnkyGFuZatbRpt0TJezXk/img.png&quot; data-alt=&quot;실제 우리의 서버&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q4UsC/btscjjT5jgI/vEnkyGFuZatbRpt0TJezXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq4UsC%2FbtscjjT5jgI%2FvEnkyGFuZatbRpt0TJezXk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;303&quot; data-origin-width=&quot;1048&quot; data-origin-height=&quot;635&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실제 우리의 서버&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;따라서 우리는 타겟 그룹을 만들어주고, 그 안에 우리가 만든 EC2하나만 넣어주면 됩니다. create target group을 선택하면 타겟 그룹을 어떻게 만들래?라는 화면이 뜨는데 instances를 선택하고 아래 Target group name은 아무렇게나 지어줍니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1952&quot; data-origin-height=&quot;1532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ce7GGN/btsb1Qk2z27/pP67M3JpoH81S0LpZdHAGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ce7GGN/btsb1Qk2z27/pP67M3JpoH81S0LpZdHAGk/img.png&quot; data-alt=&quot;타겟 그룹 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ce7GGN/btsb1Qk2z27/pP67M3JpoH81S0LpZdHAGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fce7GGN%2Fbtsb1Qk2z27%2FpP67M3JpoH81S0LpZdHAGk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1952&quot; height=&quot;1532&quot; data-origin-width=&quot;1952&quot; data-origin-height=&quot;1532&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;타겟 그룹 생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;여기서 &lt;u&gt;&lt;b&gt;중요한 것&lt;/b&gt;&lt;/u&gt;은 사용하는 프로토콜이 HTTP라는 점입니다. 클라이언트와 ALB사이는 HTTPS지만 ALB에서 SSL 터미네이션을 하기 대문에 ALB와 EC2사이는 HTTP통신입니다.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;아래로 내리면 Health checks가 있는데, 이것은 ALB가 EC2에 헬스체크를 할 수 있도록 헬스체크용 API url을 입력하라고 나옵니다. 저희는 헬스체크를 안 만들었는데 말이죠.. ㅎㅎ 일단 /admin이라고 아무거나 get으로 요청했을 때 200 응답이 내려오는 url을 입력해 줍니다.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1608&quot; data-origin-height=&quot;544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XiCBf/btscaZn9scG/ueDL89mk2sv5WCBymjjhM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XiCBf/btscaZn9scG/ueDL89mk2sv5WCBymjjhM0/img.png&quot; data-alt=&quot;임시방편 ㅎㅎ&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XiCBf/btscaZn9scG/ueDL89mk2sv5WCBymjjhM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXiCBf%2FbtscaZn9scG%2FueDL89mk2sv5WCBymjjhM0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1608&quot; height=&quot;544&quot; data-origin-width=&quot;1608&quot; data-origin-height=&quot;544&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;임시방편 ㅎㅎ&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;타겟 그룹을 생성하고 나면 타겟 등록(Register targets)화면이 나옵니다. 여기서 EC2들 중에 만드려는 타겟 그룹에 들어가는 EC2를 선택할 수 있습니다. 저희가 만든 인스타 EC2를 선택합니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3148&quot; data-origin-height=&quot;1382&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfppoR/btsbXJ0Ek6V/oJsB0wzYZiSU7jHmOxPpMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfppoR/btsbXJ0Ek6V/oJsB0wzYZiSU7jHmOxPpMk/img.png&quot; data-alt=&quot;EC2 선택하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfppoR/btsbXJ0Ek6V/oJsB0wzYZiSU7jHmOxPpMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfppoR%2FbtsbXJ0Ek6V%2FoJsB0wzYZiSU7jHmOxPpMk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3148&quot; height=&quot;1382&quot; data-origin-width=&quot;3148&quot; data-origin-height=&quot;1382&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;EC2 선택하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Include as pending below 버튼을 누르면 선택한 ec2가 아래 Review targets로 내려갑니다. 이제 해당 EC2는 타겟 그룹 소속입니다. ㅎㅎ create target group을 눌러서 생성을 마무리합니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;그리고 다시 이전 ALB생성으로 돌아가서 우리가 방금 만든 타겟 그룹을 지정해 줍니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1319&quot; data-origin-height=&quot;339&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ngrDq/btsca0UTkDe/pgnhbchtDxduwZUvSYAYVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ngrDq/btsca0UTkDe/pgnhbchtDxduwZUvSYAYVK/img.png&quot; data-alt=&quot;타겟 그룹 지정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ngrDq/btsca0UTkDe/pgnhbchtDxduwZUvSYAYVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FngrDq%2Fbtsca0UTkDe%2FpgnhbchtDxduwZUvSYAYVK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;154&quot; data-origin-width=&quot;1319&quot; data-origin-height=&quot;339&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;타겟 그룹 지정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;옆에 새로고침 버튼을 누르면 타겟 그룹 목록이 갱신되기 때문에 나오지 않는다면 한번 눌러줍니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;이제 바로 아래 Secure listener settings가 있는데 여기가 바로 대망의 SSL설정입니다. Security polict는 사용하는 TLS 버전인데, recommended가 디폴트로 설정되어 있기 때문에 건드리지 않습니다. 오른쪽에는 SSL/TLS certificate가 있는데 여기에 바로 인증서를 넣어야 합니다. 하지만 저희는 인증서가 없잖아요? AWS에서 인증서도 발급해 줍니다.  &lt;br&gt;&amp;nbsp;&lt;br&gt;AWS에 인증서 서비스는 바로 ACM입니다. AWS Certificate Manager의 약자인데요, 아래 파란색으로 쓰여있는 Request new ACM certificate를 누르면 인증서를 발급할 수 있습니다.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2898&quot; data-origin-height=&quot;914&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LDBm0/btsb2TBUe5e/sWFl63mPATtYQMdh9MpSD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LDBm0/btsb2TBUe5e/sWFl63mPATtYQMdh9MpSD0/img.png&quot; data-alt=&quot;인증서 요청&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LDBm0/btsb2TBUe5e/sWFl63mPATtYQMdh9MpSD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLDBm0%2Fbtsb2TBUe5e%2FsWFl63mPATtYQMdh9MpSD0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2898&quot; height=&quot;914&quot; data-origin-width=&quot;2898&quot; data-origin-height=&quot;914&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;인증서 요청&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 도메인 이름을 적어야 하는데, 앞서 생성했던 route53의 도메인을 이용합니다.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2502&quot; data-origin-height=&quot;1458&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AiiP2/btsb1PNeeIk/CEkej4CHnSkvMucWT7DmQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AiiP2/btsb1PNeeIk/CEkej4CHnSkvMucWT7DmQK/img.png&quot; data-alt=&quot;도메인 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AiiP2/btsb1PNeeIk/CEkej4CHnSkvMucWT7DmQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAiiP2%2Fbtsb1PNeeIk%2FCEkej4CHnSkvMucWT7DmQK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2502&quot; height=&quot;1458&quot; data-origin-width=&quot;2502&quot; data-origin-height=&quot;1458&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;도메인 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인 도메인이 nullnullstudio.co이고 앞에 서브 도메인을 django-devops라고 설정했습니다.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2910&quot; data-origin-height=&quot;256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bme9TM/btsb1QZEcsm/MlXnIrkKF1wH5sc1ReDDeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bme9TM/btsb1QZEcsm/MlXnIrkKF1wH5sc1ReDDeK/img.png&quot; data-alt=&quot;생성됨&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bme9TM/btsb1QZEcsm/MlXnIrkKF1wH5sc1ReDDeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbme9TM%2Fbtsb1QZEcsm%2FMlXnIrkKF1wH5sc1ReDDeK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2910&quot; height=&quot;256&quot; data-origin-width=&quot;2910&quot; data-origin-height=&quot;256&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;생성됨&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로고침을 하면 새로운 인증서가 생성되었는데 아직 부적격입니다. DNS를 이용한 검증을 해야 하기 때문입니다. 인증서 ID를 눌러서 들어가면 상세 정보가 나오는데 여기서 Route 53에서 레코드 생성을 누릅니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2992&quot; data-origin-height=&quot;1246&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oKFUG/btsbV6uYQx7/SANx3mVD063kvwbOPw5QIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oKFUG/btsbV6uYQx7/SANx3mVD063kvwbOPw5QIK/img.png&quot; data-alt=&quot;레코드 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oKFUG/btsbV6uYQx7/SANx3mVD063kvwbOPw5QIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoKFUG%2FbtsbV6uYQx7%2FSANx3mVD063kvwbOPw5QIK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2992&quot; height=&quot;1246&quot; data-origin-width=&quot;2992&quot; data-origin-height=&quot;1246&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;레코드 생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;그럼 자동으로 인증서에 해당하는 DNS레코드를 생성해 줍니다. 레코드 생성을 누릅니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2272&quot; data-origin-height=&quot;754&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjSk30/btscjjs2VCs/WpcX1w7XeNr6Wu3dVQ3qJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjSk30/btscjjs2VCs/WpcX1w7XeNr6Wu3dVQ3qJK/img.png&quot; data-alt=&quot;레코드 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjSk30/btscjjs2VCs/WpcX1w7XeNr6Wu3dVQ3qJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjSk30%2Fbtscjjs2VCs%2FWpcX1w7XeNr6Wu3dVQ3qJK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2272&quot; height=&quot;754&quot; data-origin-width=&quot;2272&quot; data-origin-height=&quot;754&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;레코드 생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2060&quot; data-origin-height=&quot;79&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/82pDL/btsbT113ySk/2feX5Z565qIcgIJVFYiKxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/82pDL/btsbT113ySk/2feX5Z565qIcgIJVFYiKxk/img.png&quot; data-alt=&quot;route53&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/82pDL/btsbT113ySk/2feX5Z565qIcgIJVFYiKxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F82pDL%2FbtsbT113ySk%2F2feX5Z565qIcgIJVFYiKxk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2060&quot; height=&quot;79&quot; data-origin-width=&quot;2060&quot; data-origin-height=&quot;79&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;route53&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 route53에서 호스팅 영역에 레코드가 하나 생성된 게 확인됩니다.&amp;nbsp; (아직 django-devops.nullnullstudio.co라는 서브도메인 호스팅은 생성하지 않았습니다.)&lt;br&gt;&amp;nbsp;&lt;br&gt;자 이제 인증서를 만들었으니 다시 ALB생성 화면으로 돌아갑니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;504&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLNhdD/btscjklbID3/I2ADKNFXz29HiVqWkWJCBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLNhdD/btscjklbID3/I2ADKNFXz29HiVqWkWJCBK/img.png&quot; data-alt=&quot;인증서 선택&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLNhdD/btscjklbID3/I2ADKNFXz29HiVqWkWJCBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLNhdD%2FbtscjklbID3%2FI2ADKNFXz29HiVqWkWJCBK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;203&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;504&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;인증서 선택&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;자 이제 ALB를 생성할 수 있습니다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3070&quot; data-origin-height=&quot;648&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bY7u9G/btsbUQePRGK/yyJA9qDkWV8PJxbaJN76C0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bY7u9G/btsbUQePRGK/yyJA9qDkWV8PJxbaJN76C0/img.png&quot; data-alt=&quot;생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bY7u9G/btsbUQePRGK/yyJA9qDkWV8PJxbaJN76C0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbY7u9G%2FbtsbUQePRGK%2FyyJA9qDkWV8PJxbaJN76C0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3070&quot; height=&quot;648&quot; data-origin-width=&quot;3070&quot; data-origin-height=&quot;648&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;이제 마지막으로 route53에서 django-devops.nullnullstudio.co라는 호스팅을 만들고 방금 만든 alb랑 연동해 줍니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2774&quot; data-origin-height=&quot;592&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rum6r/btsbV6uYYDb/FiJFcyi8d4fw3Z498RqJU0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rum6r/btsbV6uYYDb/FiJFcyi8d4fw3Z498RqJU0/img.png&quot; data-alt=&quot;레코드 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rum6r/btsbV6uYYDb/FiJFcyi8d4fw3Z498RqJU0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Frum6r%2FbtsbV6uYYDb%2FFiJFcyi8d4fw3Z498RqJU0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2774&quot; height=&quot;592&quot; data-origin-width=&quot;2774&quot; data-origin-height=&quot;592&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;레코드 생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;레코드 생성을 누르면 라우팅 정책이 나오는데 단순 라우팅을 선택하고 다음을 누릅니다. 그다음 단순 레코드 정의를 누르고 subdomain인 django-zero를 입력해 줍니다. 레코드 유형은 A이고 엔드포인트는 ALB를 선택합니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1160&quot; data-origin-height=&quot;1386&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciy9Of/btsbUpV0gwh/HvSc8dAvUzkCrxgw74etlk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciy9Of/btsbUpV0gwh/HvSc8dAvUzkCrxgw74etlk/img.png&quot; data-alt=&quot;짜잔&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciy9Of/btsbUpV0gwh/HvSc8dAvUzkCrxgw74etlk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fciy9Of%2FbtsbUpV0gwh%2FHvSc8dAvUzkCrxgw74etlk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1160&quot; height=&quot;1386&quot; data-origin-width=&quot;1160&quot; data-origin-height=&quot;1386&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;짜잔&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;레코드 생성을 눌러서 레코드를 생성합니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;자 그럼 한번 접속해 볼까요?&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;https://django-zero.nullnullstudio.co/main으로 가봅시다&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3292&quot; data-origin-height=&quot;1382&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Nx0WB/btsbTVU7V5Q/oTeu1CO1jPPqSLyf9FBwbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Nx0WB/btsbTVU7V5Q/oTeu1CO1jPPqSLyf9FBwbk/img.png&quot; data-alt=&quot;또잉&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Nx0WB/btsbTVU7V5Q/oTeu1CO1jPPqSLyf9FBwbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNx0WB%2FbtsbTVU7V5Q%2FoTeu1CO1jPPqSLyf9FBwbk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3292&quot; height=&quot;1382&quot; data-origin-width=&quot;3292&quot; data-origin-height=&quot;1382&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;또잉&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;크흑 역시 한 번에 되지 않는군요. 아마 방화벽 문제인 것 같아서 보안그룹을 한번 봐줍니다. 보안그룹을 보니 제가 보안그룹을 RDS 거를 가져다가 쓴 건지 3306만 뚫려있더군요? 그래서 443으로 전체 ip로 열어주었습니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3062&quot; data-origin-height=&quot;122&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dARDmt/btsbT1gD4hz/KkcP0sI6vS4Dl34iZW5PUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dARDmt/btsbT1gD4hz/KkcP0sI6vS4Dl34iZW5PUK/img.png&quot; data-alt=&quot;HTTPS 전체 포트 개방!!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dARDmt/btsbT1gD4hz/KkcP0sI6vS4Dl34iZW5PUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdARDmt%2FbtsbT1gD4hz%2FKkcP0sI6vS4Dl34iZW5PUK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3062&quot; height=&quot;122&quot; data-origin-width=&quot;3062&quot; data-origin-height=&quot;122&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;HTTPS 전체 포트 개방!!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;다시 접속해 보니&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3614&quot; data-origin-height=&quot;328&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/elupWv/btscoGnVS7S/NBwgGJHVI4aYc3GvGJU2a1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/elupWv/btscoGnVS7S/NBwgGJHVI4aYc3GvGJU2a1/img.png&quot; data-alt=&quot;접속은 됨&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/elupWv/btscoGnVS7S/NBwgGJHVI4aYc3GvGJU2a1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FelupWv%2FbtscoGnVS7S%2FNBwgGJHVI4aYc3GvGJU2a1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3614&quot; height=&quot;328&quot; data-origin-width=&quot;3614&quot; data-origin-height=&quot;328&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;접속은 됨&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;접속은 되는데 빨간 줄이 그어져 있네요. 그래서 쭈욱 살펴보니...&lt;br&gt;&amp;nbsp;&lt;br&gt;제가 도메인은 django-zero라고 만들었는데 인증서에는 django-devops라고 정의했지 뭡니까!!!&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2878&quot; data-origin-height=&quot;184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FJDuN/btsbVbJUxYN/L8GkDllCuGUv34ZuXvTdD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FJDuN/btsbVbJUxYN/L8GkDllCuGUv34ZuXvTdD0/img.png&quot; data-alt=&quot;큐...&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FJDuN/btsbVbJUxYN/L8GkDllCuGUv34ZuXvTdD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFJDuN%2FbtsbVbJUxYN%2FL8GkDllCuGUv34ZuXvTdD0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2878&quot; height=&quot;184&quot; data-origin-width=&quot;2878&quot; data-origin-height=&quot;184&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;큐...&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인증서에 연결된 도메인을 바꾸는 것보다 route53의 호스팅을 바꾸는 게 더 편해서 다시 django-devops로 서브도메인을 바꿨습니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1421&quot; data-origin-height=&quot;1179&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UhVcy/btscoCeLxQG/9dsAxhIvhcOGRZgChT0e7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UhVcy/btscoCeLxQG/9dsAxhIvhcOGRZgChT0e7K/img.png&quot; data-alt=&quot;완벽&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UhVcy/btscoCeLxQG/9dsAxhIvhcOGRZgChT0e7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUhVcy%2FbtscoCeLxQG%2F9dsAxhIvhcOGRZgChT0e7K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;415&quot; data-origin-width=&quot;1421&quot; data-origin-height=&quot;1179&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;완벽&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;자 완벽하게 https가 적용되었습니다~!!!&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;❗&lt;/b&gt;&lt;br&gt;&lt;b&gt;이대로 적용하면 우리 인스타그램이 정상적으로 동작하지 않습니다~!&lt;/b&gt;&lt;br&gt;&lt;b&gt;콘솔 로그를 확인해보니 저희 프로젝트에서 jquery를 다운받을 때 아래와 같은 코드를 사용하는데 http를 https로 변경해주시면 됩니다.&lt;/b&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;html&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;/* 기존 */
&amp;lt;!-- Jquery --&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;script src=&quot;http://code.jquery.com/jquery-latest.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
/* https로 수정 */
&amp;lt;!-- Jquery --&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;script src=&quot;https://code.jquery.com/jquery-latest.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리하며&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;ssl 인증서를 적용하기 위해 route53으로 도메인을 등록하고 호스팅을 추가하고 ACM을 통해 인증서를 발급받고 아주 우당탕탕하여 https를 적용했습니다. AWS콘솔에서 진행하는 게 많아서 글로 설명이 많이 어렵네요. 번거롭지만 자세한 사항은 유튭 영상을 확인부탁드립니다. ㅎㅎ&lt;br&gt;&amp;nbsp;&lt;br&gt;이번 시간에 저희가 만든 서버구조는 아래와 같습니다.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1439&quot; data-origin-height=&quot;827&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mbwAG/btsbTphP6NA/uausInUS4FhTkyA24JiG0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mbwAG/btsbTphP6NA/uausInUS4FhTkyA24JiG0k/img.png&quot; data-alt=&quot;서버 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mbwAG/btsbTphP6NA/uausInUS4FhTkyA24JiG0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmbwAG%2FbtsbTphP6NA%2FuausInUS4FhTkyA24JiG0k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;345&quot; data-origin-width=&quot;1439&quot; data-origin-height=&quot;827&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;서버 구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;의도치 않게 DNS와 ALB까지 사용한 큰 구조가 되었네요 ㅎㅎ SSL을 사용하기 위해서는 도메인이 필요하니 아마 가장 쉽게 SSL을 적용할 수 있는 방법이 아닐까 싶습니다. 단, 다른 곳에서 도메인을 구입하신 분은 AWS Route53에서 다른 도메인을 지원해주지 않기 때문에 다른 방법으로 SSL을 등록해야 합니다.  &lt;br&gt;&amp;nbsp;&lt;br&gt;이렇게 이번시간에는 SSL 이론과 적용에 대해서 진행해 보았습니다. 다음시간은 원래 cache에 대한 것인데, 이것은 뭔가 devops의 영역과 코딩의 영역이 섞여있네요  &lt;br&gt;&amp;nbsp;&lt;br&gt;devops영역은 이 정도로 하고 이제 다시 백엔드 코딩으로 넘어가도 좋지 않을까 싶습니다. 원래 생각했던 고오오급 기능들을 구현하면서 머리를 좀 써보는 내용을 다루지 않을까 싶군요 ^^ 고생하셨습니다  &lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Course/django : 제로부터 시작하는 인스타그램</category>
      <category>DevOps</category>
      <category>인스타클론</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/587</guid>
      <comments>https://cholol.tistory.com/587#entry587comment</comments>
      <pubDate>Sun, 23 Apr 2023 22:08:59 +0900</pubDate>
    </item>
    <item>
      <title>Django:제로부터 시작하는 인스타그램 만들기 - DevOps #4 - CI/CD구축하기, 테스트코드 작성, github 액션을 통한 CI/C</title>
      <link>https://cholol.tistory.com/586</link>
      <description>&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://cholol.tistory.com/550&quot; target=&quot;_self&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #337ab7;&quot;&gt;2021.09.15 - [Course/django : 제로부터 시작하는 인스타그램] - Django:제로부터 시작하는 인스타그램 만들기 - clone instagram 목차&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;github - &lt;a href=&quot;https://github.com/tkdlek11112/django_zero_to_instagram_devops&quot; target=&quot;_self&quot;&gt;&lt;span&gt;tkdlek11112/django_zero_to_instagram_devops: 장고 인스타그램 클론코딩 데브옵스편 (github.com)&lt;/span&gt;&lt;/a&gt;&amp;nbsp;&lt;br&gt;&lt;br&gt;유튜브 버젼 - &lt;a href=&quot;https://youtu.be/7bf4rK2rMPM&quot; target=&quot;_blank&quot;&gt;&lt;span&gt;https://youtu.be/7bf4rK2rMPM&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=7bf4rK2rMPM&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/zcHM7/hySoxj4bc9/DkI1Mb7hplxyUuvPRA83Dk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-origin-width=&quot;1280&quot; data-video-origin-height=&quot;720&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/7bf4rK2rMPM&quot; width=&quot;300&quot; height=&quot;225&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;&lt;br&gt;&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;시작하기 전에&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;이번시간에는 CI/CD에 대해서 다룹니다. CI/CD라는 말을 저는 2015년? 2016년? 정도에 처음 들었던 것 같아요. 이때 한창 유행했던 게 CI/CD, RPA등과 같은 자동화에 대한 기술들이었습니다. CI/CD라는 말을 처음 들었을 때는 &lt;b&gt;도대체 그게 뭐임?이라는&lt;/b&gt; 생각이 들었는데 ㅋㅋㅋ 사실 지금도 뭐 비슷합니다.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;일단 CI와 CD를 분리해서 봐야 하는데요, CI는 Continuous Integration이고 CD는 Continuous Deploy입니다. 번역하면 CI는 지속적인 통합이고 CD는 지속적인 배포죠. 배포라는 말은 알겠는데 통합이라는 건 대체 뭔가? 하시는 분이 있을 겁니다. 저도 통합이라고 하면 뭐지? 하는데, 실제로 어떤 일들이 일어나는지 보면, 아~ 이게 통합이구나 알 수 있습니다. ㅎㅎ&lt;br&gt;&amp;nbsp;&lt;br&gt;일단 핵심은 Continuous라는 말인데요, '지속적인'이라는 게 무슨 뜻일까요? 여태까지 우리는 django로 인스타그램 클론코딩을 할 때 변경한 사항을 커밋하고, 푸시해서 github에 올리고, 서버에서 pull 해서 변경된 소스들을 다운로드하고, restart를 통해 변경사항을 적용했습니다. 대부분의 회사에서도 비슷한 일을 하겠죠?&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;소스 수정 -&amp;gt; 변경사항 확인 (테스트) -&amp;gt; 코드 배포 -&amp;gt; 서버에 적용&lt;br&gt;&amp;nbsp;&lt;br&gt;대충 이런 식입니다. 저희는 테스트코드를 만들지 않았기 때문에 로컬에서 실행해서 기능이 잘 되나 확인하고 서버로 배포를 했었는데, CI/CD를 적용하면 소스 수정 후 커밋/푸시만 하면 뒤에 테스트, 코드배포, 서버에 적용을 자동으로 적용해 줍니다. 즉, 개발자는 소스 변경하고 커밋, 푸시만 하면 되는 거죠.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;CI/CD를 구성하는 건 회사마다 너무 다릅니다. 보통 제가 다녔던 회사에서는 CI는 구성하지만 CD는 구성하지 않습니다. 왜냐하면 자동으로 배포가 되는 게 상당히 리스키 할 수 있기 때문이죠. 많은 개발자가 소스를 매번 푸시하고 머지하고 있는 회사에서는 CD가 오히려 독이 될 수 있습니다. 하지만 푸시하는 권한이 한정된 사용자에게만 있고, 승인을 받아야 푸시가 되는 프로세스라면, CD는 도움이 될 수 있습니다.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;CI의 경우는 자동화하는 게 상당히 좋은데요, 보통 회사에서는 테스트 코드를 많이 작성해 놓기 때문에 내가 소스를 변경하고 커밋하고 푸시하는 순간 바로 테스트가 자동으로 돌면서 내가 변경한 소스가 테스트를 통과하는지 확인할 수 있습니다. 물론 내가 변경한 소스 쪽 테스트뿐만 아니라 전체 테스트가 돌기 때문에 더 쉽죠.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;CI에서는 테스트만 하는 것이 아닙니다. compile이 필요한 프레임워크의 경우 compile도 해주고, docker와 같은 이미지를 사용하는 회사라면 docker이미지로 build도 해줍니다. 즉 CI는 &lt;b&gt;배포하기 전에 갖추어야 할 모든 것을 준비한다&lt;/b&gt; 의미죠. 통합이라는 게 이제는 좀 이해가 가시죠?&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;일단 테스트 코드를 만들어 보자&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;일단 저희는 테스트코드가 없습니다. ㅋㅋㅋ 클론코딩에 집중하다 보니 간단한 단위테스트조차 없는데요, 한때 TDD라는 게 유행했던 적이 있습니다. Test Driven Development로 테스트위주의 개발을 하는 것입니다. &lt;b&gt;'아니 개발도 안 했는데 테스트를 어떻게 해?'라고&lt;/b&gt; 생각할 수 도 있는데요, 저도 참 아이러니한 방식이라고 생각합니다만 일단 기능을 구현하기 전에 예외 케이스들을 수도코드로 작성해 보고 테스트코드를 작성한 뒤, 기능을 만들면서 내가 만든 테스트코드를 통과하는지 확인하는 방식으로 진행하는 것이 보통입니다. 이렇게 하면 혹시나 발생할 수 있는 실수를 막을 수 있고, 미처 예상하지 못한 예외케이스도 발견할 수 있죠. 대신 시간이 오래 걸립니다. 그냥 기능만 만들면 30분이면 만드는 걸 테스트코드 짜느라 3시간이 걸릴 수도 있습니다.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;따라서 저는 테스트코드는 작성하되, TDD는 조금 꺼리는 스타일입니다. (제 개인적인 의견입니다 ㅎㅎㅎ ㅎ ㅎㅎ ㅓ헣ㅎ)&lt;br&gt;&amp;nbsp;&lt;br&gt;아무튼 저희는 인스타 클론코딩을 하면서 몇몇 기능들을 이미 구현했기 때문에 해당 기능에 대해 테스트코드를 한번 작성해 보겠습니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;먼저 시작하기 전에, 저희가 지난 시간에 AWS RDS를 보게 해 두었는데, 로컬에서 실행할 때도 AWS RDS를 보는 건 아닌 것 같고, 그렇다고 sqlite로 설정을 바꾸면 나중에 배포할 때 또 바꿔줘야 하는 번거로움이 있습니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;이럴 때는 로컬에서 실행할 때의 settings.py와 서버에서 실행되는 settings.py를 나누는 방법이 있습니다. settings.py가 있는 곳에 settings_local.py 파일을 만듭니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1976&quot; data-origin-height=&quot;592&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uNzAM/btsbRJAtNus/ICREJ1yCPeJga10IEnqW90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uNzAM/btsbRJAtNus/ICREJ1yCPeJga10IEnqW90/img.png&quot; data-alt=&quot;settings_local 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uNzAM/btsbRJAtNus/ICREJ1yCPeJga10IEnqW90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuNzAM%2FbtsbRJAtNus%2FICREJ1yCPeJga10IEnqW90%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1976&quot; height=&quot;592&quot; data-origin-width=&quot;1976&quot; data-origin-height=&quot;592&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;settings_local 생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;from .settings import *를 통해 settings의 모든 내용을 가져옵니다. 거기에 변경할 부분, 데이터베이스 설정만 sqlite로 변경합니다. 이러면 이제 settings가 두 개가 되는데, 로컬에서 runserver를 실행할 때 --settings=Jinstagram.settings_local 옵션을 통해서 새로 만든 settings를 보고 실행되게 할 수 있습니다. migrate도 마찬가지로 뒤에 --settings를 붙이면 aws가 아니라 sqlite3에 마이그레이트를 하게 됩니다.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1386&quot; data-origin-height=&quot;278&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FL4YX/btsbTvVzoGR/BxowQHM2CRP2kHRjVQhESk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FL4YX/btsbTvVzoGR/BxowQHM2CRP2kHRjVQhESk/img.png&quot; data-alt=&quot;옵션 추가&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FL4YX/btsbTvVzoGR/BxowQHM2CRP2kHRjVQhESk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFL4YX%2FbtsbTvVzoGR%2FBxowQHM2CRP2kHRjVQhESk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1386&quot; height=&quot;278&quot; data-origin-width=&quot;1386&quot; data-origin-height=&quot;278&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;옵션 추가&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;더 본격적으로 settings를 분리하는 방법은 다음 링크를 참조하세요~&lt;br&gt;&lt;a href=&quot;https://wikidocs.net/75560&quot; target=&quot;_self&quot;&gt;&lt;span&gt;4-08 settings.py 분리 - 점프 투 장고 (wikidocs.net)&lt;/span&gt;&lt;/a&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;이제 테스트 코드를 만들 텐데, 테스트 코드의 위치는 프로젝트마다 다양합니다. 테스트 코드만 따로 모아서 관리하는 프로젝트도 있고, 장고에 각 APP별로 테스트 코드를 작성하는 프로젝트도 있습니다. 저희는 CI를 위해 간단한 테스트만 작성할 것이므로, 각각의 APP폴더 안에 테스트 코드를 만들어보도록 하겠습니다.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1753&quot; data-origin-height=&quot;968&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/w7ts3/btsbQSjVY5H/Kme3JLYs8zYAh6BnVWXoH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/w7ts3/btsbQSjVY5H/Kme3JLYs8zYAh6BnVWXoH0/img.png&quot; data-alt=&quot;이미 tests.py 파일이 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/w7ts3/btsbQSjVY5H/Kme3JLYs8zYAh6BnVWXoH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fw7ts3%2FbtsbQSjVY5H%2FKme3JLYs8zYAh6BnVWXoH0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1753&quot; height=&quot;968&quot; data-origin-width=&quot;1753&quot; data-origin-height=&quot;968&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이미 tests.py 파일이 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;python manage.py createapp으로 만든 폴더들은 자동으로 tests.py까지 생성해 주네요. 제가 따로 만들지 않아도 user폴더와 content폴더에는 이미 tests.py파일이 있습니다. 저희는 user폴더에 있는 tests.py에 테스트를 추가해 보겠습니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# user/tests.py
from django.test import TestCase


# Create your tests here.
class TestUser(TestCase):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def test_1(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.assertEqual(1, 1)&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;테스트코드는 문법이 조금 특이합니다. 왜냐하면 값이 있다고 가정하거나, 비교해서 맞는지 검증하는 코드이기 때문에 일반적으로 사용하는 python 코드와 이름이 조금 다릅니다. 아마 처음 테스트코드를 작성하신다면 약간의 괴리감(?)이 들 수 있어요.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;TestUser라는 테스트 클래스와 그 안에 test_1이라는 테스트를 하나 만들었습니다. test_1의 내용은 간단한데요, assertEqual(1, 1) 한 줄이 있습니다. assertEqual(a, b)는 a와 b가 같은지 검증하고, 맞으면 true, 틀리면 false를 반환합니다. 즉 a=b면 테스트 통과이고, 아니라면 테스트 실패죠. 테스트 실행하는 법은 쉽습니다. 만약 IDE툴에서 코드옆에 화살표가 보이신다면 화살표를 눌러도 테스트코드가 실행됩니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1012&quot; data-origin-height=&quot;422&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3MqwS/btsbRJtHvDh/tPDfuwDM8kFWsKvgUDckek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3MqwS/btsbRJtHvDh/tPDfuwDM8kFWsKvgUDckek/img.png&quot; data-alt=&quot;화살표로 테스트 코드 실행&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3MqwS/btsbRJtHvDh/tPDfuwDM8kFWsKvgUDckek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3MqwS%2FbtsbRJtHvDh%2FtPDfuwDM8kFWsKvgUDckek%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;250&quot; data-origin-width=&quot;1012&quot; data-origin-height=&quot;422&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;화살표로 테스트 코드 실행&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스 옆에 화살표를 선택하면 클래스 전체의 테스트를 실행하고, 함수 옆에 화살표를 선택하면 함수단위로 실행됩니다. 커맨드로 전체 테스트를 실행하고 싶다면 python manage.py test (--settings=Jinstagram.settings_local)를 입력하면 됩니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2006&quot; data-origin-height=&quot;444&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PrjNB/btsbQF6pUG9/5BSdYNfVKvXk4SJqTlhkz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PrjNB/btsbQF6pUG9/5BSdYNfVKvXk4SJqTlhkz0/img.png&quot; data-alt=&quot;테스트 성공&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PrjNB/btsbQF6pUG9/5BSdYNfVKvXk4SJqTlhkz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPrjNB%2FbtsbQF6pUG9%2F5BSdYNfVKvXk4SJqTlhkz0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2006&quot; height=&quot;444&quot; data-origin-width=&quot;2006&quot; data-origin-height=&quot;444&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;테스트 성공&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트가 1건이 있는데 OK가 된 거 보니 성공했군요. assertEqual(1, 1)이 정상적으로 1과 1을 같다고 판단했나 봅니다. ㅋㅋ&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;그럼 실패되는 경우는 어떻게 되는지 값을 바꿔보겠습니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;from django.test import TestCase


# Create your tests here.
class TestUser(TestCase):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def test_1(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.assertEqual(1, 1)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def test_2(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.assertEqual(1, 2)&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;테스트 2번을 추가했습니다. 1과 2가 같아야 한다는 테스트코드를 심어놨습니다. 한번 돌려볼까요?&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1902&quot; data-origin-height=&quot;762&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXk7UW/btsbQvJjZjs/DYIiDgXYkk2Kg9WwmA27K0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXk7UW/btsbQvJjZjs/DYIiDgXYkk2Kg9WwmA27K0/img.png&quot; data-alt=&quot;테스트 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXk7UW/btsbQvJjZjs/DYIiDgXYkk2Kg9WwmA27K0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXk7UW%2FbtsbQvJjZjs%2FDYIiDgXYkk2Kg9WwmA27K0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1902&quot; height=&quot;762&quot; data-origin-width=&quot;1902&quot; data-origin-height=&quot;762&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;테스트 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아까는 OK가 나왔지만, 지금은 FAILED입니다. failures=1은 실패한 테스트의 수를 나타냅니다.&amp;nbsp;&lt;br&gt;친절하게도 어떤 테스트가 실패했는지 정보도 나오는데, test_2에서 self.assertEqual(1, 2)가 틀렸다고 나오네요. ㅎㅎ&lt;br&gt;&amp;nbsp;&lt;br&gt;자 이렇게 간단한 테스트를 해보았는데, User에 대한 테스트이니까 회원가입을 호출할 경우 정상적으로 회원가입이 되는지 확인을 해볼까요?&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# /user/tests.py
from django.test import TestCase
from user.models import User


# Create your tests here.
class TestUser(TestCase):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def test_1(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.assertEqual(1, 1)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def test_post_join(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;response = self.client.post('/user/join',
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dict(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;email=&quot;test_email@google.com&quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nickname=&quot;test_nickname&quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name=&quot;test_name&quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;password=&quot;test_password&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.assertEqual(response.status_code, 200)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;test_user = User.objects.filter(email=&quot;test_email@google.com&quot;).first()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.assertEqual(test_user.nickname, &quot;test_nickname&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.assertEqual(test_user.name, &quot;test_name&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.assertTrue(test_user.check_password(&quot;test_password&quot;))&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;test_post_join 테스트를 추가했습니다. 코드가 조금 길죠? 하나씩 봐보도록 하겠습니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;self.client.post('/user/join', dict(...)): ~/user/join API를 호출합니다. 저희가 회원가입하기 위해 만든 API입니다. param으로 email, nickname, name, password를 받아서 회원가입을 시켜줍니다. 이런 param은 dict로 넘겨주면 됩니다.&lt;/li&gt;&lt;li&gt;self.assertEqual(response.status_code, 200): 회원가입 API호출 결과가 200(성공)인지 체크합니다.&lt;/li&gt;&lt;li&gt;test_user = User.objects.filter(email='test_email@google.com').first(): 회원가입 api를 한번 호출했기 때문에 User테이블에 회원이 만들어졌을 겁니다. 만들어진 테스트 유저를 불러옵니다.&lt;/li&gt;&lt;li&gt;self.assertEqual(xxxx, xxxx): DB에 데이터와 API호출했을 때 데이터가 같은지 비교합니다. 호출한 데이터로 잘 만들어졌는지 체크하는 로직입니다.&lt;/li&gt;&lt;li&gt;self.assertTrue(xxxx): assertEqual이 같아야 한다는 테스트 코드라면, assertTrue는 True가 나올 것이라고 예상하는 테스트 코드입니다.&lt;/li&gt;&lt;/ul&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;이제 어떻게 테스트하는지 알 것 같죠? 그럼 회원가입 후 로그인까지 잘 되는지 테스트해 보겠습니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def test_post_login(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;response = self.client.post('/user/join',
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dict(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;email=&quot;test_email@google.com&quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nickname=&quot;test_nickname&quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name=&quot;test_name&quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;password=&quot;test_password&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.assertEqual(response.status_code, 200)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;response = self.client.post('/user/login',
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dict(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;email=&quot;test_email@google.com&quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;password=&quot;test_password&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.assertEqual(response.status_code, 200)&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;로그인은 test_post_login이라는 테스트로 만들었습니다. 여기서 한 가지 의문을 품으시는 분이 있을 수 있는데요, 아까 위에서 회원가입 테스트를 할 때 test_email@google.com이라는 계정을 만들었는데, 아래서도 같은 계정을 만들고 있습니다. 저희는 email을 UNIQUE로 해놓았기 때문에 같은 값이 들어가서는 안 되는데요, 어떻게 된 것일까요?&lt;br&gt;&amp;nbsp;&lt;br&gt;바로 테스트코드는 함수마다 데이터를 생성한 후 해당 테스트가 끝나면 지우게 됩니다. 즉 회원가입 테스트를 할 때 생성했던 User는 해당 테스트가 끝나면 삭제됩니다. 따라서 로그인 테스트할 때 다시 만들 수 있게 되는 거죠. 즉 데이터를 생성하고 해당 데이터를 가공하는 테스트가 필요하다면 하나의 함수 안에서 진행해야 합니다. 그래서 로그인을 테스트하기 위해 해당 함수에서 회원가입까지 진행한 것이죠.&lt;br&gt;&amp;nbsp;&lt;br&gt;이렇게 하나의 함수 안에서 하지 않고 미리 데이터를 정의하는 방법도 있습니다. 저희가 TestUser라는 클래스를 만들 때 TestCase를 상속받았는데, 그 안에 테스트에 필요한 다양한 함수들이 있습니다. 그중에 SetUpTestData라는 함수가 있는데, 요거는 모든 테스트를 시작하기 전에 필요한 데이터를 넣어놓을 수 있습니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;class TestUser(TestCase):

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@classmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def setUpTestData(cls):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;User.objects.create(email=&quot;login_test@gmail.com&quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nickname=&quot;login_test&quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name=&quot;login_test&quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;password=make_password(&quot;login_test&quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;profile_image=&quot;default_profile.png&quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def test_post_login(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;response = self.client.post('/user/login',
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dict(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;email=&quot;login_test@gmail.com&quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;password=&quot;login_test&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.assertEqual(response.status_code, 200)&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;이런 식으로 로그인 테스트를 좀 더 간단하게 만들 수 있습니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1592&quot; data-origin-height=&quot;408&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2mLNd/btsbTo98JiB/VDWPCBTcdyxiqiOi1PHbP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2mLNd/btsbTo98JiB/VDWPCBTcdyxiqiOi1PHbP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2mLNd/btsbTo98JiB/VDWPCBTcdyxiqiOi1PHbP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2mLNd%2FbtsbTo98JiB%2FVDWPCBTcdyxiqiOi1PHbP0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1592&quot; height=&quot;408&quot; data-origin-width=&quot;1592&quot; data-origin-height=&quot;408&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;테스트를 짜다 보니 재미가 붙어서 더 짜고 싶지만, 저희 목적은 테스트를 짜는 게 아니라 CI/CD이기 때문에 그만 만들고 다음 단계로 넘어가도록 하겠습니다. ㅋㅋㅋ&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;github action을 이용한 테스트 자동화&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;이제 우리가 만든 테스트를 자동으로 돌리는 Job을 만들 건데요, 예전에는 젠킨스를 많이 사용했는데, 요즘엔 github action을 많이 이용하는 것 같습니다. 젠킨스 자체가 서버에 설치하기도 해야 하고 메모리도 은근 많이 먹어서,, 공자 요금제 EC2에서는 설치하면 다른 거 아무것도 못할 정도의 리소스를 잡아먹습니다 ㅋㅋ&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;아무튼 github action이란 놈을 사용할 건데요, github action은 github에서 제공하는 workflow 자동화 툴입니다. workflow라는 말이 아주 고급스러워 보이는데, 배치를 돌리거나 CI/CD를 할 수 있는데, 젠킨스와 비슷한 툴이라고 보면 됩니다. github action의 좋은 점은 github에서 일어난 이벤트들과 연동하여 트리거할 수 있다는 점이죠. 따라서 우리는 main에서 push 혹은 pull request가 일어날 때 알아서 테스트가 돌아가는 github action을 만들어보도록 하겠습니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;말로는 아주 장황한데, 실제로는 너무 간단합니다. (요즘 너무 좋아졌네요 ㅎㅎ)&lt;br&gt;github action을 사용하기 위해선 당연히 github에 내 소스를 올린 repo가 있어야 하는데요, 강의를 따라 하셨으면 아마 여러분들의 github repo를 만드셨을 겁니다.&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3302&quot; data-origin-height=&quot;1776&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6oWbB/btsbVdN7aYV/yBvMN7zvtTTOs079Z4fK70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6oWbB/btsbVdN7aYV/yBvMN7zvtTTOs079Z4fK70/img.png&quot; data-alt=&quot;action 메뉴가 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6oWbB/btsbVdN7aYV/yBvMN7zvtTTOs079Z4fK70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6oWbB%2FbtsbVdN7aYV%2FyBvMN7zvtTTOs079Z4fK70%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3302&quot; height=&quot;1776&quot; data-origin-width=&quot;3302&quot; data-origin-height=&quot;1776&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;action 메뉴가 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저희는 보통 상단의 code 메뉴를 많이 보고 있는데, actions라는 메뉴가 있습니다. 해당 메뉴로 들어가면 위와 같이 workflow를 선택하라는 말이 나옵니다. github이 알아서 제 repo가 django라는 것을 알고, django workflow를 추천해 주네요. 만약 뜨지 않는다면 검색을 통해서 django를 선택합니다. build and test a django project라고 쓰여있습니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3580&quot; data-origin-height=&quot;1322&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/04yRW/btsbVchn8v5/2734BMClWJnG48igDvSuKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/04yRW/btsbVchn8v5/2734BMClWJnG48igDvSuKK/img.png&quot; data-alt=&quot;yml로 정의된 workflow&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/04yRW/btsbVchn8v5/2734BMClWJnG48igDvSuKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F04yRW%2FbtsbVchn8v5%2F2734BMClWJnG48igDvSuKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3580&quot; height=&quot;1322&quot; data-origin-width=&quot;3580&quot; data-origin-height=&quot;1322&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;yml로 정의된 workflow&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;configure를 누르면 위와 같이 yml파일을 생성하는 화면이 나옵니다. 내용이 어느 정도 채워져 있는데 하나씩 볼까요?&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;name: workflow의 이름입니다. 나중에 actions 사이드바에 여기에 정한 이름으로 actions들이 정렬됩니다. 디폴트로 django ci로 되어있네요.&lt;/li&gt;&lt;li&gt;on: 해당 workflow가 실행되는 시점을 정합니다. 여기에서는 main이라는 브랜치에 push, pull_request가 될 때 실행되는 코드가 적혀있습니다.&lt;/li&gt;&lt;li&gt;jobs: 실제적으로 작업들을 명시하는 곳입니다. 순서대로 실행됩니다.&lt;/li&gt;&lt;li&gt;runs-on: 해당 workflow가 실행되는 컨테이너의 운영체제를 선택합니다. ubuntu-latest로 되어있는데 우분투 최신버전으로 이 job을 돌리겠다는 의미입니다. 꼭 리눅스가 아니라 윈도우나 맥도 가능합니다. 단 윈도우나 맥은 리눅스보다 무료 사용 시간을 더 많이 잡아먹습니다.&amp;nbsp;&lt;/li&gt;&lt;li&gt;python-version: 테스트할 파이썬 버전을 뜻합니다. 여기는 3가지 버전이 디폴트로 적혀있는데, 테스트를 각각의 버전에서 실행해서 총 3번 돌립니다. 저희는 3개 중에 하나만 있어도 될 것 같네요.&lt;/li&gt;&lt;li&gt;steps: 여기에 이제 할 일들을 순서대로 나열합니다. 앞에 - 이걸로 구분된 게 스텝들인데 총 4개의 스텝이 있는 거죠. 앞에 3개는 python 세팅이고, 맨 아래 run test라고 된 곳이 실제로 테스트를 실행하는 step입니다.&lt;/li&gt;&lt;/ul&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;디폴트로 만들어준 설정을 하나도 건드리지 않아도 테스트가 가능하지만, 저희는 하나 바꿀 게 있습니다. 테스트를 실행할 때 --settings=Jinstagram.settings_local을 입력해 줘야 한다는 것이죠. 이름도 django-ci로 변경해 줍니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3618&quot; data-origin-height=&quot;1418&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GPKWF/btsb5k6N6VX/ZMfFpqSUoqbEaghoXFg1e1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GPKWF/btsb5k6N6VX/ZMfFpqSUoqbEaghoXFg1e1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GPKWF/btsb5k6N6VX/ZMfFpqSUoqbEaghoXFg1e1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGPKWF%2Fbtsb5k6N6VX%2FZMfFpqSUoqbEaghoXFg1e1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3618&quot; height=&quot;1418&quot; data-origin-width=&quot;3618&quot; data-origin-height=&quot;1418&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다 하고 나면 오른쪽 위에 commit을 누릅니다. action을 생성하는 것은 사실 저희 소스에 .github폴더를 만들고 그 안에 workflow폴더를 만들어서 그 안에 xxx.yml파일을 만드는 것과 같습니다. 이걸 github 웹사이트에서 하는 것이죠.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1007&quot; data-origin-height=&quot;901&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eFEGZH/btsbUpOQKCD/GtGWQw6Thw7xigcUzHims0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eFEGZH/btsbUpOQKCD/GtGWQw6Thw7xigcUzHims0/img.png&quot; data-alt=&quot;커밋메시지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eFEGZH/btsbUpOQKCD/GtGWQw6Thw7xigcUzHims0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeFEGZH%2FbtsbUpOQKCD%2FGtGWQw6Thw7xigcUzHims0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;447&quot; data-origin-width=&quot;1007&quot; data-origin-height=&quot;901&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;커밋메시지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 commit을 누르면 커밋 메시지를 적으라고 합니다. github action 생성이라고 적어줍니다. 그러면 commit과 함께 push가 되기 때문에 바로 action이 실행되는데요, 다시 action으로 가보면 아까와 다르게 왼쪽에 리스트가 보입니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3248&quot; data-origin-height=&quot;788&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lUQ69/btsbSLLIJ2e/9BZFMl5wWDuMJiIGmkgCnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lUQ69/btsbSLLIJ2e/9BZFMl5wWDuMJiIGmkgCnk/img.png&quot; data-alt=&quot;왼쪽에 action 리스트가 나오고 가운데는 실행한 이력이 나온다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lUQ69/btsbSLLIJ2e/9BZFMl5wWDuMJiIGmkgCnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlUQ69%2FbtsbSLLIJ2e%2F9BZFMl5wWDuMJiIGmkgCnk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3248&quot; height=&quot;788&quot; data-origin-width=&quot;3248&quot; data-origin-height=&quot;788&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;왼쪽에 action 리스트가 나오고 가운데는 실행한 이력이 나온다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;저는 미리 하나를 만들어봐서 2개가 표시되는데, 여러분은 하나가 표시될 거예요. 가운데 job이 실행된 이력이 있는데 클릭해 보면 상세한 이력을 확인할 수 있습니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2870&quot; data-origin-height=&quot;1428&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQFaiy/btsb2ThfHHy/xATnGv7vcdK8F8qTOCD950/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQFaiy/btsb2ThfHHy/xATnGv7vcdK8F8qTOCD950/img.png&quot; data-alt=&quot;테스트 완료&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQFaiy/btsb2ThfHHy/xATnGv7vcdK8F8qTOCD950/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQFaiy%2Fbtsb2ThfHHy%2FxATnGv7vcdK8F8qTOCD950%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2870&quot; height=&quot;1428&quot; data-origin-width=&quot;2870&quot; data-origin-height=&quot;1428&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;테스트 완료&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;자 엄청 쉽죠? 이제 저희가 코드를 수정하고 main에 push 하게 되면 자동으로 테스트가 돌아갑니다. 즉 우리가 일일이 테스트를 돌리지 않아도 github에서 테스트를 해준다는 거죠. 테스트뿐만 아니라 pip install requirement도 해주기 때문에 패키지를 설치해서 테스트를 돌리는 과정까지 해줍니다. package를 올바르게 설치해서 장고 앱을 실행할 수 있는지까지 테스트를 해준다는 것이죠. 저희가 사용하는 게 장고라는 프레임워크라서 그렇지 만약 스프링부트를 사용한다고 하면 build까지 해줍니다. (대단!!! )&lt;br&gt;&amp;nbsp;&lt;br&gt;자 이렇게 해서 CI가 끝났습니다. 생각보다 간단하죠? 만약 저희가 docker를 사용하고 있었다면 CI *.yml파일에 docker이미지를 만드는 코드를 추가하고 만든 이미지를 도커 허브와 같은 컨테이너 저장 서비스에 올리는 과정까지 추가할 수 있습니다. 이 부분은 조금 심화과정이기 때문에 여기서는 다루지 않겠습니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;github action을 이용한 배포&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;CI를 다 만들었으니 이제 CD를 만들어봅시다. CD는 만드는 방법이 아~~~ 주 다양한데, 여기서는 github action에서 EC2에 접속해서 git pull을 받고 django를 재시작하는 스크립트를 실행하는 걸로 만들어보겠습니다. 즉 저희가 수동으로 서버에 접속해서 실행하는 명령어를 github액션에서 실행해 주도록 설정하는 것이죠.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;이번엔 웹페이지에서 만드는 게 아니라 로컬에서 workflow를 직접 만들어보겠습니다. main을 pull받으면 .github/workflow폴더가 보일 텐데 여기에 새로운 *.yml를 추가합니다. 배포니까 django-deploy로 정해보도록 하죠.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;284&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qqiIN/btsbSFkCOQL/CKSO1f5jbehFSVZqg5C4YK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qqiIN/btsbSFkCOQL/CKSO1f5jbehFSVZqg5C4YK/img.png&quot; data-alt=&quot;django-deploy&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qqiIN/btsbSFkCOQL/CKSO1f5jbehFSVZqg5C4YK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqqiIN%2FbtsbSFkCOQL%2FCKSO1f5jbehFSVZqg5C4YK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;209&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;284&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;django-deploy&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내용은 아래와 같이 채웁니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;name: Django Deploy

on:
&amp;nbsp;&amp;nbsp;workflow_run:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;workflows: [&quot;Django CI&quot;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;types:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- completed

jobs:
&amp;nbsp;&amp;nbsp;build:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;runs-on: ubuntu-latest

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;steps:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- name: excuting remote ssh commands
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uses: appleboy/ssh-action@v0.1.10
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;with:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;host: ${{ secrets.EC2_HOST }}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;username: ${{ secrets.EC2_USER }}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;key: ${{ secrets.PRIVATE_KEY }} 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;port: 22
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;script: |
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cd /home/ubuntu/django_zero_to_instagram_devops_youtube
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;git pull
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sudo systemctl restart uwsgi&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;전체적인 구성은 이전과 같으나 다른 점이 몇 개 있습니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;on: 이전에는 push와 pull_request가 일어날 경우 실행되게 했지만 이번엔 worklofws: [&quot;Django CI&quot;]라고 되어있습니다. 배포는 항상 CI이후에 일어나기 때문에 Django CI라는 액션이 성공하면 이 workflow가 실행되도록 설정한 것입니다. 이렇게 action 실행 조건을 이전 action의 성공으로 설정할 수 있습니다.&lt;/li&gt;&lt;li&gt;steps: 여기는 크게 바뀌었는데, ssh를 이용해 서버에 접속해서 script:에 적힌 명령어를 치도록 실행됩니다. uses: appleboy/ssh-action@v0.1.10이라는게 있는데, appleboy라는 사람이 만든 ssh-action이라는 소스를 이용해 실행한다는 의미입니다. github action도 유저들이 미리 만들어놓은 소스들을 사용할 수 있습니다. 궁금하신 분은 appleboy/ssh-action repo에 들어가면 확인할 수 있습니다.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;자 여기서 커밋을 하기 전에 host, username, key를 보면 secrets.XXX로 정의된 것을 볼 수 있습니다. 이전에 mysql을 연동할 때 환경변수를 설정한 게 기억나시나요? 소스에 중요정보들이 노출되는 것을 막기 위해 시스템 환경변수를 이용했었는데, action도 마찬가지로 중요 정보가 노출될 수 있습니다. 따라서 해당 정보들을 github secret에 저장해서 사용할 수 있습니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;github secret은 github repo에 들어가서 settings메뉴에서 설정할 수 있습니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2864&quot; data-origin-height=&quot;1776&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Etqez/btsbXJzdysB/yidCpzbkTATzJS0ky5oIdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Etqez/btsbXJzdysB/yidCpzbkTATzJS0ky5oIdK/img.png&quot; data-alt=&quot;액션에서 사용할 secret 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Etqez/btsbXJzdysB/yidCpzbkTATzJS0ky5oIdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEtqez%2FbtsbXJzdysB%2FyidCpzbkTATzJS0ky5oIdK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2864&quot; height=&quot;1776&quot; data-origin-width=&quot;2864&quot; data-origin-height=&quot;1776&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;액션에서 사용할 secret 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;new repository secret버튼을 사용해서 새로운 secret 값을 생성할 수 있습니다. EC2_HOST에는 여러분들의 EC2 IP주소를 적고, EC2_USER에는 ubuntu라고 적어줍니다. 만약 여러분들이 ubuntu ec2를 사용하지 않았다면 여러분들이 접속할 때 사용하는 user를 적으면 됩니다. 마지막으로 PRIVATE_KEY인데, 만약 여러분이 pem파일로 key pair를 생성했다면 pem파일을 열어서 거기에 내용을 복사해서 넣으시면 됩니다. 만약 ppk로 키를 받으셨으면 putty를 이용해 ppk -&amp;gt; pem으로 변환하여 키를 뽑을 수 있습니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;여러분들이 putty를 설치하셨다면 puttygen이라는 프로그램도 아마 같이 설치되었을 텐데요,&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1482&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Vjmye/btsbV7NLaar/ffoIFHViOz2JxykbNpZRc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Vjmye/btsbV7NLaar/ffoIFHViOz2JxykbNpZRc1/img.png&quot; data-alt=&quot;puttygen&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Vjmye/btsbV7NLaar/ffoIFHViOz2JxykbNpZRc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVjmye%2FbtsbV7NLaar%2FffoIFHViOz2JxykbNpZRc1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1482&quot; height=&quot;512&quot; data-origin-width=&quot;1482&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;puttygen&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;이 puttygen을 이용해 ppk -&amp;gt; pem으로 변환 가능합니다.&lt;br&gt;먼저 puttygen을 실행하고, load를 선택하여 ppk을 읽어옵니다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1208&quot; data-origin-height=&quot;880&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3T0DG/btsbURqReYs/hWhzV1TFzXlCA5HDWkP541/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3T0DG/btsbURqReYs/hWhzV1TFzXlCA5HDWkP541/img.png&quot; data-alt=&quot;load&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3T0DG/btsbURqReYs/hWhzV1TFzXlCA5HDWkP541/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3T0DG%2FbtsbURqReYs%2FhWhzV1TFzXlCA5HDWkP541%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;437&quot; data-origin-width=&quot;1208&quot; data-origin-height=&quot;880&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;load&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1084&quot; data-origin-height=&quot;469&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5Z7WE/btsb1QdPWXn/Fvc5neJxHT4HZUzRuBwJN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5Z7WE/btsb1QdPWXn/Fvc5neJxHT4HZUzRuBwJN1/img.png&quot; data-alt=&quot;ppk를 읽어온다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5Z7WE/btsb1QdPWXn/Fvc5neJxHT4HZUzRuBwJN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5Z7WE%2Fbtsb1QdPWXn%2FFvc5neJxHT4HZUzRuBwJN1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;260&quot; data-origin-width=&quot;1084&quot; data-origin-height=&quot;469&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ppk를 읽어온다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;그리고 conversions-&amp;gt; export openssh key (force new file format)을 눌러서 xxx.pem으로 저장하면 끝~!&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1168&quot; data-origin-height=&quot;862&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dQVFVv/btsbT2e7dL5/imgTKvJ0Ab3UkwmpcEcrI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dQVFVv/btsbT2e7dL5/imgTKvJ0Ab3UkwmpcEcrI1/img.png&quot; data-alt=&quot;export&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dQVFVv/btsbT2e7dL5/imgTKvJ0Ab3UkwmpcEcrI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdQVFVv%2FbtsbT2e7dL5%2FimgTKvJ0Ab3UkwmpcEcrI1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;443&quot; data-origin-width=&quot;1168&quot; data-origin-height=&quot;862&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;export&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1864&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r8rSY/btsbSNW3w34/oeMB6lLS0IIQg0jJGVdcyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r8rSY/btsbSNW3w34/oeMB6lLS0IIQg0jJGVdcyk/img.png&quot; data-alt=&quot;pem으로 저장&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r8rSY/btsbSNW3w34/oeMB6lLS0IIQg0jJGVdcyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr8rSY%2FbtsbSNW3w34%2FoeMB6lLS0IIQg0jJGVdcyk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;108&quot; data-origin-width=&quot;1864&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;pem으로 저장&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 저장한 다음 문서를 읽을 수 있는 프로그램으로 pem을 읽으면 다음과 같이 private 키가 나옵니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1338&quot; data-origin-height=&quot;1274&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dWvuRw/btsbT1tKt73/XfH0EzkwInQn9DtP6PEsDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dWvuRw/btsbT1tKt73/XfH0EzkwInQn9DtP6PEsDk/img.png&quot; data-alt=&quot;private key&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dWvuRw/btsbT1tKt73/XfH0EzkwInQn9DtP6PEsDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdWvuRw%2FbtsbT1tKt73%2FXfH0EzkwInQn9DtP6PEsDk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;571&quot; data-origin-width=&quot;1338&quot; data-origin-height=&quot;1274&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;private key&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 공개하면 안 되지만 누가 이거 가져다 써도 상관없으니까요 ^^ 여러분들은 공개하지 마세요~ ㅋㅋ&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;이 문서의 전체를 복사해서 PRIVATE_KEY secret에 붙여 넣기 해줍니다. 그럼 준비 끝!!&lt;br&gt;&amp;nbsp;&lt;br&gt;그럼 우리가 만든 django-deploy.yml을 추가하고 commit후 push 해봅시다~!&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2742&quot; data-origin-height=&quot;578&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjUGeQ/btsbV6agtMW/f6QfxFjLiEsfL49YNbgC90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjUGeQ/btsbV6agtMW/f6QfxFjLiEsfL49YNbgC90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjUGeQ/btsbV6agtMW/f6QfxFjLiEsfL49YNbgC90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjUGeQ%2FbtsbV6agtMW%2Ff6QfxFjLiEsfL49YNbgC90%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2742&quot; height=&quot;578&quot; data-origin-width=&quot;2742&quot; data-origin-height=&quot;578&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;정상적으로 동작한다면 Django CI가 실행되고 나서 바로 Django Deploy가 실행되는 것을 확인할 수 있습니다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1918&quot; data-origin-height=&quot;1474&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUmOAO/btsb6ZaoWNQ/UGrJJyjkk4XwSUrK24DXKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUmOAO/btsb6ZaoWNQ/UGrJJyjkk4XwSUrK24DXKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUmOAO/btsb6ZaoWNQ/UGrJJyjkk4XwSUrK24DXKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUmOAO%2Fbtsb6ZaoWNQ%2FUGrJJyjkk4XwSUrK24DXKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1918&quot; height=&quot;1474&quot; data-origin-width=&quot;1918&quot; data-origin-height=&quot;1474&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리하며&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;간단하지만 github action을 이용한 CI/CD를 구현했습니다. CI/CD를 구현하는 방법은 아주 많습니다. 저희는 그중에 github action을 이용했고 배포 방법으로는 ec2에 직접 접속하여 소스를 다운로드하고 재시작하는 로직을 사용했습니다. 저희처럼 아주 간단한 사이드프로젝트에서는 이 방법이 좋지만 실제 회사들이 사용하고 있는 환경은 더 복잡하기 때문에 단순히 서버에 접속해서 git pull, restart형식으로 구현하지는 않습니다. AWS를 사용한다면 AWS Code Deploy라는 서비스를 많이 사용하게 됩니다. 직접 ec2에 들어가는 것이 아닌 AWS에서 제공하는 배포 서비스를 이용해 ec2에 배포하는 것이죠. 아니면 쿠버네티스(k8s)를 사용하는 곳이라면 kube명령어를 이용해 배포하는 곳도 있습니다. 이럴 경우 container이미지를 만들기 위한 CI와 이미지 저장서비스까지 이용하게 되죠. (ex. horbor.io)&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;이렇게 다양한 CI/CD방식이 있지만 동작 원리는 같습니다. 따라서 전부를 아실 필요도 없고 어떻게 돌아가는지만 알면 구현하는 찾아서 하면 됩니다. 사실 요즘은 devops분들이 해주시기 때문에 저희가 할 건 없지만요. ㅎㅎ 하지만 알고 모르고 가 상당히 중요합니다.  &lt;br&gt;&amp;nbsp;&lt;br&gt;처음에는 docker로 만들어서 이미지로 배포하는 것까지 하려고 했었는데, 그렇게 하면 CI/CD에 초점을 맞출 수 없을 것 같아서 제외했습니다. ㅎㅎ 나~~ 중에 여유가 생기면 추가해 보도록 하겠습니다.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;다음시간은 SSL 기능을 넣어서 저희 인스타 서비스가 https로 접속 가능하도록 추가해 보겠습니다. &lt;br&gt;읽어주셔서 감사합니다  &lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Course/django : 제로부터 시작하는 인스타그램</category>
      <category>DevOps</category>
      <category>인스타클론</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/586</guid>
      <comments>https://cholol.tistory.com/586#entry586comment</comments>
      <pubDate>Sat, 22 Apr 2023 02:05:19 +0900</pubDate>
    </item>
    <item>
      <title>IT회사 팀사람들과 스터디 하기, 강의 및 교재 선택부터, DDD 스터디 후기</title>
      <link>https://cholol.tistory.com/585</link>
      <description>&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2022년 두나무로 이직 후 회사 도메인 파악하랴 적응하랴 이것저것 하느라 스터디, 블로그, 유튜브와 같은 외부 활동을 거의 못했다. (는 핑계~)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 글을 보면서 혼자서 공부하는 걸 좋아하는 스타일인데, 영상보다는 역시 글이 편하다 ㅋㅋ 옛날사람인 듯&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 유튜브를 좀 찍으면서 영상과 친해져서 영상 보면서 공부하는 것도 어느 정도 익숙해졌다. 처음부터 혼자 하는 스터디를 선호한 건 아닌데, 외부 스터디모임 같은 걸 찾다 보면 언제나 시작은 으쌰!으쌰!이지만 진행 중에 흐지부지되는 경우가 많았기 때문!! 다들 그런 경험 있잖아요? ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2023년이 되면서 회사 업무에도 어느 정도 적응해 여유가 있을 무렵, 팀 사람들이 다 함께 스터디를 해보는 게 어떻겠냐고 얘기가 나왔다. 알고 보니 우리 팀에 스터디에 아주 진심인 사람(이라고 쓰고 제이콥이라고 읽는다)이 있었다. ㅋㅋㅋ 제이콥은 코틀린을 이용해 스프링을 개발하면서 DDD에 아주 진심인 개발자다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀 사람들 모두 스터디에 대한 니즈를 느끼고 있었기 때문에, 2023년 첫 스터디 DDD를 시작하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1916&quot; data-origin-height=&quot;1642&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dhzts6/btr6eUViXZO/3SKHwdJjypLaljIVlilQY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dhzts6/btr6eUViXZO/3SKHwdJjypLaljIVlilQY1/img.png&quot; data-alt=&quot;DDD 스터디페이지 - 스터디 전설의 시작&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dhzts6/btr6eUViXZO/3SKHwdJjypLaljIVlilQY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdhzts6%2Fbtr6eUViXZO%2F3SKHwdJjypLaljIVlilQY1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1916&quot; height=&quot;1642&quot; data-origin-width=&quot;1916&quot; data-origin-height=&quot;1642&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;DDD 스터디페이지 - 스터디 전설의 시작&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;스터디 진행방식&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사사람들과 스터디하는 것은 정말 매우 많은 장점이 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일단 도망가지 못한다 ㅋㅋ&lt;/li&gt;
&lt;li&gt;스터디 시간 조율이 편하다. (다들 회사에서 보니까)&lt;/li&gt;
&lt;li&gt;어느정도 검증된(?) 사람들이다. (외부 스터디 하면 모르는 사람들이랑 해야하자너,,)&lt;/li&gt;
&lt;li&gt;팀사람들이랑 친해진다.&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매우 많다고 했는데 이것밖에 생각 못한 나란 존재.. 아무튼 느낌상 엄청 좋은 것 같다 ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리의 스터디 리더 제이콥이 노션 페이지를 만들고 그라운드 룰(?)을 정했다. 공부하는 방법이나 다짐 같은 거..? 일단 우리는 각자 알아서 공부해 오고 일주일에 한 번 모여서 자신이 배운 점, 느낀 점 등을 토론하는 방식으로 진행했는데, 각자의 경험을 토대로 이야기하다 보니 아주 다양한 얘기가 나오게 되었다. 다들 어느 정도 연차가 있고 경험이 있다 보니, 다른 회사에서는 어떻게 했었고, 이런저런 이슈가 있었다는 얘기를 많이 들을 수 있었다. &lt;u&gt;스터디도 뭔가 부익부 빈익빈이라는 것을 느낀다. 경험이 많은 사람들과 하니 더 많은 걸 배울 수 있으니... ㅋㅋ&amp;nbsp;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학습방법은 일단 적당한 동영상 강의를 하나 찾아서 시청하고, 그다음 책을 읽으면서 공부하는 방법이다. 동영상 강의는 회사에서 지원해 주는 교육 플랫폼에서 찾아서 신청을 했다. 제목은 '도메인 주도 설계 기반 마이크로서비스 모델링'이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2486&quot; data-origin-height=&quot;832&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ThlZF/btr6eUA0Dq6/ogU8AtpiWQY7Rk6ESyBcB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ThlZF/btr6eUA0Dq6/ogU8AtpiWQY7Rk6ESyBcB1/img.png&quot; data-alt=&quot;동영상 강의&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ThlZF/btr6eUA0Dq6/ogU8AtpiWQY7Rk6ESyBcB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FThlZF%2Fbtr6eUA0Dq6%2FogU8AtpiWQY7Rk6ESyBcB1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2486&quot; height=&quot;832&quot; data-origin-width=&quot;2486&quot; data-origin-height=&quot;832&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;동영상 강의&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 강의에 대한 리뷰는 아래에 적는 걸로...ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교재는 도메인 주도 개발 시작하기 - 최범균, 한빛미디어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;1026&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMrpsk/btr6oXQSnY8/CkHCe1GIHqOEjMZXx1yPqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMrpsk/btr6oXQSnY8/CkHCe1GIHqOEjMZXx1yPqk/img.png&quot; data-alt=&quot;교재&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMrpsk/btr6oXQSnY8/CkHCe1GIHqOEjMZXx1yPqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMrpsk%2Fbtr6oXQSnY8%2FCkHCe1GIHqOEjMZXx1yPqk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;356&quot; height=&quot;457&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;1026&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;교재&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강의와 교재는 스터디 대장 &lt;b&gt;제이콥&lt;/b&gt;이 이미 시청하고 읽어본 것들 중에 하나를 정했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; '인프런 - 도메인 주도 설계 기반 마이크로서비스 모델링' 스터디 후기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동영상 강의는 총 37강으로 9시간 정도의 분량이다. 우리는 강의를 이론과 실습 파트로 나누고 2주에 걸쳐서 진행하기로 했다. 이론 부분에서는 DDD에 대한 내용, MSA에 대한 내용, 설계에 대한 내용을 다루었다. 앞부분은 시스템 설계에 대한 내용이 많이 나왔는데, 대부분 아는 내용이라 빠르게 넘겼다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중반부에는 DDD에 사용되는 용어들이 나오기 시작한다. 바운더리컨텍스트나 이벤트 스토밍, 유비쿼터스 언어 등등 처음 보는 개념이거나 내용은 아는데 용어를 모르는 개념들이 많이 나왔다. DDD스터디를 하면서 좋았던 점 중에 하나가 이렇게 어렴풋이 알고 있던 개념들에 대한 용어를 팀 전체가 공유할 수 있다는 점이었다. 이렇게 팀의 공통 지식이 되면 나중에 커뮤니케이션할 때 코스트가 낮아지기 때문이다. 이런 생각을 하면서 갑자기 김춘수의 꽃이 생각난다. &lt;s&gt;갑자기?&lt;/s&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;내가 그의 이름을 불러주기 전에는&lt;br /&gt;그는 다만 하나의 몸짓에 지나지 않았다.&lt;br /&gt;&lt;br /&gt;내가 그의 이름을 불러주었을 때,&amp;nbsp;&lt;br /&gt;그는 나에게로 와서&lt;br /&gt;꽃이 되었다.&lt;br /&gt;&lt;br /&gt;꽃, -김춘수-&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 이과지만 문학소년이었던 시절이 있었다 ㅋㅋㅋ 뭔가 개념은 알고 있는데 용어가 생각이 안 나서 대화할 때 힘들 때가 있는데, 그럴 때 이름이 딱 생각나면 이런 느낌 아닐까? ㅋㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;아무 생각 없이 코딩할 때,&lt;br /&gt;이 코드는 코드 더미에 지나지 않았다.&lt;br /&gt;&lt;br /&gt;내가 이 코드를 도메인 주도 설계라고 불렀을 때, &lt;br /&gt;이 코드는 나에게 와서&lt;br /&gt;DDD가 되었다.&lt;br /&gt;&lt;br /&gt;DDD, -문규진-&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강의영상 뒷부분에는 이벤트 스토밍을 직접 해보는 실습이 나오는데, 사실 이 부분은 자세하게 보지 않았다. 뭔가 실제로 이렇게 할 일이 없을 분더러, 예제가 너무 단순해서 우리 회사에 적용할 수 없다고 판단했기 때문에다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공부를 하면서 영상이나 책을 볼 때, 무조건 맞다는 마인드를 갖는 것은 좋지 않다. 특히 IT관련 공부를 할 때는, 내가 배우고 있는 이 지식이 항상 옳다는 마인드를 버려야 한다. 상황에 따라 정답이 될 수도 있고 아닐 수도 있는 케바케가 많기 때문에, 항상 이게 항상 정답일까?라는 의문을 가지고 공부하는 걸 추천한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 8시간 분량이지만 강의를 보면서 모르는 단어나 개념들을 구글링 하며 보다 보면 생각보다 시간을 많이 잡아먹는다. 2주로 나누길 잘한 것 같다. ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스터디 처음이라 다들 학습에 투자하는 시간을 모르기 때문에 너프 하게 2주로 했는데, 다음부터는 좀 더 빡세게 해도 될 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강의에 대한 평가는 음... 일단 강의 내용이 너무 올드하다. 마치 오래된 책에 나올법한 내용들로 구성되어 있고, 강의에서 사용하는 PPT 역시 너무 글씨만 많고, 글을 읽어주는 느낌이랄까? 강사도 뭔가 강의를 많이 해본 것 같은 느낌이 아니라 대기업 차장님 같은 분이 와서 얘기를 해주고 있다는 느낌을 많이 받았다. 뭔가 대기업에서 필수교육을 받아야 해서 억지로 끌려가서 영상을 시청하는 느낌..&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IT라는 분야가 매우 젊어 보이지만, 아직도 이렇게 올드한 강의가 있고 강사가 있다는 것에 놀랍고, 이런 강의를 많이 보고 있다는 것에 놀랍다. 그리고 강사님 말하는 게 너무 어눌해서 졸리다 ㅋㅋ 뭔가 또랑또랑하게 얘기해 줘야 쏙쏙 들어올 텐데.. 나도 유튜브 찍을 때 잘해야겠다는 생각이 들었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;'도메인 주도 개발 시작하기 - 최범균, 한빛미디어' 스터디 후기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동영상 강의에 이어서 책 스터디를 진행했다. 아무래도 영상 강의보다는 책이 더 DDD스터디에 적합하다고 생각해서 강의로 일단 어느 정도 DDD에 친숙해지고 책으로 본격적인 공부를 해보자! 느낌이었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책은 총 350페이지 정도 됐는데, 제이콥 선생님이 이 정도면 3주 컷이라고... 해서 3주 만에 끝냈다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1542&quot; data-origin-height=&quot;978&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/br6FEn/btr6ya2JfmL/qP7fcnpODhWKHTNkwpnJQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/br6FEn/btr6ya2JfmL/qP7fcnpODhWKHTNkwpnJQ0/img.png&quot; data-alt=&quot;제이콥 선생님의 스터디 스케쥴&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/br6FEn/btr6ya2JfmL/qP7fcnpODhWKHTNkwpnJQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbr6FEn%2Fbtr6ya2JfmL%2FqP7fcnpODhWKHTNkwpnJQ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;546&quot; height=&quot;346&quot; data-origin-width=&quot;1542&quot; data-origin-height=&quot;978&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;제이콥 선생님의 스터디 스케쥴&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책에서는 DDD를 적용한 스프링을 예제로 많이 사용하고 있다. 우리 팀에서는 자바나 스프링을 사용하지 않는 분들도 많았기에, 너무 스프링에 의존적인 내용은 스킵하고, 설계에 대한 부분만 토론을 많이 진행했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확실히 책으로 보니까 DDD에 대한 이해가 더 잘되는 느낌이었다. 내가 글이 더 편한 것도 있긴 한데, 아무래도 영상보다는 책이 이론적인 내용을 전달하는데 더 효과적인 것 같다. 반면 영상은 경험적인 내용을 전달하는데 효과적이라고나 할까? 아무튼 영상에서 봤던 바운더리컨텍스트나 애그리거트에 대해서 코드랑 같이 보니까 훨씬 이해가 잘 됐다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 디자인 패턴에 대해서 나에 생각은, &lt;u&gt;사람들이 코딩을 하다가 편하게 코딩하는 방법을 찾아서 그것을 적용했고, 서로 공유하기 위해 이름을 붙인 것이라고&lt;/u&gt; 생각하기 때문에 DDD가 엄청 혁신적인 거나 대단하게 느껴지지는 않았다. 즉, '효율적으로 개발을 계속하다 보면, 최적화된 디자인으로 수렴한다'라고 생각하고 있다. 간혹 디자인 패턴이 모든 일에 정답인 마냥 디자인 패턴에 집중하는 경우를 볼 수 있는데, 주객 전도가 된 게 아닐지 생각된다. 디자인 패턴은 단지 일을 효율적으로 하기 위한 방법일 뿐이지 목적이 아니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 이건 어디까지나 내 생각이다. ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다르게 생각하는 사람들이 있을 수 있고, 내 생각이 정답이라고 주장하고 싶지는 않다. 다들 그들만의 생각이 있을 테니까-&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 생각 없이 맹목적으로 따라가는 건 조금 비판하고 싶을 수도...&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책 후반에는 완전히 스프링위주의 설명이 지속되는데, 나는 최근에 코틀린을 이용한 스프링을 공부도 해보고, 회사에서 관련된 업무도 해보아서 아주 재밌게 읽었다. 다만 책에는 자바로 되어있고, 옛날 버전의 코드라서 지금 사용하는 버전과는 많이 다르긴 했다. 역시 IT는 빠르게 변한다니까..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책은 거의 일주일에 150페이지씩 읽었는데, 책만 읽는 게 아니라 코드를 보거나 모르는 거 찾느라 시간이 더 많이 걸렸다. 하지만 책 읽는 거보다 스터디 시간에 더 많은 것을 배울 수 있는 시간들이었다. ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1788&quot; data-origin-height=&quot;1376&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSjCGy/btr6haDJov5/nItAOAdAgONuGlfd0KajJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSjCGy/btr6haDJov5/nItAOAdAgONuGlfd0KajJK/img.png&quot; data-alt=&quot;스터디시간 논의내용&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSjCGy/btr6haDJov5/nItAOAdAgONuGlfd0KajJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSjCGy%2Fbtr6haDJov5%2FnItAOAdAgONuGlfd0KajJK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;622&quot; height=&quot;479&quot; data-origin-width=&quot;1788&quot; data-origin-height=&quot;1376&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;스터디시간 논의내용&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 &lt;b&gt;제이콥&lt;/b&gt;선생님이 요점만 딱딱 정리해 주기 때문에 책 보다 많은 것을 알게 되었고, DDD에 대한 경험이 있는 팀원도 많아서 다른 회사에서 어떻게 구현했는지, 어떤 방식으로 일했는지에 대한 내용을 많이 들을 수 있었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DDD 스터디 후기,&amp;nbsp; DDD에 대한 생각&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DDD를 스터디하면서 느낀 점은, DDD라는 게 뭔가 개발에만 한정된 내용이 아니라는 생각이 든다. DDD에서 핵심적으로 말하는 것은 도메인을 잘 정의해서 기획자와 개발자가 커뮤니케이션을 잘해보자~ 느낌이다. 유비쿼터스 언어라는 것도 결국에는 기획자와 개발자가 커뮤니케이션을 잘하기 위해 필요한 것이고, 도메인을 나누는 것도 업무를 진행할 때 어디를 손봐야 하는지 명확하게 알기 위함일 것 같다. 즉 DDD는 그냥 일을 잘하기 위해 회사차원에서 적용해야 할 정책인 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 개발적으로도 적용해야 할 내용들이 있긴 하다. 도메인 위주로 코드를 분리하고 서로에 대한 의존성 룰을 맞추는 등, 생각보다 많은 작업을 해줘야 한다. 이것 역시 개발 편의성을 위한 것이고, 나아가면 일을 효율적으로 하기 위함이라고 생각된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 어느 정도 오래된 회사 같은 경우에는 DDD를 처음부터 생각하면서 만든 프로덕트는 없을 것이라고 생각된다. 대부분 기존의 프로덕트를 DDD를 적용해서 바꿔보자!라는 식의 프로젝트가 많을 것 같고, 실제로 적용 사례 레퍼런스를 보면 기존에 있는 프로덕트를 DDD로 적용해 보자!라는 내용이 많은 것 같다. 하지만 아직까지 회사차원에서 DDD가 풀로 적용된 곳은 없다고 한다.(&lt;b&gt;제이콥&lt;/b&gt;피셜)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아까 말한 것처럼 이건 개발자뿐만 아니라 회사에 모든 인원이 참여해야만 DDD를 적용할 수 있을 것 같다. 하지만 위에서 말한 것처럼 DDD가 정답은 아닐 것이다. 모든 사람들이 효과적으로 일하도록 노력한다면 DDD보다 더 최적화된 방법으로 일할 수 있고, 그게 DDD보다 더 좋을 수도 있다. 어쩌면 여러분이 하고 있는 일들에 이미 DDD가 적용되어 있을지도 모르는 일이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서하는 첫 스터디였는데, 아주 대 만족이다  &amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무일 없다면 2023년 계속 진행되지 않을까? 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=AebXluEiKm4&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/0hBnl/hyR39D3239/pXDpQqvWSbEBbrK9JoYUr1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/AebXluEiKm4&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &amp;nbsp; DDD 스터디하면서 찍은 VLOG영상 ㅎㅎ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Study/회사 팀스터디</category>
      <category>DDD</category>
      <category>팀스터디</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/585</guid>
      <comments>https://cholol.tistory.com/585#entry585comment</comments>
      <pubDate>Tue, 28 Mar 2023 11:43:47 +0900</pubDate>
    </item>
    <item>
      <title>CRUD가 동작하는 todo 앱 만들기 by chatGPT</title>
      <link>https://cholol.tistory.com/584</link>
      <description>&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CRUD는 Create(생성), Read(읽기), Update(갱신), Delete(삭제)의 약자로, 데이터베이스에서 가장 기본적인 작업들입니다. 따라서 CRUD가 동작하는 Todo 앱을 만들기 위해서는 데이터베이스와 연동하여 해당 기능들을 구현해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 간단한 CRUD 기능을 갖는 Todo 앱의 예시 코드입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1677498691033&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 필요한 라이브러리를 import 합니다.
from flask import Flask, jsonify, request
from flask_sqlalchemy import SQLAlchemy

# Flask 앱을 생성합니다.
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///todo.db'  # 데이터베이스 설정
db = SQLAlchemy(app)

# Todo 모델을 정의합니다.
class Todo(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)
    description = db.Column(db.String(200))
    completed = db.Column(db.Boolean, default=False)

    def __repr__(self):
        return '&amp;lt;Todo %r&amp;gt;' % self.id

# Todo 생성 API
@app.route('/todo', methods=['POST'])
def create_todo():
    title = request.json['title']
    description = request.json.get('description', '')
    todo = Todo(title=title, description=description)
    db.session.add(todo)
    db.session.commit()
    return jsonify({'message': 'Todo created successfully!'})

# 모든 Todo 조회 API
@app.route('/todo', methods=['GET'])
def get_all_todos():
    todos = Todo.query.all()
    result = []
    for todo in todos:
        todo_data = {}
        todo_data['id'] = todo.id
        todo_data['title'] = todo.title
        todo_data['description'] = todo.description
        todo_data['completed'] = todo.completed
        result.append(todo_data)
    return jsonify(result)

# 특정 Todo 조회 API
@app.route('/todo/&amp;lt;int:id&amp;gt;', methods=['GET'])
def get_todo_by_id(id):
    todo = Todo.query.get_or_404(id)
    todo_data = {}
    todo_data['id'] = todo.id
    todo_data['title'] = todo.title
    todo_data['description'] = todo.description
    todo_data['completed'] = todo.completed
    return jsonify(todo_data)

# Todo 수정 API
@app.route('/todo/&amp;lt;int:id&amp;gt;', methods=['PUT'])
def update_todo_by_id(id):
    todo = Todo.query.get_or_404(id)
    title = request.json['title']
    description = request.json.get('description', '')
    completed = request.json.get('completed', False)
    todo.title = title
    todo.description = description
    todo.completed = completed
    db.session.commit()
    return jsonify({'message': 'Todo updated successfully!'})

# Todo 삭제 API
@app.route('/todo/&amp;lt;int:id&amp;gt;', methods=['DELETE'])
def delete_todo_by_id(id):
    todo = Todo.query.get_or_404(id)
    db.session.delete(todo)
    db.session.commit()
    return jsonify({'message': 'Todo deleted successfully!'})

# 앱을 실행합니다.
if __name__ == '__main__':
    app.run(debug=True)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #374151;&quot;&gt;위 코드에서는 Flask와 Flask-SQLAlchemy를 사용하여 Todo 앱을 구현하였습니다. &lt;/span&gt;Todo&lt;span style=&quot;color: #374151;&quot;&gt; 모델은 각각의 Todo를 나타내는 데이터를 저장하며, 각각의 CRUD 기&lt;/span&gt;&lt;span style=&quot;color: #374151;&quot;&gt;능은 다음과 같이 구현되어 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Create(생성)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTTP Method: POST&lt;/li&gt;
&lt;li&gt;URL: /todo&lt;/li&gt;
&lt;li&gt;Request Body: {'title': '할 일 제목', 'description': '할 일 설명'}&lt;/li&gt;
&lt;li&gt;Response Body: {'message': 'Todo created successfully!'}&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Read(읽기)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTTP Method: GET&lt;/li&gt;
&lt;li&gt;URL: /todo&lt;/li&gt;
&lt;li&gt;Response Body: [{'id': 1, 'title': '할 일 제목', 'description': '할 일 설명', 'completed': False}, {...}, {...}]&lt;/li&gt;
&lt;li&gt;HTTP Method: GET&lt;/li&gt;
&lt;li&gt;URL: /todo/{id}&lt;/li&gt;
&lt;li&gt;Response Body: {'id': 1, 'title': '할 일 제목', 'description': '할 일 설명', 'completed': False}&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Update(갱신)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTTP Method: PUT&lt;/li&gt;
&lt;li&gt;URL: /todo/{id}&lt;/li&gt;
&lt;li&gt;Request Body: {'title': '수정된 할 일 제목', 'description': '수정된 할 일 설명', 'completed': True}&lt;/li&gt;
&lt;li&gt;Response Body: {'message': 'Todo updated successfully!'}&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Delete(삭제)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTTP Method: DELETE&lt;/li&gt;
&lt;li&gt;URL: /todo/{id}&lt;/li&gt;
&lt;li&gt;Response Body: {'message': 'Todo deleted successfully!'}&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 예시 코드는 간단한 Todo 앱의 CRUD 기능을 구현한 것으로, 더욱 복잡한 앱에서는 보다 다양한 기능을 추가할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기 위에까지 가 chatGPT한테 &quot;CRUD를 이용한 TODO앱 만들기&quot;라고 물어봤을 때의 답변. ㅋㅋㅋ 블로그 유입 키워드에 &quot;CRUD를 이용한 TODO앱 만들기&quot;가 있어서 chatGPT가 잘 만들어주지 않을까?라고 생각했는데, 생각보다 훌륭하게 만들어줬다. 다만 코드에 대한 설명이 없어서 뭔가 따라 치기는 쉽겠지만 교육용 도로는 사용하지 못할 것 같다. 음.. 그냥 stack overflow정도의 느낌이랄까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 질문을 물어보고 복붙만으로 이정도 블로그 글을 쓸 수 있다는 건 좋은 것 같다. 글의 양만 좀 더 많아진다면 자동 포스팅도 되지 않을까 싶다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 추가적으로, chatGPT는 맞춤법이 틀리지 않는다. 나보다 나은듯... ㅋㅋ&amp;nbsp;&lt;/p&gt;</description>
      <category>Blog/IT, I Think</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/584</guid>
      <comments>https://cholol.tistory.com/584#entry584comment</comments>
      <pubDate>Mon, 27 Feb 2023 20:56:02 +0900</pubDate>
    </item>
    <item>
      <title>Django:제로부터 시작하는 인스타그램 만들기 - DevOps #3 - docker를 이용한 mysql 연결해보고 AWS RDS도 사용해보기</title>
      <link>https://cholol.tistory.com/583</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://cholol.tistory.com/550&quot;&gt;2021.09.15 - [Course/django : 제로부터 시작하는 인스타그램] - Django:제로부터 시작하는 인스타그램 만들기 - clone instagram 목차&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/npCLVAPvnu0&quot; width=&quot;560&quot; height=&quot;315&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;시작하기 전에&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 시간에 nginx와 uwsgi를 이용해서 장고서비스를 EC2에 띄웠습니다. 지금도 잘 되는지 한번 접속해 봐야겠군요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;http://43.201.26.170/main/&quot;&gt;로그인!&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1676715289683&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;로그인!&quot; data-og-description=&quot;&quot; data-og-host=&quot;43.201.26.170&quot; data-og-source-url=&quot;http://43.201.26.170/main/&quot; data-og-url=&quot;http://43.201.26.170/main/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;http://43.201.26.170/main/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;http://43.201.26.170/main/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;로그인!&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;43.201.26.170&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;접속이 잘 되네요 ㅎㅎ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 언제까지 이렇게 ip주소로 접속할 수는 없으니 도메인을 하나 적용해야겠습니다. 제가 자주 사용하는 건 무료 도메인 서비스인 duckdns입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;http://www.duckdns.org/&quot;&gt;Duck DNS (www.duckdns.org)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1676715348294&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Duck DNS&quot; data-og-description=&quot;Duck DNS free dynamic DNS hosted on AWS news: login with Reddit is no more - legal request support&amp;nbsp;us: become a Patreon&quot; data-og-host=&quot;www.duckdns.org&quot; data-og-source-url=&quot;http://www.duckdns.org/&quot; data-og-url=&quot;http://www.duckdns.org/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/HRyJ7/hyREOgqVuH/1EN4LM5bV7XYzpgVP2cpR0/img.png?width=1680&amp;amp;height=385&amp;amp;face=0_0_1680_385&quot;&gt;&lt;a href=&quot;http://www.duckdns.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;http://www.duckdns.org/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/HRyJ7/hyREOgqVuH/1EN4LM5bV7XYzpgVP2cpR0/img.png?width=1680&amp;amp;height=385&amp;amp;face=0_0_1680_385');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Duck DNS&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Duck DNS free dynamic DNS hosted on AWS news: login with Reddit is no more - legal request support&amp;nbsp;us: become a Patreon&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.duckdns.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사이트에 접속해서 구글로 로그인하고, 원하는 도메인 이름 선택하면 xxx.duckdns.org로 접속이 가능합니다. 저는 djangoinsta.duckdns.org로 만든 다음 제 ec2에 ip주소를 넣어주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2639&quot; data-origin-height=&quot;1140&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4UZOC/btrZKyRbDiM/VSzbXtCtnoS3zXuSTcsQzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4UZOC/btrZKyRbDiM/VSzbXtCtnoS3zXuSTcsQzk/img.png&quot; data-alt=&quot;djangoinsta.duckdns.org/main 으로 접속~!!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4UZOC/btrZKyRbDiM/VSzbXtCtnoS3zXuSTcsQzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4UZOC%2FbtrZKyRbDiM%2FVSzbXtCtnoS3zXuSTcsQzk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2639&quot; height=&quot;1140&quot; data-origin-width=&quot;2639&quot; data-origin-height=&quot;1140&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;djangoinsta.duckdns.org/main 으로 접속~!!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 이제 도메인도 넣었겠다 본격적으로 DB를 바꿔볼까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;sqlite3은 뭘까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DB의 종류는 매우 많은데, django의 경우 따로 설정하지 않으면 sqlite3이라는 db를 사용하게 됩니다. sqlite3은 파일에 저장되는 db이며 아주 간단하게 사용할 수 있다는 장점이 있는 db입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공홈 -&amp;nbsp;&lt;a href=&quot;https://www.sqlite.org/index.html&quot;&gt;SQLite Home Page&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 DB 설정은 django프로젝트에 settings.py에 가면 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;...
# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위처럼 DATABASES = 하고 django.db.backends.sqlite3이라고 되어있는 것을 확인할 수 있습니다. 만약 우리가 DB를 다른 것으로 바꾸고 싶으면 바로 이 부분을 수정하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;일단 mysql 띄우기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제 경험상 개인용으로 사용하는 DB는 크게 두 개로 나뉘는데 mysql과 postgredb입니다. 학생분들이나 멘티분들 만나보면 대부분 이 둘 중에 하나를 사용합니다. 기준은 저도 잘 모르겠네요 ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 여기서는 mysql을 사용할 예정입니다. 제가 django프로젝트에 연동할 목적으로 mysql을 사용하는 방법은 몇 가지가 있는데, 제일 선호하는 방식은 docker를 이용해서 mysql을 사용하는 방식입니다. 저희가 지난 시간에 설치했던 nginx나 uwsgi처럼 서버 자체에 mysql을 설치해도 되긴 합니다. 하지만 저희의 궁극적인 목표는 AWS에 있는 RDS를 이용해 DB를 사용하는 것이기 때문에, 서버에 직접 설치하지 않고 docker로 mysql을 설치해서 연동해 보고, 바로 RDS로 넘어가도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 docker로 mysql 띄우는 건 명령어 한 줄만 입력하면 됩니다. 하지만 그전에 docker가 깔려있어야 하는데요, EC2를 만들면 기본으로 설치되어 있으면 좋은데,, 한번 docker라고 명령어를 입력해 봅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1865&quot; data-origin-height=&quot;623&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rxjAJ/btrZKpGGGXL/K1ebh04IXke0gRQK0bfFWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rxjAJ/btrZKpGGGXL/K1ebh04IXke0gRQK0bfFWK/img.png&quot; data-alt=&quot;어림없쥬?&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rxjAJ/btrZKpGGGXL/K1ebh04IXke0gRQK0bfFWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrxjAJ%2FbtrZKpGGGXL%2FK1ebh04IXke0gRQK0bfFWK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1865&quot; height=&quot;623&quot; data-origin-width=&quot;1865&quot; data-origin-height=&quot;623&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;어림없쥬?&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치가 안되어있네요 ㅎㅎ 그래도 친절하게 어떻게 설치하라고 나옵니다 ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 내 컴퓨터에 docker를 설치할 때는 docker-desktop을 설치하는데, 서버에는 docker-ce를 설치해야 합니다. docker-ce는 community engine의 약자인 것 같은데 docker 엔진만 따로 설치됩니다. docker-ee는 community와 반대로 기업용인 enterprise engine인 것 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 방법은 아래와 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676722992025&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;curl -fsSL https://get.docker.com/ | sudo sh
sudo usermod -aG docker $USER # 현재 접속중인 사용자에게 권한주기&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2893&quot; data-origin-height=&quot;876&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ePhvnl/btrZPSVsxvf/65KTcobF2bGVpSmIQPKYiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ePhvnl/btrZPSVsxvf/65KTcobF2bGVpSmIQPKYiK/img.png&quot; data-alt=&quot;알아서 설치됨&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ePhvnl/btrZPSVsxvf/65KTcobF2bGVpSmIQPKYiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FePhvnl%2FbtrZPSVsxvf%2F65KTcobF2bGVpSmIQPKYiK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2893&quot; height=&quot;876&quot; data-origin-width=&quot;2893&quot; data-origin-height=&quot;876&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;알아서 설치됨&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에 줄을 입력하면 알아서 설치되고, 아랫줄은 현재 로그인한 유저한테 docker권한을 주는 명령어입니다. 없으니까 나중에 실행할 때 에러가 나더라구요. 설치 후 docker라고 치면 이전과 다르게 뭐라 뭐라 뜨는 걸 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 docker로 mysql을 실행하면 되는데, 아래 한 줄을 입력하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676724077448&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker run --name mysql-db -p 3306:3306 -e MYSQL_ROOT_PASSWORD=password -e MYSQL_PASSWORD=password mysql&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 docker run은 docker를 실행하는 명령어이고, 그 뒤에 옵션을 주르륵 달면 됩니다. 여기서 사용한 옵션은 --name으로 실행하는 docker 컨테이너에 이름을 넣어주고, -p옵션으로 포트를 정해주었습니다. mysql의 경우 기본적으로 3306 포트를 사용하기 때문에 외부에서 들어오는 3306 포트를 docker 컨테이너의 3306 포트로 포워딩할 수 있도록 -p 3306:3306이라고 적어줍니다. -e는 환경변수를 주는 옵션인데 MYSQL_ROOT_PASSWORD와 MYSQL_PASSWORD를 추가합니다. 이 패스워드는 나중에 django 설정에 넣어야 하니 여러분이 원하시는 비밀번호를 입력하시면 됩니다. 마지막으로 맨 뒤에 mysql은 docker 컨테이너를 실행할 이미지를 가리키는데, mysql이라고 입력하면 docker 서버에 있는 mysql 공식 이미지를 이용해서 docker 컨테이너를 실행합니다. 특정 버전을 명시해 줄 수 있지만 그냥 mysql이라고 쓰면 최신버전으로 설치됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 mysql은 5.7, 8.0 두 가지 버전을 많이 사용하는데, 저희는 그냥 최신버전을 설치하겠습니다. 아마 mysql이라고 치면 8.0이 설치되었던 것 같은 느낌이네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3374&quot; data-origin-height=&quot;305&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dJQ32f/btrZJWx0IpS/Px0XOIzXS3I6DjA2mD44P0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dJQ32f/btrZJWx0IpS/Px0XOIzXS3I6DjA2mD44P0/img.png&quot; data-alt=&quot;permission denied&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dJQ32f/btrZJWx0IpS/Px0XOIzXS3I6DjA2mD44P0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdJQ32f%2FbtrZJWx0IpS%2FPx0XOIzXS3I6DjA2mD44P0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3374&quot; height=&quot;305&quot; data-origin-width=&quot;3374&quot; data-origin-height=&quot;305&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;permission denied&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 위와 같이 권한 오류가 난다면, 터미널 껐다 켜면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2907&quot; data-origin-height=&quot;1546&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5xzFF/btrZQdL0fn7/TINGTuIViZphEbQV6cDFu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5xzFF/btrZQdL0fn7/TINGTuIViZphEbQV6cDFu1/img.png&quot; data-alt=&quot;docker로 mysql 실행&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5xzFF/btrZQdL0fn7/TINGTuIViZphEbQV6cDFu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5xzFF%2FbtrZQdL0fn7%2FTINGTuIViZphEbQV6cDFu1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2907&quot; height=&quot;1546&quot; data-origin-width=&quot;2907&quot; data-origin-height=&quot;1546&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;docker로 mysql 실행&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제대로 실행이 되면 mysql:lastest 버전의 이미지를 다운로드하는 글씨가 나오고, 그 후에 mysql이 구동되는 글씨들이 쭈르륵 나옵니다. 그리고 바로 mysql이 실행되어 버리기 대문에 터미널에서 뭘 할 수가 없습니다. ㅎㅎ 백그라운드로 실행되게 해야 하는데 일단은 바로 실행되게 만들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3390&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XK7kD/btrZPSHW4Ij/qQmqkn76iCkbEXVKmDvCT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XK7kD/btrZPSHW4Ij/qQmqkn76iCkbEXVKmDvCT1/img.png&quot; data-alt=&quot;mysql이 실행중인 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XK7kD/btrZPSHW4Ij/qQmqkn76iCkbEXVKmDvCT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXK7kD%2FbtrZPSHW4Ij%2FqQmqkn76iCkbEXVKmDvCT1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3390&quot; height=&quot;600&quot; data-origin-width=&quot;3390&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;mysql이 실행중인 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;내 컴퓨터에서 mysql 접속해 보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 그럼 mysql이 잘 떠있는지 확인하기 위해서는 컴퓨터에서 DB접속하는 프로그램으로 접속해 보면 됩니다. 저는 젯브레인에서 만든 DataGrip이라는 툴을 사용하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1708&quot; data-origin-height=&quot;1510&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nPbCR/btrZQcff3fJ/MwsjYsBGQvKOlukHgXKfJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nPbCR/btrZQcff3fJ/MwsjYsBGQvKOlukHgXKfJ0/img.png&quot; data-alt=&quot;host와 user, password 입력&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nPbCR/btrZQcff3fJ/MwsjYsBGQvKOlukHgXKfJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnPbCR%2FbtrZQcff3fJ%2FMwsjYsBGQvKOlukHgXKfJ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1708&quot; height=&quot;1510&quot; data-origin-width=&quot;1708&quot; data-origin-height=&quot;1510&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;host와 user, password 입력&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;host는 우리의 EC2를 입력해 주고, port는 3306으로 지정합니다. 그러면 EC2의 3306으로 통신하게 되고, 우리가 docker를 실행할 때 3306으로 들어온 외부 통신은 docker에 있는 3306으로 포워딩하기 때문에 mysql과 통신하게 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 지금 아무 설정 없이 하게 되면 통신 실패가 뜰탠대요, AWS console에서 방화벽을 열어주어야 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3596&quot; data-origin-height=&quot;1002&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dUsZiT/btrZNKi1Y7n/tbqxEaKo8fZ5yVokkgVFBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dUsZiT/btrZNKi1Y7n/tbqxEaKo8fZ5yVokkgVFBk/img.png&quot; data-alt=&quot;mysql open&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dUsZiT/btrZNKi1Y7n/tbqxEaKo8fZ5yVokkgVFBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdUsZiT%2FbtrZNKi1Y7n%2FtbqxEaKo8fZ5yVokkgVFBk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3596&quot; height=&quot;1002&quot; data-origin-width=&quot;3596&quot; data-origin-height=&quot;1002&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;mysql open&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mysql은 아까 말한 것처럼 3306 포트를 사용합니다. AWS RDS에서 제공하는 Aurora도 Mysql과 똑같이 3306을 기본으로 사용합니다. 나중을 위해 체크~!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포트를 열고 다시 datagrip으로 돌아와서 접속시도를 해보면 아까는 Fail이 떨어졌는데 지금은 Success가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;1478&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clHtpP/btrZLU0xkwI/qksQ0sdzZyBdbkZ4eUoBQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clHtpP/btrZLU0xkwI/qksQ0sdzZyBdbkZ4eUoBQK/img.png&quot; data-alt=&quot;성공&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clHtpP/btrZLU0xkwI/qksQ0sdzZyBdbkZ4eUoBQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclHtpP%2FbtrZLU0xkwI%2FqksQ0sdzZyBdbkZ4eUoBQK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1672&quot; height=&quot;1478&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;1478&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;성공&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 이제 DB가 생긴 것을 확인했으니, django에서 해당 DB를 바라보도록 settings.py를 수정합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676728273202&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': BASE_DIR / 'db.sqlite3',
#     }
# }

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': '43.201.26.170',
        'NAME': 'mysql-db',
        'USER': 'root',
        'PASSWORD': 'password',
        'PORT': '3306',
        'OPTIONS': {'charset': 'utf8mb4'},
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에 주석처리된 것은 sqlite3 설정이고, 아래가 mysql설정입니다. ENGINE 설정값이 기존에 sqlite3에서 mysql로 바뀐 것을 확인할 수 있습니다. 그밖에 서버 주소인 HOST, DB이름인 mysql-db, 포트 3306등이 추가된 것을 확인할 수 있습니다. 이제 한번 로컬에서 django를 실행해 보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2738&quot; data-origin-height=&quot;264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BsOsX/btrZJDr4xy3/0iVAgunasp20whOSv0BZu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BsOsX/btrZJDr4xy3/0iVAgunasp20whOSv0BZu1/img.png&quot; data-alt=&quot;에러~!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BsOsX/btrZJDr4xy3/0iVAgunasp20whOSv0BZu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBsOsX%2FbtrZJDr4xy3%2F0iVAgunasp20whOSv0BZu1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2738&quot; height=&quot;264&quot; data-origin-width=&quot;2738&quot; data-origin-height=&quot;264&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;에러~!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 실행하면 did you install mysqlclient?라는 에러를 볼 수 있습니다. 이건 저희 프로젝트에서 mysql을 사용할 준비가 안되었다는 건데요, mysql을 사용하려면 mysql 지원 패키지를 설치해야 합니다. 설치는 간단합니다. pip install mysqlclient 하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서! 아마 많은 분들이 에러를 만나실 텐데,, python에 mysqlclient가 상당히 문제가 많습니다. OS별로 어디는 잘되고 어디는 안되고 그러거든요 ㅋㅋ 아마 맥에서는 x-code 버전에 따라서 될 대가 있고 안될 대가 있고 그렇습니다 ㅡㅡ 오히려 윈도는 에러가 날 경우 이전 버전을 설치해서 해결되는 경우가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676728855536&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install mysqlclient==2.0.3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맥의 경우 아주 다양한 해결방법들이 있는데, 해결방법이 에러 케이스마다 다르기 때문에 구글링 하시는 걸 추천드립니다. 이렇게 개발환경 구성하는 게 까다로워서 아싸리 django 역시 docker로 띄우는 걸 선호하긴 합니다. (여기서는 쌩으로 하지만,, ㅎㅎ)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mysqlclient가 설치되었다면 다시 로컬에서 django를 실행해 봅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2906&quot; data-origin-height=&quot;936&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfaq7L/btrZIK5Vqba/LbYw6t2pBfzeZlfDF7EAl1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfaq7L/btrZIK5Vqba/LbYw6t2pBfzeZlfDF7EAl1/img.png&quot; data-alt=&quot;unknown database 'mysql-db'&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfaq7L/btrZIK5Vqba/LbYw6t2pBfzeZlfDF7EAl1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcfaq7L%2FbtrZIK5Vqba%2FLbYw6t2pBfzeZlfDF7EAl1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2906&quot; height=&quot;936&quot; data-origin-width=&quot;2906&quot; data-origin-height=&quot;936&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;unknown database 'mysql-db'&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에러가 나네요. mysql-db라는 데이터베이스를 알 수 없다고 나오는데 왜일까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 EC2에서 도커로 mysql-db라는 이름의 mysql을 실행했습니다. 그래서 database이름을 mysql-db라고 적었지만, 사실 도커의 이름이 mysql-db이지 database의 이름이 mysql-db가 아닙니다. 괜히 같은 이름으로 했더니 헷갈리는군요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DB이름을 변경하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676729186162&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': '43.201.26.170',
        'NAME': 'djangoinsta',
        'USER': 'root',
        'PASSWORD': 'password',
        'PORT': '3306',
        'OPTIONS': {'charset': 'utf8mb4'},
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;name을 djangoinsta로 변경했습니다. 다시 한번 django를 실행해 볼까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2532&quot; data-origin-height=&quot;610&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eaWCaX/btrZLUTKKZ6/fejDxg3PAC7dTGDIahAKs0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eaWCaX/btrZLUTKKZ6/fejDxg3PAC7dTGDIahAKs0/img.png&quot; data-alt=&quot;다시 에러 발생&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eaWCaX/btrZLUTKKZ6/fejDxg3PAC7dTGDIahAKs0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeaWCaX%2FbtrZLUTKKZ6%2FfejDxg3PAC7dTGDIahAKs0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2532&quot; height=&quot;610&quot; data-origin-width=&quot;2532&quot; data-origin-height=&quot;610&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;다시 에러 발생&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이름만 바뀌고 같은 에러가 나오는군요. 이건 실제로 djangoinsta라는 db가 없기 때문입니다. 장고는 기본적으로 ORM을 지원하고, ORM이란 모델 = 테이블 이 자동으로 매핑된다는 의미입니다. 이 기능을 활용하기 위해 필요한 것이 바로 migration인데요, 저희가 장고를 사용하면서 모델을 변경할 때마다 해주던 migrate를 해주어야 DB가 생기게 됩니다. 기존에 sqlite3은 우리가 제일 처음 migrate를 해주었기 때문에 사용할 수 있었고, mysql 역시 migrate를 해주어야 사용할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 python manage.py makemigrations, python manage.py migrate를 해봅시다~!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3334&quot; data-origin-height=&quot;311&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4Afso/btrZLRQnbsU/KFBQhYMfCg8kqeg3kdt4m0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4Afso/btrZLRQnbsU/KFBQhYMfCg8kqeg3kdt4m0/img.png&quot; data-alt=&quot;같은 에러&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4Afso/btrZLRQnbsU/KFBQhYMfCg8kqeg3kdt4m0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4Afso%2FbtrZLRQnbsU%2FKFBQhYMfCg8kqeg3kdt4m0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3334&quot; height=&quot;311&quot; data-origin-width=&quot;3334&quot; data-origin-height=&quot;311&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;같은 에러&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역시 Unknown databse가 나오는데요, 이건 저희가 mysql로 db를 띄웠지만, 거기서 djangoinsta라는 db를 생성하지 않아서 그렇습니다. 가장 초기에 database를 생성하는 건 사용자가 해주어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;datagrip에서 create schema를 통해 우리가 띄운 mysql에 djangoinsta라는 database를 추가해 줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1862&quot; data-origin-height=&quot;1262&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsm0PD/btrZNvM28rF/RwcQ7FGcd9KKAtcw87rPc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsm0PD/btrZNvM28rF/RwcQ7FGcd9KKAtcw87rPc1/img.png&quot; data-alt=&quot;schema생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsm0PD/btrZNvM28rF/RwcQ7FGcd9KKAtcw87rPc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbsm0PD%2FbtrZNvM28rF%2FRwcQ7FGcd9KKAtcw87rPc1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1862&quot; height=&quot;1262&quot; data-origin-width=&quot;1862&quot; data-origin-height=&quot;1262&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;schema생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요게 어디서는 database라고 부르는데 어디서는 schema라고 부릅니다. 아주 용어가 헷갈리죠?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;django_devops에서 오른쪽 클릭을 해서 create schema를 해줍니다. 이름은 우리가 장고 settings.py에서 설정했던 djangoinsta이고 collation에 utf8 mb_general_ci를 선택해 줍니다. 요건 테이블에 들어가는 문자에 대한 인코딩인데, 요걸 안 해주면 한글이 테이블에 들어가면 깨지게 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;772&quot; data-origin-height=&quot;270&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RMITb/btrZKxx75MM/itzZJoXAPkRaFCdWn660c0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RMITb/btrZKxx75MM/itzZJoXAPkRaFCdWn660c0/img.png&quot; data-alt=&quot;생성완료&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RMITb/btrZKxx75MM/itzZJoXAPkRaFCdWn660c0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRMITb%2FbtrZKxx75MM%2FitzZJoXAPkRaFCdWn660c0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;772&quot; height=&quot;270&quot; data-origin-width=&quot;772&quot; data-origin-height=&quot;270&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;생성완료&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성을 하면 그림처럼 djangoinsta 항목이 생기게 됩니다. 이게 django_devops라는 mysql서버에 있는 database가 생긴 겁니다. 다시 migrate를 하면 이제 에러가 안나는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1608&quot; data-origin-height=&quot;1182&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcEU5B/btrZITaVvSd/BBfdiqpunAFTo3s9G6bs8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcEU5B/btrZITaVvSd/BBfdiqpunAFTo3s9G6bs8k/img.png&quot; data-alt=&quot;완료&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcEU5B/btrZITaVvSd/BBfdiqpunAFTo3s9G6bs8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcEU5B%2FbtrZITaVvSd%2FBBfdiqpunAFTo3s9G6bs8k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1608&quot; height=&quot;1182&quot; data-origin-width=&quot;1608&quot; data-origin-height=&quot;1182&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;완료&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 이제 migrate가 완료되었습니다. datagrip에서 보면 실제로 테이블이 생긴 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1036&quot; data-origin-height=&quot;731&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dbR6mb/btrZJ2kQsyH/UsQ7mK3Bb5IHulLxMPkpYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dbR6mb/btrZJ2kQsyH/UsQ7mK3Bb5IHulLxMPkpYk/img.png&quot; data-alt=&quot;생겼다~!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dbR6mb/btrZJ2kQsyH/UsQ7mK3Bb5IHulLxMPkpYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdbR6mb%2FbtrZJ2kQsyH%2FUsQ7mK3Bb5IHulLxMPkpYk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1036&quot; height=&quot;731&quot; data-origin-width=&quot;1036&quot; data-origin-height=&quot;731&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;생겼다~!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 이제 django를 실행해 봅니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1674&quot; data-origin-height=&quot;718&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RQ3Mu/btrZK3cqOCW/5XOu8WfKMlzfCJFKQ8Pb3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RQ3Mu/btrZK3cqOCW/5XOu8WfKMlzfCJFKQ8Pb3k/img.png&quot; data-alt=&quot;실행 완료&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RQ3Mu/btrZK3cqOCW/5XOu8WfKMlzfCJFKQ8Pb3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRQ3Mu%2FbtrZK3cqOCW%2F5XOu8WfKMlzfCJFKQ8Pb3k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1674&quot; height=&quot;718&quot; data-origin-width=&quot;1674&quot; data-origin-height=&quot;718&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실행 완료&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제대로 실행되는 것을 알 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;서버에 있는 django와 mysql 연동&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 수정한 settings.py를 서버에도 적용해 봅시다. github에 push 하고 서버에서 pull~!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2333&quot; data-origin-height=&quot;364&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k4dfU/btrZK2SaTZ3/VE0HR3UouJwKVwYsCkOnI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k4dfU/btrZK2SaTZ3/VE0HR3UouJwKVwYsCkOnI0/img.png&quot; data-alt=&quot;settings 수정버전 적용 완료&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k4dfU/btrZK2SaTZ3/VE0HR3UouJwKVwYsCkOnI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk4dfU%2FbtrZK2SaTZ3%2FVE0HR3UouJwKVwYsCkOnI0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2333&quot; height=&quot;364&quot; data-origin-width=&quot;2333&quot; data-origin-height=&quot;364&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;settings 수정버전 적용 완료&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아 저희가 mysqlclient를 설치했으니 서버도 마찬가지로 설치를 해야겠네요. 통일하기 위해서 requirements.txt에 추가해 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1399&quot; data-origin-height=&quot;163&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nk2Vs/btrZUCxRZgU/1CF5sETxY26SharKFU6Ax1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nk2Vs/btrZUCxRZgU/1CF5sETxY26SharKFU6Ax1/img.png&quot; data-alt=&quot;pip freeze를 통해서 requirements.txt 업뎃&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nk2Vs/btrZUCxRZgU/1CF5sETxY26SharKFU6Ax1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fnk2Vs%2FbtrZUCxRZgU%2F1CF5sETxY26SharKFU6Ax1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1399&quot; height=&quot;163&quot; data-origin-width=&quot;1399&quot; data-origin-height=&quot;163&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;pip freeze를 통해서 requirements.txt 업뎃&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버에서도 설치를 위해 pip3 install -r requirements.txt를 해줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3081&quot; data-origin-height=&quot;882&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/D6V9A/btrZNu1IfyQ/yv1cNYimwxnIzkKs59Qe90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/D6V9A/btrZNu1IfyQ/yv1cNYimwxnIzkKs59Qe90/img.png&quot; data-alt=&quot;에러 발생!!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/D6V9A/btrZNu1IfyQ/yv1cNYimwxnIzkKs59Qe90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FD6V9A%2FbtrZNu1IfyQ%2Fyv1cNYimwxnIzkKs59Qe90%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3081&quot; height=&quot;882&quot; data-origin-width=&quot;3081&quot; data-origin-height=&quot;882&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;에러 발생!!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아니 ㅋㅋ 우분투에서도 mysqlclient 설치하다가 에러가 나는군요.. 크흑..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만~! 구글링 해보면 아주 간단하게 답이 나옵니다 ㅎㅎ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676731108223&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo apt-get install python3-dev default-libmysqlclient-dev build-essential&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 명령어로 mysqlclient관련 패키지를 설치해 주면 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2681&quot; data-origin-height=&quot;405&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dQjBUk/btrZLVyn1RX/ZlzM9fvGkXiSzUWZksI3Bk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dQjBUk/btrZLVyn1RX/ZlzM9fvGkXiSzUWZksI3Bk/img.png&quot; data-alt=&quot;성공&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dQjBUk/btrZLVyn1RX/ZlzM9fvGkXiSzUWZksI3Bk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdQjBUk%2FbtrZLVyn1RX%2FZlzM9fvGkXiSzUWZksI3Bk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2681&quot; height=&quot;405&quot; data-origin-width=&quot;2681&quot; data-origin-height=&quot;405&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;성공&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 django를 재시작하면 되는데 재시작하는 방법은 uwsgi 서비스를 내렸다 올리면 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676731301473&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo systemctl restart uwsgi&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 /tmp/uwsgi.ini 로그를 한번 확인해 봅시다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2879&quot; data-origin-height=&quot;540&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XhohE/btrZKZOyLUn/lt8gRdyYA24AKO9ryGu9lk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XhohE/btrZKZOyLUn/lt8gRdyYA24AKO9ryGu9lk/img.png&quot; data-alt=&quot;정상 실행 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XhohE/btrZKZOyLUn/lt8gRdyYA24AKO9ryGu9lk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXhohE%2FbtrZKZOyLUn%2Flt8gRdyYA24AKO9ryGu9lk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2879&quot; height=&quot;540&quot; data-origin-width=&quot;2879&quot; data-origin-height=&quot;540&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;정상 실행 확인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘 실행되었군요? 그럼 인스타에 접속해 볼까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2096&quot; data-origin-height=&quot;1355&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ltH9f/btrZUDctUA5/UoF2gZLkkYyTdWD5DBOXk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ltH9f/btrZUDctUA5/UoF2gZLkkYyTdWD5DBOXk1/img.png&quot; data-alt=&quot;잘 실행됨~!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ltH9f/btrZUDctUA5/UoF2gZLkkYyTdWD5DBOXk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FltH9f%2FbtrZUDctUA5%2FUoF2gZLkkYyTdWD5DBOXk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2096&quot; height=&quot;1355&quot; data-origin-width=&quot;2096&quot; data-origin-height=&quot;1355&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;잘 실행됨~!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘 실행되는데 뭐가 바뀐 건지 모르겠군요 ㅎㅎ 이럴 때는 회원가입이나 글을 써보면 됩니다. 우리는 DB를 mysql로 바꿨기 때문에 데이터가 저장되면 mysql에 생기게 되기 때문이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1144&quot; data-origin-height=&quot;1148&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EGhNc/btrZQec9Xco/tRkXygV9eYTbQjOiPKB5FK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EGhNc/btrZQec9Xco/tRkXygV9eYTbQjOiPKB5FK/img.png&quot; data-alt=&quot;테스트 회원가입&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EGhNc/btrZQec9Xco/tRkXygV9eYTbQjOiPKB5FK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEGhNc%2FbtrZQec9Xco%2FtRkXygV9eYTbQjOiPKB5FK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;502&quot; data-origin-width=&quot;1144&quot; data-origin-height=&quot;1148&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;테스트 회원가입&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회원가입을 했으면 다시 datagrip으로 가서 테이블을 확인합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3612&quot; data-origin-height=&quot;674&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b76xce/btrZJWrhSEn/7k0samFLD6yMXLYtVyxkP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b76xce/btrZJWrhSEn/7k0samFLD6yMXLYtVyxkP1/img.png&quot; data-alt=&quot;테이블에 데이터 확인~!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b76xce/btrZJWrhSEn/7k0samFLD6yMXLYtVyxkP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb76xce%2FbtrZJWrhSEn%2F7k0samFLD6yMXLYtVyxkP1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3612&quot; height=&quot;674&quot; data-origin-width=&quot;3612&quot; data-origin-height=&quot;674&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;테이블에 데이터 확인~!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제대로 적용이 되었으면 User테이블에 데이터가 한 건 생긴 것을 확인할 수 있습니다~!!! 구우우웃~!!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 django와 docker로 실행한 mysql과의 연동 한 단계가 끝났습니다~!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Secret 정보들 관리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RDS와 연동하기 전에 하나 수정해야 할 부분이 있는데요, 현재 장고 프로젝트를 보면 DB접속 패스워드가 노출되어 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1068&quot; data-origin-height=&quot;506&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WKqA9/btrZNJxIAmc/MQ865vpzqPoIHeeB5xpbEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WKqA9/btrZNJxIAmc/MQ865vpzqPoIHeeB5xpbEK/img.png&quot; data-alt=&quot;떡하니~&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WKqA9/btrZNJxIAmc/MQ865vpzqPoIHeeB5xpbEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWKqA9%2FbtrZNJxIAmc%2FMQ865vpzqPoIHeeB5xpbEK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;190&quot; data-origin-width=&quot;1068&quot; data-origin-height=&quot;506&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;떡하니~&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 밖에도 DB user이름이나 host ip가 코드에 적혀있는데, 이대로 github에 올리게 되면 public repo라면 공개적으로 노출됩니다. 그럼 다른 사람들도 볼 수 있기 때문에 내 서버에 들어와서 나쁜 짓(?)을 할 수 있겠죠? 실제로 이렇게 github에 코드를 잘 못 올려서 해킹되는 사례가 많습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요런 민감한 정보들을 Secret data라고 부르기도 하는데요, 요론 정보들은 보통 환경변수를 통해 관리하거나 별도 솔루션을 사용해 관리합니다. 저희도 이런 정보들을 환경변수로 바꿔보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676819220245&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': os.environ.get('MYSQL_HOST'),
        'NAME': os.environ.get('MYSQL_DB_NAME'),
        'USER': os.environ.get('MYSQL_USER'),
        'PASSWORD': os.environ.get('MYSQL_PASSWORD'),
        'PORT': '3306',
        'OPTIONS': {'charset': 'utf8mb4'},
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 이런 식으로 바꿔줍니다. os에 혹시 빨간 줄이 난다면 settings.py 맨 위에 import os를 추가해주어야 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;os.environ.get('XXX')라는 게 환경변수 'XXX'의 값을 받아오겠다~라는 뜻입니다. 환경변수라는 건 윈도에서는 아마 여러분이 JAVA를 설치할 때 설정해 보셨을 텐데, 제어판 어디 어디 들어가서 세팅하는 OS에 종속적인 상수값입니다. 리눅스에서는 보통. bash_profile이나. profile에 PATH로 추가하면 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 윈도우에서 쓸 때는 잘 세팅 안 하기 때문에... 먼저 우분투에서 어떻게 세팅되는지 한번 보여드리겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2091&quot; data-origin-height=&quot;1056&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHcHIL/btrZNu83HUv/l2HkbIAukQLaPFW2PDGmP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHcHIL/btrZNu83HUv/l2HkbIAukQLaPFW2PDGmP0/img.png&quot; data-alt=&quot;홈 경로에 있다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHcHIL/btrZNu83HUv/l2HkbIAukQLaPFW2PDGmP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHcHIL%2FbtrZNu83HUv%2Fl2HkbIAukQLaPFW2PDGmP0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2091&quot; height=&quot;1056&quot; data-origin-width=&quot;2091&quot; data-origin-height=&quot;1056&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;홈 경로에 있다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우분투 홈경로에 가서 ls -la를 하게 되면 숨김파일까지 표시되는데요, 여기서. profile을 열어봅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2367&quot; data-origin-height=&quot;1017&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PyHJ2/btrZ2yPKSOx/2dIhBlQyxb2RUtjl8Y3mKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PyHJ2/btrZ2yPKSOx/2dIhBlQyxb2RUtjl8Y3mKk/img.png&quot; data-alt=&quot;.profile&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PyHJ2/btrZ2yPKSOx/2dIhBlQyxb2RUtjl8Y3mKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPyHJ2%2FbtrZ2yPKSOx%2F2dIhBlQyxb2RUtjl8Y3mKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2367&quot; height=&quot;1017&quot; data-origin-width=&quot;2367&quot; data-origin-height=&quot;1017&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;.profile&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요론게 나오는데 여기 맨~~ 아랫줄에 하나를 추가합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2646&quot; data-origin-height=&quot;704&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ys3nB/btrZJ2Z1tiX/lebjb08yQZMBdKiv5pFZLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ys3nB/btrZJ2Z1tiX/lebjb08yQZMBdKiv5pFZLK/img.png&quot; data-alt=&quot;요롷게&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ys3nB/btrZJ2Z1tiX/lebjb08yQZMBdKiv5pFZLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fys3nB%2FbtrZJ2Z1tiX%2Flebjb08yQZMBdKiv5pFZLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2646&quot; height=&quot;704&quot; data-origin-width=&quot;2646&quot; data-origin-height=&quot;704&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;요롷게&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 추가하면 환경변수 세팅이 끝납니다. 터미널을 껐다 켜거나 source. profile을 해서 변경한 환경설정을 적용해 줍니다. 그리고 세팅된 값을 확인해 보려면 echo &amp;amp;{변수명} 하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1316&quot; data-origin-height=&quot;317&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0Uvpu/btrZJWZCu2H/Yvun7qiBZCVQakKCwkfIp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0Uvpu/btrZJWZCu2H/Yvun7qiBZCVQakKCwkfIp0/img.png&quot; data-alt=&quot;변수명 설정 완료&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0Uvpu/btrZJWZCu2H/Yvun7qiBZCVQakKCwkfIp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0Uvpu%2FbtrZJWZCu2H%2FYvun7qiBZCVQakKCwkfIp0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1316&quot; height=&quot;317&quot; data-origin-width=&quot;1316&quot; data-origin-height=&quot;317&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;변수명 설정 완료&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽쥬? 이제 소스에는 DB에 대한 호스트값이나 유저이름, 비밀번호들이 입력되지 않고 서버에 있는 환경변수값을 읽어서 세팅하게 됩니다. 요게 지금은 서버가 하나라 저희가 직접 들어가서 세팅하지만, 나중에 서버가 많아지면 자동으로 설정되게 만들어야 하고, 이게 힘들면 이렇게 공개되면 안 되는 중요정보들을 관리하는 솔루션을 사용하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 서버에서는 환경변수값을 읽어서 사용하는데, 로컬에서는 어떻게 사용하게 될까요? 방법이 여러 가지가 있는데, 내 컴퓨터에도 환경설정 값을 넣어주는 방법이 있고, 로컬환경에 알맞은 값을 디폴트로 세팅하는 방법이 있습니다. 1번은 내 컴퓨터에 환경변수를 설정해줘야 하는데, 저는 사용하는 컴퓨터가 여러대라 일일이 세팅하기 귀찮더라고요. 그래서 후자를 많이 씁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': os.environ.get('MYSQL_HOST', '43.201.26.170'),
        'NAME': os.environ.get('MYSQL_DB_NAME', 'djangoinsta'),
        'USER': os.environ.get('MYSQL_USER', 'root'),
        'PASSWORD': os.environ.get('MYSQL_PASSWORD', 'password'),
        'PORT': '3306',
        'OPTIONS': {'charset': 'utf8mb4'},
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요롷게 콤마로 default값을 줄 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 이렇게 되면 이전과 똑같이 정보가 노출되지 않나요?라고 생각할 수도 있는데, 지금은 서버에서 사용하는 값과 같은 값을 디폴트로 써서 그렇지, 실제로 서버에서 사용하는 mysql이랑 내 컴퓨터에서 사용하는 mysql은 다를 겁니다. 지금은 서버에 mysql을 접속하게 만들었지만 보통은 로컬에서 테스트할 때는 로컬용 mysql을 띄워놓고 사용하기 때문에 정보가 다르겠죠?&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': os.environ.get('MYSQL_HOST', 'localhost'),
        'NAME': os.environ.get('MYSQL_DB_NAME', 'djangoinsta'),
        'USER': os.environ.get('MYSQL_USER', 'root'),
        'PASSWORD': os.environ.get('MYSQL_PASSWORD', 'localdb_password'),
        'PORT': '3306',
        'OPTIONS': {'charset': 'utf8mb4'},
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요론식으로요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 이렇게 적용해 놨으니 한번 제대로 실행되는지 서버에 코드를 배포해 봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2538&quot; data-origin-height=&quot;1680&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOyq34/btrZ0KJxLZS/C0G9QYvhNEliQxvjUmVbsK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOyq34/btrZ0KJxLZS/C0G9QYvhNEliQxvjUmVbsK/img.png&quot; data-alt=&quot;서버에 적용&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOyq34/btrZ0KJxLZS/C0G9QYvhNEliQxvjUmVbsK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOyq34%2FbtrZ0KJxLZS%2FC0G9QYvhNEliQxvjUmVbsK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2538&quot; height=&quot;1680&quot; data-origin-width=&quot;2538&quot; data-origin-height=&quot;1680&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;서버에 적용&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;git pull로 소스를 반영하고 uwsgi를 재부팅해줍니다. 그리고 /tmp/uwsgi.log를 확인하거나 직접 브라우저로 접속해서 제대로 실행되는지 봐줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2576&quot; data-origin-height=&quot;578&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baAJtV/btrZNv1cw2h/ECwKY3BauklxJUQcMQBN51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baAJtV/btrZNv1cw2h/ECwKY3BauklxJUQcMQBN51/img.png&quot; data-alt=&quot;에러없음!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baAJtV/btrZNv1cw2h/ECwKY3BauklxJUQcMQBN51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaAJtV%2FbtrZNv1cw2h%2FECwKY3BauklxJUQcMQBN51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2576&quot; height=&quot;578&quot; data-origin-width=&quot;2576&quot; data-origin-height=&quot;578&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;에러없음!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에러가 없네요~! 아마 설정값을 제대로 못 읽어왔다면 mysql을 못 찾는다는 에러가 발생했을 겁니다. 제대로 적용 됐는지 확인하는 방법도 있는데 python 콘솔에 접속해서 직접 코드를 때려보면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1996&quot; data-origin-height=&quot;772&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEsvgQ/btrZV67evEa/a5cgg81jSFzzB7z3i008O1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEsvgQ/btrZV67evEa/a5cgg81jSFzzB7z3i008O1/img.png&quot; data-alt=&quot;직접 코드로 때리기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEsvgQ/btrZV67evEa/a5cgg81jSFzzB7z3i008O1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEsvgQ%2FbtrZV67evEa%2Fa5cgg81jSFzzB7z3i008O1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1996&quot; height=&quot;772&quot; data-origin-width=&quot;1996&quot; data-origin-height=&quot;772&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;직접 코드로 때리기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;환경변수값이 잘 나오죠?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AWS RDS로 적용하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 이제 마지막으로 AWS에 RDS를 사용해서 연결해 보도록 하겠습니다. 방법은 생각보다 심플합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AWS에서 RDS를 이용해 aurora(mysql) DB를 만든다.&lt;/li&gt;
&lt;li&gt;기본 database를 만들어준다. (djangoinsta schema생성해 준 것처럼 RDS에서도 생성해줘야 함)&lt;/li&gt;
&lt;li&gt;환경변수값을 위에서 만든 DB 정보로 바꿔준다.&lt;/li&gt;
&lt;li&gt;마이그레이션을 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 RDS를 생성하기 위해 AWS 콘솔로 접속합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2244&quot; data-origin-height=&quot;1730&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWQlWh/btrZNJE3zGZ/RuavofWOAyssqnrpQL1KZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWQlWh/btrZNJE3zGZ/RuavofWOAyssqnrpQL1KZk/img.png&quot; data-alt=&quot;RDS 생성메뉴&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWQlWh/btrZNJE3zGZ/RuavofWOAyssqnrpQL1KZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWQlWh%2FbtrZNJE3zGZ%2FRuavofWOAyssqnrpQL1KZk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2244&quot; height=&quot;1730&quot; data-origin-width=&quot;2244&quot; data-origin-height=&quot;1730&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;RDS 생성메뉴&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콘솔에서 RDS 대시보드로 넘어간 뒤 새로운 데이터베이스 생성을 누릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 위 화면처럼 어떤 DB를 만들 건지 선택하라고 나오는데, 요 화면이 거의 매년 바뀌는 것 같네요 ㅋㅋ 관련 포스팅을 여러 번 쓴 거 같은데 매번 화면이 바뀌니...&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 저희는 Aurora를 만들 겁니다. 옆에 MySQL도 있는데 Aurora는 AWS에서 MySQL을 자기네들이 조금 커스터마이징 한 DB입니다. AWS피셜로 성능이 5~13배 정도 좋다고 하네요. 실제로 사용하는 데는 MySQL과 똑같기 때문에 Aurora를 고릅니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1550&quot; data-origin-height=&quot;428&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/A3jOL/btrZYRB50F1/ntHUOlTh3pPNFzkYD0fEj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/A3jOL/btrZYRB50F1/ntHUOlTh3pPNFzkYD0fEj1/img.png&quot; data-alt=&quot;개발용&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/A3jOL/btrZYRB50F1/ntHUOlTh3pPNFzkYD0fEj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FA3jOL%2FbtrZYRB50F1%2FntHUOlTh3pPNFzkYD0fEj1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1550&quot; height=&quot;428&quot; data-origin-width=&quot;1550&quot; data-origin-height=&quot;428&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;개발용&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로덕션과 개발/테스트 템플릿을 고르는 게 나오는데 프로덕션을 선택하면 클러스터로 구성해서 DB가 두 개가 생기게 될 겁니다. 개발/테스트 선택!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1550&quot; data-origin-height=&quot;1567&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t5Pbf/btrZLVlptIV/dkf6YGTOBxRnA9JsQW4k9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t5Pbf/btrZLVlptIV/dkf6YGTOBxRnA9JsQW4k9K/img.png&quot; data-alt=&quot;관리자 계정 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t5Pbf/btrZLVlptIV/dkf6YGTOBxRnA9JsQW4k9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft5Pbf%2FbtrZLVlptIV%2Fdkf6YGTOBxRnA9JsQW4k9K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1550&quot; height=&quot;1567&quot; data-origin-width=&quot;1550&quot; data-origin-height=&quot;1567&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;관리자 계정 생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 아래는 클러스터 구분인데 요건 DB가 여러 개 생길 경우 DB이름 앞에 prefix를 정하는 겁니다. DB가 A, B가 있으면 {클러스터이름}-A, {클러스터이름}-B로 표기됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 아래는 admin계정을 정하는 게 있는데 요건 여러분이 원하는 비번을 설정해 주시면 됩니다. 아마 저희가 따로 DB계정 생성해서 쓰지 않을 것이기 때문에 요게 django에서 RDS로 접속할 때 쓰이는 계정이 될 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1526&quot; data-origin-height=&quot;613&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uwiLN/btrZNu2gPOm/aUjec3AZ5kzRKaSN3i6klk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uwiLN/btrZNu2gPOm/aUjec3AZ5kzRKaSN3i6klk/img.png&quot; data-alt=&quot;성능 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uwiLN/btrZNu2gPOm/aUjec3AZ5kzRKaSN3i6klk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuwiLN%2FbtrZNu2gPOm%2FaUjec3AZ5kzRKaSN3i6klk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1526&quot; height=&quot;613&quot; data-origin-width=&quot;1526&quot; data-origin-height=&quot;613&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;성능 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 아래는 인스턴스 스펙을 설정하는데, 처음엔 엄청 고급모델이 선택되어 있습니다 ㅎㄷㄷ 저희는 돈이 없으니 가장 싼 t3.small을 선택합니다. 요것도 공짜요금입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1545&quot; data-origin-height=&quot;442&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c7JNRO/btrZLTOOeiM/ndQKx6W1IMxA6PbikgDsO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c7JNRO/btrZLTOOeiM/ndQKx6W1IMxA6PbikgDsO0/img.png&quot; data-alt=&quot;HA&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c7JNRO/btrZLTOOeiM/ndQKx6W1IMxA6PbikgDsO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc7JNRO%2FbtrZLTOOeiM%2FndQKx6W1IMxA6PbikgDsO0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1545&quot; height=&quot;442&quot; data-origin-width=&quot;1545&quot; data-origin-height=&quot;442&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;HA&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 아래는 가용성 및 내구성이 있는데, 요건 HA라고 해서 High Available 설정입니다. 회사에서 HA, HA 거리는데 가용성이라고 쓰면 되지 왜 자꾸 HA라고 해서 못 알아먹게 하나,, 생각했었던 기억이 있네요 ㅋㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 가용성이란 말은 DB가 문제가 생겼을 때 정상작동을 지원하는 성능(?)이라고 생각하시면 됩니다. 가용성이 높으면 장애가 나도 서비스가 되도록 알아서 처리해 준다는 의미입니다. 여기서 다중 AZ를 선택하게 되면 DB가 여러 개 생기게 됩니다. 이렇게 여러 개를 생성하면 한쪽에서 장애 나면 다른 쪽 DB로 서비스되기 때문이죠. 나중에 서비스용으로 할 때는 가용성을 선택하는 게 좋으나, 저희는 일단 없어도 되기 때문에 아래를 선택합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;1768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/G9RJb/btrZKZVWnrN/JjbTG6jUps87WU6fkhxcQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/G9RJb/btrZKZVWnrN/JjbTG6jUps87WU6fkhxcQ0/img.png&quot; data-alt=&quot;길다..&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/G9RJb/btrZKZVWnrN/JjbTG6jUps87WU6fkhxcQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FG9RJb%2FbtrZKZVWnrN%2FJjbTG6jUps87WU6fkhxcQ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1198&quot; height=&quot;1768&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;1768&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;길다..&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음 설정은 좀 내용이 깁니다. 네트워크 정보를 입력하는 건데 디폴트로 해도 무난합니다. 다만 하나 봐줘야 하는 게 있는데 '퍼블릭 액세스'라고 되어있는 부분을 체크해야 합니다. 이걸 체크 안 하면 외부에서 DataGrip이나 MySQL WorkBench 같은 툴로 접속이 안됩니다. 요거 체크해 주시고, 다른 VPC설정이나 기타는 디폴트로 하겠습니다. 요거는 글로 설명하기는 좀 길어서,, 유튜브영상에서는 설명하도록 하겠습니다. ㅎㅎ 궁금하시면 유튜브로,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1232&quot; data-origin-height=&quot;1380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bh31MZ/btrZNweKW6z/0i75kd36GQcP94ETQjHHZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bh31MZ/btrZNweKW6z/0i75kd36GQcP94ETQjHHZ1/img.png&quot; data-alt=&quot;생성!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bh31MZ/btrZNweKW6z/0i75kd36GQcP94ETQjHHZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbh31MZ%2FbtrZNweKW6z%2F0i75kd36GQcP94ETQjHHZ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1232&quot; height=&quot;1380&quot; data-origin-width=&quot;1232&quot; data-origin-height=&quot;1380&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;생성!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 밖에 설정은 특별한 게 없기 때문에 데이터베이스 생성을 누릅니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DB생성은 한 5분? 정도 걸리는 것 같네요. 클라우드 서비스기 빠른 경우가 있고, 느린 경우가 있어서.. ㅋㅋ 저는 한 5분 걸린 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3119&quot; data-origin-height=&quot;1684&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xd8aH/btrZPSIBtOY/nNnlPKC20x3Dh8awT0ssTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xd8aH/btrZPSIBtOY/nNnlPKC20x3Dh8awT0ssTk/img.png&quot; data-alt=&quot;생성중...&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xd8aH/btrZPSIBtOY/nNnlPKC20x3Dh8awT0ssTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxd8aH%2FbtrZPSIBtOY%2FnNnlPKC20x3Dh8awT0ssTk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3119&quot; height=&quot;1684&quot; data-origin-width=&quot;3119&quot; data-origin-height=&quot;1684&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;생성중...&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성되는 동안 방화벽 작업을 해둡니다. 위처럼 DB가 생기는데 2개가 생기는 것처럼 보이지만 위에는 클러스터(그룹)라서 그냥 그루핑 해주는 놈입니다. 아래 라이터 인스턴스라고 쓰여있는 놈이 진짜 DB인데, 애를 선택해서 보안그룹을 눌러줍니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3136&quot; data-origin-height=&quot;634&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QWzpT/btrZPUl6VUN/WQbtY2OZYTHnKC2dKxEtbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QWzpT/btrZPUl6VUN/WQbtY2OZYTHnKC2dKxEtbk/img.png&quot; data-alt=&quot;방화벽 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QWzpT/btrZPUl6VUN/WQbtY2OZYTHnKC2dKxEtbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQWzpT%2FbtrZPUl6VUN%2FWQbtY2OZYTHnKC2dKxEtbk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3136&quot; height=&quot;634&quot; data-origin-width=&quot;3136&quot; data-origin-height=&quot;634&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;방화벽 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 기존에 RDS 사용하는 게 있어서 이것저것 추가가 많이 되어있는데, 여러분들은 3306으로 0.0.0.0/0만 있으면 될 겁니다. 이게 퍼블릭 액세스 옵션을 켜면 자동으로 생기는지 기억이 안 나네요. @_@ 만약 있다면 그냥 냅두시면 되고, 없으면 추가하시면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3205&quot; data-origin-height=&quot;1609&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pntfp/btrZLTadCBr/j3OlZ3QXYyR11oatp4S58K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pntfp/btrZLTadCBr/j3OlZ3QXYyR11oatp4S58K/img.png&quot; data-alt=&quot;실행 완료&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pntfp/btrZLTadCBr/j3OlZ3QXYyR11oatp4S58K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fpntfp%2FbtrZLTadCBr%2Fj3OlZ3QXYyR11oatp4S58K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3205&quot; height=&quot;1609&quot; data-origin-width=&quot;3205&quot; data-origin-height=&quot;1609&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실행 완료&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방화벽 설정하는 동안 실행이 됐네요. 여기서 연결 &amp;amp; 보안에 있는 엔드포인트를 잘 보셔야 합니다. 이게 저희가 접속하는 DB의 HOST입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1700&quot; data-origin-height=&quot;1522&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bV6odM/btrZYS14BlK/xukGIgsne1B3ZY1kypfUS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bV6odM/btrZYS14BlK/xukGIgsne1B3ZY1kypfUS0/img.png&quot; data-alt=&quot;데이터그립 접속&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bV6odM/btrZYS14BlK/xukGIgsne1B3ZY1kypfUS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbV6odM%2FbtrZYS14BlK%2FxukGIgsne1B3ZY1kypfUS0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1700&quot; height=&quot;1522&quot; data-origin-width=&quot;1700&quot; data-origin-height=&quot;1522&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;데이터그립 접속&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 EC2에 띄운 docker-mysql처럼 데이터그립에서 AWS RDS로 접속합니다. host는 위에서 말한 엔드포인트를 적어주시면 되고 user와 password는 아까 설정한 admin 계정을 사용하면 됩니다. 자세히 보면 Driver를 Aurora로 바꿨는데, 데이터그립은 MySQL과 Aurora를 구분하더군요. 그냥 MySQL을 사용하셔도 됩니다. (MySQL WorkBench에서도 접속 가능)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;접속을 하면 똑같이 djangoinsta라는 DB를 만들어줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1401&quot; data-origin-height=&quot;1089&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c1fGGh/btrZJWZD6DH/PJld8BAb3rrkCJIpGExadk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c1fGGh/btrZJWZD6DH/PJld8BAb3rrkCJIpGExadk/img.png&quot; data-alt=&quot;똑같이 만들어주기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c1fGGh/btrZJWZD6DH/PJld8BAb3rrkCJIpGExadk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc1fGGh%2FbtrZJWZD6DH%2FPJld8BAb3rrkCJIpGExadk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1401&quot; height=&quot;1089&quot; data-origin-width=&quot;1401&quot; data-origin-height=&quot;1089&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;똑같이 만들어주기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DB를 만들었으니 이제 마이그레이션을 해주면 되는데요, docker-mysql을 할 때는 로컬에서 마이그레이션을 시켜줬는데, 이번엔 서버에서 마이그레이션을 시켜주겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 변경된 DB로 접속하도록 환경변수를 수정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2592&quot; data-origin-height=&quot;449&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byWcxQ/btrZKpm2sF6/ze09AvHNOkHLZ171TeVXqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byWcxQ/btrZKpm2sF6/ze09AvHNOkHLZ171TeVXqk/img.png&quot; data-alt=&quot;.profile변경&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byWcxQ/btrZKpm2sF6/ze09AvHNOkHLZ171TeVXqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyWcxQ%2FbtrZKpm2sF6%2Fze09AvHNOkHLZ171TeVXqk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2592&quot; height=&quot;449&quot; data-origin-width=&quot;2592&quot; data-origin-height=&quot;449&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;.profile변경&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HOST를 바꿔주고 USER와 PASSWORD를 세팅합니다. PASSWORD는 여러분이 설정한 PASSWORD를 입력하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2645&quot; data-origin-height=&quot;1268&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqyEWW/btrZV8xesuY/MSy3ljdpQc0ckDj1hoSiCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqyEWW/btrZV8xesuY/MSy3ljdpQc0ckDj1hoSiCK/img.png&quot; data-alt=&quot;마이그레이션&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqyEWW/btrZV8xesuY/MSy3ljdpQc0ckDj1hoSiCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqyEWW%2FbtrZV8xesuY%2FMSy3ljdpQc0ckDj1hoSiCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2645&quot; height=&quot;1268&quot; data-origin-width=&quot;2645&quot; data-origin-height=&quot;1268&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;마이그레이션&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 경로로 이동한 다음 migrate!! 그럼 마이그레이션이 진행되는 화면을 볼 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다 끝나고 DataGrip에서 테이블이 정상적으로 생성되었는지 확인합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1596&quot; data-origin-height=&quot;804&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dnrYJS/btrZLVFHyuI/O0Zl6ZqJnm2pO31FUQo5HK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dnrYJS/btrZLVFHyuI/O0Zl6ZqJnm2pO31FUQo5HK/img.png&quot; data-alt=&quot;테이블 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dnrYJS/btrZLVFHyuI/O0Zl6ZqJnm2pO31FUQo5HK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdnrYJS%2FbtrZLVFHyuI%2FO0Zl6ZqJnm2pO31FUQo5HK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1596&quot; height=&quot;804&quot; data-origin-width=&quot;1596&quot; data-origin-height=&quot;804&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;테이블 생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 django를 재실행하고, RDS에 연결이 잘 되었는지 확인합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676823031234&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo systemctl restart uwsgi&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2849&quot; data-origin-height=&quot;517&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kUS6v/btrZLVsbMEh/EXMpq2HSmzNgCg4SiBj7p0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kUS6v/btrZLVsbMEh/EXMpq2HSmzNgCg4SiBj7p0/img.png&quot; data-alt=&quot;정상실행 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kUS6v/btrZLVsbMEh/EXMpq2HSmzNgCg4SiBj7p0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkUS6v%2FbtrZLVsbMEh%2FEXMpq2HSmzNgCg4SiBj7p0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2849&quot; height=&quot;517&quot; data-origin-width=&quot;2849&quot; data-origin-height=&quot;517&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;정상실행 확인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행해 보았는데 아직 docker-mysql로 접속하고 있는 것을 확인했다. 왜!?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시나 해서 docker를 내려보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3742&quot; data-origin-height=&quot;708&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOy6ru/btrZ4aVv8eI/AFvNVKCuNdfeCOOWgo3EPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOy6ru/btrZ4aVv8eI/AFvNVKCuNdfeCOOWgo3EPk/img.png&quot; data-alt=&quot;mysql 내리기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOy6ru/btrZ4aVv8eI/AFvNVKCuNdfeCOOWgo3EPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOy6ru%2FbtrZ4aVv8eI%2FAFvNVKCuNdfeCOOWgo3EPk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3742&quot; height=&quot;708&quot; data-origin-width=&quot;3742&quot; data-origin-height=&quot;708&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;mysql 내리기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;docker ps를 하면 구동 중인 도커 컨테이너 리스트가 나온다. 여기서 docker stop {container id}로 실행 중인 도커를 종료할 수 있다. down인 줄 알았는데 틀렸음.. ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;docker를 끄고 다시 접속해 보았더니...&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1810&quot; data-origin-height=&quot;902&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BsAJ7/btrZLSCnTEA/agJhryJ8kFfF47tS5XuUc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BsAJ7/btrZLSCnTEA/agJhryJ8kFfF47tS5XuUc1/img.png&quot; data-alt=&quot;mysql경로가 바뀌지 않았따.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BsAJ7/btrZLSCnTEA/agJhryJ8kFfF47tS5XuUc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBsAJ7%2FbtrZLSCnTEA%2FagJhryJ8kFfF47tS5XuUc1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1810&quot; height=&quot;902&quot; data-origin-width=&quot;1810&quot; data-origin-height=&quot;902&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;mysql경로가 바뀌지 않았따.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mysql경로가 바뀌지 않았다. 확인해 보니 uwsgi를 사용할 경우 환경변수를 읽지 못한다는 것이다. 뚜루루...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 아마 우리가 환경변수를 읽지 못했을 대 디폴트로 넣어놓은 값으로 DB가 연결되었고, 잘되고 있는 줄 착각하고 있었던 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이럴 때는 당황하지 말고, uwsgi.ini에다가 환경변수를 추가하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676824653942&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[uwsgi]
socket = /home/ubuntu/uwsgi.sock
master = true
processes = 1
threads = 2
chdir = /home/ubuntu/django_zero_to_instagram_devops
wsgi-file = Jinstagram/wsgi.py
chmod-socket = 666
vacuum = true
die-on-term = true

logger = file:/tmp/uwsgi.log
pythonpath = /home/ubuntu/.local/lib/python3.8/site-packages

env=MYSQL_HOST=database-1-instance-1.cahfm1ikomik.ap-northeast-2.rds.amazonaws.com
env=MYSQL_USER=admin
env=MYSQL_PASSWORD=adminpassword
env=MYSQL_DB_NAME=djangoinsta&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 되면 문제는 uwsgi.ini를 github에 추가해 놨었는데, ini파일은 github에서 빼야 한다는 것이다. ㅋㅋㅋ 이런 서버 설정 같은 건 코드에서 빠지는 게 맞지...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1970&quot; data-origin-height=&quot;386&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pXuyH/btrZK2LYPEd/370mj31k8qylWXdQ4m4oMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pXuyH/btrZK2LYPEd/370mj31k8qylWXdQ4m4oMk/img.png&quot; data-alt=&quot;gitignore에 추가&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pXuyH/btrZK2LYPEd/370mj31k8qylWXdQ4m4oMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpXuyH%2FbtrZK2LYPEd%2F370mj31k8qylWXdQ4m4oMk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1970&quot; height=&quot;386&quot; data-origin-width=&quot;1970&quot; data-origin-height=&quot;386&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;gitignore에 추가&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 이제 실행해 보면 정상적으로 실행됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1528&quot; data-origin-height=&quot;1006&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CFuRu/btrZKx6y0xy/UYSvNkws1laU2WpDYqFdQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CFuRu/btrZKx6y0xy/UYSvNkws1laU2WpDYqFdQ1/img.png&quot; data-alt=&quot;가입테스트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CFuRu/btrZKx6y0xy/UYSvNkws1laU2WpDYqFdQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCFuRu%2FbtrZKx6y0xy%2FUYSvNkws1laU2WpDYqFdQ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1528&quot; height=&quot;1006&quot; data-origin-width=&quot;1528&quot; data-origin-height=&quot;1006&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가입테스트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2636&quot; data-origin-height=&quot;351&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c9xP4q/btrZUA8u1iW/oUmYj9NsKCfC1Se7soNfTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c9xP4q/btrZUA8u1iW/oUmYj9NsKCfC1Se7soNfTK/img.png&quot; data-alt=&quot;확인 완료!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c9xP4q/btrZUA8u1iW/oUmYj9NsKCfC1Se7soNfTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc9xP4q%2FbtrZUA8u1iW%2FoUmYj9NsKCfC1Se7soNfTK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2636&quot; height=&quot;351&quot; data-origin-width=&quot;2636&quot; data-origin-height=&quot;351&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;확인 완료!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마치며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스팅에서는 docker를 이용해 mysql 띄우기, RDS를 이용해 aurora 띄우기를 해보고, 우리가 만든 django 서비스와 연결했습니다. RDS 같은 경우는 실무에서 굉~~ 장히 많이 사용하기 때문에 사용법을 알아두면 좋습니다. 물론 실제로 사용할 때는 환경 세팅이 매우 복잡한 경우가 많지만요. 아마 devops팀에서 잘 세팅해 줄 겁니다 ㅎㅎ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;devops 편을 3개 정도 만들었는데, 이 정도면 사실 어느 정도 개인 프로젝트 서비스하는데 많은 정보가 담겨있지 않나,, 생각이 되네요. 더 하고 싶은 건 음.. 자동배포를 만든다거나 django와 uwsgi도 docker로 만드는 내용? 요 내용은 기존 포스팅에 많으니 상관없긴 한데, 자동으로 이미지를 말아서 배포까지 되게 만들면 좋은데 말이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 포스팅에서는 자동화 관련으로 준비해 보아야겠습니다. 자동화 부분은 살짝 어려울 것 같아서 유튜브 영상은 두 개로 나눠야겠네요 ㅎㅎ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 오늘은 여기까지~~&lt;/p&gt;</description>
      <category>Course/django : 제로부터 시작하는 인스타그램</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/583</guid>
      <comments>https://cholol.tistory.com/583#entry583comment</comments>
      <pubDate>Mon, 20 Feb 2023 01:53:05 +0900</pubDate>
    </item>
    <item>
      <title>주식앱 실행하면 왜이렇게 오래걸릴까?, 로딩이 왜케 김? - 개발자가 말해드림</title>
      <link>https://cholol.tistory.com/582</link>
      <description>&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8jZ1v/btrYkK5ORpn/ISJkErIwybQUvCaySOAGh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8jZ1v/btrYkK5ORpn/ISJkErIwybQUvCaySOAGh1/img.png&quot; data-alt=&quot;많은 사람들이 사용하는 영웅문 !&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8jZ1v/btrYkK5ORpn/ISJkErIwybQUvCaySOAGh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8jZ1v%2FbtrYkK5ORpn%2FISJkErIwybQUvCaySOAGh1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;865&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;많은 사람들이 사용하는 영웅문 !&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;MTS, 로딩화면 왜 이렇게 길까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 제일 많이 일한 업종은 &quot;증권&quot;입니다. 첫 회사에서 증권에 채널 백엔드 개발을 하면서 5년, 그리고 카카오페이에서 주식서비스를 구축하는데 2년 해서 총 7년 정도 증권회사에 몸담았는데, 증권앱하면 사람들이 가장 많이 불평하는 &quot;주식앱(MTS)은 앱 실행 속도가 왜 이렇게 느려?&quot;에 대해 얘기해 볼까 합니다 ㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;주식 트레이딩 시스템(MTS)의 특징&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘에는 많은 앱 서비스가 출시되어 모바일로 거의 모든 일들을 할 수 있습니다. 주식도 마찬가지죠. 10~20년 전만 해도 사람들은 컴퓨터 앞에 앉아서 주식투자를 했습니다. 지금도 많은 화면을 보는 전문 투자자들은 컴퓨터를 사용한 HTS 프로그램을 많이 사용하고 있습니다. 하지만 간단하게 투자를 할 수 있는 MTS도 꽤나 성장했죠.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 앱이라는 건 서비스에 따라서 다양한 특징을 가지고 있는데, 예를 들어 메신저 같은 앱, 카카오톡을 보면 푸시가 아주 중요합니다. 나한테 온 메시지를 빠르게 알 수 있는 게 중요하죠. 은행이나 결제앱 같은 경우는 보안이 중요합니다. 따라서 앱을 실행할 때 다양한 인증을 거치게 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 주식 앱에서 가장 중요한 것은 무엇일까요? 실제로 거래를 하기 대문에 인증도 중요하지만, 그보다 더 중요한 것은 바로 속도입니다. 여러분이 만약 가지고 있는 삼성 주식을 가장 높은 가격일 때 팔아야 하는데, 삼성주식을 선택했더니 종목상세화면을 로딩하느라 1초가 걸리고, 매도 버튼을 눌렀는데 매도 화면을 불러오는데 1초가 걸리고, 이렇게 다양한 화면을 누르면서 계속 로딩이 돼서 결국 원하는 가격에 매도를 하지 못한다면 앱을 탓하게 될 겁니다. (실제로 많은 분들이 이런 손해배상 문의를 증권사에 하고 있음)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 증권사들은 앱에서 속도를 최고로 빠르게 하기 위해 다양한 방법을 시도하고 있습니다. 그 방법 중에 하나가 바로 '긴 로딩 시간'입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아니 속도를 빠르게 하기 위해서인데 로딩시간을 늘리면 속도가 느린거 아니냐?라고 생각할 수 있는데.... 맞습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;속도를 빠르게 하기위해 속도를 느리게 했습니다. ㅋㅋㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 사람들이 MTS에서 주식을 찾아보거나 매매하는 절차는 거의 동일합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 종목을 찾는다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 현재가 화면으로 간다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 호가를 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 매매를 누른다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 우리가 가장 많이 시간을 보내는 화면은 어디일까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 &quot;종목을 찾는다&quot;입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 관심종목화면이나 섹터, 순위 화면들을 통해서 특정 종목을 찾고 해당 종목에 대한 종목상세 화면으로 이동하여 더 세세한 정보를 확인한 후 매매를 하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 개발자의 입장에서 생각해 봅시다. 특정 종목을 찾기 위해 우리는 몇 번의 API를 호출해야 할까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 우리는 종목코드를 다 외우지 않고 종목명으로 종목을 찾습니다. 그렇다면 삼성전자라는 종목을 찾아서 신용으로 시장가 매수를 해본다고 가정해 봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 검색창에 삼성이라고 검색 -&amp;gt; 서버 요청&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 삼성에 대한 검색 결과를 가져옴 -&amp;gt; 서버 응답으로 화면 뿌림&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 그중에서 삼성전자를 선택 -&amp;gt; 삼성전자 이름으로 조회&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 삼성전자의 종목코드 000660으로 종목상세정보를 조회 -&amp;gt; 삼성전자 -&amp;gt; 000660 -&amp;gt; 000660의 종목상세 조회&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 종목상세 정보에서 신용 %를 확인 후 호가화면으로 이동 -&amp;gt; 000660에 신용정보 조회 (종목 상세에서 같이 받기도 함)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 호가 화면에서 매수 가격 결정 -&amp;gt; 호가 조회&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 매수 -&amp;gt; 매수 요청&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 딱 봐도 3~4개의 API를 호출해서 백엔드에서 정보를 받아와야 합니다. 캐시를 한다고 해도 최초 한 번은 가져와야 하며, 사용자가 이종목 저 종목 이동한다면 캐시도 소용이 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그래서!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;증권사가 택한 방법은 종목에 대한 정보를 앱 실행 시 전부 내려주어 앱에서 저장하고 있는 것입니다. 이것이 MTS가 실행 시 로딩화면이 있는 핵심 이유입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러분이 MTS를 실행하면 앱은 백엔드에서 모든 종목에 대한 간략한 정보를 받아 앱에 저장합니다. 이렇게 되면 위 절차에서 백엔드와 통신하지 않아도 할 수 있는 일이 매우 많이 생깁니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;s&gt;검색창에 삼성이라고 검색&lt;/s&gt; -&amp;gt; 앱에 데이터 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;s&gt;삼성에 대한 검색 결과를 가져옴&lt;/s&gt; -&amp;gt; 앱에 데이터 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;s&gt;그중에서 삼성전자를 선택&lt;/s&gt; -&amp;gt; 앱에 데이터 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;s&gt;삼성전자의 종목코드&lt;/s&gt; 000660으로 종목상세정보를 조회 -&amp;gt; 000660으로 종목상세 조회 백엔드 호출&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;s&gt;종목상세 정보에서 신용 %를&lt;/s&gt; 확인 후 호가화면으로 이동 -&amp;gt; 신용정보 앱에 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 호가 화면에서 매수 가격 결정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 매수&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생략이 많아졌죠?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앱에 이미 모든 종목에 대한 간략한 정보가 있기 때문에 앱에서 검색을 구현할 수 있고, 종목명과 종목코드를 저장해 놓았기 때문에 종목코드로 바로 필요한 정보를 호출할 수 있습니다. 신용정보 역시 앱에 저장되어 있기 때문에 백엔드 호출 없이 매수 가격을 결정할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭔가 시작할 때 확 느리고 사용할 때 빨라지는... 조삼모사와 같은 전략이라고 할 수 있습니다. ㅋㅋㅋ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;근데 왜 실행할 때마다 로딩이 있냐고?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 여기서 의문이 듭니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 MTS를 매일 실행하는데 왜 실행할 때마다 로딩이 있죠???????&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맞습니다. 위 말대로라면 처음 한 번만 받으면 그 뒤에는 로딩이 없어야 합니다. 하지만 우리는 매일 아침 9시 로딩화면을 보고 있죠.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것도 증권업의 &lt;b&gt;특징&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 주식투자를 많이 해보시는 분은 아실 수도 있는데, 종목에 대한 정보는 매일 변합니다. 특정 종목은 위험종목으로 지정되기도 하며 특정 종목은 상장폐지되어 없어지기도 하고 새로운 종목이 상장하여 생기기도 합니다. 이렇게 종목에 대한 정보가 바뀌는데, 하루에 한 번 거래소에서 모든 종목에 대한 정보를 증권사에 전달해 줍니다. (아침 5~6시 정도)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 여러분이 어제 긴 시간 로딩을 투자해서 받은 정보가 오늘은 다를 수 있습니다. 언젠가 여러분이 새로 상장한 종목이 안보이거나 종목을 못 찾아서 증권사에 문의했는데, 증권사에서 &quot;설정에 마스터파일 다시 받기 누르고 다시 해보세요~&quot;라는 대답을 받아본 적이 있을지도 모릅니다. 여기서 말하는 &quot;마스터파일&quot;이 바로 모든 종목에 대한 정보입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 MTS를 실행할 때 로딩이 있는 이유는 매일 변하는 마스터파일을 최신버전으로 받기 위함이며, 이 마스터파일이 있어야 빠른 종목검색 및 매매가 가능합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론, 로딩할 때 받는 정보는 마스터파일뿐만이 아니라 다양한 정보들을 받습니다. 은행 정보라던지, 대표지수정보라던지, 앱 구동에 필요한 상수값이라던지,, 제가 일했던 2015년에 앱을 실행하면 총 15개의 스텝이 차례대로 실행하면서 데이터를 처리하고, 다 끝나야 메인화면으로 이동했던 것 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 IT기업 출신이 만든 MTS(토스나 카카오페이)도 같은 구조를 사용하고 있습니다. 다만 UI/UX적으로 교묘하게 숨겨서 사용자에게 더 나은 경험을 제공하고 있을 뿐이죠.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 증권사들도 그러면 좋은데 이미 만들어놓은 프레임워크를 뜯어고칠 수가 없어서... 그래서 최근 증권사들이 새로운 앱을 내는 이유이기도 합니다. (미니스탁 같은..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 결론은 뭐냐면..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;개발자라고 업무에 대한 지식이 없으면 안 된다&quot;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;증권업에 특징을 모르고 다른 앱들과 같이 일일이 API를 호출하여 정보를 받아가는 구조로 만들었다면, 지금의 증권사들은 앱이 느리다는 사용자들에 컴플레인에 허덕이고 있었을 테니까요.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스를 알아야 개발을 잘하고, 개발을 잘해야 서비스가 잘 돌아갑니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리 모두 내가 만드는 서비스에 관심을 가져봅시다 :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Study/IT 실전 지식</category>
      <author>마이쮸(mychew__)</author>
      <guid isPermaLink="true">https://cholol.tistory.com/582</guid>
      <comments>https://cholol.tistory.com/582#entry582comment</comments>
      <pubDate>Mon, 6 Feb 2023 21:36:26 +0900</pubDate>
    </item>
  </channel>
</rss>