친구만 볼 수 있는 사진을 CSS로 흐리게 처리하면 주소를 열었을 때 원본이 그대로 나옴. 원본 주소를 아예 보내지 않게 바꾸고, 사진이 열리는 조건을 "수락" 하나로 좁힌 기록.
CSS 흐림 처리의 문제
Mbtigram 프로필에는 대표 사진 말고 사진첩이 따로 있음. 사진첩은 친구에게만 보여 주고, 친구가 아닌 사람에게는 흐릿한 미리보기만 보여 주기로 했음.
가장 쉬운 방법은 원본 사진을 내려보내고 CSS로 filter: blur()를 거는 것. 화면에서는
흐리게 보이지만 브라우저는 이미 원본을 받아 둔 상태임. 개발자 도구를 열거나 이미지 주소를
복사해 새 탭에서 열면 원본이 그대로 나옴.
게다가 업로드한 이미지는 웹 서버(nginx)가 /media/ 아래에서 바로 내보냄. 앱 서버를 거치지
않으니 누가 요청하는지 확인할 방법도 없음. 주소만 알면 누구나 받을 수 있음.
원본 주소를 보내지 않게 변경
그래서 응답 단계에서 막기로 했음. 사진마다 아주 작게 줄인 미리보기를 따로 둠. 친구가 아닌 사람이 사진첩을 열면 서버는 그 미리보기만 보내고, 원본 주소는 응답에 싣지 않음. 받은 적 없는 주소는 열 수 없음.
흐림 효과는 이제 장식임. 애초에 작게 줄인 그림이라 흐리게 하지 않아도 알아보기 어려움.
사진첩은 수락해야 열림
처음에는 친구 신청을 보내기만 해도 사진첩이 열리게 했음. 신청하려면 신청권 한 장을 써야 하니 그게 문턱이 될 거라고 생각했음.
다시 보니 문제가 있었음. 신청을 보낸 시점에는 사진 주인이 아무것도 허락하지 않은 상태임. 신청권 한 장만 있으면 누구 사진첩이든 열 수 있다는 뜻이었음. 그래서 상대가 신청을 수락해 친구가 된 뒤에만 원본이 보이게 바꿨음. 친구를 끊으면 다시 잠김.
대표 사진은 예외로 뒀음. 목록과 대화에 뜨는 아바타라 가리면 서비스가 안 돌아감.
대화 사진
1:1 대화에서 주고받는 사진은 친구 사이에서만 보낼 수 있음. 이 사진들은 /media/에 두지 않았음.
서버 안쪽 폴더에 두고, 꺼낼 때마다 서버가 그 사람이 이 대화방에 속해 있는지 다시 확인함.
응답에는 캐시하지 말라는 표시(no-store)를 붙임.
화면에 그릴 때도 <img src="주소">를 쓰지 않았음. 주소를 넣으면 그 주소를 복사해 갈 수
있기 때문. 대신 fetch로 받아서 브라우저 안에서만 유효한 blob: 주소를 만들어
그림.
캡쳐는 못 막음
화면에 보이는 건 결국 찍을 수 있음. 앱에서는 안드로이드의 FLAG_SECURE로 캡쳐를 막아서,
캡쳐하면 검게 나옴. 브라우저에는 그런 장치가 없음. 길게 눌러 저장하기와 끌어다 놓기를 막고,
보는 사람의 닉네임을 사진 위에 옅게 겹쳐 두는 정도가 할 수 있는 전부임.