선정 이유

  • 아이디어 회의에서 나온 여러 의견 중 통일된 아이디어
  • 선아
  1. 게더타운
  2. 슬렉
  3. 랭 체인을 사용한 chatGTP 구현
  4. 인스타그램( 실시간 라이브, 추천 알고리즘, 앱개발 동시진행)
  5. 쇼핑몰 (front : react , 추천 알고리즘, 상담봇, 라이브커머스, admin페이지 별도진행, 결제)
  6. 유튜브 클론코딩 (영상 업로드, 실 시간 스트리밍, 자동번역, 추천 알고리즘)
  • 상엽
  1. 추천 알조리즘을 사용한 사이트 (ex : 영상공유 사이트, 쇼핑몰, 인스타그램 등)
  2. 코드 언어변환 (ex : c++ 을 java로 변환해주는 사이트)
  • 세웅
  1. 틱톡 (영상, 채팅) → 틱톡과는 다르게 해당 카테고리의 전문가만 올릴수있는 사이트
  2. 홈쇼핑(핫딜, 알림)
  3. 식당 예약 사이트 (웹, 앱)
  • 태영
  1. 쇼핑몰
  2. 인스타그램
  • 하나의 프로젝트에서 다양한 기능을 시도해볼수있는 콘텐츠가 많았다.
  1. 소켓 io를 사용한 실시간 채팅
  2. webRTC
  3. 결제 (모킹_가짜결제)
  4. 엘라스틱 서치를 사용한 검색엔진구성
  5. 상품 자동추천
  6. keycloak를 사용한 유저관리 시스템
  7. 트래픽 과부화 방지를 위한 다중서버구축

이성일 튜터님 피드백

  • 필수기능과 추가기능을 따로나눠서 프로젝트를 기획해주세요

<결과> -필수기능-

  1. 소켓 io를 사용한 실시간 채팅
  2. webRTC
  3. 결제 (모킹_가짜결제)

-추가기능-

  1. 엘라스틱 서치를 사용한 검색엔진구성
  2. 상품 자동추천
  3. keycloak를 사용한 유저관리 시스템
  4. 트래픽 과부화 방지를 위한 다중서버구축

조호영 튜터님 피드백

  • 기능의 종류나 난이도보다는 보다 딥한 생각을 해주세요 <결과> 맡은바 기능에 따라 주말동안 연구해보고 해당 기능에서 일어날 수 있는 문제점과 해결책을 생각해보기. 기능구현을 위한 언어의 선택 이유와 비교언어에 대한 차이 알아오기

2024.01.12 진행상황

  • ERD 작성 완료
  • API 정의서 작성완료
  • 튜터님 피드백 수정중
  • 기술컨텍중

이게 왜되조 프로젝트가 끝났다.

 

작업기간 : 2023-09-26 ~ 2023-10-11

 

팀원 및 역할

김선아(팀장) _ 소스관리(git), 방명록, 달력, 기부함, 시계

김윤찬(팀원) _ tistory크롤링, 발표, 문서작업

최태영(팀원) _ css,html

염지원(팀원) _ tistory크롤링, 발표, 문서작업

박유덕(팀원) _ 화면 hide&show , 팀원 스터디

 

https://kim-sunah.github.io/sprta-5/

 

이게 왜 되조 팀소개

S M T W T F S 응애 돈줘 test1 test2 test3 test3 test3

kim-sunah.github.io


Keep (현재 만족하고 계속 이어갔으면 하는 부분)

