<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>noni.log</title>
        <link>https://velog.io/</link>
        <description>#python #mlops</description>
        <lastBuildDate>Sat, 12 Jul 2025 13:47:36 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>noni.log</title>
            <url>https://velog.velcdn.com/images/noeun-kim/profile/ebb4e45b-a43d-4426-bc28-7eae5d78cf5f/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. noni.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/noeun-kim" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Airflow 오픈소스 기여 튜토리얼]]></title>
            <link>https://velog.io/@noeun-kim/Airflow-%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4-%EA%B8%B0%EC%97%AC-%ED%8A%9C%ED%86%A0%EB%A6%AC%EC%96%BC</link>
            <guid>https://velog.io/@noeun-kim/Airflow-%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4-%EA%B8%B0%EC%97%AC-%ED%8A%9C%ED%86%A0%EB%A6%AC%EC%96%BC</guid>
            <pubDate>Sat, 12 Jul 2025 13:47:36 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/noeun-kim/post/265fc015-b459-4905-9456-9821accddca0/image.png" alt=""></p>
<p>실무에서 Airflow 를 계속 쓰다 보니 기여해 보고 싶었던 포인트가 쌓여갔다. 그런데 opensource 들은 고유의 생태계가 있기 때문에 contributing 이전에 서비스에 대한 애정을 담아 약간의 내용 숙지가 필요하다!</p>
<p>오늘은 <code>Airflow Contribution</code> 을 위한 <strong>한국어 튜토리얼</strong> 문서를 작성해 보고자 한다
(너무 간단해서 그런지 마땅한 문서가 없었다더라 ... 😇 본 문서는 입문자를 대상임을 강조해 본다)</p>
<blockquote>
<p>✔️ 최근 v2 -&gt; v3 으로 버전 업을 거치면서 기여할 포인트가 많기 생겼기 때문에 컨트리뷰터를 꿈꿨던 사람에겐 지금이 적기라고 권장하고 싶다</p>
</blockquote>
<h2 id="1️⃣-brief-guideline">1️⃣ Brief Guideline</h2>
<p>서두에 강조했던 Airflow Contribution 생태계에 대한 내용은 이미 repository 에 자세히 기술되어 있다
먼저 이 문서를 가볍게 정독해 보자</p>
<p><img src="https://velog.velcdn.com/images/noeun-kim/post/1cd57ee3-dc7a-4a09-be6c-5ced9864e383/image.png" alt=""></p>
<blockquote>
<p>Link: <a href="https://github.com/apache/airflow/tree/main/contributing-docs">https://github.com/apache/airflow/tree/main/contributing-docs</a></p>
</blockquote>
<p>기여 순서나 개발 환경 세팅, 코드 컨벤션 등 필요한 내용이 다 들어있어서 한 번만 제대로 훑어봐도 감 잡는 것이 가능하다</p>
<p>참고로 <a href="https://app.slack.com/client/TCQ18L22Z/CCQ18L37F">apache-airflow.slack.com</a> 공식 Slack Workspace 도 제공한다
이곳에서 커미터, 컨트리뷰터들의 논의 히스토리도 확인 가능하니 필요 시 참고할 것</p>
<h2 id="2️⃣-dev-env-setup">2️⃣ Dev Env Setup</h2>
<p><code>문서 숙지</code>가 기여를 위한 첫걸음이라면 <code>개발 환경 설정</code>은 그 다음으로 중요한 부분 🖍</p>
<p>공식 문서의 내용이 워낙 폭넓기 때문에 본 튜토리얼에서는 <code>개발 환경 설정</code> 핵심만 콕 집어 안내하고자 한다</p>
<h4 id="🧷-airflow는-breeze-와-pre-commit-을-통해-통일된-개발-환경을-유지하고-있다">🧷 Airflow는 breeze 와 pre-commit 을 통해 통일된 개발 환경을 유지하고 있다</h4>
<p>왜 <code>Breeze</code>를 쓰는가?</p>
<ul>
<li>pre-commit - 코드 스타일/린트/포맷 등 자동 검사</li>
<li>breeze - 컨테이너를 통한 개발 환경 관리</li>
</ul>
<p>breeze는 docker 기반으로 복잡한 의존성 문제를 한 번에 해결하고
실제 배포 환경과 유사한 테스트 환경을 바로 띄울 수 있다는 장점을 제공한다는 특징이 있다
-&gt; 즉, os 나 python 버전 및 기타 의존성으로 인한 문제를 최소화할 수 있다는 이야기
-&gt; 오픈소스 개발 환경에 적합하다고 볼 수 있다</p>
<h4 id="🧷-기여-환경-세팅-가이드">🧷 기여 환경 세팅 가이드</h4>
<pre><code class="language-bash">$ brew install python@3.11

$ mkdir ~/workspace/airflow-dev
$ cd ~/workspace/airflow-dev

$ python3.11 -m venv venv
$ source venv/bin/activate
$ pip install --upgrade pip

# 예시: fork한 airflow 저장소로 이동
cd ~/workspace/airflow  # git clone한 디렉토리
# breeze 설치 (pipx, uv, 또는 pip 중 택1)
$ pip install apache-airflow
$ airflow db reset
$ airflow db migrate
$ pip install -e ./dev/breeze


# breeze로 Airflow 개발 환경 시작
$ breeze start-airflow
$ breeze start-airflow --dev-mode # 개발 모드

