아침에 ERP 매출 현황을 열었는데 전날 집계가 아직 반영되지 않았습니다. 운영 담당자가 작업 이력을 열어 보니 일일 집계 배치의 실행 시간이 평소보다 길었습니다. 같은 시간대의 MySQL 슬로우 쿼리 로그에는 매출 테이블을 읽는 SQL이 여럿 보입니다. 이 중 어떤 문장이 일일 집계에 쓰였는지 알아야 다음 점검 대상을 정할 수 있습니다. 이 글은 ERP 운영을 바탕으로 구성한 설명용 업무 장면입니다. MySQL 8.4에서 배치 실행 이력과 슬로우 쿼리 로그를 대조해, 다음에 확인할 SQL을 좁히는 순서를 다룹니다. 배치 실행 이력으로 시간 범위 좁히기 스케줄러에서 지연된 실행 건의 실제 시작·종료 시각과 재시도 이력을 먼저 확인합니다. 재시도한 경우 실행 건별로 시간 범위를 ..
출고 마감에 앞서 주문 연동 담당자가 쇼핑몰에서 들어온 주문과 사내 주문 목록을 대조합니다. 쇼핑몰에는 접수 기록이 있는데 사내 목록에 아직 나타나지 않는 건이 있습니다. 재처리 화면에서 해당 주문을 다시 보내도 저장 응답이 늦어지면, 담당자는 앞선 등록 작업이 끝났는지부터 확인해야 합니다. 이 글은 주문 연동 운영을 바탕으로 구성한 설명용 업무 장면입니다. MySQL 8.4의 InnoDB에서 기다리는 등록 요청과 잠금을 보유한 작업을 연결하는 순서로 살펴봅니다. 주문 목록에 나타나기 전의 INSERT 연동 작업이 주문 행을 넣었더라도 트랜잭션을 아직 커밋하지 않았다면, 다른 연결의 일반 조회에서 그 행이 보이지 않을 수 있습니다. 트랜잭션은 관련 DB 변경을 묶어 확정하거..
구글 검색 결과에서 회사 홈페이지의 관리자 주소가 발견됐다고 가정해 봅시다. 서버 설정을 보니 robots.txt에 이미 Disallow: /admin/이 있습니다. 이때 먼저 열어 볼 것은 설정 파일보다 관리자 URL입니다. 로그아웃 상태에서 주소를 열었을 때 로그인 화면만 뜨는지, 관리자 전용 데이터까지 내려오는지에 따라 대응 순서가 달라집니다. 공개 파일에 적힌 수집 규칙 robots.txt는 검색 엔진 크롤러처럼 웹페이지를 자동으로 읽는 프로그램에 어느 경로를 수집할지 안내하는 공개 파일입니다. 예를 들어 아래 설정은 이 규칙을 따르는 크롤러에 /admin/으로 시작하는 경로를 가져가지 말라고 요청합니다. 이 파일을 수정해도 브라우저에서 같은 주소를 직접 요청했을 때 ..
비공개 게시글에서 첨부파일 주소를 복사했다고 가정해 보겠습니다. 글을 읽을 수 있는 계정 A에서는 파일이 열립니다. 글을 읽을 수 없는 계정 B에서도 같은 주소로 파일이 내려온다면, 게시글에 적용한 권한이 다운로드까지 이어지는지 살펴야 합니다. 확인할 곳은 두 군데입니다. 웹서버가 파일을 직접 내주는 경로와 게시판 앱이 다운로드 요청을 처리하는 경로입니다.공개 URL과 파일 저장 위치웹 루트는 웹서버가 URL을 실제 파일에 연결하는 기준 디렉터리입니다. 예를 들어 /var/www/site/public 아래의 uploads가 정적 파일로 공개돼 있다면, 브라우저가 /uploads/report.pdf를 요청했을 때 게시판 앱을 거치지 않고 파일을 받을 수 있습니다. 게시글 화면에서 첨부 링크를 감춰도 이미 ..
인증서가 만료되어 교체 후 동일하게 접속했는데, 한 브라우저는 홈페이지를 띄우고 다른 브라우저는 연결 경고를 띄우는 케이스가 간혹 있습니다. 이럴 때는 정상 화면을 다시 열어 보는 것보다 두 브라우저가 받은 서버 인증서를 비교하는 편이 빠릅니다. 어느 접속 지점에 교체가 덜 됐는지, 단말마다 인증서를 검증하는 조건이 다른지 살펴볼 단서가 됩니다. 브라우저가 받은 인증서부터 비교 경고가 뜬 환경에서 주소창의 호스트명, 오류 코드, 브라우저와 운영체제 버전, 접속망을 기록합니다. 인증서 상세를 열 수 있다면 정상 환경과 경고 환경의 서버 인증서 SHA-256 핑거프린트도 비교해봅니다. 핑거프린터가 다르면 양쪽이 서로 다른 인증서를 받은 것입니다. CDN이나 로드밸런서가 ..
브라우저 A와 B에서 같은 홈페이지 관리자 계정으로 로그인해 둡니다. A에서 비밀번호를 바꾸고 B로 돌아오니, 세션이 끊어지지 않고 열어 둔 관리자 화면이 그대로 보입니다. 이 상태에서 B로 관리자 전용 기능을 한 번 더 실행해 봅니다. 서버가 새 요청에도 관리자 데이터를 보내는지 보면 기존 세션이 살아 있는지 끊어졌는지 확인할 수 있습니다. 비밀번호 변경과 세션 종료 비밀번호는 로그인할 때 계정의 소유자를 확인하는 데 쓰입니다. 로그인 뒤에는 서버가 브라우저의 쿠키 등에 담긴 세션 식별자를 통해 같은 사용자의 요청인지 알아봅니다. 이전 비밀번호로 새 로그인이 막혀도, 서버가 기존 세션을 유효하게 처리하면 이미 로그인한 브라우저는 관리자 기능을 계속 사용할 수 있습니다. 세션..
같은 게시판에 9MB짜리 파일은 올라가는데 10MB 파일은 업로드에 실패합니다. 이때 화면에 뜬 ‘첨부 실패’ 문구만으로는 어느 설정을 확인해서 수정해야될지 확인하기 어렵습니다. Nginx가 요청을 끊었을 수도 있고, PHP가 파일을 받지 못했거나 게시판이 자체 정책으로 거절했을 수도 있습니다. Nginx 뒤에서 PHP 게시판을 운영하는 구성을 예로 들어, 성공 요청과 실패 요청을 비교해 보겠습니다. 파일 크기와 요청 본문 크기 먼저 테스트 게시판에서 허용된 형식의 파일을 준비합니다. 같은 계정과 같은 업로드 경로에서 파일 한 개씩 보내고, 제목·본문 같은 입력값은 고정한 채 파일 크기만 바꿉니다. 브라우저 개발자 도구의 Network에서 첨부를 전송한 요청을 찾아 경로, 시..
같은 브라우저에서 정상적으로 로그인된것을 확인 후 새로고침을 누르자 로그인 화면으로 돌아갑니다. 웹앱이 두 대의 서버에서 각각 실행 중인 운영환경으로 보입니다. 이때는 새로고침 요청에 세션 쿠키가 실렸는지, 그리고 그 요청을 받은 서버가 세션을 찾았는지를 차례로 보면 점검 범위가 좁아집니다. 서버가 바뀌는 순간의 세션 조회 서버 측 세션을 사용하는 웹앱에서는 로그인 상태가 애플리케이션 서버의 저장소에 기록됩니다. 브라우저는 보통 쿠키로 세션 ID를 보내고, 서버는 그 ID로 로그인 상태를 조회합니다. 로그인 요청을 받은 A가 자기 메모리에만 세션을 저장했다면, 같은 ID가 B로 전달되어도 B의 메모리에는 해당 세션이 없습니다. 이때 앱은 요청을 미인증으로 처리해 로그인 화면으..
서로 다른 네트워크에서 게시판에 접속했는데, 웹앱 로그에는 두 요청 모두 loopback ip인 127.0.0.1로 남습니다. 같은 서버의 Nginx가 요청을 앱에 넘길때 127.0.0.1은 앱에 실제로 연결한 상대의 주소입니다. 접속자 IP를 따로 기록하려면 Nginx가 어떤 값을 넘겼는지, 앱이 그 값을 어떤 조건에서 읽는지 확인해야 합니다.같은 요청, 두 로그의 IP테스트 요청 한 건을 보내고 요청 시각과 경로를 기준으로 Nginx 액세스 로그와 앱 로그를 맞춰 봅니다. Nginx의 로그 형식에 $remote_addr가 들어 있고 Nginx가 외부 연결을 직접 받는다면, 이 값은 Nginx에 연결한 상대의 주소입니다. 반면 앱의 req.socket.remoteAddress는 앱과 TCP 연결을 맺은..
HTTPS 전환을 마치고 게시판을 열었는데 글 제목과 본문은 그대로이고 개발된 소스도 그대로 입니다. 이미지도 정상인데 HTTP -> HTTPS 전환 후 이미지가 display가 안되는 케이스를 운영 초보때 많이 겪었었습니다. 이런 경우 깨진 사진 한 장을 골라 게시물에 저장된 주소와 브라우저가 실제로 요청한 주소를 나란히 확인해 보십시오. 두 주소가 다르면 어느 쪽을 고쳐야 할지 범위를 좁힐 수 있습니다. 기존 게시물에 남은 HTTP 이미지 주소 게시판 페이지와 본문 이미지는 브라우저가 각각 요청합니다. 게시판을 HTTPS로 전환해도 에디터가 예전 글에 저장한 http:// 이미지 주소는 그대로 남을 수 있습니다. HTTPS 페이지에서 이처럼 보안 연결을 쓰지 않는 리소스를 불러오는 상황..