묻고 답해요
163만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
병합이랑 변경감지를 왜쓰나요? 그냥 jpa에 있는 sql문 update를 쓰면 되지않나요?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]예전에 프로젝트를 할때jpa에 있는 sql문을 통해서 update문으로 수정을 했는데병합이랑 변경감지를 구지 쓰는 이유가 있을까요?
-
해결됨Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
특정 dir로 위치를 잡으려면 어떻게 설정을 해야할까요
config를 root dir에 위치시킨게 아니라 특정 dir에 넣고 싶은데 그럴 때는 어떻게 uri를 잡아야하나요?
-
미해결자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]
6강 질문 @RequestParm, @RequestBody
@GetMapping("/add") public int addTwoNumbers(CalculatorAddRequest request) { return request.getNumber1() + request.getNumber2(); } @PostMapping("/multiply") public int multiplyTwoNumbers(@RequestBody CalculatorMultiplyRequest request) { return request.getNumber1() * request.getNumber2(); }GetMapping 메소드에서는 @RequestParm 어노테이션을 사용하지 않아도 자동으로 쿼리 데이터를 DTO로 변환해주고 PostMapping 메소드에서는 @RequestBody 어노테이션을 사용해야만 Body 데이터를 DTO로 변환해주는 것인가요?
-
해결됨Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
jjwt 0.12 이상으로 하시는 분들에게..
jjwt가 버전업 되면서 강사님이 업데이트 해주신 코드들도 jwt valid할 때 안되는 경우가 발생하더라고요... 그래서 찾아본결과다음과 같이 작성하시면 원활하게 동작을 합니다. 참고하세요. private boolean isJwtValid(String jwt) { byte[] secretKeyBytes = Base64.getEncoder().encode(env.getProperty("token.secret").getBytes()); SecretKey signingKey = new SecretKeySpec(secretKeyBytes, SignatureAlgorithm.HS512.getJcaName()); boolean returnValue = true; String subject = null; try { JwtParser jwtParser = Jwts.parser(). verifyWith(signingKey).build(); Jws<Claims> claimsJws = jwtParser.parseSignedClaims(jwt); Claims payload = claimsJws.getPayload(); subject = payload.getSubject(); }catch (Exception ex){ returnValue = false; } if(subject == null || subject.isEmpty()){ returnValue = false; } return returnValue; }
-
해결됨스프링 DB 2편 - 데이터 접근 활용 기술
mybatis적용2 오류
[질문 내용]https://drive.google.com/file/d/14dXFBLKqzY9hcZZAXjr0e1CCKV9u_U22/view?usp=sharing 제자리에 다 맞게 넣은 것 같은데 Could not detect default configuration classes for test class 오류가 뜹니다 ...이렇게 애노테이션을 추가해도 오류가 뜹니다@ContextConfiguration(classes = ItemServiceApplication.class
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
member엔티티와 order 엔티티의 조회 시 관계
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]json으로 return 할 때 궁금한 점이 있어서 질문드립니다.이전 강의에서 member 엔티티 자체를 json 타입으로 return 할 때는 orders(컬렉션)에 대해 무한루프가 걸리지 않았지만 order를 json 타입으로 return하게 되면 강의에서 처럼 여러 엔티티들에 의해 무한루프가 걸리게 됩니다.컬렉션인 데이터의 경우 무한루프에 걸리지 않는 이유가 무엇인가요??
-
미해결코드로 배우는 React 19 with 스프링부트 API서버
TypeError: Cannot read properties of undefined (reading 'map')에 대한 문제
크롬에서의 문제입니다웹스톰 내에서는 또 다른 문제가 있다고 하네용 import { useEffect, useState } from "react"; import { getList } from "../../api/productsApi"; import useCustomMove from "../../hooks/useCustomMove"; import FetchingModal from "../common/FetchingModal"; import { API_SERVER_HOST } from "../../api/todoApi"; import PageComponent from "../common/PageComponent"; import useCustomLogin from "../../hooks/useCustomLogin"; const host = API_SERVER_HOST const initState= { dtoList:[], pageNumList:[], pageRequestDTO: null, prev: false, next: false, totalCount: 0, prevPage: 0, nextPage: 0, totalPage: 0, current: 0 } const ListComponent = (props) => { const {page, size, refresh, moveToList, moveToRead} = useCustomMove() const {exceptionHandle} = useCustomLogin() //serverData는 나중에 사용 const [serverData, setServerData] = useState(initState) //for FetchingModal const [fetching, setFetching] = useState(false) useEffect(() => { setFetching(true) getList({page,size}).then(data => { console.log(data); if(data && data.dtoList){ setServerData(data); } setFetching(false); }).catch( err => exceptionHandle(err)) }, [page,size, refresh]) return ( <div className={"border-2 border-blue-100 mt-10 mr-2 ml-2"}> {fetching ? <FetchingModal/> :<></>} <div className="flex flex-wrap mx-auto p-6"> {serverData.dtoList && serverData.dtoList.map(product => <div key= {product.pno} className="w-1/2 p-1 rounded shadow-md border-2" onClick={() => moveToRead(product.pno)} > <div className="flex flex-col h-full"> <div className="font-extrabold text-2xl p-2 w-full "> {product.pno} </div> <div className="text-1xl m-1 p-2 w-full flex flex-col"> <div className="w-full overflow-hidden "> <img alt="product" className="m-auto rounded-md w-60" src={`${host}/api/products/view/s_${product.uploadFileNames[0]}`}/> </div> <div className="bottom-0 font-extrabold bg-white"> <div className="text-center p-1"> 이름: {product.pname} </div> <div className="text-center p-1"> 가격: {product.price} </div> </div> </div> </div> </div> )} </div> <PageComponent serverData={serverData} movePage={moveToList}></PageComponent> </div> ); } export default ListComponent;Listcomponent에 문제가 있다고 해서 찾아보려고 하는데 어떻게 봐도 모르겠습니다ㅜㅜ 누구든 도와주세요
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
generated생성경로
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요.안녕하세요 compilejava를 하면 강의와는 달리 프로젝트 바로밑에 build폴더가 생기고 그안에 generated/source/annotationProcessor/main....Qitem이 생깁니다.그런데 아래를 실행하면 build폴더부터해서 아래폴더들이 다 지워집니다. 경로가 강의와는 달리 생성되는것과, 밑의 delete file을 실행했을 때, 어떻게 생성된 것들이 지워지는지 궁금합니다.(경로가 다른데)clean{ delete file('src/main/generated')}
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
JpashopApplication 실행 시
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. 처음에 선생님이 환경설정 하신다고 JpashopApplication에아래와 같은 코드 만들어놓고 메인메서드 실행하셨는데 저는 그럴때마다 Process 'jpashop [:JpashopApplication.main()]' Is Running 'jpashop [:JpashopApplication.main()]' is not allowed to run in parallel. Would you like to stop the running one? 이런 메세지 뜨면서 새로 실행이 되는데 선생님께선 Do not show this dialog in the future 체크해놓고 매 실행시마다 새로 실행이 되는게 맞는걸까요?Hello hello = new Hello(); hello.setData("hello"); String data = hello.getData(); System.out.println("data = " + data);
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
h2대신 mysql로 했습니다
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]h2console에는 이전강의시간에 했던 test만 작동되고.. jpashop이 안만들어져서 그냥 mysql로 했습니다spring: datasource: url: jdbc:mysql://localhost:3306/jpashop username: user password: user1234 driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: create properties: hibernate: dialect: org.hibernate.dialect.MySQL8Dialect format_sql: true logging: level: org.hibernate.SQL: debugddl-auto: create로 되어있는데 어플리케이션 실행후 workbench로 가보면ORM 표존 JPA 프로그래밍때 했던 DB가 그대로 있습니다..drop 된 후 새로 create 되는것이 아닌가요?스프링부트에서도 hibernate sql문 출력이 안됩니다,, 테스트에서도 @Rollback(false)를 안하면 통과이고@Rollback(false)를 하면 unknown column오류가 납니다..
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
뷰 코드 복사했는데 복사도 이상하게 되고 실행하면 오류가 뜨는데 뭐가 잘못된건가요?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]pdf 파일에 있는 뷰 코드복붙했는데실행하면 오류가 뜹니다. pdf파일 복사가 제대로 안되는데 왜 구지 pdf로 올리는지 모르겠네요 일단 코드 보여드릴게요creatememberform.html<!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <head th:replace="fragments/header :: header" /> <style> .fieldError { border-color: #bd2130; } </style> <body> <div class="container"> <div th:replace="fragments/bodyHeader :: bodyHeader"/> <form role="form" action="/members/new" th:object="${memberForm}" method="post"> <div class="form-group"> <label th:for="name">이름</label> <input type="text" th:field="*{name}" class="form-control" placeholder="이름을 입력하세요" th:class="${#fields.hasErrors('name')}? 'form-control fieldError' : 'form-control'"> <p th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Incorrect date</p> </div> <div class="form-group"> <label th:for="city">도시</label> <input type="text" th:field="*{city}" class="form-control" placeholder="도시를 입력하세요"> </div> <div class="form-group"> <label th:for="street">거리</label> <input type="text" th:field="*{street}" class="form-control" placeholder="거리를 입력하세요"> </div> <div class="form-group"> <label th:for="zipcode">우편번호</label> <input type="text" th:field="*{zipcode}" class="form-control" placeholder="우편번호를 입력하세요"> </div> <button type="submit" class="btn btn-primary">Submit</button> </form> <br/> <div th:replace="fragments/footer :: footer" /> </div> <!-- /container --> </body> </html>itemlist.html<!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <head th:replace="fragments/header :: header" /> <body> <div class="container"> <div th:replace="fragments/bodyHeader :: bodyHeader"/> <div> <table class="table table-striped"> <thead> <tr> <th>#</th> <th>상품명</th> <th>가격</th> <th>재고수량</th> <th></th> </tr> </thead> <tbody> <tr th:each="item : ${items}"> <td th:text="${item.id}"></td> <td th:text="${item.name}"></td> <td th:text="${item.price}"></td> <td th:text="${item.stockQuantity}"></td> <td> <a href="#" th:href="@{/items/{id}/edit (id=${item.id})}" class="btn btn-primary" role="button">수정</a> </td> </tr> </tbody> </table> </div> <div th:replace="fragments/footer :: footer"/> </div> <!-- /container --> </body> </html>이코드 실행하면Whitelabel Error Page라고 뜨네요뭐가문제인가요..pdf그대로 복사하면 복사가 제대로 안되서 붙여넣어지는데불편하네요
-
미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
프록시 강의 38:27 질문드립니다. (em.close())
강의에서는 em.close()했을 때도 예외가 발생한다고 하셨고, 저도 em.close()하면 영속성 컨텍스트가 종료되기 때문에 프록시 초기화 시 문제가 생길것이라고 생각했지만 실제로 해보니 예외가 발생하지 않아서 질문드립니다. Member member1 = new Member(); member1.setUsername("member1"); em.persist(member1); em.flush(); em.clear(); Member reference = em.getReference(Member.class, member1.getId()); System.out.println("reference.getClass() = " + reference.getClass()); // em.detach(reference); // 준영속 상태로 만들어버림 // em.clear(); // 영속성 컨텍스트를 완전히 초기화 em.close(); // 영속성 컨텍스트를 완전히 종료 reference.getUsername(); tx.commit();
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
MyBastis 와 Bean 그리고 Spring 호환성문제
mybastis를 2.3.1로 내려주었는데도 서버를 띄울때와 itemRepositorytest를 돌릴때 모두 오류가 뜹니다.. 첫번째로, 서버가 띄워지지않음두번째로, ItemRepositoryTest가 실행되지않음 두개가 문제인데 driver로 올리겠습니다... https://drive.google.com/file/d/12WrW91kPvb9tfqzoR64OwF05eOsLZJPl/view?usp=drive_link
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
교육 끝났는데 진행률이 100%가 안되네요?????
"스프링부트와 jpa활용 1편"마지막 교육인 "다음으로"까지 다 수강했는데진행률이 100%가 되지 않습니다???
-
해결됨실전! Querydsl
Test에서 QHello.java를 못찾아요
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오) 네2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 있는데 다 해봐도 안돼요3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 네[질문 내용] springboot 3버전으로 해결 방법을 다 써봤는데 안되어서 문의드립니다.setting -> Annotaion Processorsbuild.gradleplugins { id 'java' id 'org.springframework.boot' version '3.2.4' id 'io.spring.dependency-management' version '1.1.4' } group = 'study' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '17' } configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testCompileOnly 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok' implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta" annotationProcessor "jakarta.annotation:jakarta.annotation-api" annotationProcessor "jakarta.persistence:jakarta.persistence-api" } tasks.named('test') { useJUnitPlatform() } clean { delete file('src/main/generated') } 폴더 확인 bbuild.gradle 설정도 잘해서 build 폴더에 잘 생겼는데 Test에서 import를 못해요
-
미해결코드로 배우는 React 19 with 스프링부트 API서버
소셜로그인시 이메일 중복 관련 처리 문의
소셜로그인 강의까지 봤는데요,강의에 있는 프로세스는소셜로그인시 이메일을 가져와서 DB에 저장이 되어있지 않으면 카카오이메일로 회원가입을 시키고, DB에 저장이 되어있으면 비밀번호 없이 해당 계정으로 로그인이 되게끔 만드는 프로세스로 이해 했습니다.그런데, 기존에 회원가입을 하지 않은 사람이 소셜로그인을 할 때 이미 기존에 가입되어 있는 이메일이 있다면 다른사람 계정을 비밀번호 없이 로그인 할 수 있게되는게 지금 구현한 상황에서는 맞는거죠? ex) 기존에 회원가입한 'A' 의 이메일이 test@AAA.com 일 때신규 유입된 사람 'B'의 카카오계정 이메일이 test@AAA.com 인 경우 위와 같은 경우를 방지하려면 소셜로그인시(최초로그인) 회원가입을 시킬 때 이메일 중복체크를 하고 중복되어있다면 다른 이메일 사용을 권유 해야되는식으로 처리를 해야 하는건가요?
-
미해결Practical Testing: 실용적인 테스트 가이드
Order.class 에대하여
학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요!먼저 유사한 질문이 있었는지 검색해 보세요.서로 예의를 지키며 존중하는 문화를 만들어가요. 강의 듣다가 궁금한 점이 생겨서 질문을 작성합니다!Order 클래스는 @Entity 어노테이션이 붙어있는 도메인 객체인데 여기에 어떤 로직? 이라고 해야 하나요? List<OrderProduct> 를 바로 넣어주는 것이 아니고 List<Product>를 받아서 값을 뽑아서 new OrderProduct 로 생성하거나, calculateTotalPrice() 같은 메서드를 작성해도 괜찮은가요? (현업에서도 많이 쓰이는 방법인가요? 뭔가 따로 service로 빼도 괜찮지 않을까 라는 생각이 들었습니다. )전에 간단한 토이 프로젝트를 할 때 cascade = CascadeType.ALL 가 아닌 cascade = CascadeType.REMOVE 로 설정하고 Order을 생성한 후 OrderProduct를 수동으로 생성했었는데 CascadeType.ALL 이 더 범용적으로 많이 쓰는 방법인지테스트 코드 작성법을 배우려고 듣게 되었는데 뭔가 라이브 코딩을 따라가면서 전반적으로? 많이 배우고 있어서 좋아요! ㅎㅎ 좋은 강의 감사합니다.
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
의존관계에러
[질문 내용]대댓글을 확인안해주시는 것 같아 질문 다시 올립니다 !의존관계가 잘못되었는지 테스트 3개가 다 안 돌아갑니다 뭐가 잘못된건지 모르겠습니다 ..https://drive.google.com/file/d/1yZWpxXR6pZD3RVN6Zt3ni5hFttutBKrj/view?usp=sharing
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
h2에 다른 별도의 프로젝트를 연결하려면 어떻게 해야할까요?
h2.properties에서 포트번호를 다른 번호로 바꾸고 해봐도 이전에 했던 h2 포트로 연결이 되더라구요... 별도 프로젝트를 다른 포트로 연결하고 싶을 땐 세팅을 어떻게 해야할까요? 찾아봐도 잘 안돼서 질문드립니다.(스프링 프로젝트이고 gradle 사용하여 application.properties에 해당 h2 db 연결하려고 하는 상황입니다)
-
미해결자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]
안녕하세요 다른분 질문에서 강사님에 답변에서 질문있습니다.!!
똑같은 이름의 책 등록을 막기 위해서는 스프링 부트의 멀티스레드 구조와 단일 인스턴스 - 서버가 1대인 경우 - 일 때의 synchronized 구문, 멀티 인스턴스 - 서버가 N>=2 대 인경우 - 일 때의 DB unique key 등을 언급해야 하고, (이 과정에서 서버의 인프라도 설명이 들어갑니다!) 동시 대출을 방어하기 위해서는 DB의 Lock(잠금) 종류와 원리에 대해 설명해야 합니다. 이렇게 답변주셨는데 대용량 트래픽 개인프로젝트를 설계한다고 해야한다면 서버를 여러대 생각을 하고 DB unique key를 생각을 해야할지 먼저 서버 1대를 생각하고 synchronized 구문으로 똑같은 이름의 책 등록을 막아야할지 고민입니다.!!