# breeze 오류 발생 시 docker 상태 확인
# * macos 의 경우 docker desktop이 설치 및 실행 중이어야 정상 동작함
$ docker --version
$ docker ps</code></pre>
<h4 id="🧷-breeze-대시보드로-로컬-환경-관리">🧷 Breeze 대시보드로 로컬 환경 관리</h4>
<p>설정이 성공적으로 완료되면 아래와 같은 대시보드로 로컬 환경을 관리할 수 있다
문제 발생 시 대시보드에서 오류 로그 확인이 가능하기 때문에 효율적인 트러블슈팅이 가능하다
<img src="https://velog.velcdn.com/images/noeun-kim/post/7279981d-a04c-4bfc-9830-867a6b9fab7d/image.png" alt=""><img src="https://velog.velcdn.com/images/noeun-kim/post/ee050e71-1859-42db-b296-e3b5c8ae4de1/image.png" alt=""></p>
<pre><code>     cd airflow/ui
     pnpm install
     pnpm dev

# dag 폴더 확인이 안 돼?

/opt/airflow# airflow dags list
dag_id   | fileloc                 | owners  | is_paused | bundle_name | bundle_version
=========+=========================+=========+===========+=============+===============
test_dag | /files/dags/test_dag.py | airflow | False     | dags-folder | None

/opt/airflow# ls /opt/airflow/dags
test_dag_versioning.py

# /opt/airflow/dags: 일반적으로 로컬 dags/ 폴더 마운트 위치
# /files/dags: breeze 테스트나 샘플용 마운트 경로
$ breeze config show
* Backend: sqlite
* Postgres version: 13
* MySQL version: 8.0

* ASCIIART: enabled
* Cheatsheet: enabled

# 파일이 왜 안 잡히지? (dashboard 에서)
# 이걸로 경로 확인
$ airflow config get-value core dags_folder

# 종료 시
$ docker ps
$ docer ps {id}
$ breeze down --cleanup-build-cache
$ airflow db reset

$ AIRFLOW__CORE__DAGS_FOLDER=/opt/airflow/dags breeze start-airflow</code></pre><h4 id="🧷-성공적인-기여를-위한-마지막-포인트-test-coverage">🧷 성공적인 기여를 위한 마지막 포인트, <code>Test Coverage</code></h4>
<p>기능 수정이나 신규 feature 를 추가한 경우 pre-commit 을 통과하는 것도 중요하지만
pytest 로 구현된 unittest 도 적절히 수정하는 것이 아주 중요하다</p>
<p>기존 기능을 헤치면 안 되기 때문!</p>
<pre><code># 전체 검사를 수행하거나 단일 테스트 수행도 가능
# example)
$ pytest airflow-core/tests/unit/api_fastapi/core_api/routes/public/...</code></pre><p>docker mount 를 통해서 아래와 같이 pytest debugging 도 가능하다
<img src="https://velog.velcdn.com/images/noeun-kim/post/1e6fc06c-6033-4805-858c-54a1a0ddfdfb/image.png" alt=""><img src="https://velog.velcdn.com/images/noeun-kim/post/395e103a-8edd-4675-9ea2-c5d8b033adf2/image.png" alt=""></p>
<h4 id="🧷-merge-를-위한-마지막-관문">🧷 Merge 를 위한 마지막 관문</h4>
<p><img src="https://velog.velcdn.com/images/noeun-kim/post/f3f1cec2-37be-400a-a6c2-3af07ef906e5/image.png" alt="">
모든 관문을 거쳐 어렵게 push 한 내 PR 이 merge 되기 위해서는
설정된 Rule 을 통과해야 한다</p>
<p>Test Coverage 를 충족하는 것은 물론, 최소 인원의 리뷰어의 승인을 받아야 한다
복잡한 기능일 수록 이 과정에서 커미터 및 유관자들과의 논의가 길어질 수 있다</p>
<p>모든 Airflow 컨트리뷰터들의 건투를 빈다!</p>
<p><img src="https://velog.velcdn.com/images/noeun-kim/post/6e6dbc48-f837-4efa-82eb-f37f1bfb48f0/image.jpg" alt=""></p>
<p>(* 오류 정정 및 논의는 언제나 감사합니다)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[백엔드 개발자의 앱 개발 츄라이]]></title>
            <link>https://velog.io/@noeun-kim/%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%9D%98-%EC%95%B1-%EA%B0%9C%EB%B0%9C-%ED%95%9C%EC%9E%85-%ED%95%B4-%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@noeun-kim/%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%9D%98-%EC%95%B1-%EA%B0%9C%EB%B0%9C-%ED%95%9C%EC%9E%85-%ED%95%B4-%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Fri, 15 Nov 2024 14:46:55 GMT</pubDate>
            <description><![CDATA[<h3 id="개발-환경-설정">개발 환경 설정</h3>
<p>(MacOS pro M3 chip)</p>
<p><a href="https://www.jetbrains.com/toolbox-app/">https://www.jetbrains.com/toolbox-app/</a> 
위 링크로 jetbrain tool box 설치 후
android studio 최신 버전을 설치한다</p>
<img src="https://velog.velcdn.com/images/noeun-kim/post/2e6a021b-f8b2-4863-ad4e-8a1c844b8b2a/image.png" width="500">

<h4 id="1-google-cloud-cli-설정">1. Google Cloud CLI 설정</h4>
<p>개발 편의를 위해 gcloud cli 설치 (콘솔로 작업해도 무관하다)
아래 링크에서 본인 플랫폼에 해당하는 패키지 다운로드 후
<a href="https://cloud.google.com/sdk/docs/install?hl=ko">https://cloud.google.com/sdk/docs/install?hl=ko</a>
<img src="https://velog.velcdn.com/images/noeun-kim/post/693542f4-d4c8-4a58-9ecd-d27bbbfbb412/image.png" width="500"></p>
<pre><code># 설치 경로에서
./google-cloud-sdk/install.sh</code></pre><pre><code># 프로젝트 연결
./google-cloud-sdk/bin/gcloud init
</code></pre><p>아래 안내 메시지 확인 후 로그인을 통해 GCP 프로젝트 연결
<img src="https://velog.velcdn.com/images/noeun-kim/post/eacce070-fb94-4f2f-95eb-0e6f0137cdd8/image.png" width="500"></p>
<p>리디렉션 된 화면에서 로그인하면
<img src="https://velog.velcdn.com/images/noeun-kim/post/07dec685-78e4-40c7-b8c0-29c2afdd4faa/image.png" width="500"></p>
<p>gcloud CLI 인증 완료
<img src="https://velog.velcdn.com/images/noeun-kim/post/e5059867-f948-4144-a5a8-3ff5f5080cec/image.png" width="500"></p>
<h4 id="2-service-account-생성">2. service account 생성</h4>
<ul>
<li><em><strong>service account</strong></em> 란?</li>
</ul>
<p>GCP에서는 리소스 접근을 사용자가 직접 하지 않고,
service account 가 이를 대신하며 계정 단위로 권한을 나눠 관리한다</p>
<pre><code># 서비스 계정 생성
gcloud iam service-accounts create [SERVICE_ACCOUNT_NAME] \
    --description=&quot;[DESCRIPTION]&quot; \
    --display-name=&quot;[DISPLAY_NAME]&quot;</code></pre><ul>
<li><p>SERVICE_ACCOUNT_NAME: 서비스 계정 식별자 (필수/변경 불가능)</p>
</li>
<li><p>DESCRIPTION: 서비스 계정 설명 (선택/변경 가능)</p>
</li>
<li><p>DISPLAY_NAME: 서비스 계정 표시 이름 (선택/변경 가능/콘솔 목록에 표시)</p>
<p>ex) <code>[SERVICE_ACCOUNT_NAME]@[PROJECT_ID].iam.gserviceaccount.com</code></p>
</li>
</ul>
<p>공식 사이트에서 무료 이용 기준을 확인해 보면
<a href="https://cloud.google.com/free/docs/free-cloud-features?hl=ko#compute">https://cloud.google.com/free/docs/free-cloud-features?hl=ko#compute</a></p>
<img src="https://velog.velcdn.com/images/noeun-kim/post/bf9e311f-46e0-47e7-b4e0-37820f68ae5a/image.png" width="500">

<p>아래 조건을 준수하면 불필요한 과금 없이 개발 가능하다
(2024.09 기준)</p>
<ul>
<li>지역 제한: us-central1, us-west1, us-east1</li>
<li>머신 유형 제한: e2-micro</li>
<li>디스크 크기 제한: 30GB 이하</li>
<li>외부 IP 주소 사용 제한</li>
</ul>
<h4 id="gemini-key-발급">Gemini key 발급</h4>
<p>Google AI Studio (<a href="https://ai.google.dev/">https://ai.google.dev/</a>) 접속 후 키 생성
<img src="https://velog.velcdn.com/images/noeun-kim/post/18f8d5ce-30ee-4f33-8b66-b723cd549389/image.png" width="500"></p>
<p>프로젝트 선택하여 API 키 생성
<img src="https://velog.velcdn.com/images/noeun-kim/post/4fe95935-af2d-4cf3-a487-4fb5db5fbca2/image.png" width="500"></p>
<p>이제 거의 다 왔다!
lambda 에 코드를 얹고 client 에서 해당 api를 호출하면 이상무이다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Flutter Build Gradle, JDK, Kotlin 대삽질 여행]]></title>
            <link>https://velog.io/@noeun-kim/Flutter-Build-Gradle-JDK-Kotlin-%EB%8C%80%EC%82%BD%EC%A7%88-%EC%97%AC%ED%96%89</link>
            <guid>https://velog.io/@noeun-kim/Flutter-Build-Gradle-JDK-Kotlin-%EB%8C%80%EC%82%BD%EC%A7%88-%EC%97%AC%ED%96%89</guid>
            <pubDate>Fri, 15 Nov 2024 14:44:33 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/noeun-kim/post/c78df7a7-0422-4cfc-9028-d8dfbccb1a0c/image.png" alt=""></p>
