Computer >> 컴퓨터 >  >> 프로그래밍 >> Bash 프로그래밍

스크립트 마스터하기: 반복 작업 자동화로 생산성 극대화하는 법

견고하고 품질 높은 소프트웨어를 개발하며 경험을 쌓은 개발자일수록 대부분의 업무를 스크립트로 자동화하는 경향이 있습니다. 이러한 스크립트는 간단한 Bash 별칭(alias) 명령어부터 서버에서 주기적으로 실행되는 크론(cron) 작업까지 다양합니다.

이 튜토리얼에서는 스크립팅이 무엇인지, 다양한 활용 사례, 그리고 스크립트 사용의 장단점을 알아봅니다. 또한 실제 동작하는 몇 가지 예제 스크립트도 함께 살펴보겠습니다.

스크립트란 무엇인가?

스크립트는 Bash, Python, JavaScript 등 어떤 스크립팅 언어로든 작성할 수 있는 명령어 집합으로, 작업을 자동화하거나 프로세스를 제어하는 데 도움을 줍니다. 컴파일된 프로그램과 달리 스크립트는 일반적으로 인터프리터 방식으로 동작합니다. 즉, 사전 컴파일 없이 런타임 환경에서 바로 실행됩니다.

스크립트는 반복적인 작업을 자동화하고 워크플로우를 관리하며, 작은 문제부터 때로는 큰 문제까지 효율적으로 해결할 수 있는 강력한 도구입니다. 초보자든 숙련된 개발자든 스크립트 작성법을 익히면 생산성을 높이고 기술적 역량을 넓힐 수 있습니다.

왜 스크립트를 작성해야 할까?

스크립트로 할 수 있는 일은 이미 살펴봤습니다. 이제 스크립트가 왜 강력한 도구인지, 그리고 언제 사용해야 하는지 이해할 수 있도록 장점과 한계를 함께 알아보겠습니다.

스크립트의 장점

  1. 자동화: 데이터 처리나 파일 관리 같은 반복 작업을 간소화할 수 있습니다.

  2. 효율성: 수작업으로 처리해야 했던 작업을 자동화해 시간을 절약할 수 있습니다.

  3. 오류 감소: 명령어를 일관되게 실행함으로써 사람이 저지르는 실수를 줄일 수 있습니다.

  4. 유연성: 최소한의 수정만으로 다양한 작업에 적용할 수 있습니다.

  5. 통합성: 다른 시스템, 도구, 워크플로우와 매끄럽게 연동할 수 있습니다.

스크립트의 한계

  1. 성능: 인터프리터 오버헤드 때문에 컴파일된 프로그램보다 느릴 수 있습니다.

  2. 확장성: 대규모 또는 고도로 복잡한 작업에는 항상 적합하지 않습니다.

  3. 디버깅: 동적인 특성 때문에 디버깅이 까다로울 때가 있습니다.

  4. 보안 위험: 잘못 작성된 스크립트는 취약점을 노출시킬 수 있으며, 특히 시스템 수준 명령을 실행할 때 위험합니다.

스크립트를 사용해야 할 때와 피해야 할 때

스크립트가 적합한 경우:

  1. 작업이 단순하고 명확하게 정의되어 있거나 일회성일 때

  2. 프로토타이핑 또는 빠른 프로세스 자동화가 필요할 때

  3. 범위가 작아 복잡성을 피할 수 있을 때

스크립트가 부적합한 경우:

  1. 높은 효율이 요구되는 성능 중심 작업. 대신 전용 ETL(Extract, Transform, Load) 도구, 메시지 브로커 등 사용 사례에 맞는 대안 도구를 활용하세요.

  2. 광범위한 사용자 인터페이스가 필요한 애플리케이션. 대신 로깅, 테스트, 문서화를 갖춘 작은 애플리케이션이나 모듈형 시스템을 구축하세요.

  3. 장기 유지보수가 필요한 시나리오. 이 경우 컴파일된 프로그램이 더 안정적일 수 있습니다. 대신 CRON, Airflow, AWS Lambda/GCP Functions 같은 작업 스케줄러나 워크플로우 관리 도구를 사용하세요.

효과적인 스크립트 작성 방법

