Server76 테이블 테이블은 데이터베이스에서 정보를 정리해서 저장하는 큰 표 같은 것이다. 이 표는 가로줄(행)과 세로줄(열)로 이루어져 있다.행(Row): 테이블에서 가로로 있는 줄로, 하나의 데이터를 의미한다. 예를 들어, 친구 명단이 있는 표에서는 한 명의 친구에 대한 정보가 하나의 행이 된다.열(Column): 테이블에서 세로로 있는 줄로, 각 열은 특정한 종류의 정보를 나타낸다. 예를 들어, 친구 명단에서 "이름", "나이", "전화번호" 같은 것이 각각 하나의 열이 된다.예를 들어, 친구들의 정보를 저장하는 테이블이 있다고 하면, 다음과 같이 생길 수 있다: 번호이름나이전화번호1철수14010-1234-56782영희13010-8765-4321 2024. 8. 25. 회원 관리 - 프론트) 3. 모든 회원 조회하기 1. 멤버 컨트롤러에 회원 조회 처리 메소드 추가하기@GetMapping("/members")public String list(Model model) { List members = memberService.findMembers(); model.addAttribute("members", members); return "members/memberList";} [작동 방식]1. 리스트에 서비스 메소드인 findMemebers를 이용해 모든 회원을 저장한다.2. model(컨트롤러가 뷰로 데이터를 전달할 때 사용하는 객체)에 members라는 키로 members 리스트를 저장3. 회원 목록화면 렌더링 2. HTML 작성파일 경로: main/resources/templates/member/memb.. 2024. 8. 25. 회원 관리 - 프론트) 2. 회원 등록하기 1. 파일 생성파일 경로: main/java/파일명/Controller/MemberForm 해당 경로로 MemberForm.java를 만들어준다. package section4.section4_spring.controller;public class MemberForm { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; }} 해당 파일을 만든 이유는 폼을 들어올 데이터를 처리하기 위해서 이다. 2. 멤버 컨트롤러에 메서드 추가//URL 진입 시 처리될 코드@GetMapping("/members/ne.. 2024. 8. 25. 회원 관리 - 프론트) 1. 홈화면 추가하기 1. 파일 생성파일 경로: main/java/파일명/Controller/HomeController 해당 경로로 HomeController.java를 만들어준다. 2. 홈 컨트롤러 추가package hello.hellospring.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.GetMapping;@Controllerpublic class HomeController { @GetMapping("/") public String home() { return "home"; }} 위의 코드를 간단하게 설명하자면 /라는 경로로 들어오면 home.. 2024. 8. 25. 스프링 빈 등록하기 - 2. 자바코드로 직접 빈 등록하기 컴포넌트를 이용하는 방법은 자동으로 빈을 등록해주는 것이었다. 이번에는 자바 코드로 직접 빈을 등록해보자. ❓왜 자동이 있는데 수동으로 빈을 등록하는가?❓-> 세밀한 제어, 외부 라이브러리 통합 등 복잡하고 특정한 요수사항을 처리할 수 있다는 점이 있다. -> 우리가 수동으로 빈을 등록하는 것을 채택한 가장 큰 이유는 나중에 Repository에서 DB로 쉽게 변경하기 위해서 이다. 1. 자바를 작성할 config 파일 만들기파일 경로: src/main/java/SpringConfig 해당 경로에 SpringConfig 파일을 만든다. 2. 코드 작성하기 package section4.section4_spring;import org.springframework.context.annotation.Bea.. 2024. 8. 25. 스프링 빈 등록하기 - 1. 컴포넌트 스캔과 자동 의존관계 설정 private final MemberRepository memberRepository = new MemoryMemberRepository();기존에 필요한 객체가 있다면 위의 코드와 같이 직접 객체를 만들어와서 사용해왔다. 다만, 이렇게 할 경우 아래의 단점 들이 생기게 된다. 1. 높은 결합도: 클래스들이 서로 강하게 연결되어, 변경이 어려워집니다.2. 유연성 부족: 다른 구현체(클래스)로 쉽게 교체하기 어렵습니다.3. 테스트 어려움: 테스트할 때 실제 객체를 사용해야 하므로 느려지고 복잡해집니다.4. 가독성 및 유지보수성 저하: 코드에서 의존성을 파악하기 어렵고, 관리가 힘들어집니다.5. 재사용성 저하: 특정 상황에 맞게 유연하게 재사용하기 어렵습니다. 따라서 우리는 @Component와 @Au.. 2024. 8. 25. 회원관리 - 백엔드 개발) 4. 회원 서비스 테스트하기 우선 테스트하기 전 조치를 해야할 것이 있다. MemberService memberService = new MemberService();MemoryMemberRepository memberRepository = new MemoryMemberRepository();우리는 위의 코드와 같이 필요할 때마다 객체를 새로 만들어 주고 있다. 다만 이렇게 되었을 때의 문제 점은 테스트 할 때마다 매번 새로운 객체를 만들면 테스트 간에 공유해야 할 데이터나 상태가 초기화되어 일관성이 없는 결과가 나올 수 있다. 즉, 한 객체에 데이터를 저장한 후 다른 테스트에서 그 데이터를 확인해야 하는데, 객체가 새로 만들어지면 이전 데이터가 사라져서 테스트가 실패할 수 있다. 따라서 우리는 DI(Dependency Inj.. 2024. 8. 25. 회원관리 - 백엔드 개발) 3. 회원 서비스 개발하기 💡 서비스란, 비즈니스 로직을 처리하는 계층을 말한다. 즉, 사용자를 등록하거나 주문을 처리하는 비즈니스 로직 이 여기에 담긴다. 컨트롤러에서 요청을 받으면, 서비스가 일을 처리하고, 필요하면 데이터베이스와 연결해 데이터를 가져오거나 저장한다. 파일 경로: src/main/java/만든 파일명/service(만들어야함)/MemberService package section4.section4_spring.service;import section4.section4_spring.domain.Member;import section4.section4_spring.repository.MemberRepository;import section4.section4_spring.repository.MemoryMemberR.. 2024. 8. 24. 회원관리 - 백엔드 개발) 2. 각각의 repository 메소드 테스트 하기 test폴더를 통해서 테스트를 해보자.파일 경로: test/java/만든 파일명/repository/MemoryMemberRepositoryTest [MemoryMemberRepositoryTest.java]package section4.section4_spring.repository;import org.junit.jupiter.api.Assertions;import org.junit.jupiter.api.Test;import section4.section4_spring.domain.Member;import java.util.List;import static org.assertj.core.api.Assertions.*;class MemoryMemberRepositoryTest { MemoryMemb.. 2024. 8. 24. 회원관리 - 백엔드 개발) 1. 회원 도메인과 Repository 만들기 1. 도메인 만들기💡 도메인이란, 애플리케이션이 다루는 비즈니스 문제 영역과 그 영역을 표현하는 객체들을 의미한다. 파일위치: src/main/java/만든 파일명/domain(직접 만들어야하는 패키지)/Member [Member.java] package section4.section4_spring.domain;public class Member { private Long id; private String name; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; .. 2024. 8. 24. JSON 데이터를 직접 반환하여, 템플릿을 거치지 않고 API 응답을 처리하기(API 활용하여 개체 JSON으로 반환하기) (파일 경로: src/main/java/hello_spring/controller/HelloController) 특정 경로로 전달된 특정 매개변수 값을 받아 JSON으로 반환하기@GetMapping("hello-api")@ResponseBodypublic Hello helloString(@RequestParam("name") String name){ Hello hello = new Hello(); hello.setName(name); return hello; //객체 반환}static class Hello { private String name; public String getName() { return name; } public void setName(.. 2024. 8. 24. HTML 페이지 렌더링 시 요청받은 데이터 포함하기(매개변수를 MVC패턴으로 전달해 렌더링하기) 1. MVC 패턴을 이용하여 특정 경로로 들어오는 GET 요청 처리하는 컨트롤러 만들기(파일 경로: src/main/java/hello_spring/controller/HelloController) @GetMapping("hello-mvc")public String helloMvc(@RequestParam("name") String name, Model model){ model.addAttribute("name", name); return "hello-template";} 코드를 하나씩 해석보자. @GetMapping("hello-mvc")-> /hello-mvc 경로로 들어오는 HTTP GET 요청을 처리할 메서드를 지정합니다. public String helloMvc(@RequestPar.. 2024. 8. 24. HTML 페이지 렌더링 시 고정된 데이터 포함하기(MVC와 템플릿엔진 이용해보기) 1. Welcome Page 만들기 (파일 경로: src/main/resources/static/index.html) 아래의 html을 구성해서 간단한 Welcome Page를 만들어보자.HelloVisit Hello Page 2. MVC 패턴을 이용하여 특정 경로로 들어오는 GET 요청 처리하는 컨트롤러 만들기(파일 경로: src/main/java/hello_spring/controller/HelloController) package hello.hello_spring.controller;import org.springframework.ui.Model;import org.springframework.stereotype.Controller;import org.springframework.web.bind... 2024. 8. 24. AWS Lambda 사용기 근로관련 디스코드 봇을 만들었는데 이 프로그램이 동작할려면 매번 vscode를 실행시켜줘야하다는 문제가 있었다.이 문제를 AWS Lambda로 해결했다. 빠른 요약1. 람다에서 기본 지원하지 않는 외부 라이브러리를 모두 새로운 폴더에 설치2. 해당 폴더에 작성한 코드를 람다에서 사용할 코드로 변경후 저장3. 위의 내용물이 있는 폴더를 zip파일로 압축4. AWS Lambda 함수를 생성5. 위에서 생성한 zip파일을 코드 - 코드소스에 zip 파일로 업로드6. 트리거 추가 후 event bridge 선택7. event bridge에서 cron으로 규칙생성 [전체 코드]import requestsfrom bs4 import BeautifulSoupimport timeimport datetimeimpor.. 2024. 6. 25. 데이터를 주고 받는 방법 모음 1. 폼(form)으로 데이터 전송하기 [폼이 있는 페이지] 제목 날짜 전송하기 폼태그 내부에 있는 action은 뭔가? Action은 어떤 경로로 action을 취할 건지를 정해주는 것이다. 따라서 위의 코드를 살펴보면 /add 라는 경로로 post를 요청한다는 것을 작성해준 것이다. 폼태그 내부에 있는 method는 뭔가? Method는 GET/POST중 어떤 요청을 할 것인지를 정하는 것이다. !!!! req.body는 POST 밖에 안된다! GET은 안됨 [sever] app.post('/add', function(request, response) console.log(request.body.title); console.log(request.body.date); response.send('전송완료.. 2023. 9. 17. Socket.io - 실시간 데이터 주고 받기(2) 저번 글에서는 유저가 서버에게 데이터를 보냈다. 이번에는 서버가 유저에게 데이터를 보내는 방법을 알아보자. [sever.js] io.on('connection', function(socket){ //누군가 웹 소켓에 접속하면 실행 console.log('connect in WebSocket...'); io.emit('데이터명', '데이터');// 서버에서 유저에게 데이터 보내기 }) [socket.ejs] io.emit()은 한 유저에게만 데이터를 전달하는게 아니라 해당 사이트에 접속한 모든 유저에게 메시지를 보낸다. 만약 서버 - 특정 유저 단독으로 소통하고 싶다면? // 해당 소켓 id를 가진 유저에게만 전송한다. io.to(socket.id).emit('데이터 명', '데이터') 그렇다면 socke.. 2023. 9. 17. Socket.io - 실시간 데이터 주고 받기(1) 이전에 배운 SSE는 서버에서 일방적으로 실시간 응답만 해주었다. 이번에는 양방향으로 실시간 응답이 가능한 Web Socket을 배워보자. 1. WebSocket을 쓰기위한 socket.io 라이브러리 설치하기(server.js) npm install socket.io 터미널에 해당 코드 입력 2. socket.io 세팅하기(server.js) const http = require('http').createServer(app); const { Server } = require("socket.io"); const io = new Server(http); 해당 코드는 const app = express() 보다 아래에 작성해야한다. 3. app.listen 부분 변경하기(server.js) // [이전 코드.. 2023. 9. 16. DB 변동사항 실시간 통보해주기(change stream) 데이터가 변동이 되어도 서버에서는 감지할 수가 없다. 따라서 이번에는 DB 데이터의 실시간 변화를 감지해서 DB가 서버에 알려주는 기능을 해보자. const pipeLine = [ { $match: { } } ]; // 찾을 문서 //예시 //const pipeLine = [ // { $match: { 'fullDocument.parent': request.user._id } } //fullDocument는 필수로 붙여야함. //]; const changeStream = db.collection('message').watch(찾을문서); //어느 콜렉션에서 찾을 문서가 있는지 감시할지 changeStream.on('change', (result) => { //변동 사항이 생길 경우 작동 console.l.. 2023. 9. 15. 실시간으로 DB 데이터를 계속 가져오는법(SSE) 프로젝트를 진행하다 보면 실시간으로 DB 데이터를 가져와야하는 경우가 있다. ( 예를 들어 채팅같은 경우) 이런 경우 계속 DB에 GET 요청을 해도 되지만 이런 경우 서버에 과부화가 걸리게 된다. 따라서 우리는 서버와 유저간의 실시간 소통채널을 열어 데이터을 주고 받기를 해보려고한다. (server sent events) GET 요청할 부분 (프론트) 해당 코드는 어떤 UI가 클릭되었을 때와 같이 이벤트가 발생했을 때 작동되는 코드 내부에 넣어주면 된다. var eventSource; // get 요청하는 부분 (ajax get 하는 것과 비슷하다고 생각하면 된다) eventSource = new EventSource('경로'); eventSource.addEventListener('서버에 쓴 데이터 .. 2023. 9. 15. 채팅 기능 만들어보기 (혼자 만들어본 버전) [순서도] // 채팅 버튼 클릭 시 작동 app.post('/createchat', function(request, response){ db.collection('chatroom').findOne({ title: request.body.title }, function (error, result) { if (error) return error if (!result) { console.log('채팅방찾음x'); request.body.member.push(request.user._id.toString()); //채팅에 참여한 멤버로 현 로그인한 사용자를 넣었음. db.collection('chatroom').insertOne(request.body, function (error, result) { if (!.. 2023. 9. 13. 이미지 업로드 해보기 1. 이미지를 업로드하는 페이지 만들기 업로드 페이지 전송 해당 코드의 form을 보면 enctype이라고 우리가 이전에 보지 못한 속성이 있다. 이 속성은 뭘까? enctype이란? 폼 데이터(form data)가 서버로 제출될 때 해당 데이터가 인코딩되는 방법을 명시해주는 속성이다. enctype에 설정할 수 있는 아래 3개의 항목이 있다 application/x-www-form-urlencoded : 기본값으로, 모든 문자들은 서버로 보내기 전에 인코딩됨을 명시함. multipart/form-data : 모든 문자를 인코딩하지 않음을 명시함. / 파일이나 이미지를 서버로 전송할 때 주로 사용함. text/plain : 공백 문자(space)는 "+" 기호로 변환하지만, 나머지 문자는 모두 인코딩되지.. 2023. 9. 11. 라우터 폴더와 파일 만들어서 API 관리하기 해당 글은 이전 글들의 작업을 이어서 진행되고 있는 글입니다. 지금까지 만들었던 app.get~~ app.post~~ 이런 친구들을 라우터라고 하는데 server.js에 이 친구들이 너무 많기 때문에 용도에 따라서 파일을 분리해서 관리해보려고한다. 1. routes 폴더와 분리할 API의 파일 만들기 이번에는 연습용으로 아래의 API를 분리시켜보려고한다. app.get('/shop/shirts', function (요청, 응답) { 응답.send('셔츠 파는 페이지입니다.'); }); app.get('/shop/pants', function (요청, 응답) { 응답.send('바지 파는 페이지입니다.'); }); 2. 라우터 변수 만들기 라우터를 관리할 수 있도록 도움을 주는 함수를 이용해서 라우터 변수.. 2023. 9. 10. 회원 기능을 포함한 TODOLIST 사이트 해당 글은 이전 글들의 작업을 이어서 진행되고 있는 글입니다. 현재까지 만들어온 ToDoList 사이트는 누구든지 글을 삭제하고 수정할 수 있었다. 이번 글에서는 해당 글을 작성한 사람만 해당글을 삭제 또는 수정할 수 있는 회원기능을 포함한 사이트를 만들어 보겠다. 1. 작성한 글에 작성자의 고유 ID 담아서 DB에 저장하기 현재까지 작성된 코드는 게시물의 번호와 제목, 마감일만 DB에 보냈다. 해당 데이터로는 누가 글을 썼는지 알 수 없다. 그래서 이번에 글을 작성할 때는 위의 데이터 뿐만 아니라 로그인한 사용자의 _id까지 DB에 보내보자. 그러면 사용자의 _id는 어떻게 가져올까? 이 글에서 우리는 request.user에 대해서 배웠다. 해당 데이터는 로그인한 유저의 모든 정보를 담고 있는데 이 .. 2023. 9. 10. 검색기능 만들기(3) - Search Index 해당 글은 이전 글들의 작업을 이어서 진행되고 있는 글입니다. app.get('/search', (request, response) => { db.collection('post').find({ $text: {$search: request.query.value} }).toArray(function (error, result) { response.render('search.ejs', { keyword: result }) }); }) 이전에 만들었던 위의 코드는 한국어와 같이 조사가 많이 붙는 언어는 구분하기 못한다. 따라서 우리는 Search Index를 이용해서 탐색을 해야한다 . 1. 이전에 만들었던 Index 삭제하기 indexes로 들어가서 만들었던 index를 삭제한다. 2. Search Index.. 2023. 9. 9. 검색기능 만들기(2) - indexing 개념 해당 글은 이전 글들의 작업을 이어서 진행되고 있는 글입니다. 만약 DB에 데이터가 1000만개 있을 때 데이터를 찾으면 어떻게 될까? 1000만개를 모두 탐색해야하기 때문에 굉장히 오랜시간 걸린다. 따라서 DB는 보통 Binary Search라는 것을 사용한다. Binary Search란? 기본적으로 내림차순(오름차순)으로 정렬된 데이터에서 사용되는 탐색방법이다. 1. 전체 데이터의 평균이 되는 값을 찾는다. 2. 찾는 값이 해당 평균 값보다 큰지 작은지를 확인한다. 3. 2번 결과에 해당 되는 데이터의 평균이 되는 값을 다시 찾는다. 4. 찾는 값이 해당 평균 값보다 큰지 작은지를 확인한다. 5. 값을 찾을 때 까지 위의 방식을 반복한다. 이제 Mongo DB에서 indexing 작업을 해보자. 1... 2023. 9. 8. 이전 1 2 3 4 다음