df광진구공모전발표.pdf
0.07MB
2025 광진구 빅데이터 공모전 정합팀 분석결과보고서.pdf
14.48MB
2025 광진구 빅데이터 분석 공모전 정합팀 요약본 .pdf
1.62MB

PlayBit 개발 기록 (2주)

1. 사진 인증 기능 구현

기존에는 버튼만 눌러 미션을 완료하는 방식이었지만, 실제로 목표를 수행했는지 인증할 수 있도록 사진 인증 기능을 구현하려고하고 있다

구현 내용

* 이미지 업로드 기능 추가
* 업로드한 이미지 미리보기(Preview) 구현
* 이미지 선택 및 변경 기능 구현
* 인증 완료 후 서버로 이미지 전송하는 구조 설계
* 업로드 상태(인증 중, 완료 등) UI 구성



2. 게임 실시간 동기화 개선

기존에는 새로고침을 해야만 상대방의 진행 상황이 반영되는 문제가 있었다.

이를 해결하기 위해 Short Polling 방식을 적용하였다.

구현 내용

* 게임 화면 진입 시 방 정보 조회
* 2초마다 GET API를 호출하도록 setInterval 적용
* 페이지를 벗어나면 clearInterval로 폴링 종료
* 최신 게임 상태를 자동으로 반영하도록 수정

-> 추후 다른 방식으로 변경 예정 (웹소켓? sse?)


3. 모바일 UI 개선

기존에는 데스크톱 화면 위주였던 디자인을 모바일 중심으로 수정하였다.

수정 내용

* 랜딩 페이지 전체 레이아웃 변경
* 버튼 배치 및 크기 수정
* Tic-Tac-Toe 일러스트 추가
* 게임 화면 UI 개선
* 결과 화면 버튼 단순화
* 전체적인 여백 및 타이포그래피 수정

-> 이것도 뭔가 변경될 것 같다
그리고 중간발표에서 더 확실한 모바일뷰로 변경하기를 권유 받았다


5. 프론트엔드-백엔드 API 연동

사진 인증 기능과 게임 진행 기능을 백엔드 API와 연결하기 위한 작업을 진행할 예정




이번 2주 동안은 새로운 기능을 많이 추가하기보다는 실제 서비스에서 사용할 수 있도록 완성도를 높이는 작업에 집중하였다.

특히 사진 인증 기능과 Polling 기반의 실시간 동기화는 사용자 경험을 크게 향상시키는 기능이었다. 또한 모바일 UI 개선과 API 연동을 진행하면서 프론트엔드 개발은 단순히 화면을 만드는 것이 아니라 사용자 경험과 데이터 흐름을 함께 고려해야 한다는 점을 배울 수 있었다.

다음 단계에서는 사진인증 구현한 것을 백엔드와 api연동하고, UI개선 등을 해볼 것 같다

'GDG-프로젝트' 카테고리의 다른 글

What I learn 3  (0) 2026.07.27
what i learn 2  (2) 2026.07.13
what i learn 1  (1) 2026.06.28
WEEK4 WHAT I LEARN  (1) 2026.05.21
WEEK3 WHAT I LEARN  (2) 2026.05.18

깃헙에 이슈 올리고 확인하면 개발하고 PR
-> 다른 팀원이 검토하고 merge 하며 진행했다


1. 방 참여 페이지 / 랜딩 페이지 / 방 만들기 페이지 구현
기초적인 화면 틀을 잡았다



2. api 코드
mock data를 이용해 개발하다가 백엔드와의 연동을 위해 api 코드를 추가했다
나는 player api를 맡았다
api를 순차적으로 추가하며 백엔드와의 연결도 수시로 시도했고 성공과 실패를 반복했었다
(현재는 성공 완.)



3. 폴링 기능 추가
두 사용자간의 화면 실시간성을 어느정도 확보하기 위해 폴링 기능 코드를 추가했다.
원래는 새로고침을 해야만 상대편에서 게임을 진행했던 이력을 볼 수 있었는데 이 코드를 통해 2초마다 자동 새로고침 되어 사용자가 직접 새로고침 하지 않아도 실시간으로 게임 진행 상황을 확인 할 수 있게 되었다.



4. 화면 리디자인
페르소나에 맞춰 웹뷰가 아닌 모바일뷰로 방향을 바꾸었다. 기존의 디자인이 부자연스럽고 틱택토와의 연관성이 너무 낮아보여 우선 랜딩페이지부터 리디자인 하였다.
좀 더 게임스러워진 듯 하다

기존의 웹 뷰
수정한 모바일 뷰


배우거나 느낀점
코드 공부를 더 해야겠다 내가 짠 코드도 복습하고 팀원이 짠 코드도 보면서 학습 해야겠다.
배포도 끝냈는데 아직 디자인이 미흡하다 그것을 고치는게 급선무 특히 게임 보드 판 ..!

MVP까지는 완성했는데 뭔가 부실해보인다
중간데모때 피드백 받아 더 완성도 높은 결과물을 만들 수 있길 ..

'GDG-프로젝트' 카테고리의 다른 글

what i learn 4  (1) 2026.08.10
what i learn 2  (2) 2026.07.13
what i learn 1  (1) 2026.06.28
WEEK4 WHAT I LEARN  (1) 2026.05.21
WEEK3 WHAT I LEARN  (2) 2026.05.18

기획안

주제선정배경:
도파민 디톡스 및 좋은 습관 만들기

숏폼 시청습관을 고치고 좋은 습관을 들이고 싶은 사람을 위한 웹 서비스

기존 유사 서비스 분석
• A. 소셜 기반의 목표 달성 앱 (Goalify)
• 특징: 목표와 습관을 설정하고, 친구를 초 대해 공동 챌린지에 참여하는 서비스입니 다.
• 장점: 스트릭(연속 달성) 기능과 그룹 목 표를 통해 사용자에게 강한 '책임감'과 동 기를 부여합니다.
• B. 하드코어 RPG형 To-do 앱 (Habitica)
• 특징: 현실의 할 일을 완수하면 게임 캐릭 터가 성장하고, 나쁜 습관을 하면 체력이 깎이는 RPG 형태의 서비스입니다.
• 장점: 아이템 획득, 길드 시스템, 보스 클 리어 등 강력한 '게임적 요소 (Gamification)'를 통해 뚜렷한 보상감 을 제공합니다.

