ERP1TEAM / ERP

0 stars 0 forks source link

트러블슈팅 #16

Open Donggeon0304 opened 1 week ago

Donggeon0304 commented 1 week ago

1. 문제 정의 (Problem Definition)

2. 원인 분석 (Root Cause Analysis)

3. 해결 방안 (Solution)

  1. 클라이언트 측에서 FormData.set("create_date", null)로 필드를 명시적으로 설정하여 전송.
  2. 서버 측에서 create_date 필드가 null인 경우 기본값을 적용하도록 로직을 수정.

4. 결과 (Result)

5. 교훈 및 향후 대책 (Lessons Learned and Future Prevention)

airmungs commented 1 week ago

1. 문제 정의 (Problem Definition)

문제: Spring Boot 애플리케이션에서 JWT 토큰을 쿠키에 저장한 후, 각 사용자의 역할(Role)에 따라 페이지를 리디렉션하는 과정에서 클라이언트가 JWT 토큰을 읽지 못해 리디렉션이 실패하는 문제가 발생. 증상: 로그인이 성공했음에도 불구하고 사용자가 계속해서 로그인 페이지에 머물렀고, 권한에 따른 페이지로 리디렉션되지 않음. 발생 조건: JWT 토큰을 쿠키에 HttpOnly 속성으로 저장하여 클라이언트에서 접근할 수 없었을 때 발생.

2. 원인 분석 (Root Cause Analysis)

원인: HttpOnly 속성으로 인해 클라이언트 측에서 JWT 토큰을 읽을 수 없었음. 이로 인해 사용자의 역할(Role)을 판별하지 못하고, 적절한 권한에 따른 페이지 리디렉션이 불가능했음.

HttpOnly 속성은 보안을 강화하기 위해 클라이언트 측에서 쿠키에 직접 접근할 수 없도록 하는 속성으로, XSS 공격 등을 방지하기 위한 보안 설정임. 로그인 후 JWT 토큰은 서버 측에서 인증을 위해 필요하지만, 클라이언트는 이를 읽을 수 없기 때문에 페이지 리디렉션 로직에서 문제가 발생.

3. 해결 방안 (Solution)

서버 측에서 JWT 토큰을 읽고 권한을 판별: 클라이언트에서 JWT 토큰을 사용할 수 없으므로, 서버에서 HttpServletRequest 객체를 사용해 쿠키에 저장된 JWT 토큰을 읽는 메서드를 구현. 서버가 토큰을 분석하여 사용자의 권한(Role)을 파악하고, 해당 권한에 맞는 페이지로 리디렉션을 처리하도록 로직 수정. Security Filter Chain에서의 권한 설정: Security Filter Chain에서 인증된 사용자의 역할을 확인하고, 해당 역할에 따라 요청을 필터링하여 적절한 페이지로 리디렉션되도록 설정. 클라이언트와 서버 간의 인증 흐름 재구성: JWT 토큰을 HttpOnly 쿠키에 저장하되, 클라이언트는 서버와의 요청에서만 JWT를 사용하고, 권한에 따른 리디렉션 처리는 서버가 담당하는 방식으로 개선.

4. 결과 (Result)

서버가 HttpOnly JWT 토큰을 사용하여 사용자의 권한을 판별하고, 각 사용자에 맞는 페이지로 리디렉션하는 기능이 정상적으로 작동하게 됨. 이후 JWT 토큰 기반의 인증과 페이지 리디렉션이 안정적으로 구현되어, 로그인 후 각 권한(Role)에 따라 사용자가 올바른 페이지에 접근할 수 있게 됨.

5. 교훈 및 향후 대책 (Lessons Learned and Future Prevention)

교훈: 보안상의 이유로 JWT 토큰을 HttpOnly 쿠키에 저장하는 경우, 클라이언트가 토큰을 읽어 사용하지 못하므로 서버 측에서 이를 처리하는 로직이 필수적임. 향후 대책: HttpOnly 속성의 활용 시, 서버가 인증 및 권한 관리를 철저하게 처리하도록 하고, 클라이언트 측에서 JWT를 직접적으로 다루지 않도록 보안을 강화. 권한에 따른 페이지 리디렉션뿐만 아니라, 향후 인증 관련 로직을 재사용할 수 있도록 서비스 구조를 모듈화하는 것을 고려. 이 과정에서 JWT와 Spring Security의 통합적인 활용 방법과 보안성을 유지하면서도 사용자 경험을 향상시킬 수 있는 설계 방법에 대해 더 깊이 이해하게 되었음.

Donggeon0304 commented 1 week ago

트러블슈팅 문서

1. 문제 정의 (Problem Definition)

문제 1: 배포된 스프링 부트 JAR 애플리케이션에서 Thymeleaf 템플릿 경로로 지정된 HTML 파일을 찾지 못함. 문제 2: 정식 배포 전 테스트 환경에서 JWT 토큰이 생성되지 않음.