<blockquote>
<p>개발 환경: OSX, Android Studio, Flutter, JDK17, Gradle 7.5</p>
</blockquote>
<p>사이드 프로젝트로 Flutter 개발을 진행 중에 마주한 에러...
python이 주언어인 나에게 venv 개념을 적용할 수 없는 새로운 영역의 개발 프로젝트였다</p>
<p>아니나 다를까 개발 과정에서 가장 고통스러웠던 부분이 의존성 관리 🤯
jdk, kotlin, gradle 간의 호환성을 체크하고 패키지와 프로젝트 버전 사이에 의존성을 관리하는 게 너무 어지러웠다 😇</p>
<p><img src="https://velog.velcdn.com/images/noeun-kim/post/2752de34-f031-46a6-8548-f183127457cc/image.svg" alt=""></p>
<p>flutter 가 친절하게 문제 해결 방향을 안내해 주기는 했지만,
고쳐도 계속 나타나는 using incompatible Gradle version 에러 😔</p>
<pre><code> [!] Your project&#39;s Gradle version is incompatible with the Java version that Flutter is using    │
│ for Gradle. 
...
Then, update the Gradle version specified in                                                     │
│ /Users/-/Downloads/proj/capstone-demo/client/android/gradle/wrapper/gradle-wrapper.proper │
│ ties to be compatible with that Java version. See the link below for more information on         │
│ compatible Java/Gradle versions:                                                                 │
│ https://docs.gradle.org/current/userguide/compatibility.html#java    </code></pre><blockquote>
<p>삽질의 기록</p>
</blockquote>
<p>먼저 에러 로그가 안내해 준 대로 현재 내 로컬 JDK에 맞는 Gradle, kotlin 버전을 찾아 수정해 준다
<a href="https://docs.gradle.org/current/userguide/compatibility.html#java">https://docs.gradle.org/current/userguide/compatibility.html#java</a></p>
<pre><code># 1) ~/android/gradle/gradle-wrapper.properties 파일 수정
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https://services.gradle.org/distributions/gradle-8.3-all.zip