우리 서비스 차별점
우리는 리서치를 통해 "타인과의 상호작용(책임감) 은 살리되, 룰은 가장 단순해야 한다"는 결론을 내렸 습니다. 이에 따라 우리 서비스는 다음과 같은 차별 화된 경험을 제공합니다.
• 보드게임(틱택토) 룰 적용으로 진입 장벽 최 소화
• 복잡한 튜토리얼이나 캐릭터 육성 요소가 없습니다. 누구나 직관적으로 아는 '3x3 빙고(틱택토)' 방식을 습관 추적에 적용하 여, 유저가 고민 없이 게임을 시작할 수 있 습니다.
• 상대방과의 실시간 경쟁을 통한 재미 극대화
• 단순히 내 체크리스트를 지우는 고립된 형 태가 아닙니다. 내가 '운동 1시간 하기' 등 목표를 완수하면, 실시간으로 보드판 의 타일을 내 것(O 또는 X)으로 선점하 게 됩니다. 이 과정에서 상대방의 빙고를 막고 내가 이기기 위한 '건강한 경쟁 심 리'가 발동합니다.

플로우 차트


확정된 mvp

MVP :  두 명의 사용자가 공통의 목적을 가지고 달성을 위해 경쟁한다.

기능 :

최소 기능 :

1. 게임 할 방을 생성하기
2. 코드 입력 해서 입장하기
3. 게임 시작
    3-1. 목표 등록 기능 (9개, 3X3)
    3-2. 게임 활성화 기능 (뒤집기 X, 무승부 가능)
    3-3. 시간 제한 (24시간)

느낀점
차차 화면 구현을 시작했는데 백과의 연결이 중요한 포인트가 될 것 같다 두려움 반 설렘반 ㅎㅎ
  

'GDG-프로젝트' 카테고리의 다른 글

what i learn 4  (1) 2026.08.10
What I learn 3  (0) 2026.07.27
what i learn 1  (1) 2026.06.28
WEEK4 WHAT I LEARN  (1) 2026.05.21
WEEK3 WHAT I LEARN  (2) 2026.05.18

무작정 아이디어를 내는 것이 아니라 페르소나를 만들어보기를 중점으로 시작했다

우리의 페르소나

쇼츠에 중독된 현대인들을 대변해보자!

5-why를 통해 문제점 찾기

1. why? :  한심남은 왜 여가시간을 알차게 보내지 못했을까?
    - 쇼츠에 중독되어 계속 폰만 봤기 때문이다.
2. why? :  쇼츠에 중독이 되어 폰만 봤을까?
    - 습관적으로 폰을 켜서 쇼츠를 보기 때문이다.
3. why? : 왜 습관이 되었을까?
    - 출퇴근시 폰을 자주보는데 이 행동이 습관으로 남았기 때문이다.
4. why? : 출퇴근시 폰으로 쇼츠를 자주 보는걸까?
    - 대중교통 특성상 생산적인 일을 하긴 힘들기 때문이다.
5. why? : 왜 대중교통에서는 생산적인 일을 하기 힘들까?
    - 출퇴근 시간 사람도 많고 자세도 불편하고 자주 움직이기 때문이다.
    

문제: 안좋은 습관이 들어버린것. 관성적으로 하던 행동들..

결론: 좋은 습관을 들이게 하는 방법은 없는걸까?

해결 방향성 생각해보기
여러가지 중 ..

누군가와 같이 할 수 있는 프로그램, 내가 해놓으면 다음에 남이 추가하고 쌓여가는 느낌 -> 틱택토

MVP 적기
MVP란?
기본적인 요구를 충족시키는 동시에, 시간과 비용을 최소화하여 시장 반응을 빠르 게 측정할 수 있는 방법을 제공합니다. MVP의 주요 목적은 제한된 자원 내에서 최대한의 가치를 창출하 고, 시장에서 제품의 가능성을 탐색하는 것

우리의 MVP
두 명의 사용자가 공통의 목적을 가지고 달성을 위해 경쟁한다.

최소 기능 :
1. 회원가입 및 닉네임 설정
2. 게임 할 방을 파는 기능
3. 게임 시작
    3-1. 목표 등록 기능 (9개, 3X3)
    3-2. 게임 활성화 기능 (뒤집기 X, 무승부 가능)

유저 시나리오

1. 두명의 사용자(A,B)가 회원가입을 한다.
2. 한명의 사용자(A)가 목표를 설정해 틱택토를 진행할 방을 만든다.
3. 다른 사용자(B)에게 코드 공유 및 방 입장
4. 해당 칸에 있는 행동을 하면 O 또는 X를 표시하며 게임 진행
5. 게임 결과에 따라 결과 화면 표시

배운점 및 느낀점

당장 바로 아이디어를 내고 기획에 들어가는 것이 아니라 특정 페르소나를 설계하고 거기에서부터 기획을 시작하는것이 흥미롭고 많은 깨달음이 왔다.
생각하지도 못한 경로의 아이디어들이 나와서 회의가 즐거웠다!!
MVP라는 개념은 처음 들어보았는데 근본적인 것 부터 접근할 수 있어서 부담이 줄며 실현 가능성이 높아지는 것 같아 의지가 올랐다
이 외에도 IA 등 여러 개념을 배웠다
탄탄대로가 아닐지라도 이 기획 단계를 기억하며 개발을 차근차근 나아가면 좋겠당 ..

'GDG-프로젝트' 카테고리의 다른 글

What I learn 3  (0) 2026.07.27
what i learn 2  (2) 2026.07.13
WEEK4 WHAT I LEARN  (1) 2026.05.21
WEEK3 WHAT I LEARN  (2) 2026.05.18
WEEK2 WHAT I LEARN  (1) 2026.05.11
1. 리팩토링(Refactoring)의 필요성

App.js 파일 하나에 API 연결 로직, 데이터가 없을 때의 UI, 데이터가 있을 때의 UI(Todo 목록) 등 모든 코드가 집중되어 있어 분리가 필요한 상황입니다.

여러 개발자가 협업하며 거대한 코드를 효율적으로 관리하기 위해, 코드를 역할과 관심사에 따라 컴포넌트(부품) 단위로 쪼개어 파일별로 따로 개발하는 리팩토링을 진행합니다.
 
