컴퓨터잡동사니

 

 

한글 파일 만들기 주소

https://listmonk.app/i18n/

 

 

Listmonk 한글 설정 및 설치 방법

 

https://listmonk.app/

 

Listmonk는 기본적으로 영어 UI를 제공하지만, 일부 설정을 조정하면 한글 UI 및 한글 이메일 발송이 가능합니다.
아래에서 설치 방법과 한글 설정 방법을 정리해드릴게요.

1. Listmonk 설치 방법

Listmonk는 Go 언어로 개발되었으며, Docker로 빠르게 설치 가능합니다.

1) Docker로 Listmonk 설치 (추천)

# 1. Listmonk를 설치할 디렉토리 생성
mkdir listmonk && cd listmonk

# 2. Docker Compose 파일 다운로드
curl -LO https://github.com/knadh/listmonk/raw/master/docker-compose.yml

# 3. Docker 컨테이너 실행 (백그라운드 실행)
docker compose up -d

 

PostgreSQL 데이터 마운트한국어 번역 파일 적용

윈도우 기준 E:\Listmonk 의 임의 디렉토리 를 생성후 docker-compose.yml 파일 다운로드 합니다.

 

 

수정 사항

  1. PostgreSQL 데이터 유지

    • volumes에 ./postgres-data:/var/lib/postgresql/data 추가
  2. 한국어 번역 적용

    • volumes에 ./i18n:/listmonk/i18n 추가
    • command에서 --i18n-dir=/listmonk/i18n 설정

 

수정된 docker-compose.yml

x-db-credentials: &db-credentials
  POSTGRES_USER: &db-user listmonk
  POSTGRES_PASSWORD: &db-password listmonk
  POSTGRES_DB: &db-name listmonk

services:
  app:
    image: listmonk/listmonk:latest
    container_name: listmonk_app
    restart: unless-stopped
    ports:
      - "9000:9000"
    networks:
      - listmonk
    hostname: listmonk.example.com
    depends_on:
      - db
    command: >
      sh -c "./listmonk --install --idempotent --yes --config '' &&
             ./listmonk --upgrade --yes --config '' &&
             ./listmonk --config '' --i18n-dir=/listmonk/i18n"  # i18n 디렉토리 지정
    environment:
      LISTMONK_app__address: 0.0.0.0:9000
      LISTMONK_db__user: *db-user
      LISTMONK_db__password: *db-password
      LISTMONK_db__database: *db-name
      LISTMONK_db__host: listmonk_db
      LISTMONK_db__port: 5432
      LISTMONK_db__ssl_mode: disable
      LISTMONK_db__max_open: 25
      LISTMONK_db__max_idle: 25
      LISTMONK_db__max_lifetime: 300s
      TZ: Asia/Seoul  # 한국 시간 설정
      LISTMONK_ADMIN_USER: ${LISTMONK_ADMIN_USER:-}
      LISTMONK_ADMIN_PASSWORD: ${LISTMONK_ADMIN_PASSWORD:-}
    volumes:
      - ./uploads:/listmonk/uploads:rw
      - ./i18n:/listmonk/i18n:ro  # 한국어 번역 파일 적용 (읽기 전용)
      - ./custom-assets:/listmonk/static  # 사용자 지정 로고 및 CSS 추가
      - ./config.toml:/listmonk/config.toml:ro  # 설정 파일 추가
      
  db:
    image: postgres:17-alpine
    container_name: listmonk_db
    restart: unless-stopped
    ports:
      - "5432:5432"
    networks:
      - listmonk
    environment:
      <<: *db-credentials
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U listmonk"]
      interval: 10s
      timeout: 5s
      retries: 6
    volumes:
      - ./postgres-data:/var/lib/postgresql/data  # 데이터 유지

networks:
  listmonk:

volumes:
  listmonk-data:

 

전체  docker-compose.yml