다음은 제가 유용한 스크립트를 작성할 때 사용하는 과정입니다. 이 과정을 살펴본 후, 여러 언어로 된 스크립트 예제를 통해 직접 연습해 보겠습니다.

  1. 문제 정의: 스크립트를 작성하기 전에 해결하려는 문제를 파악하세요. 자동화할 작업과 기대 결과를 명확히 해야 합니다.

  2. 적합한 언어 선택:

    • Bash: 파일 조작, 서버 관리 같은 시스템 수준 작업에 적합합니다.

    • Python: 데이터 처리, 웹 스크래핑, 더 복잡한 자동화에 유용합니다.

    • JavaScript: 웹 개발 및 브라우저 기반 자동화에 적합합니다.

  3. 스크립트 작성: 텍스트 에디터나 통합 개발 환경(IDE)을 사용하고, 주석 작성, 의미 있는 변수명 사용, 모듈화된 코드 같은 모범 사례를 지키세요. 아래에서 자세히 다룹니다.

  4. 스크립트 테스트: 통제된 환경에서 스크립트를 테스트하여 오류 없이 의도대로 동작하는지 확인하세요.

  5. 실행 및 배포: 실제 환경에서 스크립트를 실행합니다. 필요하다면 Cron(Bash용)이나 작업 스케줄러 같은 도구로 실행 일정을 잡으세요.

실전 예제 스크립트

기본기를 익혔으니 이제 직접 연습해 보겠습니다. "book-part-1.pdf", "book-part-2.pdf", ..., "book-part-100.pdf"처럼 이름 붙은 파일이 약 100개 있다고 가정해 봅시다. 파일을 업로드하려는 웹사이트에서 하이픈(-)이 포함된 파일명을 허용하지 않기 때문에, 모든 하이픈을 밑줄(_)로 바꾸고 싶습니다.

아래는 동일한 작업을 수행하는 세 가지 언어로 작성된 스크립트입니다. 과정은 다음과 같습니다.

  1. 디렉터리 내 모든 파일을 찾고,

  2. 파일명에 하이픈(-)이 포함되어 있는지 확인한 뒤,

  3. 하이픈을 밑줄(_)로 교체합니다.

시작 상태의 파일명(하이픈 포함)은 다음과 같습니다.

스크립트 마스터하기: 반복 작업 자동화로 생산성 극대화하는 법

Bash 스크립트

먼저 Bash 스크립트입니다.