리팩토링이란?: "결과의 변경 없이 코드의 구조를 재조정하는 작업"입니다. (결과물과 로직은 똑같이 작동하되 코드만 깔끔해지는 것)

처음부터 코드를 완벽하게 짜기는 어렵기 때문에, 먼저 동작하는 코드를 작성한 뒤 가공(리팩토링)을 거치며 좋은 코드로 발전시켜 나가야 합니다.
 
2. ESLint와 Prettier 정리하기
 
프로젝트 규모가 커지거나 여러 명이 함께 개발하게 되면 코드 스타일이 서로 달라질 수 있다.
예를 들어 어떤 사람은 들여쓰기를 2칸으로 하고, 어떤 사람은 4칸으로 하며, 세미콜론을 사용하는 사람과 사용하지 않는 사람이 섞일 수 있다. 이런 차이는 코드의 동작에는 큰 영향을 주지 않지만 가독성을 떨어뜨리고 협업 효율을 낮춘다.

이러한 문제를 해결하기 위해 사용하는 것이 Linting과 Formatting이다.

Linting: 코드에서 오류 가능성이나 비효율적인 문법을 검사하는 작업
Formatting: 코드 스타일을 일정한 규칙에 맞게 자동으로 정리하는 작업

대표적인 도구로 ESLint와 Prettier가 있다.
 
ESLint는 JavaScript와 React 코드에서 문법 오류나 잘못된 코드 스타일을 검사해주는 도구이다.
Prettier는 코드 스타일을 자동으로 정리해주는 Formatter 도구이다.
 
3. Context가 있는데도 상태 관리 라이브러리를 사용하는 이유
 
Context는 전역으로 값을 공유하는 데는 편리하지만, 상태가 자주 바뀌거나 여러 컴포넌트가 동시에 복잡하게 상태를 읽고 수정해야 하는 경우에는 코드가 복잡해질 수 있다. 또한 Provider 구조가 많아지면 코드가 길어지고, 상태 업데이트 로직을 따로 관리하기 어려워질 수 있다.
 
4. 상태 관리 라이브러리 종류
 
대표적인 상태 관리 라이브러리에는 Redux Toolkit, Zustand, Jotai, Recoil, MobX 등이 있다.

Redux Toolkit은 구조가 명확하고 큰 프로젝트에 적합하지만, 초보자에게는 설정과 개념이 어렵게 느껴질 수 있다. Zustand는 코드가 짧고 사용법이 단순해서 작은 프로젝트나 입문 단계에서 적용하기 좋다. Jotai는 atom 단위로 상태를 관리하는 방식이고, Recoil도 atom과 selector 개념을 사용한다. MobX는 상태 변화를 자동으로 추적하는 방식이다.
 
5. 느낀점
prettier로 코드 스타일을 정리해보려고 했는데 어떻게 하는지 감이 안와서 하지 못했다 ..
auto 가 아니라 수동으로 하는데 prettier에서 정한 스타일의 기준을 뭔지 모르겠어서 수정을 하지 못했다 ㅠㅠ 
수정을 해보면 계속 오류가 났다 ..  (linting은 잘 넘어갔다)
이외에도 파일을 정리하고 다듬는 과정에서 한번에 완성된 코드를 만들기보다 점차 깎아나가는 것이 더 좋은 개발 방법이라는 생각이 들었다. 

'GDG-프로젝트' 카테고리의 다른 글

what i learn 2  (2) 2026.07.13
what i learn 1  (1) 2026.06.28
WEEK3 WHAT I LEARN  (2) 2026.05.18
WEEK2 WHAT I LEARN  (1) 2026.05.11
WEEK1 WHAT I LEARN  (1) 2026.05.11

[1]   API 통신 맛보기

 

<API 연결 후 화면 작업>

1. 웹 통신 및 프론트엔드/백엔드 기본 개념
 
역할 놀이로서의 서버와 클라이언트:
- 서버(Server): 고객의 요청에 따라 무언가를 제공(서빙)하는 컴퓨터를 의미합니다
- 클라이언트(Client): 서비스를 요청하고 제공받는 고객(주로 브라우저)을 의미합니다
이 둘의 관계는 절대적이지 않으며, 서버끼리 데이터를 주고받을 때는 요청하는 서버가 클라이언트 역할을 하기도 합니다
 
API 및 프론트엔드/백엔드:API: 클라이언트와 서버가 데이터를 주고받기 위한 통로이자 약속입니다.
- 프론트엔드: 사용자가 직접 마주하고 상호작용하는 화면 영역을 개발합니다
- 백엔드: 사용자의 눈에 보이지 않는 뒤편에서 보안, 인증, 데이터 로직 등을 처리합니다.
 
2. fetch 내장 함수를 이용한 외부 데이터 호출
 
외부 API 테스트 사이트인 'JSONPlaceholder'를 활용하여 데이터(Todo 리스트 200개)를 가져오는 실습을 진행합니다
자바스크립트 내장 함수인 fetch를 사용해 브라우저 외부(서버)에 있는 데이터를 호출하며, 이 과정은 비동기 처리가 기본이 됩니다
 
3. 유즈 스테이트(useState) 사용 시 무한 루프의 대참사
 
호출한 데이터를 화면에 그리려고 단순히 useState의 상태 변경 함수(setTodos)를 컴포넌트 본문에 그대로 넣었을 때 무한 데이터 요청 루프가 발생하는 현상을 보여줍니다
원인 복습: 리액트 컴포넌트는 State가 바뀌면 업데이트(렌더링)가 일어납니다
 
코드 실행 -> fetch로 데이터 가져옴 -> setState로 상태 변경 -> 컴포넌트 리렌더링 -> 다시 fetch 실행 -> 무한 반복
이로 인해 짧은 시간 동안 서버에 수백 번 넘는 요청을 보내게 되므로, 컴포넌트의 순수성을 해치지 않으면서 외부에 영향을 주려면 새로운 접근이 필요함을 인지합니다.
 
