inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

172만명의 커뮤니티!! 함께 토론해봐요.

MVC와 API의 차이점

미해결

자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]

안녕하세요 강사님!! 다름이 아니라 공부를 하다가 MVC와 API의 차이점(?)에 대해 알아보게 되었습니다! 그래서 내린 결론이 Spring MVC구조의 @Controller는 컨트롤러의 리턴값이 ViewResolver에 의해 해석되어서 특정 View가 html응답으로 전송된다. 반면 REST API구조의 @RestController에 의한 호출은 View를 리턴하는 것이 목적이 아닌, 데이터를 전송하는 것을 목적으로 응답이 전송되어 진다. 라고 내렸습니다. 첫번째로, 위에서 제가 내린 결론이 맞는 말인지와 두번째로, 그럼 MVC를 쓰는 경우와 API를 쓰는 경우가 언제인지가 궁금합니다. 제가 아직 개념이 부족해서 그런건지는 몰라도 MVC를 쓰면 프론트엔드의 역할이 없어지는게(?) 아닌가 하는 착각이 들어서... 답변 부탁드리겠습니다!!

  • java
  • spring
  • aws
  • mysql
  • spring-boot
  • jpa
JMJ 댓글 1 좋아요 0 조회수 1151

코드 확인 부탁드립니다 ㅠ

미해결

자바(Java) 알고리즘 문제풀이 입문: 코딩테스트 대비

import java.util.*; public class Main { public static void main(String[] args){ Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[][] arr = new int[n][n]; for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { arr[i][j] = sc.nextInt(); } } int m = sc.nextInt(); int[] moves = new int[m]; for(int i = 0; i < m; i++){ moves[i] = sc.nextInt(); } ArrayList<Stack<Integer>> board = new ArrayList<>(); for(int i = 0; i < n; i++) { Stack<Integer> temp = new Stack<>(); for(int j = 0; j < n; j++) { if(arr[n-1-j][i] == 0) break; temp.push(arr[n-1-j][i]); } board.add(temp); } Stack<Integer> basket = new Stack<>(); int result = 0; for(int i = 0; i < m; i++) { int num = moves[i]-1; Stack<Integer> stack = board.get(num); if(stack.empty()) continue; int popNum = stack.pop(); if(!basket.isEmpty() && basket.peek() == popNum) { basket.pop(); result += 2; } else { basket.push(popNum); } } System.out.print(result); } } 어느 부분에서 틀린지 모르겠습니다. 확인 해주시면 감사하겠습니다.ㅠㅠ

  • java
  • 코딩-테스트
모깅 댓글 2 좋아요 0 조회수 219

searchParams props

미해결

Next + React Query로 SNS 서비스 만들기

안녕하세요 search 페이지 props에서 searchParams props가 기본적으로 제공된다고 알고있는데 저는 콘솔로 찍어보니 나오지 않습니다..! 혹시 제가 잘못적용한건지 아니면 다시한번 확인해야 될곳이 있을까요?/ import SelectBox from "@/components/common/SelectBox"; import SelectStack from "@/components/common/SelectStack"; import Peoples from "@/components/people/Peoples"; import SearchForm from "@/components/common/SearchForm"; type Props = { searchParams: { page: string; size: string; sort?: string; keyword?: string; position?: string; teckStack?: string; }; }; export default function Page({ searchParams }: Props) { console.log("??", searchParams); return ( <div> <div className="relative flex items-center gap-4"> <h1 className="text-[36px] font-bold">People</h1> </div> <div className="flex justify-between"> <div className="flex gap-3"> <SelectBox options={option} title="포지션" /> <SelectStack /> </div> <SearchForm keyword={searchParams.keyword as string} /> </div> <Peoples searchParams={searchParams} /> </div> ); }

  • react
  • next.js
  • react-query
  • next-auth
  • msw
댓글 1 좋아요 0 조회수 256

wordpress에서 js파일 모듈작업

미해결

워드프레스(WordPress) 완전정복

wordpress에서 js파일을 작게 쪼개서 관리를 하려고 모듈작업을 하려고 좀 찾아봤는데 시원하게 나온게 별로 없더라구요. webpack을 이용해서 하는 방법도 있는거 같은데 좀 이해가 되지 않는거 같구요. 혹시 강사님이 쓰시는 방법이 있으시다면 소개좀 부탁드립니다.^^ 여기서 지금 일주일째 못나가고 있네요.ㅠㅠ

  • wordpress
