테오 스프린트 16기 모집 공지를 보고 .. 많이 늦었지만 ^^ 지난 기수에 즐겁게 참여했던 기억을 되살려 5일간의 여정을 기록합니다.
첫째날은 각자 만들고 싶은 서비스를 발표하고 원하는 프로젝트를 선택해 팀을 구성합니다.
피크 타임(Pick Time)
각양각색의 좋은 아이디어들이 많았는데 저는 ‘피크타임’을 선택했습니다. 카카오톡 선물하기의 위시리스트처럼 본인이 받고 싶은 선물을 리스트업 할 수 있는 서비스는 많지만 선물을 주는 사람을 위한 서비스는 처음 봤거든요.
실제로 저는 친구의 생일이 다가오면 선물하고 싶은 것들을 마구잡이로 메모장에 적어둔 뒤, 그 중에서 베스트를 찾는 편인데요. "내가 최종 선택을 하기 전 이 목록을 친구에게 전달해 직접 선물을 고를 수 있게 한다면?" 받는 사람도 더 만족스럽지 않을까 하는 생각에 이 서비스를 선택했습니다.
팀이 구성되고 난 뒤에는 팀캔버스로 이동해 팀원들과 아이스브레이킹 타임을 가집니다. 개발에 대한 가치관, 스프린트에 참여하며 기대한 부분이 무엇인지, 어떤 서비스를 만들고 싶은지 등 다양한 주제로 꽤 긴 시간 대화를 나눠요. 사실 사적인 대화를 나누지 않고 오로지 개발 얘기만 나누며 아이스브레이킹 타임을 가진 건 처음이었는데요 .. 정말 즐거웠습니다. 특히 모두가 이 스프린트에 진심이란 걸 실감하게 돼서 더더욱 열심히 해야겠다 다짐했어요 !
둘째날은 우리가 만들고 싶은 서비스에 대한 모든 아이디어를 발산하는 시간이었어요. 주고 싶은 선물을 리스트업하는 서비스 라는 큰 맥락을 가지고 이 서비스의 목적/대상/추구하는 가치에 대해 고민하고, 유사 서비스를 알아보며 우리의 프로젝트에 대한 대화를 나누었습니다.
다양한 의견을 주고 받은 후에는 키워드들을 모아 워드 클라우드를 만들어요.
다음으로 워드 클라우드를 보며 실제 서비스에 해당 키워드들을 어떻게 녹여낼지 고민합니다. 이 시간에는 각자 찾아온 레퍼런스를 공유하며 의견을 제시하고, 그 의견의 허점을 찾아 어떻게 해결할 수 있을지 고민해요.
예를 들어 저는 키워드 중 정성, 낭만을 보며 받는 사람을 위한 메시지 카드를 제안했습니다. 그런데 만일 카드 작성이 귀찮은 유저가 있다면 어떻게 해야 할지 질문을 받았어요. 이러한 경우, 기본 문구로 작성된 메시지 카드를 고정값으로 넣어 과정을 간소화하는 방법을 제시해 회의를 이어갔습니다.
본격적으로 서비스의 페이지를 구상하는 날입니다.
페이지가 대략적으로 결정된 후, 발산했던 아이디어를 취합해 구현할 기능을 결정했어요. 기능들은 given, when, then의 순서로 인터렉션을 구체화합니다. 이렇게 상세하게 상황들을 나누어 생각하다보니 분기처리, 예외처리, 페이지 별 기능 나누는데 큰 도움이 되었어요.
마지막으로 페이지 디자인을 확정하고 우선순위를 정해 개발할 준비를 마쳤습니다.
저는 상품을 추가, 삭제, 수정하는 기능을 맡았습니다. 유저가 상품의 링크를 입력해 선물을 추가하면 og 태그의 이미지, 타이틀, 설명을 가져와 상품 리스트로 생성되는 방식이에요.
그런데 선물 추가 api를 연결하며 CORS 에러가 발생했습니다.
Cross-Origin Resource Sharing 의 약자로 웹 브라우저에서 실행되는 스크립트가 다른 출처(Origin)의 리소스에 접근할 수 있는 권한을 부여하는 것입니다. 보안 상의 이유로 동일 출처 정책(same-origin policy)에 따라 브라우저는 기본적으로 다른 출처의 리소스에 접근을 제한합니다. 하지만 CORS를 통해 서버가 특정 출처로부터의 요청을 허용하도록 설정하면, 브라우저는 해당 출처와의 상호작용을 허용할 수 있습니다.
저는 'http://localhost:3000.com' 에서 백엔드의 서버 'https://api.-----' 에 요청을 보내고 있습니다. 그런데 브라우저가 동일 출처가 아닌 다른 주소로 요청을 보냈기 때문에 CORS 에러가 발생한 것이었어요.
CORS는 다음의 순서로 동작합니다.
따라서 근본적으로 문제를 해결하려면 서버에서 Access-Control-Allow-Origin을 수정해야 합니다.
📍 참고
출처를 비교하는 로직은 서버에서 구현된 스펙이 아니라 브라우저에 구현되어 있는 스펙입니다. 서버 간 통신을 할 때는 이 정책이 적용되지 않습니다.
개발 환경에서는 프록시 서버를 사용해 해당 문제를 해결할 수 있습니다.
Proxy는 대리라는 뜻으로 클라이언트와 서버 사이에서 중계 역할을 수행하는 서버입니다. 클라이언트는 프록시 서버를 통해 다른 네트워크 서비스에 접근하거나 요청을 전달합니다.
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function (app) {
app.use(
createProxyMiddleware("/api", {
target: "https://api.----",
changeOrigin: true,
}),
);
};
위 코드는 프록시 미들웨어 라이브러리를 통해 백엔드 서버에 요청을 보낸 방법입니다.
클라이언트가 '/api'라는 Path parameter로 요청을 보내면 프록시가 도메인이 'http://api.——' 인 서버에 요청을 보내고, 그 응답값을 클라이언트에게 전달합니다. 즉, 클라이언트에서 백엔드 서버에 보낸 요청을 프록시 서버가 가로채 전달하여 CORS 에러를 방지하는 것입니다.
짜잔! 문제를 해결하고 성공적으로 선물이 추가되는 모습입니다.
짧은 기간 동안 이렇게 하나의 서비스가 뚝딱 완성될 수 있다니 정말 신기해요 .. 디자이너, 프론트, 백엔드 모두가 최선을 다 한 결과가 이렇게 구현되니 정말 뿌듯하네요 ㅎㅎ
이번 스프린트는 CORS 에러를 해결하기 위해 백엔드와 디버깅하던 순간들이 유독 기억에 남아요. 새벽까지 이런저런 설정을 바꾸며 네트워크 탭을 기웃거리고 .. 갖은 개발 블로그를 탐독하던 시간이 .. 피곤했지만 유익한 시간이었어요 ! 덕분에 api와 한 걸음 가까워졌습니다 ㅎㅎ
같이 개발한 6조 너무 고생하셨구 기회의 장을 마련해주신 테오 너무 감사합니다 ~!