4. 유즈 이펙트(useEffect)를 통한 해결 및 렌더링 분리
무한 루프 문제를 해결하기 위해 외부에 영향을 주거나 동기화할 때 사용하는 useEffect 훅을 도입합니다.
useEffect 내부로 fetch 로직을 격리하고, 두 번째 인자인 의존성 배열(Dependency Array)을 빈 배열([])로 설정하여 컴포넌트가 처음 화면에 나타날 때(마운트) 딱 한 번만 데이터를 받아오도록 제어합니다.
이를 통해 데이터가 오기 전에는 "데이터가 아직 없어요"라는 화면을 띄우고, 통신이 완료되면 200개의 리스트를 무한 루프 없이 안정적으로 렌더링하는 데 성공합니다.

 

< 비동기 처리의 이해>

1. API와 인터페이스의 개념

인터페이스(Interface)를 쉽게 이해할 수 있도록 자판기에 비유.

사용자는 자판기 내부의 복잡한 로직을 몰라도 돈을 넣고 버튼을 누르면(Input) 원하는 음료수(Output)를 얻을 수 있다.

개발 관점에서 Input은 URL과 추가 정보(Request Body)에 해당하며, Output은 받아오는 데이터에 해당

2. JSON 데이터 양식
서버로부터 리턴받는 데이터는 주로 JSON(JavaScript Object Notation) 형태로 받아옴.

JSON은 자바스크립트 객체와 유사한 모양을 가진 문자열 중심의 데이터 양식(배열, 객체, 문자열 등으로 구성)

3. 동기와 비동기 처리 (Asynchronous)
순차적으로 코드가 실행될 것이라는 예상과 달리, fetch 함수를 쓰면 시작/종료 로그가 먼저 찍히고 데이터가 나중에 출력되는 현상이 발생. 이처럼 순서대로 기다리지 않고 처리되는 것을 비동기

비동기 처리를 하는 이유: 만약 API 데이터를 받아오는 데 5초가 걸린다면, 동기적 방식에서는 브라우저가 화면을 읽다가 5초 동안 멈춰버려 유저가 이탈하게 됨.

따라서 자바스크립트 엔진은 브라우저 내부의 무언가(Web API)에 데이터 요청 처리를 맡겨두고 다음 코드를 계속 읽어 내려갑니다. 덕분에 유저는 화면이 멈추지 않은 상태에서 데이터가 로딩되는 것을 볼 수 있습니다.

4. JSON Placeholder URL 분석 및 객체 변환

예: /users/1/todos -> 유저 아이디가 1번인 사용자의 할 일(Todo) 데이터를 요청한다는 의미입니다.

fetch 내부에 쓰인 response.json() 함수는 서버에서 받아온 문자열 형태의 JSON 데이터를 자바스크립트가 진짜 사용할 수 있는 객체(Object)로 변환해주는 역할을 합니다.
 
 

 

[2] 동기/비동기 처리 학습하기

 

< 동기 / 비동기 처리(Promise, 콜백함수, async/await 포함) 학습하고 정리하기>

1. 동기(Synchronous) vs 비동기(Asynchronous)

1) 동기 (Synchronous)
개념: 요청과 결과가 동시에 일어나는 방식입니다. 하나의 작업이 시작되면 그 작업이 끝날 때까지 다음 작업들은 대기(Blocking)해야 합니다.

특징: 설계가 매우 직관적이고 순서대로 실행되지만, 앞선 작업이 오래 걸릴 경우 전체 프로그램이 멈추는(딜레이) 단점이 있습니다.

2) 비동기 (Asynchronous)
개념: 요청과 결과가 동시에 일어나지 않는 방식입니다. 특정 작업의 완료를 기다리지 않고, 즉시 다음 코드를 실행합니다(Non-Blocking).

웹 개발에서 필요한 이유: 서버에서 데이터를 받아오거나 대용량 파일을 로드할 때 네트워크 지연이 발생합니다. 비동기 처리를 하지 않으면 화면이 멈추거나, 데이터가 채워지기 전에 빈 화면이 먼저 렌더링되어 에러가 발생할 수 있습니다.

2. 비동기 처리를 제어하는 3가지 핵심 개념
자바스크립트는 기본적으로 싱글 스레드로 동작하기 때문에, 비동기 작업의 순서를 제어하고 결과를 안정적으로 받아오기 위해 다음과 같은 개념들을 사용합니다.

1) 콜백 함수 (Callback Function)
정의: 다른 함수의 인자로 넘겨져서, 특정 작업이 끝난 뒤에 실행되도록 예약된 함수를 말합니다.

문제점 (콜백 지옥 - Callback Hell): 비동기 작업의 결과를 가지고 또 다른 비동기 작업을 연속적으로 수행해야 할 때, 콜백 함수가 계속 중첩되면서 코드의 가독성이 떨어지고 유지보수가 불가능해지는 '멸망의 피라미드' 현상이 발생합니다.

2) Promise
정의: 콜백 지옥을 해결하기 위해 ES6에서 도입된 객체로, 비동기 작업의 최종 완료 또는 실패를 나타내는 그릇입니다.

3가지 상태:

Pending (대기): 비동기 처리 로직이 아직 완료되지 않은 상태

Fulfilled (이행): 비동기 처리가 성공적으로 완료되어 결과 값을 반환한 상태 (resolve() 호출)

Rejected (실패): 비동기 처리가 실패하거나 오류가 발생한 상태 (reject() 호출)

후속 처리 메서드:

.then(): 작업이 성공(Fulfilled)했을 때 실행할 로직을 정의합니다.

.catch(): 작업이 실패(Rejected)했을 때 에러를 처리합니다.

.finally(): 성공/실패 여부와 상관없이 무조건 마지막에 실행됩니다.

3) async / await
정의: ES8에서 도입된 문법으로, Promise를 기반으로 작동하지만 비동기 코드를 마치 동기 코드처럼 직관적으로 작성할 수 있게 해주는 문법적 설탕(Syntactic Sugar)입니다.

특징:

async: 비동기 작업을 수행할 함수 앞에 붙입니다. 이 키워드가 붙은 함수는 항상 Promise를 반환합니다.

await: async 함수 내부에서만 사용 가능하며, Promise가 처리(이행 또는 거부)될 때까지 함수의 실행을 잠시 중단하고 기다립니다.

에러 처리: 기존 동기식 코드에서 사용하던 try ... catch 문을 그대로 사용하여 비동기 에러를 직관적으로 잡아낼 수 있습니다.
 
[3] fetch/axios 학습하기
 
< fetch와 axios에 대해 학습하고 정리하기>
 