x-db-credentials: &db-credentials                             # Use the default POSTGRES_ credentials if they're available or simply default to "listmonk"
  POSTGRES_USER: &db-user listmonk                            # for database user, password, and database name
  POSTGRES_PASSWORD: &db-password listmonk
  POSTGRES_DB: &db-name listmonk

services:
  # listmonk app
  app:
    image: listmonk/listmonk:latest
    container_name: listmonk_app
    restart: unless-stopped
    ports:
      - "9000:9000"                                           # To change the externally exposed port, change to: $custom_port:9000
    networks:
      - listmonk
    hostname: listmonk.example.com                            # Recommend using FQDN for hostname
    depends_on:
      - db
    command: [sh, -c, "./listmonk --install --idempotent --yes --config '' && 
                      ./listmonk --upgrade --yes --config '' && 
                      ./listmonk --config '' --i18n-dir=/listmonk/i18n"]
                                                              # --config (file) param is set to empty so that listmonk only uses the env vars (below) for config.
                                                              # --install --idempotent ensures that DB installation happens only once on an empty DB, on the first ever start.
                                                              # --upgrade automatically runs any DB migrations when a new image is pulled.

    environment:                                              # The same params as in config.toml are passed as env vars here.
      LISTMONK_app__address: 0.0.0.0:9000
      LISTMONK_db__user: *db-user
      LISTMONK_db__password: *db-password
      LISTMONK_db__database: *db-name
      LISTMONK_db__host: listmonk_db
      LISTMONK_db__port: 5432
      LISTMONK_db__ssl_mode: disable
      LISTMONK_db__max_open: 25
      LISTMONK_db__max_idle: 25
      LISTMONK_db__max_lifetime: 300s
      TZ: Asia/Seoul  # 한국 시간 설정
      LISTMONK_ADMIN_USER: ${LISTMONK_ADMIN_USER:-}           # If these (optional) are set during the first `docker compose up`, then the Super Admin user is automatically created.
      LISTMONK_ADMIN_PASSWORD: ${LISTMONK_ADMIN_PASSWORD:-}   # Otherwise, the user can be setup on the web app after the first visit to http://localhost:9000
    volumes:                                                  # Mount an uploads directory on the host to /listmonk/uploads inside the container. 
      - ./uploads:/listmonk/uploads:rw                        # To use this, change directory path in Admin -> Settings -> Media to /listmonk/uploads
      - ./i18n:/listmonk/i18n:ro  # 한국어 번역 파일 적용 (읽기 전용)
      - ./custom-assets:/listmonk/static  # 사용자 지정 로고 및 CSS 추가
      - ./config.toml:/listmonk/config.toml:ro  # 설정 파일 추가   
      
  # Postgres database
  db:
    image: postgres:17-alpine
    container_name: listmonk_db
    restart: unless-stopped
    ports:
      - "5432:5432"
    networks:
      - listmonk
    environment:
      <<: *db-credentials
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U listmonk"]
      interval: 10s
      timeout: 5s
      retries: 6
    volumes:      
      # - type: volume
      #   source: listmonk-data
      #   target: /var/lib/postgresql/data
      - ./postgres-data:/var/lib/postgresql/data  # 데이터 유지

networks:
  listmonk:

volumes:
  listmonk-data:

 

/프로젝트_디렉터리/
│── docker-compose.yml
│── config.toml      # 여기에 생성
│── custom-assets/   # 로고, CSS 등의 정적 파일 저장
│   ├── logo.png
│   ├── style.css
│── uploads/
│── i18n/
│── postgres-data/

 

 

 

설치 및 실행 방법

  1. 한국어 번역 파일 저장
    E:\Listmonk\i18n\ko.json 파일을 생성 후, 번역된 JSON을 넣습니다.

ko.json 파일

https://github.com/braverokmc79/listmonk/blob/master/i18n/ko.json

 

 

2. 로고 및 UI 변경 방법

다음 github 주소 디렉토리의  파일명과 같게  logo.png,  logo.svg, style.css 등을 생성해서 수정합니다.

https://github.com/braverokmc79/listmonk/tree/master/static/public/static

  1. custom-assets 디렉터리를 생성:

custom-assets/logo.png로 새로운 로고 파일을 저장합니다.

 

CSS 스타일 변경:

  • custom-assets/style.css 파일을 만들어 UI를 수정할 수 있습니다.
  • 예를 들어, listmonk 텍스트를 변경하고 싶다면
.navbar-brand {
  content: "My Custom Email System";
  font-weight: bold;
}

설정 파일 수정 (config.toml)

  • config.toml 파일을 생성하고, 원하는 이름으로 변경할 수 있습니다.
  •  
[app]
name = "My Custom Email System"

 

4. 적용 방법

이제 변경 사항을 적용하려면 다음 명령을 실행하면 됩니다.

docker compose down
docker compose up -d --build

 

또는

  1. 도커 컨테이너 실행

cd E:\Listmonk
docker-compose up -d

 

  1. 웹 인터페이스 접속
    브라우저에서 http://localhost:9000으로 접속 후, 한국어 설정을 확인합니다.

 

static 파일을 변경이 안되면 다음과 같이 command 를 변경한다.

 command: [sh, -c, "./listmonk --install --idempotent --yes --config '' && 
                      ./listmonk --upgrade --yes --config '' && 
                       mkdir -p /listmonk/static && cp -r /listmonk/static /listmonk/static_backup && 
                      ./listmonk --config '' --i18n-dir=/listmonk/i18n"]

위 와 같이 설정을 해도 변경이 안된다면, 다음과 같이

 

 

관리자 화면에서 설정 =>디자인 수정에서 =>관리자 화면 및  공개화면 js 변경

function updateFooter() {
        const footer = document.querySelector("footer.container");
        if (footer) {
            console.log("업데이트 실행");
            footer.innerHTML = '제공: <a target="_blank" rel="noreferrer" href="https://macaronics.net">macaronics.net</a>';
        }
}
updateFooter();

function updateLogoImages() {
  const fullImg = document.querySelector('.navbar-brand div.logo a .full'); 
  if (fullImg) {
    fullImg.src = 'https://cdn.jsdelivr.net/gh/braverokmc79/web_publishing_project1@1.0.0/img/logo-email.svg';
    fullImg.style.width = '150px';
    fullImg.style.maxHeight = 'none';
    console.log("변경 성공")
  }
}

// 함수 실행
updateLogoImages();


document.addEventListener("DOMContentLoaded", function () {    
    setTimeout(updateFooter, 500); // 0.5초 후 실행
    setTimeout(updateFooter, 1000); // 1초 후 실행
    setTimeout(updateLogoImages, 300); // 0.3초 후 실행
    setTimeout(updateLogoImages, 500); // 0.5초 후 실행
    setTimeout(updateLogoImages, 2000); // 2초 후 실행
});

 

 

 

 

 

 

 

config.toml

1. config.toml 생성하기

  1. docker-compose.yml과 같은 디렉터리에 config.toml 파일을 만듭니다.

touch config.toml

 

2.config.toml 파일 내용 예시:

[app]
name = "My Custom Email System"  # 서비스 이름 변경
address = "0.0.0.0:9000"

[db]
user = "listmonk"
password = "listmonk"
database = "listmonk"
host = "listmonk_db"
port = 5432
ssl_mode = "disable"

 

2. docker-compose.yml에서 설정 추가

위에서 만든 config.toml을 컨테이너에 연결하려면, docker-compose.yml의 volumes 섹션에 다음을 추가하세요

    volumes:
      - ./uploads:/listmonk/uploads:rw
      - ./i18n:/listmonk/i18n:ro  
      - ./custom-assets:/listmonk/static  # 사용자 지정 로고 및 CSS 추가
      - ./config.toml:/listmonk/config.toml:ro  # 설정 파일 추가

3. 적용 방법

파일을 생성하고 수정한 후, 아래 명령어로 적용하세요.

docker compose down
docker compose up -d --build

 

결론

✅ config.toml은 docker-compose.yml과 같은 디렉터리에 두고,
✅ custom-assets/는 로고, CSS 등의 정적 파일을 저장하는 용도로 사용하세요.

 

 

 

 

 

 

3️⃣ Settings → General 에서 "Custom CSS URL" 항목에 custom.css 경로 입력

3. Listmonk에서 이메일 발송 설정

Listmonk는 자체 메일 서버가 없기 때문에, SMTP 서버를 연결해야 합니다.
무료 SMTP 서버 중 하나를 사용하면 됩니다.

 

 

 

 

 

 

2.Listmonk에서 Outlook SMTP 설정 방법

Listmonk의 config.toml 파일에서 SMTP 설정을 아래와 같이 구성하면 됩니다

 

1.설정 방법 다음 주소에서  "Outlook.com의 POP, IMAP 및 SMTP 설정" 탭을 클릭한다.
https://support.microsoft.com/ko-kr/office/outlook-com의-pop-imap-및-smtp-설정-d088b986-291d-42b8-9564-9c414e2aa040

 


2.설정하기  : https://outlook.live.com 에 접속한다.
https://outlook.live.com/mail/0/options/mail/forwarding

우측 상단 톱니바퀴 클릭한후  -> 전달 및 IMAP 클릭
 

 

 

2. 중요한 보안 및 설정 고려 사항

앱 비밀번호 사용

  • 개인 이메일 비밀번호를 사용하면 보안상 위험합니다.
  • 대신 Outlook(Office365)에서 앱 비밀번호를 생성하여 사용하세요.
  • 앱 비밀번호 생성 방법:
    1. Microsoft 계정 보안 페이지로 이동
    2. "추가 보안 옵션" → "앱 암호 생성"에서 생성
    3. 위의 password 항목에 입력

2단계인증이 활성화 되면   앱 암호  일부 앱과 디바이스 암호 생성 메뉴가 나옵니다.

 

SMTP TLS 설정

  • Outlook SMTP 서버는 TLS(STARTTLS) 프로토콜을 요구합니다.
  • tls = true가 설정되어 있어야 정상적으로 동작합니다.

 

 

 

 

1️⃣ Outlook SMTP 정보

  • SMTP 서버: smtp.office365.com
  • 포트: 587
  • 보안: STARTTLS
  • 사용자 이메일: your-email@outlook.com
  • 비밀번호: Outlook 계정 비밀번호 또는 앱 비밀번호 사용

 

2️⃣ Listmonk SMTP 설정 (config.toml)

[smtp]
host = "smtp.office365.com"
port = 587
username = "your-email@outlook.com"
password = "your-app-password"  # 앱 비밀번호 사용 권장
from = "Your Name <your-email@outlook.com>"
tls = true

 

주의: Outlook에서는 보안상의 이유로 앱 비밀번호(App Password) 사용을 권장합니다.
앱 비밀번호를 발급하려면 Microsoft 계정 보안 설정에서 "앱 암호 생성" 기능을 사용하세요.


 

 

 

 

 

 

연동 후 테스트 방법

  1. Listmonk 서버 재시작
./listmonk --config config.toml
  • Listmonk 관리자 페이지 접속 (http://your-listmonk-url/admin)
  • Settings > SMTP 설정 확인
  • "Send Test Email" 버튼 클릭하여 테스트 발송

 

Outlook SMTP 연동 후 가능한 기능

  • Listmonk를 통해 Outlook 메일 계정으로 대량 이메일 발송 가능
  • Outlook 이메일 주소를 사용하여 뉴스레터, 마케팅 이메일 발송
  • Outlook 계정을 이용하여 이메일 자동화 및 구독자 관리 가능

 

 

❌ Outlook SMTP 연동의 단점 및 제한 사항

대량 이메일 발송 제한:

  • Outlook SMTP는 하루 300~500건 정도의 이메일 발송 제한이 있음.
  • 기업용 Microsoft 365 계정(E5 등급)을 사용하면 발송 제한을 늘릴 수 있음.
  •  
  • 대량 메일을 발송해야 한다면 SendGrid, Mailgun, Amazon SES 같은 전문 SMTP 서비스를 사용하는 것이 좋음.

 

SMTP 속도 제한:

  • Outlook의 SMTP 서버는 빠른 대량 전송에 최적화되지 않음.
  • 마케팅 이메일을 대량으로 보낼 경우 지연(delays) 발생 가능.

 

결론: Outlook SMTP 연동 가능하지만, 대량 발송에는 비효율적

  • 소규모 뉴스레터(일일 100~200건 발송)라면 Outlook SMTP 사용 가능
  • 대량 발송이 필요하면 SendGrid, Mailgun, Amazon SES 같은 SMTP 서비스 추천
  • Outlook 계정을 이용하여 개인 또는 비즈니스 메일을 자동화하는 용도로는 적합
  •  

 

대량 이메일 발송은 다음 을 추천
SMTP 서비스(SendGrid, Mailgun 등)

 

 

 

 

 

 

3.Listmonk Supabase(PostgreSQL 기반의 BaaS)를 연동 방법

 

연동 방법

  1. Listmonk 데이터베이스를 Supabase로 설정

    • Listmonk는 기본적으로 PostgreSQL을 사용하므로 Supabase의 PostgreSQL과 호환됩니다.
    • config.toml에서 DB 연결 정보를 Supabase의 PostgreSQL 연결 정보로 변경하면 됩니다.

 

  1. Supabase에서 SMTP 설정

    • Supabase는 자체적으로 이메일 전송 기능을 제공하지 않으므로, Listmonk의 SMTP 설정을 통해 이메일을 발송해야 합니다.
    • Listmonk에서 SMTP 서버로 SendGrid, Mailgun, Amazon SES 등의 SMTP 서비스를 설정하면 됩니다.

 

  1. Supabase에서 Webhook 또는 API 활용

    • Supabase의 Row Level Security (RLS) 정책을 설정하고 Listmonk가 필요한 데이터를 접근할 수 있도록 API를 설정할 수 있습니다.
    • Supabase Functions 또는 Webhook을 사용해 특정 이벤트(예: 유저 가입) 발생 시 자동으로 Listmonk에 데이터를 추가하는 연동도 가능합니다.

 

예제 설정

1️⃣ config.toml에서 Supabase PostgreSQL 연결

[database]
host = "your-supabase-host"
port = 5432
user = "your-db-user"
password = "your-db-password"
database = "your-db-name"
sslmode = "require"

 

2️⃣ Listmonk의 SMTP 설정 (예: Mailgun)

[smtp]
host = "smtp.mailgun.org"
port = 587
username = "postmaster@yourdomain.com"
password = "your-mailgun-password"
from = "Your Service <no-reply@yourdomain.com>"

 

3️⃣ Supabase API를 통해 Listmonk에 구독자 추가

Supabase Edge Functions을 활용하여 새로운 사용자가 가입될 때 Listmonk에 자동 등록할 수 있습니다.

import { createClient } from '@supabase/supabase-js';

const supabase = createClient('https://your-project.supabase.co', 'your-anon-key');

async function addSubscriber(email: string) {
    const response = await fetch('https://your-listmonk-instance/api/subscribers', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Basic your-listmonk-api-key'
        },
        body: JSON.stringify({
            email,
            name: email.split('@')[0],
            status: "enabled",
            lists: [1]  // 구독할 리스트 ID
        })
    });

    return response.json();
}

// Supabase에서 특정 이벤트 발생 시 실행
supabase
  .from('users')
  .on('INSERT', async (payload) => {
    await addSubscriber(payload.new.email);
  })
  .subscribe();

 

 

결론

  • Supabase의 PostgreSQL을 Listmonk의 DB로 사용할 수 있음.
  • Listmonk에서 SMTP 설정을 통해 이메일 발송 가능.
  • Supabase의 API/Webhook을 이용해 Listmonk와 자동화 가능.

이 방식으로 Supabase와 Listmonk를 연동할 수 있습니다.

 

 

Supabase 무료 플랜에서 가능한 것들

PostgreSQL 사용 가능 → Listmonk의 DB로 사용 가능
API 및 Webhook 사용 가능 → Listmonk와 데이터 연동 가능
Edge Functions 사용 가능 → 사용자 가입 시 자동으로 Listmonk에 추가 가능
스토리지 1GB 제공 → 이미지나 첨부 파일 저장 가능
월 50,000 요청 가능 → API 호출이 적은 경우 충분

 

Supabase 무료 플랜의 제한 사항

월 50,000 데이터베이스 요청 제한 → 대량 이메일 발송 시 한계
Auto-Scaling 미지원 → 트래픽 증가 시 성능 저하 가능
장시간 유휴 상태 시 DB 자동 종료 → 트래픽이 적으면 연결이 끊길 수 있음
이메일 전송 기능 없음 → SMTP 설정이 필요 (SendGrid, Mailgun, Amazon SES 등)
백업 기능 제한 → 유료 플랜에서는 자동 백업 지원

 

 

 

 

★nginx 연동

도커 컨테이너 내부 주소 확인

docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' listmonk_app

 

이 명령어의 의미

  • docker inspect → 특정 컨테이너의 상세 정보를 가져옴
  • -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' → 네트워크 설정 중 IPAddress 값을 출력
  • listmonk_app → listmonk 컨테이너의 이름

 

실행 결과: 예

172.18.0.3
 

ngixn/conf.d/도메인주소r.conf

server {
    listen 80;
    server_name 도메인주소;

    location / {
        proxy_pass http://172.18.0.3:9000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering off;
    }
}

 

587 등 포트 개방 필수: 

 

 

 

 

엑셀 → CSV 변환 코드 (파이썬)

  1. 엑셀 파일에서 email, name, attributes 컬럼을 읽음
  2. attributes 컬럼이 여러 개일 경우 JSON 형태로 변환
  3. Listmonk에 맞는 CSV로 저장
import pandas as pd
import json

# ???? 엑셀 파일 불러오기 (파일명 변경 가능)
excel_file = "users.xlsx"

# ???? 데이터 읽기
df = pd.read_excel(excel_file)

# ???? attributes 컬럼 만들기 (email, name 제외한 나머지 컬럼을 JSON 변환)
df["attributes"] = df.drop(columns=["email", "name"]).apply(lambda x: json.dumps(x.dropna().to_dict(), ensure_ascii=False), axis=1)

# ???? 필요한 컬럼만 유지
df = df[["email", "name", "attributes"]]

# ???? CSV 저장 (UTF-8 인코딩, 따옴표 포함)
csv_file = "listmonk_users.csv"
df.to_csv(csv_file, index=False, quotechar='"')

print(f"✅ 변환 완료! 저장된 파일: {csv_file}")

 

 

사용 방법

  1. users.xlsx 파일을 준비 (컬럼: email, name, 추가 데이터...)
  2. 위 파이썬 코드를 실행
  3. listmonk_users.csv 파일이 생성됨
  4. Listmonk에서 업로드

 

 

 

 

about author

PHRASE

Level 60  라이트

일이 비록 작더라도 하지 않으면 이룰 수 없고, 자식이 비록 어질더라도 가르치지 않으면 현명하지 않다. -장자

댓글 ( 0)

댓글 남기기

작성

컴퓨터잡동사니 목록    more