우리조는 각자의 장단점이 뚜렸했다.

  • 윤찬님은 기초부터 딥하게 파고들어가는 스타일이셨기 때문에 이해가 안되면 대충 넘기지 않고 물어보셔서 설명을 하면서 다시한번 본인들이 왜 이런코드를 쓰게되었는지 생각할 수 있었다.
  • 태영님은 온라인 환경에서 굉장히 적극적이셨기 때문에 다른조에서 새로운 기능이나 우리 프로젝트에 추가되면 좋을것같은 기능을 알아오셨다.
  • 지원님은 구글링을 너무너무 잘하셨다.
    특히 크롤링같은 경우 윤찬님과 함께 하셨는데 하루만에 node.js 크롤링 방법을 알아오셨고(아쉽게도 프로젝트에 적용하지는 못했지만) 기존의 방법으로 기능이 동작하지 않자 새로운 방법을 바로바로 알아오시고 적용시키셔서 프로젝트가 원활하게 진행되었다.
  • 유덕님은 베이스가 탄탄하셔서 지원님과 윤찬님이 많이 의지할수있는 지지대 역할을 해 주셨다.
    사실 나는 코드리뷰는 하고싶지 않았는데 본인코드 개선에 굉장히 적극적이셨고 본인이 적극적인만큼 팀원들도 함께 으쌰으쌰 하고싶어하셔서 다 함께 본인들의 코드를 다시한번 확인할 수 있는 기회가 생겼다.

Problem (불편하게 느끼고 개선이 필요하다고 생각되는 부분)

  • 소스관리를 fork를 사용해서 진행했는데 내가 git 사용법을 설명하지 못해서 병합관리를 할 수 있게된 사람이 태영님밖에 없다.
  • 기능상으로 에러는 없지만 비밀번호를 암호화 한 조가 있어서 '우리도 할껄....' 하는 생각이 들었다.
    발표 당일 아침에 '그래도 뭐 하나 더 넣자' 하고 달력에 날짜별 프로젝트 진행상황 출력기능을 넣고끝냈는데 그것보다 비밀번호 암호화가 더 있어보였다.
    db까지 보여줄거라는 생각을 못해서 못넣은게 아쉬웠다.
  • 처음에 지원님이 node로 크롤링을 아주 잘 해주셨는데 프로젝트를 node로 만들지 않아 버린 소스가 있다.
    연휴동안 node로 프로젝트를 만들었고 그곳에 지원님 소스를 넣었지만 함께하는 프로젝트에서 역시 node구현기능을 팀원에게 설명할 수 없어서 발표에 쓸 수 없었다.

Try (Problem해결책, 다음 회고때 판별 가능한것, 당장 실행 가능한것)

  • 시간을 들여서 깃 사용법을 숙지시켜주고싶다.
  • 비밀번호 암호화는 다음 프로젝트때는 넣어야겠다
  • 다음에는 node로 프로젝트를 만들어서 크롤링 기능을 넣어야겠다.