1. fetch() 함수 개요
1) 개념
정의: 자바스크립트의 내장 함수로, 브라우저 환경에서 별도의 설치 없이 서버와 HTTP 통신을 할 수 있게 해주는 API입니다.

특징: 인터넷 익스플로러를 제외한 대부분의 모던 브라우저에서 기본적으로 지원하며, Promise 기반으로 동작합니다.

2) 장단점
장점:
 별도의 내장 라이브러리 설치(npm, CDN 등)가 필요 없어 가볍고 편리합니다.
 자바스크립트 표준 API이므로 환경에 구애받지 않고 안정적으로 사용할 수 있습니다.

단점:
 HTTP 에러 상태 코드(예: 404, 500)가 반환되어도 catch()로 가지 않고, 네트워크 장애가 발생해야만 에러로 취급합니다. (응답의 response.ok 속성을 직접 확인해야 함)
 JSON 데이터로 변환하기 위해 반드시 .json() 메서드를 호출하는 추가적인 파싱 과정을 거쳐야 합니다.
 구형 브라우저(IE 등) 지원을 위해 별도의 폴리필(Polyfill)이 필요할 수 있습니다.

2. axios 라이브러리 개요

1) 개념
정의: Node.js와 브라우저 환경을 모두 지원하는 HTTP 클라이언트 외부 라이브러리입니다.

특징: fetch와 마찬가지로 Promise 기반으로 작동하며, 웹 개발에 필요한 편리한 부가 기능들을 다수 내장하고 있습니다.

2) 장단점
장점:
 응답 데이터를 자동으로 JSON으로 파싱해 주므로 코드 가독성이 좋습니다.
 HTTP 에러 상태 코드(4xx, 5xx)를 자동으로 감지하여 바로 catch 블록으로 던져줍니다.
 인터셉터(Interceptors) 기능을 제공하여 요청(Request)이나 응답(Response)이 처리되기 전에 공통 로직(예: JWT 토큰 주입, 로딩 스피너 제어)을 쉽게 구현할 수 있습니다.
 요청 취소(Cancel token) 기능 및 요청 타임아웃 설정이 간편합니다.

단점:
 프로젝트에 추가적인 모듈 패키지(npm install axios) 설치가 필요하므로 프로젝트 용량이 미세하게 늘어납니다.
 
 
[4] Mock Data를 이용하여 api 연결해보기
 
기존 JSON 파일들
public/data/
category.json
item.json
priceSelected.json
sorted.json
 
fetch 주소
/data/item.json
/data/category.json
/data/priceSelected.json
/data/sorted.json
 
1단계: src/apis 폴더 안에 shopApi.js 만들기

여기서 핵심은

fetch('/data/item.json')
 

public/data/item.json 파일을 가져오는 코드입니다.

 

 

await response.json()
 

가져온 JSON 데이터를 JavaScript 객체/배열로 바꿔주는 코드입니다.

 

기존 방식:

import { itemData } from '../data/mockData'
 

새 방식:

const data = await getItemData()
setItems(data)
 

즉 이제는 데이터를 파일에서 바로 import하는 게 아니라:

public/data/json 파일
→ fetch
→ src/apis/shopApi.js
→ 페이지 컴포넌트
→ 화면 출력
 
 [5] 쇼핑몰 웹 기능 구현하기 - 관리자 페이지
 
 
 
느낀점!!!!!!!!!!
 
보이는 것은 동일한 화면이어도 데이터를 어떻게 불러오냐에 따라 달라진다는게 신기하고 아직 막 와닿지는 않는다. 
api와 비동기 방법에 대해서 더 공부를 해봐야할 것같다 ... 
어떤 이유 때문에 어떤 방법을 쓰는 건지를 머리에 넣을 필요가 느껴짐 .. 
어렵 ㅠㅠ

'GDG-프로젝트' 카테고리의 다른 글

what i learn 2  (2) 2026.07.13
what i learn 1  (1) 2026.06.28
WEEK4 WHAT I LEARN  (1) 2026.05.21
WEEK2 WHAT I LEARN  (1) 2026.05.11
WEEK1 WHAT I LEARN  (1) 2026.05.11

1. CSS 학습하기

 

HTML과 CSS는 각자의 문법을 갖는 별개의 언어이며 HTML은 CSS를 포함할 수 있다. 그러나 HTML없이 단독으로 존재하는 CSS는 의미가 없다.

Rule Set의 집합을 스타일시트(Style Sheet)
프로퍼티는 표준 스펙으로 이미 지정되어 있는 것을 사용하여야하며 사용자가 임의로 정의할 수 없다.
여러 개의 프로퍼티를 연속해서 지정할 수 있으며 세미콜론(;)으로 구분한다.
 
html css 연결은 link style : <link rel="stylesheet" href="css/style.css">
각 프로퍼티에 따라 사용할 수 있는 키워드가 존재한다. 예를 들어 display 프로퍼티의 값으로 사용할 수 있는 키워드는 block, inline, inline-block, none이 있다.
 
Box는 콘텐트(Content), 패딩(Padding), 테두리(Border), 마진(Margin)로 구성된다.
 
일반적으로 화면을 스크롤하면 배경 이미지도 함께 스크롤된다. 화면이 스크롤되더라도 배경이미지는 스크롤되지 않고 고정되어 있게 하려면 background-attachment 프로퍼티에 fixed 키워드를 지정한다.
 

.css와 .module.css의 가장 큰 차이는 스타일의 적용 범위(scope) 

<일반 .css 파일 방식>
CSS 클래스 이름이 전역적으로 공유됩니다.
프로젝트 규모가 커질수록
클래스 이름 중복
의도하지 않은 스타일 덮어쓰기
유지보수 어려움
어느 컴포넌트의 스타일인지 추적 어려움
같은 문제가 자주 발생합니다.

<.module.css 방식>
CSS Module은 클래스 이름을 자동으로 고유하게 변환합니다.

컴포넌트마다 독립적인 스타일 사용 가능
클래스 이름 충돌 방지
유지보수 쉬움
이라는 장점이 있습니다.

.css는 프로젝트 전체에 영향을 주는 전역 스타일이고,
.module.css는 특정 컴포넌트에만 적용되는 지역 스타일이다.

