의존성 조언 두번째 방법에서 문제점이 UserService.login은 여전히 의존성이 감춰져있다. 위와 마찬가지로 Userservice.login을 테스트할 때 clock에 의존하고 있는지 알 수 없다. 이거였는데 세번 째 방법도 UserService를 사용하는 메서드는 login(user)만 남겨서 user가 Clock에 의존하는지 모르지 않나요? 아까 맥도날드 예제에서는 인터페이스를 사용하면 일을 시킨다고 설명하셨는데 이것도 인터페이스를 사용해서 일을 시키는거니 이렇게 구현하면 내부에서 clockHolder를 사용해도 외부에서 몰라도 되나요?
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예 [질문 내용] 사용자 정의함수를 db에 등록시켜놓은 다음에 jpql로 사용을 해보니 따로 방언을 등록하지 않아도 사용이 가능합니다. List<String> str = em.createQuery("select create_prefix(m.username) from Member m", String.class).getResultList(); create_prefix는 직접 등록한 함수입니다. 수업에서는 방언으로 사용자 정의 함수를 등록해야지 적용이 된다고 하는데 이 경우 왜 작동되는지 알고싶습니다.
#include <stdio.h> #include <windows.h> int main(int argc, char* argv[]) { int ch; FILE* fr, * fw; //const UINT default_cp = GetConsoleOutputCP(); //printf("%u\n", default_cp); const char* in_filename = "원본.txt"; const char* out_filename = "사본.txt"; unsigned long count = 0; if ((fr = fopen(in_filename, "r")) == NULL) { printf("can't open %s\n", in_filename); exit(EXIT_FAILURE); } if ((fw = fopen(out_filename, "w")) == NULL) { printf("can't open %s\n", out_filename); exit(EXIT_FAILURE); } //SetConsoleOutputCP(CP_UTF8); while ((ch = fgetc(fr)) != EOF) { fputc(ch, stdout); fputc(ch, fw); count++; } fclose(fr); fclose(fw); //SetConsoleOutputCP(default_cp); printf("file %s has %lu characters\n", in_filename, count); printf("copied to %s\n", out_filename); printf("한글 출력 확인"); return 0; } 제가 제대로 이해한건지 헷갈리네요... 강의 2:45 콘솔창에서 한글이 깨지는 이유는 텍스트 파일의 인코딩 방식은 UTF8(== 인코딩방식 == 코드페이지)인데 콘솔창의 인코딩 방식과 다르기 때문이 맞나요? 원본.txt에 담겨있는 데이터는 컴퓨터 내부에서 바이너리로 저장되어있습니다. (프로그램을 통해 인코딩을 해도 이 바이너리 데이터 자체는 바뀌지않음) 이 바이너리 데이터를 메모장은 UTF8 인코딩 방식을 통해서 인코딩 한 후 출력하기 때문에 메모장에서는 한글이 제대로 출력 되는 것이고, 프로그램은 이 바이너리 데이터를 그대로 읽어왔지만 콘솔창의 인코딩 방식은 UTF8이 아니기 때문에 인코딩 과정에서 한글은 제대로 인코딩이 안되고 그렇기에 한글은 깨지는것. 그러므로 SetConsoleOutputCP(CP_UTF8); 를 통해 콘솔창의 인코딩방식을 UTF8로 바꾸어 준 후 실행하면 한글이 제대로 출력 됨. 마지막으로 복사한 사본.txt파일의 데이터는 원본.txt에 담겨있는 바이너리 데이터 그 자체를 그대로 복사한 것이고 그것을 메모장에서 열면 인코딩방식이 일치하기에 사본.txt파일은 한글이 깨지지 않는다. 맞을까요? 감사합니다!!!
@Autowired로 EntityManager를 주입받을때 여러 쓰레드가 동시에 접근하면 동시성 문제가 발생합니다. 하지만 @Transactional 을 추가해준다면 //1 @Repository @RequiredArgsConstructor @Transactional public class AutowiredRepository { private final EntityManager em; } //2 @Repository public class PersistenceContextRepository { @PersistenceContext private EntityManager em; } @PersistenceContext 처럼 Transaction에 의해 쓰레드간 동시성 문제를 해결해준다 고 생각하는데 맞게 생각한건지 궁금합니다. 두가지 방법 다 EntityManager를 호출 할때마다 Proxy를 통해 EntityManager를 생성하여 Thread-Safe를 보장해준다라고 볼수 있는 건가요?? 답변주시면 정말 감사하겠습니다.
예시로 보여주신 부분 중에 명시적으로 main thread 에서 dll을 로딩하고 추가적인 thread를 생성했을 때 dllmain의 thread attach 이벤트가 호출되는데 얘기해주시는 설명에서는 thread 마다 dll을 명시적으로 로딩하고 프리해줘야 사용할 수 있다고 해주셔서요 추가적으로 만든 thread에서 dll 명시적 로딩을 하지 않음에도 main thread에서 명시적 로딩한 dll의 dllmain의 thread attach 가 호출되는 부분이 궁금합니다 다른 thread에서 main thread 에서 명시적 로딩한 dll의 hmodule과 함수포인터를 얻어와 바로 사용해도 되는걸까요? 강의 감사합니다!
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release. 이러한 오류가 뜨는데, 실행하는데는 문제가 없습니다. 이 오류를 고쳐야 할 것 같은데, 어떻게 고쳐야할까요?
쿠폰 생성 발급 로직도 컬럼에 쿠폰의 개수를 지정해놓으면 이전 강의랑 똑같은 거 같은데 왜 이번 강의는 쿠폰 엔티티를 새로 생성해서 그 개수를 체크하는 건지 궁금합니다. 이전 컬럼에 개수를 두어 관리하는 거랑 지금처럼 엔티티를 생성하는 방식의 차이점이 너무 궁금해요 항상 감사합니다.
안녕하세요, 집에서 해당 강의로 입문한 독학러 입니다. 제가 배열과 메모리, 포인터와 산술 연산을 제 기준으로 쉽게 풀어서 이해를 하였는데 이해한게 맞는건지 확인을 부탁드리고자 글을 작성하게 되었습니다. 포인터변수의 크기 포인터변수의 크기는 자료형이 무엇이든 x86(32비트)에선 4바이트, x64(64비트)에선 8바이트가 나왔습니다. 이러한 이유가 메모리주소에서 확인할 수가 있었는데 일단 x86(32비트)에선 왜 4바이트가 나오냐에 대한 생각인데 메모리 주소를 포인터 변수에 저장한다고 가정했을 때 메모리 주소도 값이잖아요? 해당 값을 일단 출력해보면 아래와 같이 나옵니다. 이 사진으로 생각할 수 있는건 16진수의 8자리 그리고 4바이트. 즉 4바이트가 표현할 수 있는 가짓수는 2^32 = 4,294,967,296 0 ~ 4,294,967,295까지 여기서 4,294,967,295는 16진수로 FFFFFFFF. 위 사진의 자릿수와 같은 8자리다. 즉 메모리 주소의 가짓수는 unsigned int과 마찬가지로 4,294,967,296만큼 가질 수 있으며 00000000 ~ FFFFFFFF 이기 때문에 x86(32비트)에선 포인터 변수는 해당 16진수의 값을 저장해야 하니 4바이트인 것이다. x64(64비트)에서도 위와 동일한 이유로 8바이트가 되는 것이다, 라고 이해했습니다. 맞게 이해했을까요?? 배열과 포인터의 산술연산 배열과 포인터의 산술연산을 보고 제일 먼저 떠오른게 "주사위 게임"이였습니다. 일단 배열을 선언하면 1차든 2차배열이든 몇겹이든 메모리 공간에 1차원적으로 차례대로 나열되어 메모리 공간이 확보되는걸 선생님 강의를 통해 이해했는데요. 이 메모리를 주사위 게임의 게임판 처럼 변형하여 생각을 해본다면 아래와 같이 될 것 같습니다. <- 배열의 메모리공간 가정 주사위 놀이판을 편집을 해왔습니다. 여기서 위 그림대로 배열을 선언한다 가정했을 때 arr[3][5]가 될 것 입니다. 1~5까진 arr[0][0] ~ arr[0][4] 6~10까진 arr[1][0] ~ arr[1][4] 11~15까진 arr[2][0] ~ arr[2][4] 자료형을 적지않은 이유는 1바이트 자료형이든 4바이트 자료형이든 저 위 그림 한칸 한칸을 하나의 인덱스라고 생각해주시면 될 것 같습니다. 만약 int 4바이트라고 가정한다면 위 그림 1번칸엔 메모리 주소 0~3까지 있을 것이고 2번칸엔 4~7까지 있다고 생각할 수 있습니다. 그러면 이제 저 주사위놀이판 위에 이제 말을 배치해야 인덱스칸에 접근할 수 있다고 생각해봅시다. 그럼 그 말은 포인터변수가 될 것입니다. *ptr = arr; 여기서 arr은 &arr[0][0] 즉 메모리의 첫주소 값을 가지고 있기 때문에 이게 몇차원 배열이든 배열변수의 이름만 적어서 포인터변수에 첫 주소를 저장합니다. 그러면 이제 1번칸에 말이 접속하여 인덱스에 포인터변수로 접근할 수 있게 된다고 생각했습니다. 1번칸은 [0][0] 여기서 5번칸 [0][4]으로 이동한다고 가정 한다면 4칸을 이동해야 합니다. 그러면 여기서 말에다가 4칸을 더하면 ptr += 4;을 하면 포인터변수의 주소는 [0][4]을 가리키고 있을 것 입니다. 여기서 바꿔 생각한다면[0][4]가 아니라 [0][i] 라고 했을 때 ptr += i; 을 더하면 [0][0] ~ [0][i] 까지 이동할 수 있을 것 입니다. 위 방법대로 한다면 1차원이든 2차원이든 3차원이든 배열 맨 끝 [인덱스]에 포인터 변수로 접근할 수 있다고 생각합니다. 그러면 이제 1번칸 [0][0]에서 6번칸 [1][0]에 가고 싶다고 가정을 한다면 총 5칸을 가야 도달할 수 있습니다. 왜냐하면 arr[3][5]으로 선언했기 때문에 뒤에 [5]인덱스가 0~4까지 총 5가짓수이기 때문입니다. 그러면 포인터변수(말)에게 ptr+=1*5을 하면 6번칸 [1][0]에 도달할 수 있습니다. 1번칸 [0][0]에서 11번칸 [2][0]에 갈려면 ptr += 2*5을 하면 됩니다. 즉 이걸 바꿔서 생각해본다면[0][0]에서 [j][0]로 가기 위해서는 ptr += j * 5(인덱스 총 갯수)을 이용하면 옮겨갈 수 있습니다. 여기서 빼기도할 수 있는데 현재 ptr이 [0][0]에 있다고 가정하고 ptr += 2 * 5를 하면 [2][0]으로 가게 되는데 여기서 [1][0]으로 간다고 가정하면 ptr += -1 * 5를 하면 [1][0]으로 가게 된다. 위와 같은 방식으로 배열에 포인터변수로 접근하여 사용하니까 아주 쉽게 사용이 되더라구요, 반복문에서는 따로 위 그림처럼 포인터변수 = 말, 배열 = 주사위게임판 이라 생각하고 머릿속에 그리면서 하니까 원하는 값을 얻을 수 있고 이러한 방식이 괜찮은 방법 중 하나일까요? 아니면 잘못 이해하고 있는걸까요? 문장 정리능력이 없다보니 이렇게 긴 글을 적어놨는데 읽어주시면 감사하겠습니다.
안녕하세요 주니어 개발자 길라잡이가 되주셔서 감사합니다. fulltext index에 대해서 질문이 있습니다. 임계점이 올경우 튜닝으로도 해결할 수 없는 문제라고 말씀해주셨는데요 경험담이라고 해주셨는데 그 경험담을 듣고 싶어서 질문을 남겨봅니다. 공식 문서에서 찾아보니까 https://dev.mysql.com/doc/refman/8.0/en/innodb-fulltext-index.html#innodb-fulltext-index-deletion 동시 경합이 발생할 수 있다고 작성이 되어있는데 이 문제로 발생한건가요 ? 아니면 다른 인덱스와 다르게 인덱스 용량 때문에 발생한 문제이신건가요 ? FULLTEXT INDEX의 한계 검색을 해도 다 좋은점만 나오더라구요..
강의 15:16 처럼 3차원 배열의 인덱스 c + col r + (col row) *d)를 함수를 통해 사용해보려 했습니다. #include <stdio.h> #include <stdlib.h> int row = 3, col = 2, depth = 2; int idx3(int c, int r, int d) { static const cr = col * row; return c + col * r + cr * d; } int main() { int* ptr = (int*)malloc(sizeof(int) * row * col * depth); if (!ptr) exit(1); for (int d = 0; d < depth; d++) for (int r = 0; r < row; r++) for (int c = 0; c < col; c++) ptr[idx3(c, r, d)] = idx3(c, r, d); for (int d = 0; d < depth; d++) { for (int r = 0; r < row; r++) { for (int c = 0; c < col; c++) printf("%d", ptr[idx3(c, r, d)]); printf("\n"); } printf("\n"); } return 0; } 실행시켰더니 expression must have a constant value라고 뜨면서 에러가 납니다. 표현식은 상수를 가져야한다는 뜻인것같습니다. Q1. static변수 cr에 col *row를 넣었기때문인것같은데 원인이 무엇인가요? 정적변수에는 변수를 넣으면 안되는건가요? Q2. 또 강의 15:30에서 static을 통해 cr을 사용하면 속도가 빨라지는 이유는 정적 변수 cr은 프로그램이 끝날 때까지 계속 메모리에 남아있으므로 초기화를 1번만 해주기 때문에 이후에는 연산을 할 필요가 없어서 그런것 맞나요? 감사합니다!!!
안녕하세요! 강의 마지막 코드를 제가 제대로 이해했는지 궁금하여 질문 드립니다. #define CRT SECURE_NO_WARNINGS #include <stdio.h> void swap(int* u, int* v) { printf("%p %p\n", u, v); int temp = *u; u = v; *v = temp; } int main() { int a = 123; int b = 456; printf("%p %p\n", &a, &b); swap(&a, &b); printf("%d %d\n", a, b); return 0; } a와 b의 주소 값이 매개 변수의 값으로서 함수 swap()에 입력된다. 즉 int* u = &a가 되고, int* v = &b가 된다. swap() 함수의 변수 u는 main() 함수의 변수 a의 주소가 저장된 포인터 변수가 됐고, v또한 마찬가지다. u, v에 각각 a와 b의 주소 값이 저장됐기 때문에 이것을 실행하면 main() 함수의 a, b의 주소 값과 동일하게 출력된다. 이후 변수 temp에 변수 a의 주소를 redirection 하여, 해당 주소 안에 저장된 값을 대입한다(a의 주소로 접근 -> 주소 안에 있는 값 123 temp에 대입). a의 주소로 직접 접근하여 그 주소의 값을 b의 주소 안에 저장된 값으로 변경한다. 이후 b의 주소로 직접 접근하여 그 주소의 값을 변수 temp의 저장된 값으로 변경한다. swap() 함수에서 a, b의 주소로 직접 접근해 값을 변경했기 때문에 함수들의 영역이 달라도 main() 함수 변수들의 값은 정상적으로 swap 된다. 감사합니다.
int main() { int count = 0; while (1) { printf("Current count is %d. Continue?(y/n)\n", count); if (getchar() == 'n') break; else if (getchar() == 'y') count++; else printf("Please input y or n\n"); while (getchar() != '\n') continue; } return 0; } 강의에서 int c = getchat() 해서 c를 사용하니까 잘 되던데, if문이랑 else if문에 getchar()을 그대로 넣으면 왜 오류가 나는지 궁금합니다!
while문을 한번만 써서 int main() { const int secret_code = 337; int guess = 0; while (guess != secret_code) { printf("Enter secret code :"); scanf("%d", &guess); } printf("Great!"); return 0; } 이렇게 쓰니까 결과는 잘 나오던데 틀린 방법인가요? 아니면 for문으로 int main() { for (int code = 0;code != 337;printf("Enter secret code :"), scanf("%d", &code)) ; printf("Great!"); return 0; } 이렇게 하는 것도 안되나요?? 잘 돌아가긴 해서 질문 남깁니다!
안녕하세요. JPA 최적화 강의를 수강하고, 개인적으로 DDD를 책으로 공부해본 후에 개인 토이 프로젝트를 진행하던 중, 뜻밖에 의문이 생겼는데 여쭐 곳이 없어서 이렇게 질문 올리게 되었습니다. 맨 땅에 헤딩으로 이런저런 강의, 책, 다른 분들의 소스를 참고 하려다보니 여러 개념이 뒤섞여서 혼동이 옵니다.. ㅠㅠ 현재 프로젝트에서는 크게 에그리거트를 CUSTOMER, EXTERNAL, SECURITYMEDIA 3개로 나누어 설계했는데요. 강의에서도, 책에서도 DOMAIN 계층에 있는 서비스는 해당 도메인에 대한 순수한 CRUD를 수행하는 것으로 보았습니다. DDD 책에서는 여러 에그리거트가 필요로 하는 기능을 구현할 때는 도메인 서비스로 구현하라고 이야기 했구요. 처음에는 책에서 조언하는 대로 도메인 서비스로 구현해보고자 하다가, 좀처럼 구현이 안되어서 다른 분들이 구현한 소스를 참조하다 보니 application(응용)영역을 FACADE라는 상위 계층을 두는 것을 방식을 알게 되었습니다. 소스를 따라가보니 각 애그리거트의 DOMAIN 영역에 있는 서비스를 주입하여, 각 도메인 영역에 있는 서비스를 적절히 호출하기에 책에서 본 도메인 서비스와 같은 역할을 하겠구나 하여,, 해당 프로젝트 구성 방식을 따라 개발해보기로 했습니다. 그런데 개발을 하다보니,, 참조하는 소스에서 메소드 단위의 트랜잭션의 적용을 facade 영역이 아닌, 도메인 영역의 서비스 구현체에서 하는 것을 알게 되었습니다. 제가 개발하고자 기능은 여러 애그리거트를 생성, 변경하는 하나의 행위가 하나의 트랜잭션으로 묶여야 하는데 말이죠. 이러한 이유 때문에 현재 소스는 FACADE에서는 하나의 도메인 영역의 서비스를 주입하여 하나의 메소드를 호출하도록 되어있고, 도메인 영역에 있는 해당 서비스의 구현체에서 여러 애그리거트의 서비스, 레포지토리를 주입받아 하나의 메소드에서 트랜잭션 단위로 수행하도록 구현되어있습니다.. @Service @RequiredArgsConstructor public class SecurityMediaFacade { private final SecurityMediaService securityMediaService; public SecurityMediaInfo.Main registerOtp(SecurityMediaCommand.RegisterSecurityMediaRequest req) { //디지털otp 발급 // 디지털 otp 발행 return securityMediaService.issueSecurityMedia(req, SecurityMediaType.DIGITAL_OTP); } ... } public interface SecurityMediaService { public SecurityMediaInfo.Main issueSecurityMedia(SecurityMediaCommand.RegisterSecurityMediaRequest req, SecurityMediaType type); ... } @Slf4j @Service @RequiredArgsConstructor public class SecurityMediaServiceImpl implements SecurityMediaService { private final CustomerReader customerReader; private final SecurityMediaStore securityMediaStore; private final TokenStore tokenStore; private final ExternalClientService externalClientService; @Override @Transactional public SecurityMediaInfo.Main issueSecurityMedia(SecurityMediaCommand.RegisterSecurityMediaRequest req, SecurityMediaType type) { // 요청고객 찾기 Customer customer = customerReader.findCustomerByRnn(req.getRnn()); SecurityMedia newOtp = null; if(!customer.existActiveSecurityMedia()) { // otp 신규 SecurityMedia initOtp = req.toEntity(SecurityMediaType.DIGITAL_OTP, customer); newOtp = securityMediaStore.store(initOtp); // 토큰 발급 요청 Token newToken = externalClientService.getToken(customer, newOtp); newOtp.addToken(newToken); tokenStore.store(newToken); } return new SecurityMediaInfo.Main(newOtp); } 위에는 프로젝트의 구성인데.. 첫 단추부터 잘못 끼운 것도 같아서 시작 단계인 지금에서라도 좀 개선을 해보려고 하는데요. 사실 도메인 서비스가 제가 의도로 하는 여러 애그리거트의 서비스 기능을 묶어서 하는 건지 아무리 읽어봐도 혼선이 옵니다. 혹시 DDD 책에서 이벤트라는 개념이 나오는데 도메인 서비스가 아니라, 이 이벤트를 통해 다른 애그리거트의 응용 서비스를 호출하도록 핸들링 하는게 올바른 방법일까요? 지금과 같은 구조를 유지해도 된다면.. facade 영역의 메소드를 트랜잭션으로 묶고, 각 도메인 계층의 서비스들에서 선언된 해당 도메인에 대한 crud 메소드를 적절히 호출해가면서 facade 영역에서 비즈니스 로직을 처리해도 될까요? 너무 글이 장황하고 기네요.. ㅠㅠ 혹시 도움을 주신다면 너무나도 감사드리겠습니다.