1. 어려웠던 부분: 오늘 같은 팀에서 유일하게 프론트엔드를 다룰 줄 아셔서 혼자 캐리하고 계시던 팀원분이 하차하셨다. 팀 발제되고나서 다른 팀원분들이 우리팀 폭파될거라고 했던 지난 금요일. 그 얘기 들었을 때 너무 화가 났는데 진짜 현실이 되어버렸다. 하차하시는 분과 몇시간 얘기를 나눴다. 미리 이렇게 얘기를 나누고 들어드렸더라면 하차를 막을 수 있었으려나 하는 후회가 몰려왔다. 그분의 이야기를 들어보니 부담감도 있으시고 일단 항해99 운영에 대한 불만이 이미 많으신 상태에 이런 저러한 이유로 이미 더이상 그분의 의사를 막을 수 없는 상황이었다. 항해99 우리반 41명으로 시작했는데 이제 남은 인원은 24명이다. 여기서 프로젝트 4번을 할 수 있다고 했는데, 이미 두 번을 날려버렸다. 쉽지가 않다 정말. 오늘은 에러 천국인 S3 보다 상황이 너무 어려운 하루 ㅜ _ ㅜ
2. 느낀 점 : 프론트엔드와 백엔드의 협업이 진짜 어렵고 중요하다. 많은 조들이 프론트쪽에서 API 명세서에 대한 개념을 배우지 않으셔서 키값을 명세서와 다르게 설정하시고 구현하시는 바람에 고생하시는 걸 봤다. 이 부분을 기획할 때 좀 더 설명을 드렸으면 좋았을 것 같다는 생각을 했다.
3. 새로 알게 된 내용: 오늘 추가된 기능인 S3를 이용해 CRD (작성, 조회, 삭제) 구현을 마치고, 새로 추가된 기능에 관련된 코드리뷰를 진행했다. S3를 이용해 조회기능을 구현할 때는, ResponseDto 에 키값을 담아서 반환을 해주면 된다.
4. 셀프칭찬 (오늘 잘한 일): 혼자 남으신 프론트엔드 00님을 돕고싶어서, 리액트는 잘 모르지만 에러가 나올때마다 구글링을 하면서 어떻게라도 도와드리려고 했다. 잘하고 못하고를 떠나 열심히 해주시는 분인데 처음에 00님을 의심한 나를 반성하게 됐다. 당연히 코딩이 처음인 사람은 못하는게 당연하고 느린게 당연한데, 00님 뿐만 아니라 나에게도 너무 높은 잣대를 세웠던게 아닌가하는 생각을 하면서, 오늘은 이제라도 반성하는 나를 칭찬해야지 ~_~
1. 어려웠던 부분: 오늘 머지한 백엔드 파일의 자잘한 오류들을 수정하고 S3 이미지 업로드를 시도했다. 무한 구글링으로 블로그를 찾아봤는데 계속해서 bad request 400 오류가 발생했다. 지성님이 한줄씩 디버깅 하는걸 알려주시면서 파봤는데도 결국 해답을 찾지 못했는데, 갑자기 에러와 씨름한지 12시간 반이 넘었을 쯤 정상 작동되었다. 다른 조원 분들이 나와 같은 오류를 겪으시길래 도와드리면서 알아차린 사실인데, 그 전엔 왜 갑자기 정상작동하는지 몰랐는데 다른분들과 오류를 공유하면서 알게되었다. 정답은 바로 권한설정에서 ACL (엑세스 제어 목록) 부분에서 [모든사람]-[객체]-[나열] 권한을 줘야 하는 부분이었다. 오늘 게시글에 이미지 업로드 부분까지 완료하고 싶었는데 하루종일 오류만 고치다 끝난 하루가 되었다.
2. 느낀 점 : 오늘 우리 팀원 중 한분이 하차하셨고 다른 팀에서도 하차하시는 분이 계셨다. 하루가 다르게 자꾸만 하차인원이 늘어간다. 오늘 오류랑 씨름하느라 하루가 다 갈때쯤에서야 소식을 들었는데, 반 분위기가 심상치 않은 것 같다. 뭐, 그래도 어쩌겠는가 ~_~ 난 일단 내가 할 수 있는 최선을 다하고 열심히 못했던 공부를 하고 일인분하면서 잘 버텨야겠다.
3. 새로 알게 된 내용: 에러의 이유를 모를땐 브레이크 포인트를 찍으면서 한줄씩 파고들어서 터지는 부분을 봐야 한다. (아직 정확한 방법은 모름 ^_^)
4. 셀프칭찬 (오늘 잘한 일): 난 13시간 에러랑 씨름했지만, 그래도 나의 삽질 덕분에 다른분들의 시간을 줄여드릴 수 있었다. . . . !
1. 어려웠던 부분 : 이번주는 팀원들과 각자 구현기능을 맡아서 깃헙으로 협업하는 과정을 연습하는 주차였다. 지난 주차 레벨2 과제 구현에 이어서 Spring Security를 사용하여 인증 인가를 받고, 좋아요와 회원탈퇴 기능까지 구현해야하는 주차였다. 지난 주차에 CRUD와 연관관계 매핑이 완벽히 숙지되지 않아서 이번주는 과제구현과 코드의 흐름 이해까지 동시에 진행해야하는 주차였다. 스프링시큐리티와 AOP 그리고 예외처리의 기본 개념을 이해할 새도 없이 과제부터 일단 구현해야해서 뭔가 개념 정리가 완전히 되지 않은 부분이 찝찝하다.
2. 느낀 점 : 이번 주차에만 스프링 5명이 하차했다. 이쯤되니 항해99 과정이 과연 항해99가 홍보한 것처럼 제로베이스인 사람이 해도 되는 과정인가 하는 생각이 들었다. 밤샘 비행을 일주일 내내 했을때도 잘 아프지 않았던 내가 머리가 아파올 만큼 매일 늦은시간까지 최선을 다하고 있는데, 너무 벅차다. 심화주차또한 폭풍전야를 맞이하듯이 보냈는데, 미니프로젝트 팀발제를 보고 한번 더 머리를 얻어 맞은 느낌이었다. 팀을 배치하실 때 각자의 실력을 고려해서 좀 더 형평성 있는 팀을 구성해줘야 하는게 아닌가라는 생각이 들었다. 물론 나도 스프링팀에서 잘하는 편이 아니다. 못하는 사람을 탓하는게 아니라 항해99가 어쨌든 프로젝트 전에 1인분은 할 수 있도록 케어를 해줬어야 하는게 아닌가 하는 생각이 들었다.
3. 새로 알게 된 내용: 스프링시큐리티를 사용하여 인증 인가를 구현하는 법을 배웠다. 또, 강의자료를 통해 소셜로그인(카카오로그인) 기능도 구현하는 연습을 해봤는데, 차마 복습할 시간이 없어서 프로젝트 때 구현하진 못했다. 이번주차를 통해 한번 더 CRUD 흐름을 잡을 수 있었다.
4. 셀프칭찬 (이번주 잘한 일): 이젠 다른사람의 코드를 꽤나 잘 베끼는 ^_^ 수준이 되었다. 베끼다보니 코드를 이해하게 되고, 또 베낀 코드를 다시 내가 응용해서 추가기능을 구현해 보는 그런 주차였던 것 같다. 나처럼 제로베이스로 힘들어 하시더 유리님이랑 지금까지 그만두지 말자고 버티자고 으쌰으쌰 해왔는데, 유리님이 하차하시면서 나도 많이 흔들린 목요일 이었다. 그런데 금요일 팀 발제 이후 정말 참아왔던 힘듬이 터졌던 것 같다. 마음이 잘 잡히지 않았지만 그래도 새로운 미니프로젝트에서 맡은 부분 코드구현에 집중하려고 했던 나의 태도를 칭찬한다. 일단 맡은 일에 최선을 다하자 !
5. 이번주 할 일: 미니프로젝트 잘 마무리 하기 ( 수정해야할 부분 고치고, 추가 기능도 시도해 보기 )
브라우저에서는 보안적인 이유로cross-originHTTP 요청들을 제한합니다. 그래서cross-origin요청을 하려면 서버의 동의가 필요합니다. 만약 서버가 동의한다면 브라우저에서는 요청을 허락하고, 동의하지 않는다면 브라우저에서 거절합니다.
이러한 허락을 구하고 거절하는 메커니즘을 HTTP-header를 이용해서 가능한데, 이를 CORS(Cross-Origin Resource Sharing)라고 부릅니다. 그래서 브라우저에서cross-origin요청을 안전하게 할 수 있도록 하는 메커니즘입니다.
cross-origin
cross-origin이란 다음 중 한 가지라도 다른 경우를 말합니다.
프로토콜 - http와 https는 프로토콜이 다르다.
도메인 - domain.com과 other-domain.com은 다르다.
포트 번호 - 8080포트와 3000포트는 다르다.
출처(Origin)가 무엇인가요?
서버의 위치를 의미하는https://google.com과 같은 URL들은 마치 하나의 문자열 같아 보여도, 사실은 여러 개의 구성 요소로 이루어져있다.
이때 출처는Protocol과Host, 그리고 위 그림에는 나와있지 않지만:80,:443과 같은 포트 번호까지 모두 합친 것을 의미한다. 즉, 서버의 위치를 찾아가기 위해 필요한 가장 기본적인 것들을 합쳐놓은 것이다.
또한 출처 내의 포트 번호는 생략이 가능한데, 이는 각 웹에서 사용하는HTTP,HTTPS프로토콜의 기본 포트 번호가 정해져있기 때문이다.
그러나 만약https://google.com:443과 같이 출처에 포트 번호가 명시적으로 포함되어 있다면 이 포트 번호까지 모두 일치해야 같은 출처라고 인정된다. 하지만 이 케이스에 대한 명확한 정의가 표준으로 정해진 것은 아니기 때문에, 더 정확히 이야기하자면 어떤 경우에는 같은 출처, 또 어떤 경우에는 다른 출처로 판단될 수도 있다.
CORS는 왜 필요한가요?
CORS가 없이 모든 곳에서 데이터를 요청할 수 있게 되면, 다른 사이트에서 원래 사이트를 흉내낼 수 있게 됩니다. 예를 들어서 기존 사이트와 완전히 동일하게 동작하도록 하여 사용자가 로그인을 하도록 만들고, 로그인했던 세션을 탈취하여 악의적으로 정보를 추출하거나 다른 사람의 정보를 입력하는 등 공격을 할 수 있습니다. 이러한 공격을 할 수 없도록 브라우저에서 보호하고, 필요한 경우 에만 서버와 협의하여 요청할 수 있도록 하기 위해서 필요합니다.
CORS는 어떻게 동작하나요?
Simple requests인 경우
서버로 요청을 합니다.
서버의 응답이 왔을 때 브라우저가 요청한Origin과 응답한 헤더Access-Control-Request-Headers의 값을 비교하여 유효한 요청이라면 리소스를 응답합니다. 만약 유효하지 않은 요청이라면 브라우저에서 이를 막고 에러가 발생합니다.
Simple requests란?
HTTP method가 다음 중 하나이면서
GET
HEAD
POST
자동으로 설정되는 헤더는 제외하고, 설정할 수 있는 다음 헤더들만 변경하면서
Accept
Accept-Language
Content-Language
Content-Type이 다음과 같은 경우
application/x-www-form-urlencoded
multipart/form-data
text/plain
Simple requqets라고 부릅니다. 이 요청은 추가적으로 확인하지 않고 바로 본 요청을 보냅니다.
preflight 요청일 경우
Origin헤더에 현재 요청하는 origin과,Access-Control-Request-Method헤더에 요청하는 HTTP method와Access-Control-Request-Headers요청 시 사용할 헤더를OPTIONS메서드로 서버로 요청합니다. 이때 내용물은 없이 헤더만 전송합니다.
브라우저가 서버에서 응답한 헤더를 보고 유효한 요청인지 확인합니다. 만약 유효하지 않은 요청이라면 요청은 중단되고 에러가 발생합니다. 만약 유효한 요청이라면 원래 요청으로 보내려던 요청을 다시 요청하여 리소스를 응답받습니다.
preflight 요청이란?
Simple requests가 아닌cross-origin요청은 모두 preflight 요청을 하게 되는데, 실제 요청을 보내는 것이 안전한지 확인하기 위해 먼저 OPTIONS 메서드를 사용하여cross-originHTTP 요청을 보냅니다. 이렇게 하는 이유는 사용자 데이터에 영향을 미칠 수 있는 요청이므로 사전에 확인 후 본 요청을 보냅니다.
요청 헤더 목록
Origin
Access-Control-Request-Method
preflight요청을 할 때 실제 요청에서 어떤 메서드를 사용할 것인지 서버에게 알리기 위해 사용됩니다.
Access-Control-Request-Headers
preflight요청을 할 때 실제 요청에서 어떤 header를 사용할 것인지 서버에게 알리기 위해 사용됩니다.
응답 헤더 목록
Access-Control-Allow-Origin
브라우저가 해당 origin이 자원에 접근할 수 있도록 허용합니다. 혹은*은 credentials이 없는 요청에 한해서 모든 origin에서 접근이 가능하도록 허용합니다.
Access-Control-Expose-Headers
브라우저가 액세스할 수 있는 서버 화이트리스트 헤더를 허용합니다.
Access-Control-Max-Age
얼마나 오랫동안preflight요청이 캐싱 될 수 있는지를 나타낸다.
Access-Control-Allow-Credentials
Credentials가 true 일 때 요청에 대한 응답이 노출될 수 있는지를 나타냅니다.
preflight 요청에 대한 응답의 일부로 사용되는 경우 실제 자격 증명을 사용하여 실제 요청을 수행할 수 있는지를 나타냅니다.
간단한 GET 요청은preflight되지 않으므로 자격 증명이 있는 리소스를 요청하면 헤더가 리소스와 함께 반환되지 않으면 브라우저에서 응답을 무시하고 웹 콘텐츠로 반환하지 않습니다.
Access-Control-Allow-Methods
preflight 요청에 대한 대한 응답으로 허용되는 메서드들을 나타냅니다.
Access-Control-Allow-Headers
preflight 요청에 대한 대한 응답으로 실제 요청 시 사용할 수 있는 HTTP 헤더를 나타냅니다.