# 2) ~/android/app/src/build.gradle 파일 수정
plugins {
   id &quot;com.android.application&quot;
   id &quot;kotlin-android&quot;
   id &quot;dev.flutter.flutter-gradle-plugin&quot;
   id &quot;com.google.gms.google-services&quot;  // Google Services plugin
}
...
android {
    compileSdkVersion 34
    sourceSets {
        main.java.srcDirs += &#39;src/main/kotlin&#39;
    }
    lintOptions {
        disable &#39;InvalidPackage&#39;
        checkReleaseBuilds false
    }
    defaultConfig {
        applicationId &quot;com.mycompany.test&quot;
        minSdkVersion 23
        targetSdkVersion 34
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }
        minSdkVersion 23
        targetSdkVersion 34
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }
    ...
    }
}
}
    ...
    }
}
...
dependencies {
    implementation &quot;org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.10&quot;
}</code></pre><p>그래도 동일 &gt; 다른 버전 &gt; 반복 &gt; 다른 버전 &gt; ...
그런데 뭔가 이상하다</p>
<p>로컬 java home 은 17 인데 android studio flutter 는 자꾸만 21로 잡는다?
아래 명령어를 다 사용해 봐도 요지부동!</p>
<pre><code>$ ./gradlew clean
$ ./gradlew --refresh-dependencies
$ ./gradlew lintDebug -PwriteBaselineFile=true</code></pre><p>그러다 문득 <code>$ flutter create .</code> 명령어를 실행하라는 코멘트를 발견한다
결과는?</p>
<pre><code>All done!
You can find general documentation for Flutter at: https://docs.flutter.dev/
Detailed API documentation is available at: https://api.flutter.dev/
If you prefer video documentation, consider: https://www.youtube.com/c/flutterdev

In order to run your application, type:

  $ cd .
  $ flutter run

Your application code is in ./lib/main.dart.

The configured version of Java detected may conflict with the Gradle version in your new Flutter app.

[RECOMMENDED] If so, to keep the default Gradle version 8.3, make
sure to download a compatible Java version
(Java 17 &lt;= compatible Java version &lt; Java 21).
You may configure this compatible Java version by running:
`flutter config --jdk-dir=&lt;JDK_DIRECTORY&gt;`
Note that this is a global configuration for Flutter.


Alternatively, to continue using your configured Java version, update the Gradle
version specified in the following file to a compatible Gradle version (compatible Gradle version range: 8.4 - 8.7):
/Users/-/Downloads/proj/grammar-backend/client/android/gradle/wrapper/gradle-wrapper.properties

You may also update the Gradle version used by running
`./gradlew wrapper --gradle-version=&lt;COMPATIBLE_GRADLE_VERSION&gt;`.

