개발 트러블슈팅 완전 정복 | 웹개발·백엔드·데브옵스 실무 에러 해결법. Docker, GitHub Actions, TypeScript, MySQL, Redis 등 실전 경험 기반의 개발 블로그
금요일
월요일
Redis 연결 에러 완전 정복: ECONNREFUSED 127.0.0.1:6379 트러블슈팅
Redis 붙이다가 처음 보는 에러 아니다. 누구나 한 번쯤은 밟는다.
Error: connect ECONNREFUSED 127.0.0.1:6379
이거 뜨면 일단 당황하지 말고 순서대로 확인하면 금방 해결된다. 원인은 대부분 세 가지 중 하나다.
에러가 뜨는 주요 상황
| 상황 | 에러 메시지 |
|---|---|
| Node.js (ioredis) | [ioredis] Unhandled error event: Error: connect ECONNREFUSED 127.0.0.1:6379 |
| Node.js (node-redis) | Error: Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED |
| Spring Boot | Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException |
| Python (redis-py) | redis.exceptions.ConnectionError: Error 111 connecting to localhost:6379. |
| Docker 컨테이너 간 | connect ECONNREFUSED 127.0.0.1:6379 (컨테이너 내부에서 호스트 Redis 접근 시도) |
레벨 1: 입문자 — Redis가 켜져 있나요?
가장 흔한 원인. Redis 서버가 꺼져 있으면 당연히 붙을 수 없다.
Redis 실행 상태 확인
# 프로세스 확인
ps aux | grep redis-server
# 포트 리스닝 확인
ss -tlnp | grep 6379
# systemd 기반 (Ubuntu/CentOS)
sudo systemctl status redis
Redis 직접 연결 테스트
redis-cli ping
# 정상이면: PONG
# 실패하면: Could not connect to Redis at 127.0.0.1:6379: Connection refused
Redis 실행 방법
# systemd로 시작
sudo systemctl start redis
sudo systemctl enable redis # 부팅 시 자동 시작
# 백그라운드 실행
redis-server --daemonize yes
레벨 2: 실무자 — 포트/바인딩/방화벽 확인
Redis는 켜져 있는데 연결이 안 되면 이쪽을 본다.
bind 설정 문제
/etc/redis/redis.conf 기본 설정:
# 기본값: 127.0.0.1만 허용 (로컬호스트 전용)
bind 127.0.0.1
# 외부 접속 허용하려면 (주의: 보안 설정 필수)
bind 0.0.0.0
# 변경 후 재시작
sudo systemctl restart redis
방화벽 확인
# UFW (Ubuntu)
sudo ufw status
sudo ufw allow 6379
# 외부에서 포트 테스트
nc -zv <서버IP> 6379
requirepass 설정 시 인증 필요
redis-cli -a yourpassword ping
# 또는 연결 후 AUTH
redis-cli
> AUTH yourpassword
> PING
레벨 3: 고급 — Docker, Kubernetes 환경
이게 제일 헷갈린다. 컨테이너 안에서 127.0.0.1:6379는 컨테이너 자신을 가리킨다.
Docker Compose로 Redis 연결
# docker-compose.yml
version: '3.8'
services:
app:
build: .
environment:
- REDIS_HOST=redis # 127.0.0.1이 아니라 서비스명!
- REDIS_PORT=6379
depends_on:
- redis
redis:
image: redis:7-alpine
ports:
- "6379:6379"
// Node.js - 잘못된 예
const redis = new Redis({ host: '127.0.0.1', port: 6379 });
// 올바른 예
const redis = new Redis({
host: process.env.REDIS_HOST || 'redis',
port: parseInt(process.env.REDIS_PORT || '6379'),
});
호스트 머신의 Redis에 접근하는 경우
services:
app:
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
- REDIS_HOST=host.docker.internal
언어별 연결 코드 및 에러 핸들링
Node.js — ioredis
const Redis = require('ioredis');
const redis = new Redis({
host: process.env.REDIS_HOST || '127.0.0.1',
port: parseInt(process.env.REDIS_PORT || '6379'),
password: process.env.REDIS_PASSWORD || undefined,
retryStrategy(times) {
return Math.min(times * 50, 2000);
},
maxRetriesPerRequest: 3,
});
redis.on('error', (err) => console.error('Redis 연결 에러:', err.message));
redis.on('connect', () => console.log('Redis 연결 성공'));
Python — redis-py
import redis, os
r = redis.Redis(
host=os.getenv('REDIS_HOST', '127.0.0.1'),
port=int(os.getenv('REDIS_PORT', 6379)),
password=os.getenv('REDIS_PASSWORD'),
decode_responses=True,
socket_connect_timeout=5,
retry_on_timeout=True,
)
try:
r.ping()
print("Redis 연결 성공")
except redis.exceptions.ConnectionError as e:
print(f"Redis 연결 실패: {e}")
Spring Boot — application.yml
spring:
data:
redis:
host: ${REDIS_HOST:localhost}
port: ${REDIS_PORT:6379}
password: ${REDIS_PASSWORD:}
timeout: 5000ms
lettuce:
pool:
max-active: 10
max-idle: 10
min-idle: 2
원인별 체크리스트
| 체크 항목 | 확인 방법 | 조치 |
|---|---|---|
| Redis 서버 실행 중? | ps aux | grep redis | systemctl start redis |
| 포트 리스닝 중? | ss -tlnp | grep 6379 | 포트 충돌 확인 |
| bind 설정 맞음? | redis.conf 확인 | bind 0.0.0.0 |
| 방화벽 열려 있음? | ufw status | 포트 허용 |
| Docker 환경? | 컨테이너 여부 확인 | 서비스명으로 host 변경 |
| 인증 필요? | requirepass 설정 확인 | password 파라미터 추가 |
| TLS 사용 중? | Redis 6.0+ 설정 확인 | tls:// 스킴 및 인증서 설정 |
| 원격 서버? | 네트워크 경로 확인 | VPN, 보안그룹 확인 |
자주 하는 실수 TOP 3
1. Docker에서 localhost 씀
컨테이너 안에서 localhost는 컨테이너 자신이다. 다른 컨테이너의 Redis에 붙으려면 서비스명을 써야 한다.
2. 환경변수 안 쓰고 하드코딩
로컬에서 127.0.0.1로 하드코딩해두고 스테이징/프로덕션에 그대로 올리면 터진다. 처음부터 환경변수로 빼두자.
3. Redis 안 뜨고 앱부터 뜸
depends_on은 컨테이너 시작 순서만 보장하지 Redis 준비를 보장하지 않는다. healthcheck를 써야 한다.
redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
app:
depends_on:
redis:
condition: service_healthy
마무리
Redis 연결 에러의 90%는 위 체크리스트로 해결된다. 나머지 10%는 TLS, 클러스터 모드, Sentinel 설정 같은 고급 주제인데 그건 따로 다루겠다.
에러 메시지를 봤을 때 "Redis가 켜져 있냐 → 주소/포트가 맞냐 → 네트워크가 열려 있냐" 이 순서로만 확인해도 대부분 잡힌다.