필수과제 트러블슈팅

트러블슈팅 정리


1. API 응답 타입 불일치

1-1. 문제

client-api-config.yml에서 productId 타입을 stringnumber로 변경했으나,
프론트엔드에서 productId가 여전히 "1" (String)으로 전달되어 서버의 Long 타입과 불일치 발생.

1-2. 원인

shop.htmlonclick 핸들러에서 따옴표로 감싸져 있어 숫자가 문자열로 변환됨.

// ❌ 문제 코드
onclick="updateQuantity('${product.id}', 1)"  // String으로 전달

// ✅ 수정 코드
onclick="updateQuantity(${product.id}, 1)"    // Number로 전달

1-3. 해결

shop.html 3곳 수정:
1. onclick 따옴표 제거
2. updateQuantity() 함수 =====
3. updateCartSummary() 함수 =====


2. /api/users/me 500 에러

2-1. 문제

로그인은 정상이나 /api/users/me 호출 시 500 에러 발생.
Authorization: Bearer {token} 헤더는 정상적으로 전달되고 있었음.

2-2. 원인

서버 내부 로직 오류. Docker 로그 확인 필요.

2-3. 해결

# Docker 컨테이너 로그 확인
docker logs -f {스프링컨테이너명}

로그에서 Exception 스택트레이스 확인 후 원인 파악.


3. /api/users/me 직접 접근 시 403 에러

3-1. 문제

브라우저 주소창에서 직접 /api/users/me 접근 시 403 Forbidden 발생.

3-2. 원인

브라우저 주소창으로 직접 접근 시 Authorization: Bearer {token} 헤더가 전달되지 않아
Spring Security가 인가 실패 처리.

3-3. 해결

정상적인 동작. 브라우저 주소창 직접 접근이 아닌,
프론트엔드 코드에서 JWT 토큰을 헤더에 담아 API 호출해야 함.


4. 주문 생성 시 INVALID_INPUT 에러

4-1. 문제

{
  "code": "INVALID_INPUT",
  "message": "잘못된 입력값입니다.",
  "data": { "orderItems": "주문 상품은 1개 이상이어야 합니다." }
}

4-2. 원인

프론트엔드에서 items로 보내는데, 서버 DTO의 필드명은 orderItems였음.
@JsonProperty("items")로 매핑은 되어 있었으나,
실제 요청 페이로드에서 productId"1" (String)으로 전달되어
@NotEmpty 검증 실패.

4-3. 해결

shop.html onclick 따옴표 제거로 productId를 Number로 전달.

// ❌ 수정 전
onclick="updateQuantity('${product.id}', 1)"

// ✅ 수정 후
onclick="updateQuantity(${product.id}, 1)"

5. Enum → String 직렬화

5-1. 문제

응답 DTO의 상태값이 Enum 타입인데, 프론트엔드에서 String 타입으로 받아야 함.

5-2. 해결

방법 1. application.yml 전역 설정

spring:
  jackson:
    serialization:
      write-enums-using-to-string: true

방법 2. Enum 클래스에 어노테이션 추가

@JsonFormat(shape = JsonFormat.Shape.STRING)
public enum OrderStatus {
    PENDING, PAID, CANCELLED
}

6. PortOne 결제 시 "해지가맹점" 에러

6-1. 문제

결제창은 정상적으로 열리나 결제 승인 시 아래 에러 발생.

결제 승인 과정에서 문제가 발생하였습니다: 해지가맹점

6-2. 원인

AWS Parameter Store의 PORTONE_CHANNEL_KG 값이
PortOne 콘솔의 실제 활성 채널키(A3SV2)와 불일치하거나,
KG이니시스 테스트 MID(INIpayTest) 자체가 만료/제한된 상태.

6-3. 해결

  1. AWS Parameter Store → PORTONE_CHANNEL_KG 값을 A3SV2 채널키로 변경
  2. 위 조치 후에도 동일 에러 발생 시 PortOne 고객센터(채널톡) 문의
    • 문의 내용: "KG이니시스 테스트 MID INIpayTest 해지가맹점 에러 발생"

7. application-local.yml 보안 노출

7-1. 문제

application-local.yml.gitignore에 등록되어 있음에도
이전에 커밋되어 GitHub에 민감 정보(DB 비밀번호, JWT 시크릿, PortOne API 키 등)가 노출됨.

7-2. 해결

Step 1. GitHub 노출 여부 확인

git log --all --full-history -- "**/application-local.yml"

Step 2. Git 추적에서 제거

git rm --cached src/main/resources/application-local.yml
git commit -m "remove sensitive config file"

Step 3. .env 파일로 전환

// build.gradle
implementation 'me.paulschwarz:spring-dotenv:4.0.0'
# .env
PORTONE_API_SECRET=your-secret
JWT_SECRET=your-jwt-secret
# .gitignore에 추가
.env

8. 주문번호 생성 패턴

8-1. 코드

"ODN-" + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE)
       + "-" + UUID.randomUUID().toString().replace("-", "").substring(0, 10).toUpperCase()

8-2. 생성 결과 예시

ODN-20260319-A1B2C3D4E5
ODN-20260319-F6G7H8I9J0
ODN-20260319-K1L2M3N4O5

8-3. 주의사항

.replace("_", "") → UUID는 -(하이픈)를 사용하므로 사실상 효과 없는 코드.
-를 제거하려면 .replace("-", "")로 수정 필요.

0개의 댓글