πŸš€ λΈ”λ‘œκ·Έλ₯Ό μ™œ 써야 ν•˜λŠ”μ§€?!

κ°œλ°œμžλŠ” 기술 λΈ”λ‘œκ·Έλ₯Ό 톡해 μžμ‹ μ˜ κ²½ν—˜μ„ κ³΅μœ ν•˜κ³ , λ‹€λ₯Έ κ°œλ°œμžλ“€κ³Ό 지식을 κ³΅μœ ν•˜λ©° μ„±μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ˜ν•œ, λΈ”λ‘œκ·Έλ₯Ό μš΄μ˜ν•¨μœΌλ‘œμ¨ μžμ‹ μ˜ ν”„λ‘œμ νŠΈλ‚˜ 포트폴리였λ₯Ό 보닀 μ‰½κ²Œ κ³΅μœ ν•˜κ³ , 개인 λΈŒλžœλ”©μ—λ„ 도움이 λ©λ‹ˆλ‹€.


μ†”μ§ν•˜κ²Œ κ΄‘κ³ λ‘œ μ–Όλ§ˆλ₯Ό 벌 수 μžˆλŠ”μ§€ ν•œλ²ˆ μ‹¬μ‹¬ν•΄μ„œ μ‹œμž‘ν–ˆμŠ΅λ‹ˆλ‹€. γ…Žγ…Žγ…Žβ€¦

κ°œλ°œμ— λŒ€ν•΄ 살짝이라도 μ•Œκ³  κ³„μ‹œλ©΄ μΆ”μ²œ ν•©λ‹ˆλ‹€!


πŸ”¨ 쀀비물이 무엇이 ν•„μš”ν•œμ§€?!

μžλ™ν™”λœ Git Blogλ₯Ό μš΄μ˜ν•˜κΈ° μœ„ν•΄ ν•„μš”ν•œ 쀀비물은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  • Git 계정 및 λΈ”λ‘œκ·Έ ν˜ΈμŠ€νŒ… ν”Œλž«νΌ (e.g. GitHub, GitLab, Bitbucket, Gitea λ“±)

  • 정적 μ‚¬μ΄νŠΈ 생성기 (e.g. Jekyll, Hugo, Pelican λ“±)

  • λ§ˆν¬λ‹€μš΄ 에디터 (e.g. Typora, Visual Studio Code λ“±)

  • μžλ™ν™” 슀크립트 (e.g. GitHub Actions, Travis CI λ“±)

μ œκ°€ μ„Έμ› λ˜ μ•„ν‚€ν…μ²˜λŠ” GitHub Actionsλ₯Ό μ‚¬μš©ν•˜μ—¬ Jekyll 기반의 정적 λΈ”λ‘œκ·Έλ₯Ό μžλ™ν™”ν•˜λŠ” λ°©λ²•μž…λ‹ˆλ‹€.

1. Github blog λ₯Ό μ‚¬μš©ν•œλ‹€. (API μ‚¬μš© ν•  수 μžˆλ‹€λ©΄ μ–΄λ–€ λΈ”λ‘œκ·Έμ—¬λ„ μƒκ΄€μ—†μŠ΅λ‹ˆλ‹€.)

2. μŠ€μΌ€μ₯΄λŸ¬λ₯Ό 돌릴 수 μžˆλŠ” ν™˜κ²½μ΄ μžˆμ–΄μ•Όλœλ‹€. (μžλ™μœΌλ‘œ μ£Όμ œμ— λŒ€ν•΄ ChatGpt ν•œν…Œ 써달라고 ν• κ±°κ±°λ“ μš”.)

3. κ°„λ‹¨ν•˜κ²Œ μ‹€ν–‰ μ‹œν‚¬ 파일이 μžˆμ–΄μ•Όλ©λ‹ˆλ‹€. (Python, Node ...)

κ°„λ‹¨ν•˜κ²Œ μ •λ¦¬ν•˜λ©΄ μ•„ν‚€ν…μ²˜λŠ” μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

    1. Python 을 μ΄μš©ν•΄μ„œ ChatGpt 연동 ν›„ 주제λ₯Ό DB λ˜λŠ” ꡬ글 μ‹œνŠΈλ‘œ λͺ¨μ•„ λ†“λŠ”λ‹€.
    2. Github action μŠ€μΌ€μ₯΄λŸ¬λ₯Ό μ‚¬μš©ν•˜μ—¬ λ‘κ°œμ˜ μž‘μ„ λ§Œλ“ λ‹€. 
        a. 주제 생성 및 κ²ΉμΉ˜μ§€ μ•Šκ²Œ 관리 ν•˜λŠ” Job
        b. μ£Όμ œμ— λŒ€ν•΄ 컨텐츠λ₯Ό λ§Œλ“œλŠ” Job
    3. μŠ€μΌ€μ₯΄λŸ¬κ°€ μ •μƒμ μœΌλ‘œ 돈 ν›„ Github > commit & deploy 진행 μ‹œν‚¨λ‹€. (CI/CD ꡬ좕)