See
https://docs.gradle.org/current/userguide/compatibility.html#java for details
on compatible Java/Gradle versions, and see
https://docs.gradle.org/current/userguide/gradle_wrapper.html#sec:upgrading_wrapper
for more details on using the Gradle Wrapper command to update the Gradle version
used.</code></pre><p>OMG 😳 flutter prj를 잡아주고 성공하자 매우매우 친절한 로그가 출력된다
현재 플젝에 jdk config 지정, gradle 버전 재설정 하니 flutter run 성공!</p>
<p><code>$ flutter config --jdk-dir=&lt;JDK_DIRECTORY&gt;</code>
<code>$ ./gradlew wrapper --gradle-version=&lt;COMPATIBLE_GRADLE_VERSION&gt;</code></p>
<p>기초 구조를 git 에서 pull 받고 flutter config 지정도 없이 doctor, pub get 을 난무했더니 버전이 꼬일대로 꼬인 것이었다
특히 venv 처럼 응용하겠다고 fvm 커맨드를 난사한 것도 영향이 컸다</p>
<blockquote>
<p><strong>제일 좋은 지침서는 공식 문서!</strong></p>
</blockquote>
<p>오늘의 교훈이다... 수많은 블로그, stack overflow, llm 의 도움을 받았지만 가장 명쾌한 것은 공식 문서와 디버깅 로그였다</p>
<p>힌트는 역시 가장 가까운 곳에... 🥹</p>
<p>flutter 에도 nvm 과 유사하게 sdk 버전 관리를 지원하는 <code>fvm</code> 이 있다
설치된 여러 jdk 중 프로젝트에 따라 호환되는 버전을 스위칭하는 컨셉 같다
<code>$ fvm use 3.10.5</code> 같이 손쉽게 사용 가능한 기본 개념이니 익숙해지면 좋을 듯하다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Lambda + FastAPI 간단 배포해 보기 (feat. pydantic_core 오류)]]></title>
            <link>https://velog.io/@noeun-kim/Lambda-FastAPI-%EA%B0%84%EB%8B%A8-%EB%B0%B0%ED%8F%AC%ED%95%B4-%EB%B3%B4%EA%B8%B0-feat.-pydanticcore-%EC%98%A4%EB%A5%98</link>
            <guid>https://velog.io/@noeun-kim/Lambda-FastAPI-%EA%B0%84%EB%8B%A8-%EB%B0%B0%ED%8F%AC%ED%95%B4-%EB%B3%B4%EA%B8%B0-feat.-pydanticcore-%EC%98%A4%EB%A5%98</guid>
            <pubDate>Fri, 26 Jul 2024 02:02:33 GMT</pubDate>
            <description><![CDATA[<p>Lambda + FastAPI 를 활용한 간단한 서버리스 앱 개발 과정을 공유합니다.
<em>(MacOS 기준)</em></p>
<blockquote>
<h4 id="1-가상환경-생성">1. 가상환경 생성</h4>
</blockquote>
<p>Lambda 에 FastAPI 서버 Script를 업로드 하는 것 외에도 관련 Dependency 파일을 함께 업로드 해야 합니다. 이때 개발 환경을 가상환경으로 관리하는 것이 유리하므로 Python 내장 모듈인 venv 를 활용해 보겠습니다.</p>
<p>ദ്ദി ˉ͈̀꒳ˉ͈́ )✧ 참고로, venv 는 로컬 파이썬 버전이 적용되기 때문에 버전 변경이 필요한 경우는 pyenv 패키지를 추가로 활용해야 합니다.</p>
<pre><code># 가상환경 생성할 경로 이동
$ cd lambda-test

# 가상환경 생성
$ python -m venv lambda-test </code></pre><p>Pycharm 에서 FastAPI 프로젝트를 생성합니다. Environment - Select existing 을 선택하여 생성한 lambda-test 환경을 적용합니다.
<img src="https://velog.velcdn.com/images/noeun-kim/post/6cee002d-c5fe-434c-8884-4e105777c22b/image.png" width="500"></p>
<p>bin 하위에서 Python Interpreter 를 지정합니다.
<img src="https://velog.velcdn.com/images/noeun-kim/post/2a7e0b99-ce15-43e5-817f-c77b76b50aa5/image.png" width="350"></p>
<p>ദ്ദി ˉ͈̀꒳ˉ͈́ )✧ 더 간단하게는, 아래 이미지와 같이 Pycharm 프로젝트 생성 단계에서 Generate new 를 통해 Poetry, Conda 와 같은 가상환경 관리 도구를 사용할 수 있습니다. 
<img src="https://velog.velcdn.com/images/noeun-kim/post/669b340f-9831-4d51-8aa2-cf09996d9492/image.png" width="500"></p>
<p>이때는 pyenv, venv 모듈을 통해 미리 가상환경을 생성해 둘 필요가 없겠죠!</p>
<blockquote>
<h4 id="2-api-작성-및-업로드">2. API 작성 및 업로드</h4>
</blockquote>
<p>Lambda 를 통해 배포할 API 코드입니다. response body 에 response header 를 반환합니다.
<img src="https://velog.velcdn.com/images/noeun-kim/post/839b8e93-20b8-4420-9bdd-a0ebff3901ec/image.png" width="500"></p>
<p>실행을 위해 pip 로 mangum, uvicorn, fastapi 설치를 진행합니다. 
<img src="https://velog.velcdn.com/images/noeun-kim/post/b620b1ae-dd88-4605-b454-921278d7c59d/image.png" width="400"></p>
<p>api 실행 후 postman 으로 호출 테스트를 해 보니 정상 호출이 확인됩니다.
<img src="https://velog.velcdn.com/images/noeun-kim/post/a0a44a58-fee8-44a5-a638-0e0fa503c88e/image.png" width="400"></p>
<p>정상 동작하는 python 코드를 lambda에 업로드합니다. <strong>런타임 설정</strong> 시 가상환경의 python 버전과 맞춰 주어야 합니다.
<img src="https://velog.velcdn.com/images/noeun-kim/post/6837b524-3dd0-4261-a3d1-bbd2a8063fbd/image.png" width="400"></p>
<p>lambda 생성 후 작성해 둔 코드를 업로드, Deploy 합니다.
<img src="https://velog.velcdn.com/images/noeun-kim/post/0ca92522-e2b4-48b6-b22c-54d092651440/image.png" width="500"></p>
<p>추가로 <strong>런타임 설정</strong> 편집이 필요합니다. lambda_function.py 파일을 업로드했고, mangum 으로 fastapi app 객체를 변환하여 handler 객체에 넣어 주었기 때문에 아래와 같이 설정합니다.</p>
<p><em>lambda_function.handler</em>
<img src="https://velog.velcdn.com/images/noeun-kim/post/c07f7bf2-1b42-40ad-b361-5da28d56d893/image.png" width="700">
<img src="https://velog.velcdn.com/images/noeun-kim/post/8bd89773-c749-44d4-9b2e-d588adaac0c9/image.png" width="500"></p>
<p>테스트를 위해 test event 를 정의합니다. 작성한 api 는 get method 의 &quot;/&quot; 호출 내용만 정의해 두었지 때문에 http method와 path를 맞춰서 작성 하였습니다.
<img src="https://velog.velcdn.com/images/noeun-kim/post/fb1e4950-99fe-4566-b360-b62eb258169d/image.png" width="500"></p>
<p>Test 를 실행해 보아도 아직 dependency 가 주입되지 않아서 fastapi 모듈을 찾지 못합니다. 
<img src="https://velog.velcdn.com/images/noeun-kim/post/48c986cf-e10d-4ae9-afcc-5bdf0e213005/image.png" width="500"></p>
<blockquote>
<h4 id="3-계층-적용">3. 계층 적용</h4>
</blockquote>
<p>lambda 의 계층(layer) 탭에서 dependency를 주입해야 합니다.</p>
<p>lambda-test 가상환경의 경로로 이동해서 python 환경 하위의 site-packages 내용을 추출합니다.
<img src="https://velog.velcdn.com/images/noeun-kim/post/cedef5fc-13f3-43ea-916f-99bf5bff6561/image.png" width="500"></p>
<pre><code> $ mkdir python &amp;&amp; cp -rf site-packages/* ./python
 $ zip -r python-dependency.zip python</code></pre><p>계층(layer) 탭 - 계층 생성
<img src="https://velog.velcdn.com/images/noeun-kim/post/563230bc-79ce-4ed1-a4a0-431eb5418092/image.png" width="500"></p>
<p>추출한 python-dependency.zip 파일을 업로드합니다. 아키텍처와 런타임을 생성한 lambda 함수와 동일하게 설정합니다.
<img src="https://velog.velcdn.com/images/noeun-kim/post/7d192427-209a-4ae1-bb41-fa3a2af29759/image.png" width="500"></p>
<p>lambda 함수로 돌아와서 계층을 추가합니다.
<img src="https://velog.velcdn.com/images/noeun-kim/post/a3a62498-9fe3-4b1e-8b32-9f3299d3523f/image.png" width="500">
<img src="https://velog.velcdn.com/images/noeun-kim/post/ca93c23b-b4cd-4ff5-b42b-1230d9645009/image.png" width="500"></p>
<p>계층을 추가하고 Test 를 다시 실행해 보니 테스트가 여전히 실패합니다. ☠️☠️☠️
<img src="https://velog.velcdn.com/images/noeun-kim/post/44c30455-e604-468a-82ed-76590c53abbc/image.png" width="500"></p>
<pre><code>Response
{
  &quot;errorMessage&quot;: &quot;Unable to import module &#39;lambda_function&#39;: No module named &#39;pydantic_core._pydantic_core&#39;&quot;,
  &quot;errorType&quot;: &quot;Runtime.ImportModuleError&quot;,
  &quot;requestId&quot;: &quot;0027364d-fdd9-4c86-9506-6a61d535aada&quot;,
  &quot;stackTrace&quot;: []
}</code></pre><p>해당 에러는 pydantic_core 가 지정한 lambda 아키텍처와 호환되지 않기 때문에 발생합니다. 아래 명령어로 설정과 동일한 런타임(python 3.9), 아키텍처(x86_64)를 지정하여 pydantic-core 를 다시 설치합니다.</p>
<pre><code>$ pip install pydantic-core --platform manylinux2014_x86_64 --target=python3 --python-version 3.9 --only-binary=:all: --upgrade</code></pre><p>이후에 site-packages 하위에서 python-dependency.zip 추출을 반복하고, 신규 버전으로 계층을 편집해 줍니다.
<img src="https://velog.velcdn.com/images/noeun-kim/post/54249be6-b6d5-4e3d-8987-6e08286740bc/image.png" width="500">
<img src="https://velog.velcdn.com/images/noeun-kim/post/66f3f312-8104-4c48-a36d-ed09de4fbcf4/image.png" width="500"></p>
<p>수정을 마친 후 다시 테스트를 진행해 보면 정상 호출이 확인 됩니다.
<img src="https://velog.velcdn.com/images/noeun-kim/post/b6c1ca1e-45b0-486e-9bdb-10f83bac5305/image.png" width="500"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Technical Interview 대비 기초 CS 정리]]></title>
            <link>https://velog.io/@noeun-kim/Technical-Interview-%EB%8C%80%EB%B9%84-%EA%B8%B0%EC%B4%88-CS-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@noeun-kim/Technical-Interview-%EB%8C%80%EB%B9%84-%EA%B8%B0%EC%B4%88-CS-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Sun, 10 Dec 2023 14:54:16 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/noeun-kim/post/e0f929d0-42d8-49f3-992f-e66366ef0c75/image.jpeg" alt=""></p>
<p>기술 면접이라 함은 개발자의 숙명과도 같은 것
게다가 면접 대비가 아니더라도 기초 CS 전공 지식은 실무에서도 중요한데 오늘은 그 핵심 내용을 요약하고 있는 책을 소개해 볼까 한다</p>
<p>직무에 따라 면접 질문의 카테고리는 조금씩 다르지만 CS 기초는 장르불문 중요하다</p>
<p>이 책이 정리한 목차를 보면 힌트를 얻을 수 있는데</p>
<p><img src="https://velog.velcdn.com/images/noeun-kim/post/1446f8f4-4922-4a7c-90ba-43a639765989/image.png" alt=""></p>
<p>전공자라면 누구나 배우는 운영체제부터 네트워크, 알고리즘까지 큰 줄기를 훑도록 안내한다</p>
<p><img src="https://velog.velcdn.com/images/noeun-kim/post/4d253cfd-8618-48f9-a6c8-dd24dbba5e25/image.png" alt=""></p>
<p>특히 세부 분야가 많은 IT 직군은 학부나 주니어 시절 다양한 프로젝트를 경험하다 보면 얕게 경험한 기술 스택은 많은데 그 내용을 깊게 정리하고 이해하는 경험은 하기 힘든 경우가 많다</p>
<p>그러한 점에서 필자는 이 책을 신규 채용을 노리는 신입 개발자나 이직을 꿈꾸는 주니어 개발자들에게 추천하고 싶다! 한마디로 컴퓨터 공학 전공자들을 위한 실질적이고 효율적인 면접 대비 자료로써 핵심 CS 지식을 꼼꼼하게 정리해둔 점이 돋보인다~</p>
<p>특히 책 테마 자체가 면접 준비에 대한 내용이기 때문에 각 챕터 끝 부분마다 면접 예상 질문과 코멘트에 대한 내용이 포함된다! 보통은 기술 정리본을 읽고 예상 면접 질문을 리스트하는 일은 독자의 일인데 아주 친절하다 </p>
<p><img src="https://velog.velcdn.com/images/noeun-kim/post/dfd297f3-9e6e-4812-96d7-1ced60e16b29/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS 정복기: Architecting on AWS 교육]]></title>
            <link>https://velog.io/@noeun-kim/AWS-%EC%A0%95%EB%B3%B5%EA%B8%B01-Architecting-on-AWS</link>
            <guid>https://velog.io/@noeun-kim/AWS-%EC%A0%95%EB%B3%B5%EA%B8%B01-Architecting-on-AWS</guid>
            <pubDate>Thu, 16 Nov 2023 02:41:35 GMT</pubDate>
            <description><![CDATA[<h2 id="aws-training">AWS Training</h2>
<p>운좋게 아키텍처 관련 교육 기회를 얻었다. AWS 는 자체적으로 기술 교육 팀을 운영하면서 다양한 교육 세션을 제공하는데, 무료나 온라인 세션도 많기 때문에 Solution Associate Architect 등등 AWS 자격증에 관심이 있거나 실습을 곁들인 공부를 하고 싶다면 들어보는 걸 추천한다.</p>
<blockquote>
<p><strong>대상 교육</strong>: <a href="https://aws.amazon.com/ko/training/classroom/architecting-on-aws/">https://aws.amazon.com/ko/training/classroom/architecting-on-aws/</a>
<strong>교육 순서</strong>: AWS 관리 콘솔 &gt; IAM &gt; 네트워크 &gt; 컴퓨팅 &gt; VPC &gt; 스토리지 &gt; 데이터베이스 &gt; 모니터링 &gt; VPC 고가용성 &gt; 자동화 컨테이너 &gt; 서버리스 &gt; 엣지 서비스 &gt; S3 + CloudFront &gt; 백업/복구 &gt; 멀티 티어 아키텍처 구축 실습</p>
</blockquote>
<p>강의 커리큘럼은 위와 같은데 전반적인 기초 내용을 다루고 있어서 독학 할 때 참고하기에 유용해 보인다. 알고 있지만 제대로 모르는 AWS 이론을 한 바닥 정리하는 데 큰 도움이 될 듯하여 냉큼 신청했다.</p>
<h3 id="미리-알아둘-내용">미리 알아둘 내용</h3>
<ul>
<li>AZ(Availability-Zone; 가용영역): 고가용성 제공, 개별 데이터센터의 그룹, 서울에 4개</li>
<li>Resion(리전): 가용영역 3개 이상, 전체 32개 (2023.11 기준)</li>
<li>Edge Location(엣지 로케이션): 캐싱(서비스 속도 향상) 제공 일종의 서버 인프라, 정확하게는 리전/가용영역과 별개로 CloudFront(AWS CDN)와 Route53(AWS DNS)의 캐시서버</li>
</ul>
<hr>
<h3 id="well-architected-framework">Well-Architected Framework</h3>
<p>세부 서비스가 200개에 달하기 때문에 AWS 통한 서버 구성에 자칫 어지러움을 느끼기 쉽다. 이 부분을 지원하기 위에서인지 에땁에스 측에서 정석 아키텍처의 기본 요소를 아래와 같이 소개했다.</p>
<blockquote>
</blockquote>
<ol>
<li>보안 (IAM)</li>
<li>비용 최적화 (Auto Scaling)</li>
<li>신뢰성 (AZ, 복구 테스트)</li>
<li>성능 효율성 (Serverless, 지연 시간 감소)</li>
<li>운영 우수성 (CloudFormation, 템플릿화 통한 운영 속도 개선)</li>
<li>지속 가능성</li>
</ol>
<p><img src="https://velog.velcdn.com/images/noeun-kim/post/43de6558-0504-4cb1-b709-bef9481985c8/image.gif" alt=""></p>
<p>이 여섯 가지 요소에 집중하고 인프라를 바라보면 보다 안전한 환경을 구성할 수 있기도 하고, SA를 준비 중이라면 실무 관점에서도 도움이 될 것 같다. 아래는 이번 강의 골자를 요약한 내용으로 위 여섯 가지 요소를 기억하며 정리하도록 하자.</p>
<hr>
<h4 id="1-iam-identity-and-access-management">1. IAM (Identity and Access Management)</h4>
<p>보안 주체(User, Group, Role)와 정책(Policy, Permission) 관련 내용을 아래 도표로 정리했다.
<img src="https://velog.velcdn.com/images/noeun-kim/post/f13fcc6d-3dd3-46b8-90fb-7e83392dfd70/image.png" alt=""></p>
<ul>
<li>자격 증명 기반 정책 예시<pre><code class="language-json">{
  &quot;Version&quot;: &quot;2012-10-17&quot;,
  &quot;Statement&quot;: [
      {
          &quot;Effect&quot;: &quot;Allow&quot;,
          &quot;Action&quot;: [
              &quot;s3:*&quot;
          ],
          &quot;Resource&quot;: &quot;*&quot;
      }
  ]
}</code></pre>
</li>
<li>리소스 기반 정책 예시<pre><code class="language-json">{
  &quot;Version&quot;: &quot;2012-10-17&quot;,
  &quot;Statement&quot;: [
      {
          &quot;Sid&quot;: &quot;AddCannedAcl&quot;,
          &quot;Effect&quot;: &quot;Allow&quot;,
          &quot;Principal&quot;: {
              &quot;AWS&quot;: [
                  &quot;arn:aws:iam::111122223333:root&quot;,
                  &quot;arn:aws:iam::444455556666:root&quot;
              ]
          },
          &quot;Action&quot;: [
              &quot;s3:*&quot;,
          ],
          &quot;Resource&quot;: &quot;*&quot;,
      }
  ]
}</code></pre>
</li>
</ul>
<h4 id="2-vpc">2. VPC</h4>
<h5 id="-private-vs-public-subnet">* Private VS Public Subnet</h5>
<p><img src="https://velog.velcdn.com/images/noeun-kim/post/3e9088b1-6d36-45e2-b8d6-773f6732a2b1/image.png" alt=""></p>
<ul>
<li>IP<ul>
<li>Private IP - 변경되는 IP</li>
<li>Elastic IP - 고정된 IP (발급 받고 안 지우면 비용 나감 :cry:)</li>
</ul>
</li>
<li>ENI (탄력적 네트워크 인터페이스) - EC2 와 같은 인스턴스에 연결해서 사용</li>
<li>NAT <ul>
<li>외부망으로 직접 들어오는 접근은 막고 싶지만, 외부로 나가는 접근은 허용하고 싶을 경우 사용 </li>
<li>Private Subnet 의 RT 를 0.0.0.0/0 모든 요청에 대해, NAT 게이트웨이를 통하도록 설정하여 구성할 수 있음</li>
</ul>
</li>
</ul>
<h4 id="3-firewall">3. Firewall</h4>
<p>AWS 자격증 시험에 단골 등장하는 내용이라고 한다. NACL 과 Security Group(보안그룹)은 비교할 만한 내용이 많으므로 시험을 준비 중이라면 꼭 정리하고 넘어가 보도록 하자.
<img src="https://velog.velcdn.com/images/noeun-kim/post/0dbd5ee2-0a06-4f75-8bcb-c16f920b932e/image.png" alt=""></p>
<h4 id="4-computing-modules">4. Computing Modules</h4>
<ul>
<li><p>AMI: EC2 실행에 필요한 위한 세팅의 모음</p>
</li>
<li><p>서버리스(suverless)</p>
<ul>
<li>서버 관리 없이 app 빌드/실행 지원해 주는 클라우드 네이티브 개발 모델</li>
<li>실제로 서버가 없는 것은 아니고 컨테이너와 유사하게 사용자가 서버에 대해 신경 써야 하는 요소를 줄인 것</li>
<li>(sample) 프로그래밍 언어 등을 설정해 주면 LaMDA가 관련 서버 구성을 담당해 줌</li>
</ul>
</li>
<li><p>Storage
<img src="https://velog.velcdn.com/images/noeun-kim/post/ef5ada16-f252-4782-a20f-0b1e82708333/image.png" alt=""></p>
<ul>
<li>Elastic Block Storage (EBS)
인스턴스에 탑재 되는 볼륨으로써 데이터 특정 시점 복사본으로 Amazon EBS 스냅샷 생성이 가능하다. AMI 데이터 저장에 사용되며 스냅샷은Amazon S3에 보관되고 새 EC2 인스턴스 재생성 시 사용될 수 있다. (ref: <a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AmazonEBS.html">https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AmazonEBS.html</a>)</li>
</ul>
</li>
<li><p>Tenancy
<img src="https://velog.velcdn.com/images/noeun-kim/post/30e67807-e6f3-4a16-9dd1-18d09bd517f7/image.png" alt=""></p>
</li>
</ul>
<h4 id="5-pricing">5. Pricing</h4>
<ul>
<li>EC2 Spot Instance
남는 EC2 호스트 용량 사용하는 인스턴스로써 최대 비용을 기존의 90%까지 절약 가능한 장점이 있지만, 온디맨드 복귀가 필요할 때는 2분 이내에 빠르게 워크로드를 복구해야 한다는 단점이 존재한다. 
(내결함성, 유연성, 스테이트리스 워크로드에 활용하는 것이 최적)</li>
</ul>
<h3 id="lab">Lab</h3>
<p>앞서 정리한 내용을 바탕으로 간단한 아키테처 구현 실습을 진행했다. 
<em>(참고로, 정리된 내용은 인프라 구성에 필요한 모든 개념을 포함한 것이 아니며 실습과 관련된 강의 내용만을 발췌한 것이기 때문에 보다 심도 깊은 학습을 원한다면 추가 조사가 필요하다)</em></p>
<p><img src="https://velog.velcdn.com/images/noeun-kim/post/c47cbd44-709b-4908-b121-c5c838e1865a/image.png" alt=""></p>
<p>목표 아키텍처는 위 다이어그램과 같다. 구현할 VPC 안에는 Public과 Private Subnet 이 각각 존재한다. 생성한 EC2 Instance는 퍼블릭 액세스가 가능하고, 프라이빗 서브넷에 인스턴스 격리를 격리할 것이다.</p>
<p> 먼저 Public Subnet 을 통해 외부 인터넷과 통신해야 하기 때문에 Internet Gateway 설정이 필요하다. 외부 인터넷 통신(이 실습에서는 IPv4)을 활성화하려면 해당 인스턴스의 프라이빗 IPv4 주소와 연결된 퍼블릭 IPv4 주소를 알아야 한다. </p>
<p> <img src="https://velog.velcdn.com/images/noeun-kim/post/ef6c4e1e-7053-4b7a-aa39-a9ec3aac3d83/image.png" alt=""></p>
<p> 또한 외부 요청은 받지 않지만, 외부로 호출은 보내고 싶은 서비스를 위해 Private Subnet 을 구성해야 한다. 이때는 NAT Gateway 를 활용한다. 위 구조를 위해 크게는 VPC, Subnet, Instance 순서로 설정 및 생성해야 한다. 구체적인 절차는 아래와 같다.</p>
<ol>
<li>Amazon VPC 생성</li>
<li>Public 및 Private Subnet 생성
 1) 가용영역 할당
 2) CIDR block 설정
 3) Public IP 할당 (public subnet)
 4) Internet Gateway 생성 (public subnet)
 5) VPC 연동
 6) Route Table 생성 및 Rule 추가 (Internet 혹은 NAT Gateway) + Association</li>
<li>Security Group 생성 </li>
<li>Instance 생성
 1) VPC, Subnet, Security Group 할당
 2) IAM Role 배정</li>
</ol>
<hr>
<h3 id="마치며">마치며</h3>
<p>기초적인 부분일지라도 정확한 개념을 알고 넘어가는 것이 중요하다. AWS 클라우드 서비스의 기본 컴포넌트와 탄생 배경을 알게 되어 유익한 시간이었다. IAM 과 Subnet 등의 네트워크 구성 부분에서 실습에서 다루지 못한 디테일한 내용이 많이 남아 있기 때문에 AWS 입문자라면 서비스 시나리오를 정해서 가상 인프라를 구성해 보면 좋을 것 같다. </p>
]]></description>
        </item>
    </channel>
</rss>