그래서 React/Next.js에서는 스타일 충돌을 막고 유지보수를 쉽게 하기 위해 .module.css를 많이 사용합니다.
2. TailwindCSS, React Router 세팅
커스텀 훅의 이점: useFetchUser와 같은 커스텀 훅을 만들어 사용하면, 여러 페이지에서 공통으로 사용하는 로직(데이터 패칭, 상태 관리 등)을 한 곳으로 모아 코드의 중복을 줄일 수 있습니다.

주의사항: 커스텀 훅은 유용하지만 너무 남발하지 않는 것이 좋으며, 더 나은 방법들이 있을 수 있음을 인지해야 합니다

여러 페이지를 가진 서비스를 만들기 위해 페이지별로 URL을 할당하는 방법을 소개. 리액트 라우터 라이브러리 .. 패키지 관리, 라이브러리 설치, 설치 확인 등 ..
랜더함수 다시 넣으면 브라우저 주소창에 /user/1 또는 /user/2를 입력하여 각기 다른 유저 페이지가 정상적으로 출력

react router 적용과정
터미널에
npm i react-router
npm run dev
작성

main.jsx 수정
import { createBrowserRouter, RouterProvider } from 'react-router'
라우터 기능을 가져오는 코드 작성

tailwindcss 적용과정

터미널에
npm install tailwindcss @tailwindcss/vite
작성
vite.config.js 수정

 plugins: [
    react(),
    tailwindcss(),
  ],
tailwindcss 추가한것이 핵심


3-1. props, state 그리고 hooks 맛보기

 

리액트의 탄생 배경과 Virtual DOM


탄생 배경: 2010년경 페이스북은 좋아요 버튼 클릭 시 전체 페이지를 다시 불러와야 하는 서버 부하 문제를 해결하고자 했습니다. 이를 위해 페이지의 일부만 동적으로 바꾸는 방식(AJAX 등)을 고민하게 되었습니다.

Virtual DOM (가상 돔): 직접적인 DOM 조작은 브라우저 리소스를 많이 소모합니다. 리액트는 메모리상에 가상의 돔을 두고, 변경된 부분만 비교하여 한 번에 업데이트하는 방식을 채택하여 효율성을 높였습니다


리액트 상태 관리: useState Hook

상태(State)의 필요성: 단순한 자바스크립트 변수는 값이 변해도 브라우저가 이를 인지하여 화면을 다시 그리지 않습니다.

useState: 브라우저가 컴포넌트의 변화를 감지할 수 있도록 낚싯바늘을 거는 것과 같은 Hook 개념입니다

구조: const [state, setState] = useState(initialValue); 형태로 사용하며, setState 함수를 통해서만 상태를 변경해야 화면이 업데이트(Re-rendering)됩니다


컴포넌트 간 데이터 전달: Props
Props (Properties): 부모 컴포넌트가 자식 컴포넌트에게 데이터를 전달하는 방식입니다.

특징: 데이터는 위에서 아래로 흐르는 단방향 구조를 가지며, 전달받은 Props가 변경되면 해당 자식 컴포넌트도 다시 렌더링됩니다

컴포넌트 생애 주기 (Life Cycle)

컴포넌트의 생애는 크게 세 단계로 나뉩니다.

Mount (마운트): 컴포넌트가 처음 나타날 때.
Update (업데이트): Props나 State가 변경되어 화면이 바뀔 때
Unmount (언마운트): 컴포넌트가 사라질 때.

과거에는 클래스형 컴포넌트로 이를 관리했으나, 현재는 함수형 컴포넌트와 Hook을 사용하는 방식이 주류가 되었습니다.
 
 
3-2. React Hooks
 
useState는 React에서 값이 변하는 데이터를 저장할 때 사용하는 기능이다. 일반 변수는 값이 바뀌어도 화면이 자동으로 바뀌지 않지만, useState를 사용하면 값이 변경될 때 React가 화면을 다시 렌더링해준다. 예를 들어 쇼핑몰에서 장바구니 개수, 검색창 입력값, 로그인 상태처럼 계속 바뀌는 데이터를 관리할 때 사용한다. useState는 현재 값을 저장하는 변수와 값을 변경하는 함수를 함께 제공하며, 값을 변경하면 React가 변경 사항을 감지해서 화면을 다시 그려주는 방식으로 동작한다.

useEffect는 특정 작업을 자동으로 실행하기 위해 사용하는 기능이다. 보통 페이지가 처음 실행될 때 데이터를 가져오거나, 어떤 값이 바뀌었을 때 추가 작업을 하고 싶을 때 사용한다. 예를 들어 쇼핑몰 페이지가 열리자마자 상품 목록을 불러오거나, 검색어가 변경될 때마다 검색 결과를 다시 보여주는 기능에 사용할 수 있다. useEffect는 컴포넌트가 실행되는 시점이나 상태 변화에 맞춰 자동으로 동작하기 때문에 React에서 매우 자주 사용되는 기능이다.

useNavigate는 React Router에서 페이지 이동을 할 때 사용하는 기능이다. React는 페이지 전체를 새로고침하지 않고 화면만 바꾸는 방식으로 동작하는데, useNavigate는 원하는 주소로 이동하도록 도와준다. 예를 들어 쇼핑몰에서 상품을 클릭했을 때 상세 페이지로 이동하거나, 로그인 성공 후 메인 페이지로 이동할 때 사용할 수 있다. 버튼 클릭과 같은 이벤트가 발생하면 navigate('/경로')를 실행하고, React Router가 해당 주소에 맞는 화면을 보여주는 방식으로 작동한다.

정리하면 useState는 변하는 데이터를 저장하는 기능이고, useEffect는 특정 작업을 자동 실행하는 기능이며, useNavigate는 페이지를 이동시키는 기능이다. 이 세 가지는 React 프로젝트에서 가장 기본적이면서도 중요한 기능들이다.
 
 
4. react 발전시키기 , 쇼핑몰 화면 발전시키기 
react router 로 변경하구 
css도 tailwindcss 로 바꾸고
usenavigate로 이동하도록 설정도 하구 
useeffect로 활성화 비활성화도 해봤어요 
 
버튼을 눌르면 활성화가 되기도 합니다 console에서 확인도 가능!

 

5. 느낀점!!

이제 본격적인 시작인 느낌이 들고 더 어지럽고 .... 눈물이 나온다 .....

근데 뭔가 삐걱이지만 되고있는거 같아서 뿌듯^^

