텍스트
2024년 4월, SKT에서 주최하는 스마틴 앱 챌린지 이하 스택 (STAC)이라는 대회가 열리게 되었고, 같은 학교 친구의 제안으로 바운더리라는 팀이 만들어졌다.
스택에서는 아이디어로 서류 심사 - 중간 심사를 판별했다. 그만큼 개발 실력보다도 아이디어의 중요성을 강조하고 있었다.
팀원 한 명이 경계선 지능인을 위한 학습 서비스라는 아이디어를 가지고 있었다. 단순히 아이디어를 가지고 있던 것이 아닌 본인만의 아이디어 구체화도 진행한 상황이었다.
팀원은 좋은 아이디어가 나오지 않는다면 경계선 지능인을 위한 학습 서비스를 개발하자라고 말을 했다.
1주일 동안 4명이 머리를 모아 생각을 해보았지만 경계선 지능인을 위한 학습 서비스를 이길만한 아이디어가 없었고, 이 아이디어로 프로젝트를 진행하게 되었다.
아이디어를 회의를 통해 구체화를 진행하고, 스택의 서류를 4명에서 파트별로 분리해 서류를 작성했다.
저는 서비스 내용과 서비스 경쟁력 파트를 작성했다. 작성 내용은 여기서 확인할 수 있다.
스택 측에 서류를 제출하고 1달 후에 서류 합격이라는 메시지를 받게 되었다. 그리고, 2주 후 친구 2명이 서울에 가서 중간 발표회 발표를 하고 왔다. 서류에서는 아이디어만 본다면 중간발표에서는 그 아이디어에 대한 개발 구상도와 계획 등을 보고 개발이 가능한가를 판별했다. 다행히도 팀은 중간 발표회 마저 합격하고, 결선에 진출하게 되었다.
저는 스택 결선 진출이 2번째 큰 대회 결선 진출 경험이었다. 큰 회사가 주최하는 대회를 대상으로 결선에 진출했고, 제가 낸 아이디어는 아니었지만 아이디어를 인정받았다는 생각에 뿌듯했다.
그리고 결선에 진출하게 되면서 개발 멘토 1명과 디자인 멘토가 우리 팀에 배정되었다. 멘토님들은 각각 1회 학생 지역으로 이동해 멘토링을 진행하고 온라인으로 2시간 (각각 1시간) 멘토링을 진행해 주셨다.
저희 팀에는 전문 디자이너가 없었다. 전문이라는 표현보다도 디자인을 전공으로 한 팀원이 없었고, 그나마 한 번쯤 해봤다 하는 프런트엔드 2명에서 디자인을 했다. 앱을 디자인하기 전 팀원들이 Boundary Color이라는 컬러 라이브러리를 만들어 놓았는데 무지개 빛 나는 그러데이션 컬러였다. 이 컬러를 메인 컬러로 사용해서 디자인을 했다.
디자인을 마무리하고, 디자인 멘토님에게 온라인 멘토링을 받았다.
1번과 2번 피드백을 받았을 때 단순히 디자인을 수정하려고 했지만 3번을 듣고, 이건 완전히 바꿔야겠다고 생각했다. 디자인을 빠르게 바꾸고, 또 한 번 피드백을 받았다.
이번 피드백은 디자이너가 아니라면 다 맞추기 힘든 부분이라고 멘토님께서 직접 수정해 주셨다. 감사합니다:)
조금 늦게 말한 것 같지만 우리 팀에는 프런트엔드 2명 / 백엔드 및 AI 개발 2명으로 구성되어 있다.
초기에 프런트엔드는 Svelte Kit을 사용했다. Svlete Kit을 선택한 이유는 빠른 개발과 Svelte kit의 좋은 router 덕분에 api 연결을 빨리할 수 있다고 생각했다. Svelte Kit을 사용하면서 리엑트, 뷰, 넥스트 등 다른 라이브러리/프레임워크보다 사용이 훨씬 편했고, 문법도 간단해서 페이지 하나를 만드는데도 시간이 많이 들지 않았다. 우리는 피그마에서 파트를 나누어서 개발을 했다. 
이렇게 역할을 나누니 충돌이 일어나지 않아서 좋았다. 하지만 협업의 비중은 줄었었던 것 같다.
2024년, 8월 10일 개발 멘토님과 커피숍에서 멘토링을 진행했다. 멘토님은 백엔드 개발자셨고, 멘토링 진행 당시 백엔드의 진전도가 프런트보다 낮았기에 백엔드 멘토링을 우선으로 봐주셨다. 1시간 정도 백엔드를 봐주시고, 프런트엔드 쪽에서 궁금한 것을 봐주셨다.
우리 질문은 스벨트 킷에서 캘린더 라이브러리가 없어서 동적으로 해야 할지 라이브러리를 만들지 고민을 말했다. 멘토님께서는 그런 노력을 들이는 것보다 RN으로 마이그레이션 하는 것을 추천하셨고, 우리도 끊임없는 고민 끝에 마이그레이션을 결정했다. 마이그레이션을 결정한 것도 베포까지 고려한 선택이었다.
그리고 멘토님께서 우리가 프리토킹 등 회의를 하는 모습을 보면서 기획이 계속 바뀌는 것 같다고 했다. 우리도 어느 정도 알고 있었지만 심각한 줄은 몰랐다.
멘토님께서 들었을 때 똑같은 말을 여러 번 하고 있고, 지금 시점에서는 개발에만 집중하고 있어야 하는 시기인데 기획을 계속 바꾸는 건 문제점이라고 말씀하셨다.
오늘 밤을 새워서라도 기획을 다 완성하고 가신다고 하셨고, 흔히 말하는 리더의 역할을 해주셨다. 
피그마에 적어서 우선순위를 매겼고, 하나씩 해결해 가면서 구체화를 시키고 더 이상은 기획에 대한 변경은 없어야 한다고 당부하셨다. 그리고, 꼭 리더가 아니어도 팀이 산에 가고 있으면 누군가는 말해주어야 한다고 하셨다. 아직도 이 말씀이 굉장히 와닿는다.
멘토링을 마치고 RN으로 마이그레이션을 시작했다. RN으로 처음 개발을 해보고, 사용도 처음 해보았는데 리엑트와 비슷해서 개발을 할 수 있었다. 확실히 RN을 사용하니 확장 프로그램, 라이브러리 등 훨씬 편한 것들이 많아서 개발할 때 편했다. 캘린더도 여러 가지 종류가 있어 원하는 디자인에 맞게 선택도 할 수 있었다.
퍼블리싱은 생각한 시간보다 빨리 끝났고, API 연결을 시작했다.
이번 개발에서는 Api를 연결할 때 시간 사용 대비 개발 속도가 매우 늦었다. 백엔드에서 만들어준 api를 포스트맨을 사용해서 작동 여부를 확인했다. 모두 200 또는 201로 정상이었다. 당연히 api를 연결할 때 에러는 프런트 쪽 에러인 확률이 높다고 생각해 구글링이란 구글링은 다해봤지만 나오지 않았다. 그리고 백엔드 팀원한테 말을 하니 api 내부 에러라고 했다.
처음에는 그러려니 했지만 api를 하나씩 연결하면서 보니 api 내부 에러가 많았다.
짜증도 났지만 이 상황을 이해했던 건 개발 시간이 충분하지 않아 급하게 만들었기 때문이라고 생각했다.
이번 개발을 하면서 아이/보호자 페이지를 개발할 때 가장 어려웠던 것 하나씩을 뽑아 보면 아이는 SST 피드백이었고, 보호자는 상황 추가 / 상황 리스트업 / 상황 삭제 페이지였다.
SST 상황 대처 학습 피드백 페이지는 아이가 상황 대처 학습을 하면 피드백을 주는 페이지다. 아이 페이지에서 유일하게 AI가 활용되었고, 피드백을 AI가 준다. 디자인과 퍼블리싱에서는 2개의 창으로 나누어져 위의 창에는 피드백을 주고, 아래 창에는 대신해야 할 말을 알려주려고 했지만 개발에서는 그렇게 되지 않았다.
api에서 보이는 json 형식이
{
feedback: string
}
이런 식으로 되어있었는데 값을 두 칸을 받아오려면
{
feedback: string
feedback2: string
}
이렇게 되어있어야 받아올 수 있었다.
백엔드 팀원에게 요청했지만 굳이 이렇게 할 필요가 있냐라고 말을 전달받았고, 2칸으로 구성하지 않고, 1칸에 피드백과 대신해야 할 말을 넣자라고 했다. 일단은 피드백이 띄워지는 게 우선사항이었고, 2칸으로 구성하는 건 최우선 사항은 아니었기에 1칸으로 구성하게 되었다. 리펙토링에서는 2칸으로 바뀌었으면 좋겠다.
AI가 피드백을 줄 때 길이 제한 대신 문장 개수 제한을 주어 너무 많은 텍스트가 생성되는 경우도 있었다. 3 문장으로 설정을 해놓아도 1 문장에 40단 억 가 나오는 경우도 있었다. AI의 문장 수를 줄이기에는 짧은 문장이 경우에는 칸이 너무 많이 남아있었고, 다 필요한 말이었기에 React Native의 ScrollView 컴포넌트를 사용해서 메시지 박스에 글자 수가 너무 많다면 스크롤이 생기도록 구현했다.
사실 이 페이지를 개발하는데 어려웠다고 하기보다는 다른 페이지들보다 테스트가 많았기에 시간이 오래 걸렸다. AI단에서도 테스트를 하고 Api를 만들어줬지만 api 연동 후 ai가 잘못된 피드백을 알려주는 경우가 있었기에 앱에서 또 한 번 테스트를 하게 되었다.
이 페이지에서는 한 페이지에 상황 추가/삭제 리스트 업까지 3개의 기능을 가지고 있어 api를 3개 연동했었어야 했다. api 연동을 하면서 어렵다 할 부분은 없었지만 나의 실수로 문제가 생겼다. 우선 상황 리스트업 api가 POST였지만 GET으로 해버려서 에러는 뜨지 않았지만 동작이 하지 않았었다. 당연히 에러가 뜨지 않는 게 정상이었고, 값도 불러오지 않는 게 정상이었다. 이 실수로 서버 측 문제인가 싶어서 물어보았지만 서버에서도 문제가 없었고, 같이 개발하는 프런트엔드 팀원에게 물어보니 내가 POST를 GET으로 구현했음을 알 수 있었다,,
두 번째 실수는 등록 시 응답 상태 코드가 201이었지만 응답 상태 코드를 200으로 입력해 HTML이 반환되었고, api가 동작하지 않았다. Swgger UI에 그렇게 설명이 잘되어 있었는데 그걸 200으로 적다니 지금 봐도 실망이다. 다른 api의 상태 코드가 200이었기에 200을 적었던 것 같다. 구글링으로 해결이 되지 않아서 GPT에게 물어보니 응답 상태 코드가 200이 맞는지를 확인해라고 알려주었다. 만약 GPT가 이 이야기를 해주지 않았다면... 생각도 하기 싫다.
개발할 때는 계속 스키마를 보면서 하는 게 맞는 것 같다. 형식이 비슷하다고 생각하고 개발을 하니 실수가 많이 생긴다. 바운더리 개발에서 반성해야 할 부분이 아닌가 싶다.
빌드가 개발보다 더 어렵다고 말할 수 있을 정도로 빌드하기가 어려웠다. 앞서 말했듯이 React Native와 expo를 사용하여 개발을 했고, native cli와는 다르게 expo에서 빌드를 해야 했다.
먼저 expo에서 빌드를 하면 에러가 나온다. 하지만 에러가 두리뭉실하게 나오는 경우가 많았다. 예를 들자면
이런 명령어를 쳐서 미리 테스트해 보고 빌드해라 -> 어떻게 고치는지 알려주지 않음.
000이 없다. ex. 이미지가 없다. -> 어떤 이미지인지 알려주지 않음.
이렇게 이상하게 알려주었다. 그리고, 가끔 에러 메시지가 뜰 때가 있지만 그 에러를 구글링 하면 모든 사람이 다르게 해결했고, 비슷하게 해결한 것도 아닌 정말 다른 문제를 정말 다르게 해결하는 경우가 대다수였다.
최종적으로 바운더리 프로젝트에서는 3개의 문제가 있었다.
1번과 2번은 그럴싸할 이유였지만 3번은 정말 이해가 되지 않았어요. expo에 빌드하기 위해서는 깃허브 커밋 기록을 반영하는데 로컬에서 환경변수를 설정해도 깃허브 파일에서는 달라지는 점이 없다.
이 3가지 문제를 해결하고, 처음으로 빌드를 성공하게 되었다. 개발 기간 중 1주 이상이나 빌드에 붙잡혀 있었는데 하늘을 날아다닐 것 같은 기분이었다. 하지만 지옥은 이제부터 시작되었다.
빌드만 되면 플레이스토어에 올릴 수 있을 것이라고 생각했다. expo app을 web에서 실행시켰을 때 모든 동작이 이상 없이 작동되었기 때문이다.
우선 CSS 무너짐 현상은 우리가 style 코드에서 margin을 '10px'으로 정해놓은 것이 많았는데 '10px' 형식으로 하면 안 되고 그냥 10만 적어야 했었다. ex) margin-top: 10,
정말 다행히도 CSS는 잘 고쳐졌다. 단순히 px을 붙이고 안 붙이고 문제였다니 놀라웠다.
2번째 axios문제는 첫 번째에서 해결하지 못했다. 첫 번째에서는 api 경로 지정 문제라고 생각해. env를 만들어서 안에 api url을 담는 방식으로 바꾸었다. 하지만 오히려 이상한 에러만 나고, 에러는 고쳐지지 않았다.
우리는 이 방법을 해도 동작하지 않자 구글링을 하면서 10페이지까지 다 확인하며 적용해 보았지만 에러는 고쳐지지 않았다. 이젠 우리 쪽 문제가 아닌 것 같았고, 백엔드 친구들한테 이거 너희 문제 있는 것 같다고 전달했다.
정말 다행히도 백엔드 문제가 맞았다. 아니었으면 정말 답도 없었다. 문제는 http와 https였는데 우리의 서버는 https인데 api 측에서 http만 되도록 되어있었던 것이었다. 그러면 왜 웹에서 개발할 때는 되었는가라는 의문이 들지만 일단 됐기에 넘어갔다.
apk의 axios에서 문제가 터졌다. 이번 문제는 연결된 api들이 갑자기 동작하지 않았다. 스택에서 플레이스토어 등록하는 시간을 이미 놓치고 원스토어 등록하려고 하고 있었다. 갑작스럽게 apk에서 api가 동작하지 않았다. 팀원 중 한 명이 여름방학 동안 인턴을 진행했고, 이때 만나게 된 사수님께 연락을 드려 문제를 알게 되었다. 우리는 클라이언트 개발을 하면서 임의의 형태로 AccessToken이라고 이름을 지어줬는데 이 형태는 안드로이드에서 허용을 해주지 않았다. 안드로이드에서 허용을 해주기 위해서는 Authorization를 사용해야 했다.
이 문제를 알고 난 후 아래와 같은 형식으로 api 연결을 마무리 지었다.
const response = await axios.post(
`api-url/cognition`,
{ addPoint: 100 },
{
withCredentials: true,
headers: {
Authorization: `Bearer ${accessToken}`,
},API
}
);
원스토어는 1일이면 스토어 심사가 끝나고 올릴 수 있다는 정보를 알게 되었고, 스택 마지막 퍼즐인 베포를 위해서 원스토어 등록하기로 했다. 우리 팀은 이미 개발을 다 끝냈기에 당당히 올렸지만
개인정보 수집 동의 체크 박스를 만들지 않아 원스토어 등록에 실패했다.
이후 스택 주최 측에 메시지를 보내 apk로도 평가를 할 수 있다는 이야기를 받았지만, 스토어 등록 점수 및 다운로드 점수 2점은 받을 수 없게 된다고 말씀해 주셨다. 아쉽지만 apk만 스택에 제출하게 되었다.
시연영상은 8. 기록 세션에 있다.
정말 많은 것을 배울 수 있는 프로젝트였다. 모든 프로젝트에서 배울 점이 있지만 바운더리는 더더욱 배울 점이 많았다고 생각한다. 처음으로 앱을 개발해 보았다는 점. 앱을 빌드해 본 경험 나에겐 너무 소중할 것 같고, V2를 개발하거나 또 한 번 앱을 개발해야 한다면 더 잘할 수 있다고 다짐한다.
같이 개발한 프런트엔드 팀원이 개발할 때 많이 알려주고, 팀원이 가지고 있는 마인드에 이까지 올 수 있었다 생각한다.
팀원들 좋은 경험과 배움 만들어주어서 고마워!
아직 대상/최우수상/우수상/장려상 중 어떤 상을 수상하게 될지는 모르지만 수상이 확정이 되었다. 
T 아카데미에 10월 2일 결선 결과가 발표되었다. 일반학교 생활정보부문에 당당히 바운더리가 이름을 올렸다. 정말 기분이 좋았고, 어떤 상을 받든 팀원과 행복한 개발을 할 수 있어서 좋았다. 그리고 완성도를 더 높여 스토어에 앱을 등록한 후 경계선 지능인의 학습을 돕고 싶다.
위의 내용들을 적기 위해서 한 과정들을 볼 수 있습니다. 많이들 봐주세요!
개발한 앱 시연영상입니다.
긴 글 읽어주셔서 감사합니다:) 내용에 오류가 있다면 댓글로 알려주세요.
팀장이 잘생긴거 같네요