각자의 느낀점

  • 김선아 : 
    팀원들이 협조를 잘 협조해주었고 소통도 원활하게 되었다.
    프로젝트 기간 중 연휴가 끼어있어서 어쩔수없이 쉬는날에 연락하는 일이 많았는데 다들 귀찮아하지 않고 잘 받아주어서 고맙다고 생각했다.
    의사소통 과정에서 조금 문제가 있긴 했지만 협업관리 툴을 통해 작업 진행상황을 실시간으로 파악해 의도와 다른길로 가고있으면 바로 바로잡을 수 있었다.
    프로젝트 종료 후 코드리뷰를 하면서 나는 원래 설명을 잘 못했는데 다른사람들에게 설명하면서 어휘력이 조금 늘은것같아 기뻤다

  • 김윤찬 : 
    제가 이번 프로젝트가 끝나고 느낀점은 
    업무적으로는 많이 노력했다고 생각했는데도 원하는 만큼 하지 못해서 아쉬웠던 것 같고 아직 가야할 길이 멀다고 느껴졌습니다. 하지만 많이 성장했다고 생각합니다.
    협업을 하면서는 제가 맡은 파트가 적다보니 팀원들에게 도움을 주지 못한 것 같아 미안한 마음이 크게 들었고 다른 팀과 프로젝트를 할 때에도 짐이 되지 않게  더 열심히 해야겠다고 생각했습니다.

  • 최태영 : 
    개인적으로 혼자 코드를 짤 떄는 자신의 코드에 대해  피드백해주는 사람이 없어서 자신이 처음 생각한 것이 제일 좋다고 생각하는 경향이 있었는데 팀원들이랑 팀을 이뤄서 하니 피드백이란게 생겨서 결과물의 퀄리티가 올라가는 경험을 하여서 좋았다. 
    그리고 비록 지금은 작은 프로젝트지만 나중에 큰 프로젝트를 한다면 협업이란 경험이 꼭 필요하다고 생각한다.

  • 염지원 : 
    협업을 위해 소통을 한다는 것이 장단점이 있었던 것 같다.
    코드를 공유하거나 모르는 것을 질문하고 설명해주고, 또 프로젝트에 있어 서로의 부족함을 채워나가는 점은 좋았다. 그러나 소통을 시작할 때의 어색함과 어려움, 그리고 협업인 만큼 한 작업을 하더라도 소통이 필요했던 것이 불편함으로 다가왔다. 또한 실력의 편차로 인해 내가 일인분의 몫을 다 할 수 없다고 생각한 점이 마음이 불편할 수 밖에 없었고, 코드 외적인 부분에서 하나라도 더 맡아서 하려했던것 같다.
    이러한 장단점 모두 꼭 필요했던 경험이라고 생각하며, 공부를 더 열심히 해서 앞으로의 프로젝트에서는 일인분 이상의 능력을 발휘할 수 있도록 노력해야겠다.

  • 박유덕 : 
    평소에 어렵지 않다고 생각하던 일이 다수의 인원으로 나눠서 하게 되면 꽤 어려운 일이 될 수도 있다는 점을 느꼈고, 그와 더불어 되려 어렵다고 생각하는 부분을 동료에게 맡길 수 있다는 점 또한 느낀 것 같다. 
    평소에 누군가와 소통을 잘 하려는 타입은 아니라서 소통에 대해 꽤나 부담스러운 면도 있었기에 앞으로는 스스로 소통의 중요성을 조금 더 인지하며 협업을 해야겠다는 생각을 했다.

 

[Error] Origin null is not allowed by Access-Control-Allow-Origin. Status code: 0
[Error] Failed to load resource: Origin null is not allowed by Access-Control-Allow-Origin. Status code: 0 (commentList.js, line 0)

어제까지 멀쩡했던 파일에 type = "module"을 추가하니 스크립트 인식에러가 났다.

이때는 주소창을 확인해보자

vs code에서 art + b (맥은 option + b) 

의 명령어는 해당 파일을 브라우저에서 실행한다는 명령어인데 

module은 파일을 암호화하기때문에 브라우저에서 인식이 안된다.

 

하지만 서버에 올라가면 서버가 알아서 복호화 작업을 거쳐서 오류없이 실행시켜준다.

vs code에서는 라이브서버 단축키는 Alt + L + O 이다

조건

1.
가족들이 함께 볼 수 있도록 프론트도 구현해서 배포하세요.
2.
문제를 선택할 수 있도록 영어 단어를 랜덤으로 3개 띄워주세요.
3.
선택한 문제의 단어를 글자 단위로 숨깁니다. (e.g., "apple" -> "_ _ _ _ _")
4.
화면에 26개 알파벳을 띄워주세요.
5.
선택한 알파벳과 정답을 비교합니다.
6.
일치하는 알파벳이 있을 경우 기존 UI에서 사라지고 해당 위치에 표시됩니다.
7.
틀릴 경우 기존 위치에서 알파벳이 빨간색으로 바뀌고, 오류 횟수를 증가시킵니다.
8.
오류 날 때마다 ‘교수대-밧줄-머리-팔-손-몸통-다리-발’ 순서로 그려서 그림이 완성되면 ‘실패’ 를 띄웁니다. (오류 횟수 8번 이상은 실패)

배포 링크

https://kim-sunah.github.io/sparta/hangman/index.html

 

Document

Hangman 아래의 알파벳을 사용하여 단어를 맞춰주세요

kim-sunah.github.io

https://github.com/kim-sunah/sparta/tree/main/hangman

참여 소감

구글에서 받아온 소스에서 변경 몇개만 했다.