ps.λ‚˜μ€‘μ— κ·Έλ¦Ό μΆ”κ°€ μ˜ˆμ •μž…λ‹ˆλ‹€. 

🧐 λΈ”λ‘œκ·Έ 글을 μžλ™ν™” ν•˜λŠ”λ°©λ²• !?

λΈ”λ‘œκ·Έλ₯Ό μžλ™ν™”ν•˜λŠ” 방법은 크게 두 κ°€μ§€λ‘œ λ‚˜λˆŒ 수 μžˆμŠ΅λ‹ˆλ‹€.

μ²«μ§ΈλŠ” 정적 μ‚¬μ΄νŠΈ 생성기와 Git ν˜ΈμŠ€νŒ… ν”Œλž«νΌμ„ μ‚¬μš©ν•˜μ—¬ λΈ”λ‘œκ·Έλ₯Ό λ§Œλ“  λ’€, Git Actionκ³Ό 같은 CI/CD 도ꡬλ₯Ό μ΄μš©ν•˜μ—¬ 컨텐츠λ₯Ό μžλ™μœΌλ‘œ μƒμ„±ν•˜κ³ , λΉŒλ“œ 및 λ°°ν¬ν•˜λŠ” λ°©λ²•μž…λ‹ˆλ‹€. 이 방법은 λΈ”λ‘œκ·Έμ˜ ꡬ쑰가 정적이기 λ•Œλ¬Έμ— μž‘μ„±λœ 컨텐츠가 λ§Žμ§€ μ•Šλ‹€λ©΄ μ’€ 더 μ‰½κ²Œ μžλ™ν™”ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ‘˜μ§ΈλŠ” 동적인 λΈ”λ‘œκ·Έλ₯Ό λ§Œλ“€μ–΄ μ„œλ²„λ₯Ό 톡해 μžλ™ν™”ν•˜λŠ” λ°©λ²•μž…λ‹ˆλ‹€. 이 방법은 λΈ”λ‘œκ·Έκ°€ 동적인 νŠΉμ„±μ„ 띄기 λ•Œλ¬Έμ— 컨텐츠λ₯Ό μƒμ„±ν•˜κ³  λ°°ν¬ν•˜λŠ” 과정이 더 λ³΅μž‘ν•΄μ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ 이 방법을 μ‚¬μš©ν•˜λ©΄ λΈ”λ‘œκ·Έμ— μ’€ 더 λ§Žμ€ κΈ°λŠ₯을 μΆ”κ°€ν•  수 있으며, λΈ”λ‘œκ·Έ μš΄μ˜μ— μžˆμ–΄μ„œ λ”μš± μœ μ—°μ„±μ΄ μžˆμŠ΅λ‹ˆλ‹€.

μ–΄λ–€ 방법을 μ„ νƒν•˜λ”λΌλ„ λΈ”λ‘œκ·Έλ₯Ό μžλ™ν™”ν•˜λŠ” 것은 κ°œλ°œμžλ‘œμ„œμ˜ μ—­λŸ‰μ„ λ†’μ΄λŠ”λ° 큰 도움이 λ©λ‹ˆλ‹€. 컨텐츠λ₯Ό μƒμ„±ν•˜κ³ , λ°°ν¬ν•˜λŠ” 과정을 μžλ™ν™”ν•¨μœΌλ‘œμ¨ κ°œλ°œμžλŠ” μ’€ 더 λ§Žμ€ μ‹œκ°„μ„ κ°œλ°œμ— 집쀑할 수 있으며, λΈ”λ‘œκ·Έ μš΄μ˜μ— λŒ€ν•œ 뢀담을 쀄일 수 μžˆμŠ΅λ‹ˆλ‹€.

μ €λŠ” λ‘λ²ˆμ§Έ λ°©λ²•μœΌλ‘œ 진행할 μ˜ˆμ •μž…λ‹ˆλ‹€.