MJ JI 댓글 2 좋아요 0 조회수 334

프리즈마로 api만드시는 강의는 언제쯤 나올지 알 수 있을까요?

미해결

Next + React Query로 SNS 서비스 만들기

안녕하세요 선생님 프리즈마로 api만드시는 강의는 언제쯤 나올지 알 수 있을까요? 직접만든 api랑 이번수업에서 배울next로 플젝을 만들고 싶은데 궁금합니다.

  • react
  • next.js
  • react-query
  • next-auth
  • msw
챠챠_ 댓글 2 좋아요 0 조회수 274

Access Token과 Refresh Token을 어디에 저장해야 할까요?

미해결

현재 프로젝트를 진행중인데, Access Token과 Refresh Token을 헤더에 담아 로컬스토리지에 저장하는 방법을 사용중입니다. 그런데 로컬 스토리지는 보안에 취약하다는 글을 보았습니다. 로컬 스토리지에 담아도 jwt 정책으로 대응이 가능하다는 글도 있었습니다. Access Token과 Refresh Token을 어디에 저장해야 할까요? 만약 로컬 스토리지나 쿠키에 저장한다면 어떻게 관리해야하나요?

  • java
  • spring
  • accesstoken
  • refreshtoken
  • localStorage
  • cookies
유하정 댓글 1 좋아요 0 조회수 2175

섹션 6. 순수 jbdc

해결됨

스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술