추가된 기능

1. 주제선택 기능 추가

2. 틀릴 경우 글씨색 변경

3. 직접그린 손그림을 넣었다

 

재밌었다!

 

코육대 이벤트 페이지

https://hanghaeplus-coyukdae.oopy.io/

 

항해 플러스: 제1회 코육대

이번 추석, 굳어버린 코딩 근육을 깨울 코딩 육상 대회가 왔다!

hanghaeplus-coyukdae.oopy.io

 

이것으로 나의 코육대는 끝났다

선물받고싶다

이왕이면 비싼걸루!

기능구현

- 연산 가능한 기본 계산기 구현

참여소감

- 구글에 '계산기'라고 치면 기본 css랑 html 구조가 나와서 편했다.

- js 는 https://velog.io/@whwodgns 이 블로그를 참고했는데 기본틀을 가져와서 제약사항에서 걸리는 부분만 수정했다

- spring으로 만들었으면 더 쉬웠을것같은데 내일배움캠프 node과정 수료중이라 js만 사용했더니 코드가 엄청 길어지고 복잡해졌다.

   다른사람들은 어떻게 만들었을지 궁금하다

고육데 이벤트 페이지 링크

https://hanghaeplus-coyukdae.oopy.io

개발언어

  • html
  • css
  • java script

제약사항

세뱃돈의 총 금액은 항상 0 이상이며, 디스플레이는 0으로 시작합니다.
입력에서는 연산자가 숫자 사이에만 나타납니다.
연산자가 주어지면, 해당 연산자를 사용하여 앞뒤 숫자를 계산하세요.
연산 결과는 소수점 이하를 버림하여 정수로 표시합니다.
세뱃돈은 한국 원화(KRW)로 주어지며, 최대 10자리 숫자까지만 입력됩니다.
10자리 숫자를 넘어가는 결과값은 Infinity 로 표기됩니다.
더하기, 곱하기, 나누기 다음 숫자를 입력하지 않고 ‘=’ 를 입력할 경우 alert을 띄워줍니다.
실수로 입력한 것을 모두 지울 수 있는 ‘AC’, 마지막에 입력한 값만 지울 수 있는 ‘C’ 버튼이 있어야 합니다.
0 나누기 0 과 같은 예외 결과값은 ‘숫자 아님’ 으로 표시됩니다.
연산자를 연달아 선택할 경우 마지막에 선택한 연산자가 적용되어야 합니다.

html

<!DOCTYPE html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <title>세뱃돈계산기</title>
    <link rel="stylesheet" href="style.css">
</head>

<body>
    <div class="container">

        <div class="calculator">
            <div class="display">
                <div>0</div>
            </div>

            <div class="button_container">

                <div class="button_content">
                    <button class="button_reset">CE</button>
                    <button class="button_reset">C</button>
                </div>

                <div class="button_content">
                    <button class="button_number">7</button>
                    <button class="button_number">8</button>
                    <button class="button_number">9</button>
                    <button class="button_operator">-</button>
                </div>

                <div class="button_content">
                    <button class="button_number">4</button>
                    <button class="button_number">5</button>
                    <button class="button_number">6</button>
                    <button class="button_operator">÷</button>
                </div>

                <div class="button_content">
                    <button class="button_number">1</button>
                    <button class="button_number">2</button>
                    <button class="button_number">3</button>
                    <button class="button_operator">×</button>
                </div>

                <div class="button_content">
                    <button class="button_number">0</button>
                    <button class="button_number">.</button>
                    <button class="calculate">=</button>
                    <button class="button_operator">+</button>
                </div>

            </div>
        </div>
    </div>

</body>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="index.js" type="module"></script>

</html>

css