Git blog λ§Œλ“œλŠ”λ²•

  • λΈ”λ‘œκ·Έ μ €μž₯μ†Œ 생성 및 Jekyll ν…Œλ§ˆ 적용
  • GitHub, GitLab, Bitbucket λ“±μ˜ Git ν˜ΈμŠ€νŒ… ν”Œλž«νΌμ—μ„œ μƒˆλ‘œμš΄ μ €μž₯μ†Œλ₯Ό μƒμ„±ν•˜κ³ , Jekyll 기반의 정적 λΈ”λ‘œκ·Έ ν…Œλ§ˆλ₯Ό μ μš©ν•©λ‹ˆλ‹€.
  • 제 κ²½μš°λŠ” μ€Œμ½”λ”©λ‹˜ Blog ν…œν”Œλ¦Ώμ„ κ°–κ³ μ™€μ„œ μ‚¬μš©ν–ˆμŠ΅λ‹ˆλ‹€.

μžλ™ν™” 슀크립트 μž‘μ„±

  • GitHub Actions을 μ‚¬μš©ν•˜μ—¬ λΈ”λ‘œκ·Έλ₯Ό μžλ™μœΌλ‘œ λΉŒλ“œν•˜κ³  λ°°ν¬ν•˜λŠ” μžλ™ν™” 슀크립트λ₯Ό μž‘μ„±ν•©λ‹ˆλ‹€.

Github action 전에 μ€€λΉ„ μž‘μ—… ν•΄λ‹Ήν•˜λŠ” Github Reposittory > setting > security > action

  • MY_EMAIL, MY_NAME, MY_TOKEN, OPENAI_API_KEY μΆ”κ°€ν•΄μ£Όμ„Έμš”.

blog3.png

이 μŠ€ν¬λ¦½νŠΈλŠ” λΈ”λ‘œκ·Έ μ €μž₯μ†Œμ˜ .github/workflows 디렉토리에 μž‘μ„±λ©λ‹ˆλ‹€.

  • μ•„λž˜λŠ” yaml μ˜ˆμ‹œμž…λ‹ˆλ‹€.

    name: Auto Publish Blog Posts by 손(Son/손민기)
    
    on:
    schedule:
        - cron: '0 0 * * *'
    
    jobs:
    generate-blog-post:
        runs-on: ubuntu-latest
        steps:
        - name: Checkout Repository
            uses: actions/checkout@v2
    
        - name: Set up Python
            uses: actions/setup-python@v2
            with:
            python-version: 3.x
    
        - name: Cache Python packages
            uses: actions/cache@v2
            with:
            path: ~/.cache/pip
            key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
            restore-keys: |
                ${{ runner.os }}-pip-
    
        - name: Install Required Python Packages
            run: |
            python -m pip install --upgrade pip
            pip install gitpython
            pip install -r requirements.txt
    
        - name: Generate Blog Post
            env:
            OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
            run: python generate_blog_post.py
    
        - name: Commit Changes
            env:
            MY_EMAIL: ${{ secrets.MY_EMAIL }}
            MY_NAME: ${{ secrets.MY_NAME }}
            MY_TOKEN : ${{ secrets.MY_TOKEN }}
            run: |
            git config --local user.email $MY_EMAIL
            git config --local user.name $MY_NAME
    
            git remote set-url origin https://$MY_NAME:$MY_TOKEN@github.com/smk692/smk692.github.io.git
    
            git add .
            git commit -m "Add a new blog post"
            git push
    
    deploy:
        needs: generate-blog-post
        runs-on: ubuntu-latest
        steps:
        - name: Checkout Repository
            uses: actions/checkout@v2
    
        - uses: actions/setup-node@v3
            with:
            node-version: v14.17.4
    
        - name: Cache node modules
            uses: actions/cache@v2
            with:
            path: ~/.npm
            key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
            restore-keys: |
                ${{ runner.os }}-npm-
    
        - name: Npm install
            run: npm install
    
        - name: Update blog
            env:
            MY_EMAIL: ${{ secrets.MY_EMAIL }}
            MY_NAME: ${{ secrets.MY_NAME }}
            MY_TOKEN : ${{ secrets.MY_TOKEN }}
            run: |
            git config --local user.email $MY_EMAIL
            git config --local user.name $MY_NAME
    
            git remote set-url origin https://$MY_NAME:$MY_TOKEN@github.com/smk692/smk692.github.io.git
    
            npm run deploy
    
  • GitHub Actions을 μ‚¬μš©ν•˜μ—¬ λΈ”λ‘œκ·Έ 컨텐츠 μ—…λ°μ΄νŠΈν•˜λŠ” 파이썬 μ½”λ“œμž…λ‹ˆλ‹€. (generate_blog_post.py)

    # ...import λΆ€λΆ„ μƒλž΅ 
    
    def generate_contents(topic):
        openai.api_key = os.getenv("OPENAI_API_KEY")
    
        prompt_contents = f'''
            {topic} λŒ€ν•΄μ„œ μžμ„Έν•˜κ²Œ μ μ–΄μ€˜
        '''
    
        contents = connection_chatgpt(prompt_contents)
    
        contents = '\n'.join(contents.strip().split('\n')[3:])
    
        return contents
    
    def connection_chatgpt(prompt):
        response = openai.Completion.create(
            model="text-davinci-003",
            prompt=prompt,
            temperature=1,
            max_tokens=3800,
            top_p=1,
            frequency_penalty=0.0,
            presence_penalty=0.6,
        )
        contents = ""
        for choice in response.choices:
            contents += choice.text
    
        return contents
    
    def create_blog_post(topic, tags, categories, contents):
    
        # 폴더가 μ—†μœΌλ©΄ 생성
        if not os.path.exists(directory_path):
            os.makedirs(directory_path)
    
        # λΈ”λ‘œκ·Έ ν¬μŠ€νŠΈμ— μ‚¬μš©λ  메타데이터
        metadata = [
            "---",
            "layout: post",
            f"title: \"{topic}\"",
            f"date: '{now.strftime('%Y-%m-%d %H:%M:%S')}'",
            f"author: 손(Son/손민기)",
            f"tags: {tags}",
            f"categories: {categories}",
            "---"
        ]
    
        # λΈ”λ‘œκ·Έ 포슀트 파일 생성
        with open(file_name, "w") as f:
            
            f.write("\n".join(metadata))
            f.write("\n")
            f.write(contents)
    
        print(f"λΈ”λ‘œκ·Έ 포슀트 파일이 μƒμ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€: {file_name}")
    
    if __name__ == "__main__":
    
        topic       = "λΈ”λ‘œκ·Έ μžλ™ν™”!"
        tags        = "gitblog"
        categories  = "μžλ™ν™”"
    
        contents = generate_contents(topic)
        pprint.pprint(contents)
    
        create_blog_post(topic, tags, categories, contents)