ai를 쓰고 바로 복붙하지 않고 코드를 해석하면서 하고 또 하나씩 건들여보면서 감을 익히고 있다

갈길이 구만리지만 ... ..... 구만리 뚜벅뚜벅 걸으면 돼!!!!!!!!!!!!!!!!!!!!!!1

'GDG-프로젝트' 카테고리의 다른 글

what i learn 2  (2) 2026.07.13
what i learn 1  (1) 2026.06.28
WEEK4 WHAT I LEARN  (1) 2026.05.21
WEEK3 WHAT I LEARN  (2) 2026.05.18
WEEK1 WHAT I LEARN  (1) 2026.05.11

1. JS 살펴보기

id 로그인할때 많이 쓴다.
고유한 아이디가 있으면 자바에서 컨트롤하기 쉽다.
addEventlistener
listener => 잘 귀 기울여 듣다가 사건이 발생하면 실행한다.
브라우저가 하는일 .
html 파일을 열고
한줄 씩 읽음 (파싱)
파싱 중 script 발견 => 화면이 늦게 뜸 (유저들 개빡), id보다 먼저 실행됨 (순서가 꼬인다) => script 를 맨 마지막에 써야합니다. 
 
자바스크립트 ... 브랜든 아이크가 만들어봄
문서 리더기였다가 자바스크립트를 실행시켜줄 무언가가 되었다.
크롬 브라우저 덕분에 프론트엔드 직군이 생겼다고 볼 수 있는 것이지요

크롬 : 압도적으로 개발하기 편리하고 압도적으로 빨랐다.
v8엔진 ..  

노드는 자바스크립트를 실행할 수 있는 환경 '런타임 환경' 입니다.
 
 
2. HTML & JavaScript 살펴보기

 

html 웹페이지의 내용과 구조를 담당하는 언어
반드시 <! DOCTYPE html> 으로 시작해야한다.
<head></head> 사이에는 document title, 외부 파일의 참조, 메타데이터의 설정 등이 위치하며 이 정보들은 브라우저에 표시되지 않는다.
웹브라우저에 출력되는 모든 요소는 <body></body> 사이에 위치한다.

HTML 요소는 시작 태그(start tag)와 종료 태그(end tag) 그리고 태그 사이에 위치한 content로 구성
요소는 중첩될 수 있다
어트리뷰트(Attribute 속성)이란 요소의 성질, 특징을 정의하는 명세, 요소에 추가적 정보(예를 들어 이미지 파일의 경로, 크기 등)를 제공

시맨틱 태그란 브라우저, 검색엔진, 개발자 모두에게 콘텐츠의 의미를 명확히 설명하는 역할을 한다. 시맨틱 태그에 의해 컴퓨터가 HTML 요소의 의미를 보다 명확히 해석하고 그 데이터를 활용할 수 있는 시맨틱 웹이 실현될 수 있다

기본태그들
html tag
head tag
title tag
style tag
link tag
script tag
body tag
<b> 볼드체 => <strong>
<i> / <em> 이탤릭체
<br> 줄바꾸기

존 문서나 텍스트의 선형성, 고정성의 제약에서 벗어나 사용자가 원하는 순서대로 원하는 정보를 취득할 수 있는 기능을 제공한다. 한 텍스트에서 다른 텍스트로 건너뛰어 읽을 수 있는 이 기능을 하이퍼링크(hyper link)라 한다. a(anchor) tag가 그 역할을 담당

변수를 선언할 때 var 키워드를 사용한다. 할당 연산자 =는 변수에 값을 할당하기 위해 사용한다(데이터 타입/변수/리터럴)
c나 java와 다르게 데이터 타입을 미리 정하지 않는다. 동적으로 변수의 타입이 결정됨

예를 들어 숫자(number) 타입 1과 문자열(string) 타입 ‘1’은 비슷하게 보이지만 다른 타입의 값이다. 숫자 타입의 값은 주로 산술 연산을 위해 만들지만 문자열 타입의 값은 주로 텍스트로 출력하기 위해 만든다. 이처럼 개발자는 명확한 의도를 가지고 타입을 구별하여 값을 만들 것이고 자바스크립트 엔진은 타입을 구별하여 값을 취급할 것이다.

객체는 데이터와 그 데이터에 관련한 동작(절차, 방법, 기능)을 모두 포함할 수 있는 개념적 존재이다. 달리 말해, 이름과 값을 가지는 데이터를 의미하는 프로퍼티(property)와 동작을 의미하는 메소드(method)를 포함할 수 있는 독립적 주체이다.

자바스크립트는 객체(object) 기반의 스크립트 언어로서 자바스크립트를 이루고 있는 거의 “모든 것”이 객체이다. 원시 타입(Primitives)을 제외한 나머지 값들(배열, 함수, 정규표현식 등)은 모두 객체이다.
 
 
3. React 시작하기
 
협업 및 유지보수의 한계: 수천 줄의 HTML 코드를 여러 개발자가 동시에 작업할 때 발생하는 충돌과 비효율성을 해결하기 위해 등장
컴포넌트 기반 개발: 화면을 독립된 부품(Component) 단위로 나누어 개발함으로써 재사용성을 높이고 관리를 용이하게 함
DOM 트리와 렌더링: 브라우저가 HTML을 읽어 DOM 트리를 만드는 과정을 설명하며, 자바스크립트로 이를 효율적으로 조작하기 위한 도구
JSX와 바벨(Babel): 자바스크립트 내에 HTML 태그를 직접 쓰는 듯한 JSX 문법을 사용하며, 이를 브라우저가 이해할 수 있는 코드로 변환해 주는 바벨
SPA (Single Page Application): 한 페이지 내에서 자바스크립트가 화면을 동적으로 조작하여 앱처럼 동작하는 방식을 다룸
라이브러리 vs 프레임워크: 리액트는 자유도가 높은 라이브러리이며, 필요에 따라 다양한 외부 라이브러리를 조합해 사용해야 함을 강조
컴포넌트 규칙: 함수명과 파일명은 반드시 대문자로 시작해야 기존 HTML 태그와 구분된다.
 
 
4. react 프로젝트 시작해보기 
npm create vite@latest . 명령어를 사용해서 react를 시작해봤어요 ....
쇼핑몰 화면 구현도 조금 해봤어요 .......... 
구현해본 쇼핑몰 화면
 
 
 