2. 원인 분석 (Root Cause Analysis)

문제 1: Thymeleaf 경로 문제

HTML 파일을 찾는 경로가 /로 시작할 경우, 상대 경로가 아닌 절대 경로로 해석되어 서버의 루트 디렉토리를 참조하게 됨. 이로 인해 애플리케이션의 컨텍스트 경로가 포함되지 않아 템플릿을 찾지 못하는 문제가 발생. 문제 2: JWT 토큰 생성 문제

개발기간 중 테스트를 위한 배포 중 JWT 토큰을 설정할 때 setSecure(true)로 되어 있어, HTTPS 연결에서만 쿠키가 전송됨. 로컬 개발 환경에서는 HTTP로 요청하므로, 토큰이 발급되지 않는 문제가 발생.

3. 해결 방안 (Solution)

문제 1: Thymeleaf 경로 수정

HTML 경로에서 /로 시작하는 부분을 제거하여 상대 경로로 변경:

변경 전: return "views/home"; // /views/home.html 변경 후: return "home"; // views/home.html Thymeleaf의 기본 템플릿 경로를 설정하여 모든 경로에서 HTML 파일을 올바르게 참조하도록 조정.

문제 2: JWT 토큰 생성 설정 수정

JWT 생성 로직에서 boolean isSecure = requet.isSecure(); cookie.setSecure(isSecure)을 추가:

변경 전: cookie.setSecure(true); // HTTPS에서만 쿠키 전송 변경 후: boolean isSecure = request.isSecure(); cookie.setSecure(isSecure); // HTTP이면 false, HTTPS이면 true 이후 보안을 위해 프로덕션 환경에서는 HTTPS를 사용하는 것이 권장됨.

4. 결과 (Result)

문제 1: HTML 경로를 수정한 후, 서버에서 Thymeleaf 템플릿을 정상적으로 찾을 수 있게 되어 페이지가 올바르게 렌더링됨. 문제 2: JWT 토큰 생성 설정을 수정한 후, HTTP 요청에서도 쿠키가 정상적으로 발급되어 인증이 가능해짐.

5. 교훈 및 향후 대책 (Lessons Learned and Future Prevention)

경로 설정 시, 절대 경로와 상대 경로의 차이를 인지하고, 운영 환경에 맞게 적절히 설정하는 것이 중요함. JWT 토큰을 설정할 때는 개발 환경과 프로덕션 환경의 차이를 고려하여, 적절한 보안 설정을 미리 계획해야 함. HTTPS로 전환할 경우, 웹 서버 및 애플리케이션 설정을 점검하여 보안 설정을 적절히 구성하는 것을 잊지 말 것.

hajoo29 commented 1 week ago
  1. 문제 정의 (Problem Definition) 문제: 출고 준비를 위해 상품에 선입고 순으로 Lot Number를 할당하기 위한 재귀 함수를 작성하는 과정에서 로직 오류가 발생함. 증상: 해당 Lot Number를 가진 상품의 재고가 0개인 경우에도 재고할당으로 간주하여 데이터베이스에 해당 데이터가 저장됨. 재고 오류로 인해 Lot Number에 해당하는 상품의 재고가 음수값 일 때, 음수 값을 유효한 수량으로 할당하는 문제가 발생함.

  2. 원인 분석 (Root Cause Analysis) 원인: 데이터베이스에서 가져온 Lot 수량이 0인 경우를 체크하지 않고, 선입고 순으로 존재하는 Lot Number를 무조건 유효한 Lot Number로 간주하여 할당 처리하였고 이로 인해 할당을 위한 남아있는 상품 수량이 0개 이하인 경우에도 조건문이 작동하게 되어, 음수로 설정된 수량에 대해서도 Lot Number를 할당하는 로직이 실행되게 되었음.

  3. 해결 방안 (Solution) 데이터가 존재하는 Lot Number 에 대해 발동되는 재귀함수의 return 자료형을 Lot Number를 할당한 데이터들의 리스트인 List로 부여하지 않고, boolean 자료형으로 부여하여 Lot Number의 재고가 0개 이하인 경우 데이터를 할당하지 않고 다음재귀를 호출함, 유효한 재고가 할당될경우 현재 재귀를 종료하며 데이터 저장을 위한 List는 다음 재귀함수 호출시 파라미터 데이터로 넘김. 재고가 모두 할당되었을경우 return true 하여 재귀함수를 종료함. 재고 할당에 실패하였을경우 return false 하여 true 값이 리턴하였을경우 할당된 데이터들의 리스트인 List를 JPA repository를 통해 데이터베이스에 저장함

  4. 결과 (Result) Lot Number 에 해당하는 재고가 0개이거나 음수값일 경우 할당으로 처리하지 않고 다음 재귀를 호출함

  5. 교훈 및 향후 대책 (Lessons Learned and Future Prevention) 데이터베이스에서 가져온 값의 유효성을 항상 검증해야하는 것이 중요하고 입력값이 예상 범위에서 벗어났을 경우를 생각해야함. 재귀함수 설계시 종료조건을 명확히 하여 잘못된 데이터 처리로 이어지지 않도록 유의하도록 함. 재귀함수 설계시 boolean 변수를 활용하여 오류를 감지하고 대응할 수 있도록 함 다양한 데이터를 입력을 통해 로직의 유효성을 여러번 검토해보는 노력이 필요함.