#!/bin/bash
# Replace "-" with "_" in file names
DIRECTORY="/path/to/your/folder"
for FILE in "$DIRECTORY"/*; do
 if [[ "$FILE" == *-* ]]; then
 NEW_NAME=$(echo "$FILE" | sed 's/-/_/g')
 mv "$FILE" "$NEW_NAME"
 echo "Renamed: $FILE -> $NEW_NAME"
 fi
done

상단에 파일이 위치한 디렉터리(폴더) 경로를 정의합니다. 디렉터리의 각 파일에 대해 이름에 -가 포함되어 있는지 검사합니다. 포함되어 있다면, echo 명령어로 기존 파일명을 가져온 후 sed 명령어로 -_로 치환하여 새 파일명을 만들고 변수 NEW_NAME에 저장합니다. 마지막으로 이동 명령어 mv에 기존 파일명과 새 파일명을 인수로 전달해 이름을 변경합니다.

Python 스크립트

다음은 Python 버전입니다.

import os
# Replace "-" with "_" in file names
directory = "/path/to/your/folder"
for filename in os.listdir(directory):
 if "-" in filename:
 old_path = os.path.join(directory, filename)
 new_filename = filename.replace("-", "_")
 new_path = os.path.join(directory, new_filename)
 os.rename(old_path, new_path)
 print(f"Renamed: {filename} -> {new_filename}")

Python에서도 단계는 거의 비슷합니다. 먼저 디렉터리를 정의하고, 디렉터리 내 각 파일을 순회합니다. 디렉터리의 모든 파일을 가져오려면 os 패키지의 listdir 메서드를 사용해야 합니다.

그다음 줄에서 파일명에 -가 포함되어 있는지 확인합니다. 포함되어 있다면 디렉터리 경로와 파일명을 결합해 현재 파일 경로(old_path)를 구합니다. replace 메서드로 -_로 바꿔 새 파일명을 만들 수 있습니다.

이후 old_path를 만든 것과 같은 방식으로 새 파일 경로(new_path)를 생성합니다. 마지막으로 os 패키지의 rename 메서드에 기존 경로와 새 경로를 인수로 전달해 호출합니다.

JavaScript 스크립트

이번에는 JavaScript 버전을 살펴보겠습니다.

const fs = require('fs');
const path = require('path');
const directory = '/path/to/your/folder';
fs.readdir(directory, (err, files) => {
 if (err) {
 console.error('Error reading directory:', err);
 return;
 }
 files.forEach(file => {
 if (file.includes('-')) {
 const oldPath = path.join(directory, file);
 const newFilename = file.replace(/-/g, '_');
 const newPath = path.join(directory, newFilename);
 fs.rename(oldPath, newPath, err => {
 if (err) {
 console.error(`Error renaming ${file}:`, err);
 } else {
 console.log(`Renamed: ${file} -> ${newFilename}`);
 }
 });
 }
 });
});

JavaScript 구현은 Python과 다소 비슷하지만 더 많은 코드를 작성해야 합니다. 일반적으로 개발자들은 이런 종류의 스크립트에 JavaScript를 선호하지 않고 대부분 Bash나 Python을 사용합니다. JavaScript는 브라우저 기반 자동화 스크립트에 더 적합합니다.

그래도 코드를 살펴보겠습니다. 이 JavaScript 코드에서는 fspath, 두 개의 패키지를 사용합니다. 상단에서 디렉터리를 정의하고, fs 패키지의 readdir 메서드에 디렉터리를 인수로 전달해 디렉터리 내 파일들을 읽습니다. 디렉터리와 함께 파일을 다 읽었을 때 실행될 콜백 함수도 전달합니다.

콜백 함수 안에서는 각 파일을 순회하며 파일명에 하이픈(-)이 포함되어 있는지 확인합니다. 포함되어 있다면 path 패키지에 디렉터리와 파일명을 인수로 전달해 기존 경로를 구합니다. 이어서 replace 메서드로 모든 하이픈을 밑줄로 바꿔 새 파일명을 만듭니다.

기존 경로와 마찬가지 방식으로 새 파일명을 인수로 사용해 새 경로를 구합니다. 그런 다음 fs 패키지의 rename 메서드에 기존 파일명과 새 파일명을 모두 전달해 파일 이름을 변경합니다. 이름 변경이나 디렉터리 읽기 중 오류가 발생하면 오류 메시지를 출력하고, 그렇지 않으면 성공 메시지를 출력합니다.

스크립트 실행 방법

자, 이제 이 스크립트들을 실제로 사용하는 방법입니다.

  1. /path/to/your/folder를 파일이 실제로 있는 디렉터리 경로로 바꾸세요.

  2. 해당 환경에서 스크립트를 실행하세요.

    • Bash: .sh 파일로 저장한 뒤 bash script.sh로 실행

    • Python: .py 파일로 저장한 뒤 python script.py로 실행

    • JavaScript: .js 파일로 저장한 뒤 node script.js로 실행

아래 스크린샷은 Bash 스크립트를 실행해 파일명을 변경하는 모습입니다.

스크립트 마스터하기: 반복 작업 자동화로 생산성 극대화하는 법

스크립트 마스터하기: 반복 작업 자동화로 생산성 극대화하는 법

주기적으로 실행되는 스크립트

주기적 스크립트는 시스템 상태를 매주 점검하거나, 로그를 정리하거나, 데이터 업데이트를 가져오는 것처럼 정해진 간격으로 실행되도록 설계된 스크립트입니다. 이러한 스크립트는 보통 어떤 형태로든 작업 스케줄러를 사용합니다.

일반적인 접근 방식

  1. CRON 작업: 대부분의 운영체제가 CRON을 지원하며, 정의된 일정에 따라 스크립트를 실행할 수 있습니다.

  2. 작업 큐(Task Queue): Celery(Python), Bull(Node.js), Sidekiq(Ruby) 같은 도구를 사용하면 더 유연하게 예약 작업을 처리할 수 있습니다.

  3. 클라우드 스케줄러: AWS Lambda + EventBridge, Google Cloud Scheduler, Azure Logic Apps 같은 서비스를 통해 서버리스 아키텍처에서 주기적 스크립트를 설정할 수 있습니다.

주기적 스크립트의 좋은 활용 사례로는 시스템의 사용량/성능에 대한 일간 또는 주간 리포트 전송을 들 수 있습니다. 제품에 가입하고 구독한 사용자 수를 집계하는 스크립트를 작성해 매일 또는 매주 이메일로 리포트를 보내도록 할 수 있습니다.

스크립트 작성 모범 사례

스크립트를 작성할 때 기억해야 할 사항들입니다.

1. 주석 활용: 스크립트의 복잡한 부분은 주석으로 설명하세요.

아래 예제에서 주석이 없다면 세율이 왜 백분율이 아니라 소수로 표현되는지 파악하는 데 추가 시간이 걸릴 수 있습니다.

# Calculate the total price with tax
def calculate_price_with_tax(price, tax_rate):
 # Tax rate is expressed as a decimal (e.g., 0.07 for 7%)
 return price + (price * tax_rate)

2. 오류 처리: 발생 가능한 오류를 고려하고 우아하게 처리하세요.

아래 예제에서는 파일이 없어도 스크립트가 크래시되지 않고, 대신 유용한 오류 메시지를 표시합니다.

try:
 with open('data.csv', 'r') as file:
 data = file.readlines()
except FileNotFoundError:
 print("Error: 'data.csv' file not found. Make sure the file exists before running the script.")
except Exception as e:
 print(f"An unexpected error occurred: {e}")

3. 모듈화 설계: 스크립트를 재사용 가능한 함수나 모듈로 나누세요.

아래 예제처럼 기능을 작고 재사용 가능한 함수로 분리하면 스크립트의 일부를 독립적으로 디버깅하거나 재사용할 수 있습니다.

def fetch_data_from_api(api_url):
 # Fetch data from the given API
 pass
def process_data(data):
 # Process the data into the desired format
 pass
def save_to_file(data, filename):
 # Save processed data to a file
 pass
# Main script
if __name__ == "__main__":
 data = fetch_data_from_api("https://example.com/api")
 processed_data = process_data(data)
 save_to_file(processed_data, "output.json")

4. 입력값 검증: 예상치 못한 오류나 보안 위험을 막기 위해 사용자 입력을 검증하세요.

검증이 없으면 유효하지 않거나 악의적인 데이터(특정 상황에서는 SQL 인젝션 문자열 등)가 입력될 수 있습니다.

import re
# Validate that the input is a valid email address
def validate_email(email):
 pattern = r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
 if not re.match(pattern, email):
 raise ValueError("Invalid email address format")
 return email
# Example usage
try:
 user_email = validate_email(input("Enter your email: "))
 print(f"Valid email: {user_email}")
except ValueError as e:
 print(e)

5. 버전 관리: Git 등 버전 관리 도구로 변경 사항을 추적하세요.

변경으로 인해 스크립트가 깨졌다면 git checkout으로 이전 커밋으로 손쉽게 되돌릴 수 있습니다. 게다가 팀원들과도 원활하게 협업할 수 있습니다.

git init
git add script.py
git commit -m "Initial commit"

결론

스크립트 작성은 생산성과 문제 해결 능력을 크게 끌어올릴 수 있는 기술입니다. Bash, Python, JavaScript 같은 스크립팅 언어의 기본기를 익히면 작업을 자동화하고 워크플로우를 간소화하며 소중한 시간을 절약할 수 있습니다. 작게 시작하고, 조금씩 확장하며, 다양한 사용 사례에 맞춰 스크립트를 작성해 보며 이 귀중한 기술을 마스터해 보세요.

여러분에게 과제 하나를 드리겠습니다. 이 예제 스크립트를 실행하고 검증하려면 100개의 파일을 직접 만들어야 한다고 생각할 수 있습니다. 하지만 그건 많은 시간이 걸립니다.

저는 그 100개의 파일을 생성하는 스크립트를 작성했습니다. 여러분도 파일명에 하이픈이 들어간 파일 100개를 생성하는 스크립트를 직접 작성해 보길 권합니다. 그다음 예제 스크립트를 실행해서 하이픈을 밑줄로 변환해 보세요.

처음에는 어려워 보일 수 있지만, 믿어주세요. 파일 100개를 생성하는 데 단 5줄의 Bash 코드면 충분합니다. 100개뿐만 아니라 5줄의 코드로 백만 개, 십억 개, 조 단위의 파일까지도 생성할 수 있습니다.

스크립트에 대해 더 배우고 싶다면 제 이메일 뉴스레터(https://5minslearn.gogosoon.com/)를 구독하고 SNS에서 저를 팔로우해 주세요.

즐거운 스크립팅 되세요!