* {
    box-sizing: border-box;
    padding: 0;
    margin: 0;
  }
  
  @font-face {
    font-family: 'LAB디지털';
    src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_20-07@1.0/LAB디지털.woff') format('woff');
    font-weight: normal;
    font-style: normal;
  }
  
  .container {
    width: 100vw;
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
  }
  
  .calculator {
    border: 3px solid rgb(164,164,151);
    width: 350px;
    height: 500px;
    padding: 5px;
    display: flex;
    flex-direction: column;
    justify-content: space-evenly;
    background-color: rgb(176, 176, 159);
    box-shadow: 3px 3px 3px 3px black;
    border-radius: 15px;
  }
  
  .display {
    display: flex;
    height: 20%;
    border: 1px solid white;
    justify-content: right;
    align-items: center;
    margin-left: 8%;
    margin-right: 8%;
    color: rgb(249, 128, 0);
    background-color: rgb(5,5,5);
    font-size: x-large;
  }
  
  .display span {
    margin-right: 10px;
    font-family: 'LAB디지털';
  }
  
  .button_container {
    display: flex;
    flex-direction: column;
    height: 60%;
    border: 1px solid black;
    margin-left: 8%;
    margin-right: 8%;
    background-color: rgb(18, 17, 17);
  
  }
  
  .button_content{
    border: 1px solid black;
    flex: 1 0 20%;
    display: flex;
    flex-direction: row;
    
  }
  
  .button_number {
    flex: 1 0 25%;
    background-color: rgb(82, 86, 78);
    color: white;
    font-family: 'LAB디지털';
    font-size: large;
    border-radius: 15px;
  }
  
  .button_number:hover{
    background-color: rgb(58, 60, 56);
  }
  
  .button_operator {
    flex: 1 0 25%;
    background-color: ivory;
    color: black;
    font-family: 'LAB디지털';
    font-size: large;
    border-radius: 15px;
  }
  
  .button_operator:hover{
    background-color: rgb(234, 240, 222);
  }

    
  .calculate {
    flex: 1 0 25%;
    background-color: ivory;
    color: black;
    font-family: 'LAB디지털';
    font-size: large;
    border-radius: 15px;
  }
  
  .calculate:hover{
    background-color: rgb(234, 240, 222);
  }
  
  
  .button_reset {
    flex: 1 0 25%;
    background-color: rgb(249, 128, 0);
    color: white;
    font-family: 'LAB디지털';
    font-size: large;
    border-radius: 15px;
  }
  
  .button_reset:hover{
    background-color: chocolate;
  }
  
  body {
    background-image: url("https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Hubble_ultra_deep_field.jpg/400px-Hubble_ultra_deep_field.jpg");
  }

java script

const calculator = document.querySelector('.calculator'); // calculator 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있음.
const buttons = calculator.querySelector('.button_container'); // calculator__keys 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있음.
const operator = document.querySelector('.calculator__operator'); // calculator__operator 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있음.
const display = document.querySelector('.display'); // calculator__display 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있음.

function calculate(n1, operator, n2) {
    console.log(n1, operator, n2)
    let result = 0;
    if(Number(n1)==0 && Number(n2)==0){
        return "숫자아님"
    }else if (operator === '+') {
        result =  Math.floor(Number(n1) + Number(n2)); // '+'버튼을 눌렀을 때
    }
    else if (operator === '-') {
        result =  Math.floor(Number(n1) - Number(n2)); // '-'버튼을 눌렀을 때
    }
    else if (operator === '×') {
        result =  Math.floor(Number(n1) * Number(n2)); // '*'버튼을 눌렀을 때
    }else if (operator === '÷') {
        result = Math.floor(Number(n1) / Number(n2)); // '/'버튼을 눌렀을 때
    }
    if(String(result).length>10){
        return "Infinity"
    }
    return String(result);
    
}

let firstNum = '';
let operatorForAdvanced = '';
let previousKey = '';
let previousNum = '';