5. 컴포넌트의 개념을 다시 한번 복습하고, ‘왜 컴포넌트로 나누어야 하는지’와 ‘어떤 기준으로 컴포넌트를 나누는 것이 좋은지
컴포넌트란 화면을 여러 개의 작은 부분으로 나누어 각각을 하나의 요소처럼 관리할 수 있도록 하는 개념
컴포넌트를 나누는 기준으로는 먼저 화면의 구조(UI)를 기준으로 구분
시각적으로 구분되는 단위, 기능적인 역할에 따라 나눌 수도 있다.
컴포넌트 분리는 코드의 효율성과 유지보수성을 높이기 위한 설계방식
 
 
 
6. 느낀점!!
 
css가 낯설고 html 도 매우매우 낯설고 jsx, react 등등 하나도 모르는데 화면이 변해가는 것을 보는건 재밌는거 같아요 .
근데 ai를 많이 사용해서 머리에 많이 안남는거 같아 이부분을 보완할 방법을 찾아야할 것 같습니다.!!
프로젝트를 완성하는 것도 중요하지만 ... 머리에 새겨지는것도 필요하니깐요 ...
앞으로는 코드를 이해하며 과제를 해보도록 도전 !~~
 
 
 
 

'GDG-프로젝트' 카테고리의 다른 글

what i learn 2  (2) 2026.07.13
what i learn 1  (1) 2026.06.28
WEEK4 WHAT I LEARN  (1) 2026.05.21
WEEK3 WHAT I LEARN  (2) 2026.05.18
WEEK2 WHAT I LEARN  (1) 2026.05.11

[data dictionary]

ID

매물확인방식 

보증금

월세

전용면적

해당층

총층

방향

방수

욕실수

주차가능여부

총주차대수

관리비

중개사무소

제공플랫폼

게재일

허위매물여부

 

[데이터 전처리]

결측치 있는 피처 - 전용면적(787), 해당층(229), 총층(16), 방수(16), 욕실수(18), 총주차대수(696)

 

결측치가 5% 미만인 총층, 방수, 욕실수는 결측치 행 삭제로 제거 

총주차대수 : boxplot으로 확인 후 이상치 제거 -> 매물들의 총층을 세구간으로 나누기(1-7층/8-14층/15층~) -> 각 구간별 총 주차대수의 평균 구하기 -> 결측치가 있는 매물의 층 구간에 맞추어 평균값으로 채워넣기

df_train = df_train.drop(df_train[df_train['총주차대수'] >= 73.375].index)

df_train = df_train.assign(nclass = np.where(df_train['총층']<8, 'a',
                                    np.where(df_train['총층']<15, 'b',
                                                                  'c')))
                                                                  
df_train.groupby('nclass')\
        .agg(mean = ('총주차대수', 'mean'))
        
df_train.loc[df_train['nclass'] == 'a', '총주차대수'] = df_train.loc[df_train['nclass'] == 'a', '총주차대수'].fillna(11.0)
df_train.loc[df_train['nclass'] == 'b', '총주차대수'] = df_train.loc[df_train['nclass'] == 'b', '총주차대수'].fillna(20.0)
df_train.loc[df_train['nclass'] == 'c', '총주차대수'] = df_train.loc[df_train['nclass'] == 'c', '총주차대수'].fillna(27.0)

 

해당층 - 같은 방식으로 각 구간의 평균값으로 결측치 채움, 해당층이 총층보다 높은 값으로 채워진 경우는 총층을 해당층으로 변경

df_train.groupby('nclass')\
        .agg(mean = ('해당층', 'mean'))
 
 df_train.loc[df_train['nclass'] == 'a', '해당층'] = df_train.loc[df_train['nclass'] == 'a', '해당층'].fillna(3.0)
 df_train.loc[df_train['nclass'] == 'b', '해당층'] = df_train.loc[df_train['nclass'] == 'b', '해당층'].fillna(6.0)
 df_train.loc[df_train['nclass'] == 'c', '해당층'] = df_train.loc[df_train['nclass'] == 'c', '해당층'].fillna(9.0)
 
 df_train.loc[(df_train['총층'] < 3.0) & (df_train['해당층'] == 3.0), '해당층'] = df_train['총층']

 

전용면적 - 방수가 같은 매물들끼리 전용면적의 평균을 구하고 방수에 맞추어 해당 값으로 채움

df_train.groupby('방수')\
        .agg(mean = ('전용면적', 'mean'))

df_train.loc[df_train['방수'] == 1.0, '전용면적'] = df_train.loc[df_train['방수'] == 1.0, '전용면적'].fillna(25.45)
df_train.loc[df_train['방수'] == 2.0, '전용면적'] = df_train.loc[df_train['방수'] == 2.0, '전용면적'].fillna(31.22)

 

방향, 매물확인방식, 주차가능여부 - 더미변수로 만들기

 

제공플랫폼- 빈도 인코딩

중개사무소 - 라벨 인코딩

 

게재일 - 날짜데이터로 변환 후 년, 월, 일 피처 생성

 

경과일 (새 피처) - 데이터셋에서 가장 최근에 올라온 매물날짜를 기준으로 각 매물들이 올라온지 얼마나 되었는지 나타내는 피처 생성

latest_date = train_encoded['게재일'].max()
train_encoded['경과일'] = (latest_date - train_encoded['게재일']).dt.days
latest_date = test_encoded['게재일'].max()
test_encoded['경과일'] = (latest_date - test_encoded['게재일']).dt.days

 

[모델링]

import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier, VotingClassifier
from xgboost import XGBClassifier
from lightgbm import LGBMClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score


# 2. 개별 모델 정의
rf_model = RandomForestClassifier(n_estimators=100, random_state=42)
xgb_model = XGBClassifier(use_label_encoder=False, eval_metric='logloss', random_state=42)
lgb_model = LGBMClassifier(random_state=42)

# 3. 보팅 분류기 생성 (Soft Voting)
voting_clf = VotingClassifier(
    estimators=[
        ('random_forest', rf_model),
        ('xgboost', xgb_model),
        ('lightgbm', lgb_model)
    ],
    voting='soft'  
)

# 4. 모델 학습
voting_clf.fit(X_train, y_train)

+ Recent posts