5ore5o commented 1 week ago
  1. 문제 정의 (Problem Definition) 문제: 재고 테이블에 시간 데이터가 없어서 일일 재고 내역 테이블을 만들지 못함. 이를 해결하기 위해 새로운 재고 로그 테이블을 생성하고, 재고 테이블이 변경될 때 재고 로그 테이블도 함께 업데이트되도록 트리거를 사용했으나, 재고 물량 변화가 당일의 변동만 반영되지 않고 전체 재고 수량으로 잘못 계산됨. 증상: 재고 수량이 증가하거나 감소할 때, 당일 발생한 변동만 기록되어야 하는데, 전체 재고 물량을 기준으로 계산되어 로그에 잘못된 수치가 저장됨. 발생 조건: 재고 테이블의 값이 변경될 때마다 트리거가 실행되어 재고 로그 테이블을 업데이트하지만, 트리거의 로직이 잘못되어 일일 변동이 아닌 전체 재고량이 반영됨.
  2. 원인 분석 (Root Cause Analysis) 원인: 재고 로그 테이블을 생성하면서 트리거 로직이 전체 재고 물량을 기반으로 변동 값을 기록하게 설정됨. 일일 변동 수량을 계산하지 않고 재고 테이블의 총 재고 수량을 바로 기록하여 잘못된 값이 로그 테이블에 저장됨. 트리거 로직의 문제: 트리거가 실행될 때마다 재고 테이블의 총 수량을 참조하는 방식으로 설계되어 있었기 때문에, 해당 날짜의 재고 변동만 기록해야 하는 로그 테이블에서 잘못된 값이 발생함. 시간 필드의 누락: 처음 재고 테이블을 설계할 때 시간 정보가 포함되지 않았고, 이를 수정하는 대신 새로운 재고 로그 테이블을 만들어서 문제를 해결하고자 했음.
  3. 해결 방안 (Solution) 트리거 로직 수정: 재고 테이블과 새로운 재고 로그 테이블 간의 트리거 로직을 조원들과 함께 검토하여 수정. 재고 테이블에서 발생한 일일 변동만 로그 테이블에 반영될 수 있도록 로직을 재설계함. 기존 전체 재고량을 기록하던 방식에서 벗어나, 당일 발생한 변동 값만 계산하여 로그 테이블에 기록하도록 트리거를 수정함. 재고 변경 시점 기준 처리: 재고 테이블에서 변동이 있을 때마다, 이전 재고 수량과의 차이를 계산해 로그 테이블에 반영하는 방식으로 처리. 새로운 테이블 생성: 기존 재고 테이블을 수정할 수 없는 상황이었으므로, 새로운 재고 로그 테이블을 생성하여 시간 정보를 관리하고, 트리거를 통해 데이터를 기록함.
  4. 결과 (Result) 문제 해결 후, 재고 테이블에서 발생한 일일 변동이 정확하게 재고 로그 테이블에 반영되기 시작함. 트리거 로직을 수정한 후, 전체 재고량 대신 당일 발생한 재고 변동만 기록되어 데이터의 정확성이 확보됨. 새로운 로그 테이블을 생성해 시간 정보와 함께 일일 변동을 기록하는 방식으로 문제를 해결함.
  5. 교훈 및 향후 대책 (Lessons Learned and Future Prevention) 정확한 트리거 로직 설계 필요성: 트리거를 설정할 때, 전체 수량이 아닌 일일 변동 수량을 정확하게 반영할 수 있는 로직을 설계하는 것이 중요함을 배움. 시간 정보의 중요성: 재고 변동 내역을 관리할 때, 시간을 기준으로 데이터를 추적하는 것이 필수적임. 초기 테이블 설계 단계에서 시간을 포함한 필드를 고려해야 함. 협업의 중요성: 팀원들과 함께 문제를 분석하고 해결책을 도출하는 과정에서 문제를 더 빠르게 해결할 수 있었으며, 협업을 통해 다양한 시각에서 문제를 분석하는 것이 중요하다는 것을 깨달음. 새로운 테이블을 통한 문제 해결: 기존 테이블을 수정할 수 없는 상황에서는 새로운 테이블을 생성하여 문제를 해결할 수 있는 방법을 적극적으로 고려해야 함.