buttons.addEventListener('click', function (event) {
    const target = event.target; // 클릭된 HTML 엘리먼트의 정보가 저장되어 있음.
    const action = target.classList[0]; // 클릭된 HTML 엘리먼트에 클레스 정보를 가져옴.
    const buttonContent = target.textContent; // 클릭된 HTML 엘리먼트의 텍스트 정보를 가져옴.
    if (target.matches('button')) {
        // if(previousKey ===''){
        //     display.textContent=0
        // }
        if(display.textContent<0){
            alert("세뱃돈은 항상 양수입니다")
        }
        if (action === 'button_number') { //클릭된 HTML 엘리먼트의 클래스 네임이 'number'라면
            if (display.textContent == 0 && operatorForAdvanced === '') {
                display.textContent = buttonContent;
                firstNum = display.textContent // 첫번째 숫자를 변수에 할당
            } // 기존 계산기 숫자가 0이고, 오퍼레이터 버튼이 안눌린 상태의 분기
            else if (display.textContent != 0 && operatorForAdvanced === '' && display.textContent.length<10) {
                display.textContent = display.textContent + buttonContent;
                // textContent는 문자열이기 때문에 기존 계산기에서 보여지는 숫자에 +연산자로 구현 
                firstNum = display.textContent;
            } // 기존 계산기 숫자가 0이 아니고, 오퍼레이터 버튼이 안눌린 상태의 분기
            // ex) 15를 누르기 위해 1을 누른 상태의 분기(두자리 연속 누르기 위한 코드)
            else if (display.textContent != 0 && operatorForAdvanced !== '') {
                if (previousKey === operatorForAdvanced) {
                    display.textContent = buttonContent;
                    previousKey = display.textContent;
                    // 직전키를 변수에 할당 (직전키가 오퍼레이터냐 숫자냐에 따라 계산기의 다양한 기능을 구현하기 위함)
                    previousNum = display.textContent; // 직전 숫자를 변수에 할당
                } // 기존 계산기 숫자가 0이 아니고, 오퍼레이터 버튼이 눌린 상태의 분기
                // ex) 15+7을 하기 위해 15와 +를 누른 상태(두번째 숫자를 누르기 위한 코드)
                else if (previousKey !== operatorForAdvanced && display.textContent.length<10) {
                    display.textContent = display.textContent + buttonContent;
                    previousNum = display.textContent;
                } // ex) 15+17을 하기 위해 15와 +, 1을 누른 상태(17을 완성하기 위한 코드)
            }
        }
        if (action === 'button_operator') { // //클릭된 HTML 엘리먼트의 클래스 네임이 'operator'일때 분기
            operatorForAdvanced = buttonContent; // 오퍼레이터 누를 때 누른 텍스트 정보 할당
            previousKey = operatorForAdvanced; // 직전키에 오퍼레이터 텍스트 정보 할당

        }
        if (target.textContent === 'AC') { // AC(초기화) 버튼을 누를 때 분기
            display.textContent = 0;
            firstNum = '';
            previousNum = '';
            operatorForAdvanced = '';
            previousKey = '';
        }
        if (target.textContent === 'C') { // AC(초기화) 버튼을 누를 때 분기
            display.textContent = display.textContent.slice(0,-1);
            previousNum = display.textContent;
            // alert(1)
        }
        if (buttonContent === '=') { // Enter(계산) 버튼을 누를 때
            if (firstNum !== '' && operatorForAdvanced === '') {
                display.textContent = 0;
                firstNum = '';
                previousNum = '';
                operatorForAdvanced = '';
                previousKey = '';
                alert("잘못된 계산식")
            }
            else if (firstNum !== '' && previousNum === '') {
                display.textContent = calculate(display.textContent, operatorForAdvanced, display.textContent)
            } // 기존에 작성했던 calculate 함수를 이용하여 계산 상황에 따른 전달인자와 함께 호출
            else if (previousKey === display.textContent) {
                display.textContent = calculate(firstNum, operatorForAdvanced, previousNum)
                firstNum = display.textContent;
                previousNum = '';
                operatorForAdvanced = '';
                previousKey = '';
            }
            else if (previousKey !== display.textContent && previousNum !== '') {
                display.textContent = calculate(display.textContent, operatorForAdvanced, previousNum)
            }
            else if (previousKey !== display.textContent && previousNum === '') {
                display.textContent = firstNum;
            }
        }
    }
});

+ Recent posts