βœ… μ™„μ„±λœ 결과에 λŒ€ν•œ μŠ€ν¬λ¦°μƒ·!

  • Github action κΈ€ 생성 된 κ²°κ³Ό

    blog1.png

  • Github action κΈ€ 배포 된 κ²°κ³Ό

    blog1.png

  • Github blog μ—…λ°μ΄νŠΈ 된 κ²°κ³Ό

    blog4.png


μ†Œκ°

μ΄μƒμœΌλ‘œ λΈ”λ‘œκ·Έ μžλ™ν™”μ— λŒ€ν•΄ μ•Œμ•„λ³΄μ•˜μŠ΅λ‹ˆλ‹€.

μžλ™ν™”λ₯Ό 톡해 κ°œλ°œμžλŠ” λΈ”λ‘œκ·Έ μš΄μ˜μ„ 보닀 효율적으둜 ν•  수 있고, 더 λ§Žμ€ μ‹œκ°„μ„ κ°œλ°œμ— 집쀑할 수 μžˆμŠ΅λ‹ˆλ‹€.

λ§Žμ€ κ°œλ°œμžλΆ„λ“€μ΄ 이 글을 보고 μžμ‹ λ§Œμ˜ μžλ™ν™”λœ λΈ”λ‘œκ·Έλ₯Ό μš΄μ˜ν•˜μ‹œκΈΈ λ°”λžλ‹ˆλ‹€!

ps. κ°„λ‹¨ν•˜κ²Œ 짠거라 ν•„μš”ν•˜λ©΄ κ°–κ³  κ°€μ‹œλ©΄ λ©λ‹ˆλ‹€. (λŒ€μ‹  λŒ“κΈ€ ν•˜λ‚˜λ§Œ μ μ–΄μ£Όμ„Έμš”.)

    λ°˜λ°• μ‹œ 무쑰건 μƒκ°ν•œκ²Œ λ§žμŠ΅λ‹ˆλ‹€.