이 부분이 임포트가 아예 안 됩니다ㅠㅠ import org.springframework.jdbc.datasource.DataSourceUtils; 그래서 DataSourceUtils .getConnection(dataSource); 이렇게 인텔리제이에서 빨간 불이 들어오구요ㅠㅠ DataSourceUtils에만 빨간 불이 들어옵니다!! 어떻게 해결해야 할까요!! private Connection getConnection() { return DataSourceUtils.getConnection(dataSource); } private void close(Connection conn, PreparedStatement pstmt, ResultSet rs) { try { if (rs != null) { rs.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if (pstmt != null) { pstmt.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if (conn != null) { close(conn); } } catch (SQLException e) { e.printStackTrace(); } } private void close(Connection conn) throws SQLException { DataSourceUtils.releaseConnection(conn, dataSource); }

  • java
  • spring
  • mvc
  • spring-boot
권정익 댓글 1 좋아요 0 조회수 205

next-auth로 다시 한번 질문을 올립니다...

해결됨

Next + React Query로 SNS 서비스 만들기

공지의 올려주신대로 auth.ts 를 수정하였으며 loginModal 의 redirect:true export const { handlers: { GET, POST }, auth, signIn, } = NextAuth({ pages: { signIn: "/i/flow/login", newUser: "/i/flow/signup", }, callbacks: { // async signIn() // async authorized({ auth }) { // if (!auth) { // // 쿠키가 없으면 로그인 페이지로 돌리기 // return NextResponse.redirect("http://localhost:3000/i/flow/login"); // } // return true; // }, }, providers: [ CredentialsProvider({ async authorize(credentials) { const authResponse = await fetch( `${process.env.NEXT_PUBLIC_BASE_URL}/api/login`, // NEXT_PUBLIC_BASE_URL=http://localhost:9090 { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ id: credentials.username, password: credentials.password, }), } ); // 여기 주목!!! 서버에서 에러가 발생할 때 그 에러 내용이 서버에 담겨 있을 겁니다. console.log(authResponse.status, authResponse.statusText); if (!authResponse.ok) { const credentialsSignin = new CredentialsSignin(); if (authResponse.status === 404) { credentialsSignin.code = "no_user"; } else if (authResponse.status === 401) { credentialsSignin.code = "wrong_password"; } throw credentialsSignin; } const user = await authResponse.json(); console.log("user", user); // id, name, image, email만 허용 return { id: user.id, name: user.nickname, image: user.image, }; }, }), ], }); 아래와 같은 오류가 계속 해서 발생하고 있습니다. TypeError: next_dist_server_web_exports_next_request__WEBPACK_IMPORTED_MODULE_0__ is not a constructor pakage.json 의 버젼은 아래와 같이 사용하고 있고요 "@auth/core": "^0.27.0", "next-auth": "^5.0.0-beta.16", 혹시 이 부분의 같은 에러가 나오신 분들 중 해결 하신 분들이 있을까요?

  • react
  • next.js
  • react-query
  • next-auth
  • msw
댓글 1 좋아요 0 조회수 363

프로젝션 'new 명령어로 조회' 질문 입니다.

해결됨

자바 ORM 표준 JPA 프로그래밍 - 기본편

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 안녕하세요? 프로젝션 쿼리에 new 명령어 관련 헷갈리는 부분이 있어서 질문 드립니다! try{ Member member = new Member(); member.setUsername("member1"); member.setAge(10); em.persist(member); em.flush(); em.clear(); List<MemberDTO> result = em.createQuery("SELECT new jpql.MemberDTO(m.username, m.age) FROM Member m", MemberDTO.class) .getResultList(); MemberDTO memberDTO = result.get(0); System.out.println("memberDTO = " + memberDTO.getAge()); System.out.println("memberDTO = " + memberDTO.getUsername()); tx.commit(); } 위와 같은 쿼리를 실행하게 되면 상위에서 생성한 member 객체에 있는 값을 result 로 복사하고 result 값을 memberDTO List의 인덱스 0으로 들어 간 값을 조회하라는 뜻이 맞는건가요..? 수업듣다가 제가 이해한게 맞는지 헷갈려서 질문 드립니다.. 답변 부탁드립니다!! 감사합니다.

  • java
  • jpa
자바만판다 댓글 1 좋아요 0 조회수 341

섹션 7 GraphQL 관련 질문 드립니다

해결됨

[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스

안녕하세요 섹션 04-05-graphql-mutation-product 따라하고 있는데 도중에 저런 에러 메세지가 떴습니다. 디버깅 하려고 해도 Network 부분에 message 부분이 안 뜨네요ㅠ 검색해보니 쿠키 및 인터넷 기록 삭제해보라고 나오는데.. 삭제해도 해결이 안 되고요ㅠㅠ 어떻게 해야 해결될까요? 도움 부탁드립니다

  • react
  • node.js
  • seo
  • graphql
  • next.js
edo020424 댓글 2 좋아요 0 조회수 287

클랙식 테마를 운영 중 블럭 테마로 개편할 때

해결됨

워드프레스 제대로 개발하기 - 어드민 편

안녕하세요. 기존에 classic theme 로 만들어진, classic editor 와 classic widget 으로 운영 중인 사이트를 block theme로 바꾸고, block editor 를 사용하게 되면, 기존에 작성된 글들에 문제가 없을까요? 프런트엔ㅌ 화면이나 rss feeding.. 블럭에디터에도 강의 중에 배운 postmeta를 추가할 수 있는지? 블럭테마를 운영 중에 글쓰기에는 classic editor를 사용해도 문제가 없는지? 기존에 사용하던 플러그인이나 윗젯들을 블럭테마에서도 잘 돌아가는지? 궁금합니다. 추가로 기타 주의할 점이 있을까요? 영감을 받을 수 있는 짧은 코멘트라도 주시면 감사하겠습니다.

  • wordpress
  • php
Su Yeoun Lee 댓글 2 좋아요 0 조회수 406

SpinLock & Busy Waiting 강의 질문입니다.

미해결

자바 동시성 프로그래밍 [리액티브 프로그래밍 Part.1]

안녕하세요! 강의 너무 잘 듣고 있는 수강생입니다. 이전 동기화와 CPU의 관계 강의에서는 CPU가 두 개 이상의 명령어를 처리하면 원자성이 보장이 안된다고 설명을 하셨는데, SpinLock & Busy Waiting 강의에서 test_and_set(int *lock) 메서드는 CPU 하드웨어 계층에서 원자성이 보장된다는 게 이해가 잘 가지를 않습니다. test_and_set(int *lock) 이 메서드는 하나의 명령어만 처리하는 건가요??

  • java
  • 동시성
  • multithread
  • synchronisation
bom 댓글 1 좋아요 1 조회수 267

8.2에서 보이는 site안에 page파일과 7.6에서 보이는 page파일의 코드가 다른거 같습니다.

해결됨

기초부터 배우는 Next YTMusic 클론 코딩 (with next.js 14, UI 마스터)

8.2에서 보이는 site안에 page파일과 7.6에서 보이는 page파일의 코드가 다른거 같습니다. 깃허브에는 7.7 챕터가 따로 있던데... 혹시 그 브랜치에 site안의 page파일을 그대로 사용하면 될까요??

  • react
  • 인터랙티브-웹
  • 클론코딩
  • next.js
  • tailwind-css
  • zustand
임민규 댓글 1 좋아요 2 조회수 210

is not valid JSON 에러 ..!

미해결

Next + React Query로 SNS 서비스 만들기

import { http, HttpResponse } from "msw"; const testData = [ { result: "success", userId: 2, nickname: "닉네임", favoriteCount: 223, viewCount: 336, position: "Backend", userFileUrl: "/Users/user/Desktop/pictures/userPicture.jpg", year: "경력없음", techStack: "react, java, ---", softSkill: "소통, 적극성, ---", links: "http://블로그주소", alarmStatus: true, content: "안녕하세요 구인 중입니다", }, ]; export const handlers = [ http.post("/api/post", () => { return HttpResponse.text(JSON.stringify("ok")); }), http.get("/api/get", ({ request }) => { console.log("request", request); return HttpResponse.json(testData); }), ]; export default handlers;"use client"; import { redirect } from "next/navigation"; export default function Home() { const handleClick = () => { fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/get`, { method: "get", }) .then((res) => console.log("res", res.json())) // JSON 형식으로 변환된 데이터를 가져옴 .then((data) => console.log("res?", data)); // JSON 데이터를 로그에 출력 }; return ( <> <div> <button onClick={handleClick}>test btn</button> <p>계정을 생성하세요</p> <form> <div> <> <label htmlFor="id">아이디</label> <input type="text" id="id" name="id" required /> </> <> <label htmlFor="name">이름</label> <input type="text" id="name" name="name" required /> </> <button type="submit">가입하기</button> </div> </form> </div> </> ); } browser.ts, handlers.ts, http.ts, MSWComponent.tsx, server.ts 는 제로초님과 다 동일하게 설정하였고 get부분에서 위와같이 하였는데 Unexpected token '<', "<!DOCTYPE "... is not valid JSON 라는 에러가 계속 발생합니다 ㅠㅠ 어떤부분이 문제일까요.. ! console.log("res", res.json())) 이부분에서 res만 콘솔로 확인하면 이렇게 나옵니다..!

  • react
  • next.js
  • react-query
  • next-auth
  • msw
댓글 1 좋아요 0 조회수 891

무한 스크롤 prefetch SSR 로그인 쿠키 관련 질문

해결됨

Next + React Query로 SNS 서비스 만들기

안녕하세요 제로초님, api/users/{id} 에서 Followers 데이터는 제가 상대방을 팔로잉 했고 로그인 정보 쿠키가 잘 전달되면 상대방의 팔로워 수와 관계없이 제가 팔로우 했다면 저의 userId만 배열에 담겨서 돌아오기 때문에 api/posts/followings 혹은 api/posts/recommends의 Comments 데이터도 이와 동일할 것이라고 생각했습니다. 추천 포스트는 prefetch를 진행하고( Suspense를 적용하지 않음) 팔로잉 포스트는 SSR을 할 때 서버에서 로그인 여부를 판단하는 쿠키를 함께 보내야 하기 때문에 prefetch에서는 next의 cookies를 사용해서 쿠키를 전달했습니다 . 하지만 Comments 배열에 로그인 유저가 아닌 다른 유저의 id도 함께 날라옵니다. 추천 포스트가 아닌 팔로잉 포스트는 useSuspenseInfiniteQuery를 사용했는데 로그인 유저의 id만 잘 전달받았습니다. 이게 Suspense 내부에 있어서 그런가 싶어서 Suspense를 걷어내고 prefetch만 사용했을 때도 동일하게 로그인 유저가 아닌 다른 유저의 id도 확인할 수 있었습니다. 왜 로그인 쿠키를 보내는데도 다른 유저의 정보도 날라오는지 궁금합니다. 어디가 잘못된 것일까요? useSuspenseInfiniteQuery를 사용한 팔로잉 포스트는 추천 포스트와 어떤점이 달라서 정상 작동한 것일까요? 추가) 이 글 작성하고 추천 포스트에도 useSuspenseInfiniteQuery를 적용했는데 팔로잉 포스트처럼 안 나오고 이전과 동일하게 다른 유저의 id도 함께 날라오는데 왜 그럴까요? 추천 포스트 결과 현재 로그인 한 유저의 id는 'jihwan3' Comments에 'jihwan2'도 함께 날라오는중 팔로잉 포스트 결과 현재 로그인 한 유저의 id는 'jihwan3' Comments에 'jihwan3'만 날라오는 중 Hearts도 jihwan3가 좋아요를 안 눌러서 비어있는 모습 page.tsx import { Suspense } from "react"; import { auth } from "@/auth"; import { Container } from "./_component/styled"; import HomeTab from "./_component/HomeTab"; import HomeTabProvider from "./_component/HomeTabProvider"; import PostForm from "./_component/PostForm"; import SuspenseDecider from "./_component/SuspenseDecider"; import Loading from "../_component/LoadingUI"; export default async function Home() { const session = await auth(); return ( <Container> <HomeTabProvider> <HomeTab></HomeTab> <PostForm me={session} /> <Suspense fallback={<Loading />}> {/* @ts-expect-error Server Component */} <SuspenseDecider /> </Suspense> </HomeTabProvider> </Container> ); } SuspenseDecider.tsx import { QueryClient, HydrationBoundary, dehydrate } from "@tanstack/react-query"; import getRecommendPosts from "../_lib/getRecommendPosts"; import getRecommendPostsServer from "../_lib/getRecommendPostsServer"; import PostDisplay from "./PostDisplay"; export default async function SuspenseDecider() { const queryClient = new QueryClient(); await queryClient.prefetchInfiniteQuery({ queryKey: ["posts", "recommends"], queryFn: getRecommendPostsServer, initialPageParam: 0, getNextPageParam: (lastPage, pages) => lastPage.at(-1)?.postId, pages: 1, }); return ( <HydrationBoundary state={dehydrate(queryClient)}> <PostDisplay /> </HydrationBoundary> ); } getRecommendPostsServer.ts import { QueryFunction } from "@tanstack/query-core"; import { Post as IPost } from "@/model/Post"; import { cookies } from "next/headers"; type Prop = { pageParam: number; }; const getRecommendPostsServer: QueryFunction<IPost[], [_1: string, _2: string], number> = async ({ pageParam }: Prop) => { const response = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/posts/recommends?cursor=${pageParam}`, { method: "get", headers: { Cookie: cookies().toString(), }, }); if (response.ok) return response.json(); else throw new Error(); }; export default getRecommendPostsServer; postDisplay.tsx "use client"; import { use } from "react"; import { TabContext } from "./HomeTabProvider"; import RecommendPosts from "./RecommendPosts"; import FollowingPosts from "@/app/(afterLogin)/home/_component/FollowingPosts"; export default function PostDisplay() { const { selectedMenu } = use(TabContext); if (selectedMenu === "recommend") { return <RecommendPosts />; } return <FollowingPosts />; } RecommendPosts.tsx "use client"; import { useEffect, Fragment } from "react"; import { InfiniteData, useInfiniteQuery } from "@tanstack/react-query"; import { useInView } from "react-intersection-observer"; import getRecommendPosts from "../_lib/getRecommendPosts"; import Post from "../../_component/Post"; import { Post as IPost } from "@/model/Post"; export default function RecommendPosts() { const { isFetching, fetchNextPage, hasNextPage, data } = useInfiniteQuery<IPost[], Object, InfiniteData<IPost[]>, [_1: string, _2: string], number>({ queryKey: ["posts", "recommends"], queryFn: getRecommendPosts, initialPageParam: 0, getNextPageParam: (lastPage) => lastPage.at(-1)?.postId, }); const { ref, inView } = useInView({ /* Optional options */ threshold: 0, delay: 100, }); useEffect(() => { if (inView) !isFetching && hasNextPage && fetchNextPage(); }, [inView, isFetching, hasNextPage, fetchNextPage]); if (!data) return null; // 이거 에러는...? type error인데.. -> InfiniteData로 해결 return ( <> {data.pages.map((ele: IPost[], idx: number) => ( <Fragment key={idx}> {ele.map((post: IPost) => ( <Post key={post.postId} post={post}></Post> ))} </Fragment> ))} <div ref={ref} style={{ height: "50px" }}></div> </> ); } getRecommendPost.ts import { QueryFunction } from "@tanstack/query-core"; import { Post as IPost } from "@/model/Post"; type Prop = { pageParam: number; }; const getRecommendPosts: QueryFunction<IPost[], [_1: string, _2: string], number> = async ({ pageParam }: Prop) => { const response = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/posts/recommends?cursor=${pageParam}`, { method: "get", credentials: "include", }); if (response.ok) return response.json(); else throw new Error(); }; export default getRecommendPosts; FollowingPosts.tsx "use client"; import { Fragment, useEffect } from "react"; import { useSuspenseInfiniteQuery, InfiniteData } from "@tanstack/react-query"; import { useInView } from "react-intersection-observer"; import getFollowingPosts from "../_lib/getFollowingPosts"; import Post from "../../_component/Post"; import { Post as IPost } from "@/model/Post"; export default function FollowingPosts() { const { isFetching, fetchNextPage, hasNextPage, data } = useSuspenseInfiniteQuery<IPost[], Object, InfiniteData<IPost[]>, [_1: string, _2: string], number>({ queryKey: ["posts", "followings"], queryFn: getFollowingPosts, initialPageParam: 0, getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) => lastPage.at(-1)?.postId, }); const { ref, inView } = useInView({ threshold: 0, delay: 100, }); useEffect(() => { if (inView) !isFetching && hasNextPage && fetchNextPage(); }, [inView, fetchNextPage, hasNextPage, isFetching]); if (!data) return null; return ( <> {data.pages.map((ele: IPost[], idx: number) => ( <Fragment key={idx}> {ele.map((ele) => ( <Post key={ele.postId} post={ele}></Post> ))} </Fragment> ))} <div ref={ref} style={{ height: "100px" }}></div> </> ); }

  • react
  • next.js
  • react-query
댓글 1 좋아요 0 조회수 287

트랜젝션 옵션의 전파에 대해 질문드립니다.

미해결

실전! 스프링 데이터 JPA

예전에 영한님이 답변하신 내용 중에 스프링이 제공하는 트랜잭션은 처음 시작한 트랜잭션을 기반으로 전파됩니다. 그러니까 서비스에서 트랜잭션을 시작하면 리포지토리의 트랜잭션이 해당 트랜잭션을 그대로 이어 받습니다. 라는 내용이 있었습니다. 그렇다면, 컨트롤러, 서비스, 리포지토리 순으로 코드가 진행된다고 할 때, 만약 서비스 계층에 @Trasnactional(readonly=false) 가 걸려있고 리포지토리 계층에 @Trasnactional(readonly=true) 가 걸려있으면 서비스 계층이 먼저 호출되므로 readonly=false 옵션이 적용된 채로 리포지토리 계층까지(기존 리포지토리 계층의 옵션은 무시된채로) 코드가 흘러가는걸까요?

  • java
  • spring
  • spring-boot
  • jpa
Jaesang Yoon 댓글 2 좋아요 0 조회수 239

consumer 셋팅 숫자 출력이 안됩니다.

미해결

실습으로 배우는 선착순 이벤트 시스템

docker exec -it kafka kafka-console-consumer.sh --topic coupon_create --bootstrap-server localhost:9092 --key-deserializer "org.apache.kafka.common.serialization.StringDeserializer" --value-deserializer "org.apache.kafka.common.serialization.LongDeserializer" 라고 터미너에 입력한 후에 테스트 코드 package com.example.coupon_server.service; import com.example.coupon_server.repository.CouponRepository; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @SpringBootTest public class ApplyServiceTest { @Autowired private ApplyService applyService; @Autowired private CouponRepository couponRepository; @Test @DisplayName("쿠폰 한개 적용 테스트") public void applyOneCoupon() { applyService.applyCoupon(1L); long count = couponRepository.count(); assertThat(count).isEqualTo(1); } @Test @DisplayName("쿠폰 여러개 적용 테스트") public void applyMultiCoupon() throws InterruptedException { int threadCount = 1000; ExecutorService executorService = Executors.newFixedThreadPool(32); CountDownLatch latch = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { long userId = i; executorService.submit(() -> { try { applyService.applyCoupon(userId); } finally { latch.countDown(); } }); } latch.await(); Thread.sleep(10000); long count = couponRepository.count(); assertThat(count).isEqualTo(100); } @Test @DisplayName("한명당 한개의 쿠폰만 발급") public void applyOneCouponPerUser() throws InterruptedException { int threadCount = 1000; ExecutorService executorService = Executors.newFixedThreadPool(32); CountDownLatch latch = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { long userId = i; executorService.submit(() -> { try { applyService.applyCoupon(1L); } finally { latch.countDown(); } }); } latch.await(); Thread.sleep(10000); long count = couponRepository.count(); assertThat(count).isEqualTo(1); } } 로 작성했지만 터미널에서 강사님과 같이 숫자들이 찍히자 않습니다. 그리고 터미널 안의 글씨 너무 작은것 같아요

  • java
  • docker
  • spring-boot
  • kafka
  • redis
SJ 댓글 3 좋아요 0 조회수 475

섹션 10. try - with - resources

해결됨

김영한의 실전 자바 - 중급 1편

질문입니다! 상황 1 . 우선 NetworkClientExceptionV5는 RuntimeException을 상속 받은 상태입니다. public class NetworkClientExceptionV5 extends RuntimeException { public NetworkClientExceptionV5(String message) { super(message); } } 그러면 NetworkClientExceptionV5를 상속받은 ConnectException과 SendException도 RuntimeException이 되는 거구요. public class ConnectExceptionV5 extends NetworkClientExceptionV5 { private final String address; public ConnectExceptionV5(String address, String message) { super(message); this.address = address; } public String getAddress() { return address; } } public class SendExceptionV5 extends NetworkClientExceptionV5 { private final String data; public SendExceptionV5(String data, String message) { super(message); this.data = data; } public String getData() { return data; } } 상황 2 . 그리고 NetworkClientV5는 AutoCloseable을 구현했습니다. import exception.ex5.exception.ConnectExceptionV5; import exception.ex5.exception.SendExceptionV5; public class NetworkClientV5 implements AutoCloseable { private final String address; private boolean connectError; private boolean sendError; public NetworkClientV5(String address) { this.address = address; } public void connect() { if (connectError) { throw new ConnectExceptionV5(address, address + " 서버 연결 실패"); } // 연결 성공 System.out.println(address + " 서버 연결 성공"); } public void send(String data) { if (sendError) { throw new SendExceptionV5(data, address + " 서버에 데이터 전송 실패 : " + data); } // 전송 성공 System.out.println(address + " 서버에 데이터 전송 : " + data); } public void disconnect () { System.out.println(address + " 서버 연결 해제"); } public void initError(String data) { if (data.contains("error1")) { connectError = true; } if (data.contains("error2")) { sendError = true; } } @Override public void close() throws Exception { System.out.println("NetworkClientV5.close"); disconnect(); } } ==질문입니다!!== NetworkServiceV5에서 public class NetworkServiceV5 { public void sendMessage(String data) { String address = "http://example.com"; try (NetworkClientV5 client = new NetworkClientV5(address)) { client.initError(data); // 추가 client.connect(); client.send(data); } } } try (NetworkClientV5 client = new NetworkClientV5(address))에서 컴파일 오류가 납니다. client에서 올라오는 예외들은 다 RuntimeException이므로 따로 throws를 안 해줘도 되는데 왜 해결하려고 하면 throws를 선언하거나 catch를 해야한다고 하는 건가요? RuntimeException은 예외를 throws 선언없이 자동으로 밖으로 던지기에 catch를 안 해도 상관이 없을텐데 왜 alt + enter을 누르면 throws 선언과 catch를 해야만 된다고 하는 건지 이해가 가지 않습니다. 제가 생각하는 건 이런식으로 흘러간다고 생각했습니다. main()에서 (error1 | error2)를 입력 받음 -> sendMessage를 호출 -> sendMessage에서 코드 진행 -> (client.connect | client.send)를 만나서 NetworkClientV5에 들어감 -> (ConnectException | SendException)을 터트림 -> NetworkClientV5에서 예외를 밖으로 던짐 (런타임이라서 throws 선언 안 해도 던져짐) -> NetworkService로 예외가 날라옴 -> 여기서도 처리가 불가능 하니, 예외를 밖으로 던짐 (여기서 throws 선언을 안해도 던져져야 한다고 생각함. 날아온 예외는 RuntimeException이기 때문에) -> main으로 예외가 넘어옴 -> main에는 catch (Exception e)가 있어서 예외를 잡고 정상흐름으로 돌아옴. 마지막은 메인메서드 입니다! import exception.ex5.exception.SendExceptionV5; import java.util.Scanner; public class NetworkmainV5 { public static void main(String[] args) { NetworkServiceV5 service = new NetworkServiceV5(); Scanner scanner = new Scanner(System.in); while (true) { System.out.print("전송할 문자 : "); String input = scanner.nextLine(); if (input.equals("exit")) { break; } try { service.sendMessage(input); } catch (Exception e) { exceptionHandler(e); } System.out.println(); } System.out.println("프로그램을 종료합니다."); } // 공통 처리 예외 private static void exceptionHandler(Exception e) { System.out.println("사용자 메시지 : 죄송합니다. 알 수 없는 문제가 발생했습니다."); System.out.println("==개발자용 디버깅 메시지=="); // 스택 트레이스 출력 e.printStackTrace(System.out); // 스택 트레이스 출력 System.err //e.printStackTrace(); // 필요하면 예외별로 별도의 추가 처리 가능 if (e instanceof SendExceptionV5 sendEx) { System.out.println("[전송 오류] 전송 데이터 = " + sendEx.getData()); } } }

  • java
  • 객체지향
권정익 댓글 1 좋아요 0 조회수 200

회원가입 과제 완료용

미해결

[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스

안녕하세요!! 과제 완료해서 피드백 부탁드리고자 올렸습니다! 앞으로 잘 부탁 드립니당~ <html> <!DOCTYPE html> <html lang="ko"> <head> <title>회원가입</title> <link rel="stylesheet" href="./02-signup.css"> </head> <body> <div class="signUpContent"> <h2> 회원 가입을 위해<br> 정보를 입력해주세요 </h2> <label for="email" class="label text">* 이메일</label> <input id="email" class="input_text" type="text"> <label for="name" class="label text">* 이름</label> <input id="name" class="input_text" type="text"> <label for="password" class="label text">* 비밀번호</label> <input id="password" class="input_text" type="password"> <label for="password_chk" class="label text">* 비밀번호 확인</label> <input id="password_chk" class="input_text" type="password"> <div class="signUpChk"> <input id="gender_w" class="input_radio" type="radio" name="gender"> <label for="gender_w" class="label gender">여성</label> <input id="gender_m" class="input_radio" type="radio" name="gender"> <label for="gender_m" class="label gender">남성</label> </div> <div class="agreeChk"> <input type="checkbox" id="input_chk"> <span class="agree_text"> 이용약관 개인정보 수집 및 이용, 마케팅 활용 선택에 모두 동의합니다. </span> </div> <div class="out-line"> <div class="line"></div> </div> <button> <span>가입하기</span> </button> </di> </body> </html> <css> * { box-sizing: border-box; } h2 { font-size: 32px; color: #0068FF; font-weight: 700; line-height: 47px; } .out-line{ padding: 30px 0px; } .line { border-bottom: 1px solid #E6E6E6; } .label{ font-size: 16px; font-weight: 400; line-height: 24px; } .signUpContent{ width: 670px; height: 960px; border: 1px solid #AACDFF; border-radius: 20px; box-shadow: 7px 7px 39px rgba(0, 104, 255, .25) ; display: flex; flex-direction: column; padding: 72px 100px 70px 100px; } .label.text{ padding: 20px 20px 0 0; color: #797979; } .input_text{ border-style: none; border-bottom: 1px solid #CFCFCF; height: 60px; } .signUpChk{ display:flex; justify-content: center; align-items: center; padding: 50px 0; } .input_radio{ margin: 0 5px 0 0; width: 20px; height: 20px; } .label.gender{ padding-right: 30px; } .agreeChk{ display: flex; justify-content: center; align-items: center; } .agree_text{ height: 22px; font-size: 14px; font-weight: 400; line-height: 20px; } button{ width: 470px; height: 75px; background-color: #FFF; border: 1px solid #0068FF; border-radius: 10px; } button > span { font-size: 18px; font-weight: 400; color: #0068FF; }

  • react
  • node.js
  • seo
  • graphql
  • next.js
개발하는 알파카 댓글 2 좋아요 0 조회수 300

데이터 베이스 쿼리 실행 시점 관련 문의

미해결

자바 ORM 표준 JPA 프로그래밍 - 기본편

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 이전에 데이터베이스에 반영되는 실행 시점은 em.flush() 트랜잭션 커밋 JPQL 쿼리 실행 으로 알고 있습니다. 그런데 11:45초 쯤부터 em.persist(team) 을 실행할때 id 값을 갖고 오기위해 new Member 이전에 insert문이 실행된다면 위의 경우가 아닌 것으로 판단되는데 em.persist 호출해도 쓰기 지연 SQL에 쌓이는 것이 아닌 바로 쿼리를 실행하게 되는 건가요?

  • java
  • jpa
김가가가 댓글 2 좋아요 0 조회수 222

인기 태그

인프런 TOP Writers

주간 인기글