Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[톰캣 구현하기 - 1, 2단계] 로이스(원태연) 미션 제출합니다. #307

Merged
merged 50 commits into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
a7059f1
docs: 1단계 요구 사항 정리
TaeyeonRoyce Sep 1, 2023
5c56749
feat: Http Request Method 종류 추가
TaeyeonRoyce Sep 1, 2023
3e64009
feat: Http 요청 메세지 시작줄 객체 추가
TaeyeonRoyce Sep 1, 2023
29024cd
feat: Http 요청 헤더 객체 추가
TaeyeonRoyce Sep 1, 2023
37779e1
feat: Http 요청 객체 추가
TaeyeonRoyce Sep 1, 2023
baacb35
feat: Http 요청 메세지 시작줄 생성 검증 테스트 추가
TaeyeonRoyce Sep 1, 2023
42ab1b8
feat: Http 요청 메세지 파서 추가
TaeyeonRoyce Sep 1, 2023
be5ceea
refactor: 패키지 분리
TaeyeonRoyce Sep 1, 2023
0739d92
feat: Http Response 객체 추가
TaeyeonRoyce Sep 2, 2023
e23b14b
feat: Http 요청 처리 구조 구현
TaeyeonRoyce Sep 2, 2023
43e6481
feat: index.html 처리 Controller 추가
TaeyeonRoyce Sep 2, 2023
18b2b0e
test: 파일 입출력 학습 테스트 작성
TaeyeonRoyce Sep 2, 2023
a97a899
test: 데이터 입출력 학습 테스트 작성
TaeyeonRoyce Sep 2, 2023
aac19b1
feat: 정적 리소스 반환 로직 추가
TaeyeonRoyce Sep 2, 2023
d701b96
feat: Http 응답 객체 메세지 변환 로직 추가
TaeyeonRoyce Sep 2, 2023
834b4c7
feat: Http Method 추가
TaeyeonRoyce Sep 2, 2023
88ace28
feat: 요청 자원에 맞는 자원 반환 로직 구현
TaeyeonRoyce Sep 2, 2023
c0de791
feat: css, js와 같은 자원 요청에 대한 처리 구현
TaeyeonRoyce Sep 2, 2023
d1db1b5
feat: Query String 파싱 추가
TaeyeonRoyce Sep 2, 2023
989ffd2
refactor: HttpRequestMessageReader 파싱 작업 하도록 수정
TaeyeonRoyce Sep 2, 2023
b50ddfa
feat: Query String을 파싱해서 아이디, 비밀번호 검증 로직 추가
TaeyeonRoyce Sep 2, 2023
27fc20e
feat: Query String 유무에 따른 페이지 반환 로직 분리
TaeyeonRoyce Sep 2, 2023
dbd8130
feat: Login 요청을 POST method로 요청하도록 수정
TaeyeonRoyce Sep 2, 2023
949771a
feat: 회원가입 기능 추가
TaeyeonRoyce Sep 2, 2023
1f0d99a
refactor: Body 읽는 메서드 분리
TaeyeonRoyce Sep 2, 2023
4346b28
refactor: HandlerMapping 에서 mapping되는 Controller 변경
TaeyeonRoyce Sep 2, 2023
37a9fcd
feat: 로그인 성공 시 Cookie에 JSessionID 발급 로직 구현
TaeyeonRoyce Sep 2, 2023
3fe087b
docs: 요구사항 정리
TaeyeonRoyce Sep 2, 2023
f4fed2f
feat: Session 추가
TaeyeonRoyce Sep 2, 2023
c5ece7b
refactor: Controller 응답 로직 개선
TaeyeonRoyce Sep 2, 2023
404a454
refactor: Redirect 상태 코드 변경
TaeyeonRoyce Sep 2, 2023
80c86d0
fix: 출력형식에 맞게 응답 메세지 작성 시 공백 추가
TaeyeonRoyce Sep 3, 2023
e8fcea4
fix: 정적 자원이 아닌 다른 형식에 대한 응답 기능 추가
TaeyeonRoyce Sep 3, 2023
356207b
fix: 존재하지 않는 페이지 접근시 404페이지와 not found 상태로 응답되도록 수정
TaeyeonRoyce Sep 3, 2023
27f6f95
test: 페이지 요청 테스트 추가
TaeyeonRoyce Sep 3, 2023
a02f80e
refactor: 패키지 경로 및 클래스 이름 수정
TaeyeonRoyce Sep 3, 2023
6abf103
feat: 405 상태 코드 응답 추가
TaeyeonRoyce Sep 3, 2023
346ee70
test: 테스트 추가
TaeyeonRoyce Sep 3, 2023
495319c
docs: 요구사항 체크리스트 정리
TaeyeonRoyce Sep 3, 2023
a1116ef
refactor: code smell 반영
TaeyeonRoyce Sep 3, 2023
26aca4b
refactor: 사용자 입력 데이터 로깅 제거
TaeyeonRoyce Sep 3, 2023
5f19ea3
test: 학습 테스트 방식 개선
TaeyeonRoyce Sep 4, 2023
d97a854
refactor: 헤더 메서드 네이밍 수정
TaeyeonRoyce Sep 4, 2023
9e70384
refactor: 대소문자 관계없이 문자열 비교 방식 수정
TaeyeonRoyce Sep 4, 2023
3f55297
refactor: 문자열 substring 방식 수정
TaeyeonRoyce Sep 4, 2023
dc8bde3
refactor: 표준 용어에 맞게 클래스 이름 수정
TaeyeonRoyce Sep 4, 2023
3897354
refactor: 예외 타입 수정
TaeyeonRoyce Sep 4, 2023
3f86696
fix: redirect 시 body가 포함되지 않도록 수정
TaeyeonRoyce Sep 4, 2023
ef811f1
fix: 메모리 누수 제거
TaeyeonRoyce Sep 4, 2023
1f93890
refactor: 쿠키 파싱 작업 역할 분리
TaeyeonRoyce Sep 4, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,17 @@
# 톰캣 구현하기

## 기능 요구 사항

### GET /index.html 응답하기 ✅

### CSS 지원하기 ✅

### Query String 파싱 ✅

### HTTP Status Code 302 ✅

### POST 방식으로 회원가입 ✅

### Cookie에 JSESSIONID 값 저장하기 ✅

### Session 구현하기 ✅
TaeyeonRoyce marked this conversation as resolved.
Show resolved Hide resolved
43 changes: 21 additions & 22 deletions study/src/test/java/study/FileTest.java
Original file line number Diff line number Diff line change
@@ -1,53 +1,52 @@
package study;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;

import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import java.util.Objects;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

/**
* 웹서버는 사용자가 요청한 html 파일을 제공 할 수 있어야 한다.
* File 클래스를 사용해서 파일을 읽어오고, 사용자에게 전달한다.
* 웹서버는 사용자가 요청한 html 파일을 제공 할 수 있어야 한다. File 클래스를 사용해서 파일을 읽어오고, 사용자에게 전달한다.
*/
@DisplayName("File 클래스 학습 테스트")
class FileTest {

/**
* resource 디렉터리 경로 찾기
*
* File 객체를 생성하려면 파일의 경로를 알아야 한다.
* 자바 애플리케이션은 resource 디렉터리에 HTML, CSS 같은 정적 파일을 저장한다.
* resource 디렉터리의 경로는 어떻게 알아낼 수 있을까?
* <p>
* File 객체를 생성하려면 파일의 경로를 알아야 한다. 자바 애플리케이션은 resource 디렉터리에 HTML, CSS 같은 정적 파일을 저장한다. resource 디렉터리의 경로는 어떻게 알아낼 수
* 있을까?
*/
@Test
void resource_디렉터리에_있는_파일의_경로를_찾는다() {
final String fileName = "nextstep.txt";

// todo
final String actual = "";
final URL resource = getClass().getClassLoader().getResource(fileName);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

어떤 과정으로 resource를 찾아내나요?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

동적으로 클래스를 포함한 자바 파일들을 메모리에 로딩하는 ClassLoader에서 해당하는 자원을 찾아 URI를 반환합니다. (이때, 최상위 BootLoader까지 위임하여 찾으므로 절대경로를 사용해야 하는 것 같습니다!
그리고 JVM에 로딩한 ClassLoader를 얻기 위해 FileTest.getClass().getClassLoader()를 사용한 것 같습니다..!

final String actual = Objects.requireNonNull(resource).getFile();

assertThat(actual).endsWith(fileName);
assertThat(actual).isNotNull()
.endsWith(fileName);
}

/**
* 파일 내용 읽기
*
* 읽어온 파일의 내용을 I/O Stream을 사용해서 사용자에게 전달 해야 한다.
* File, Files 클래스를 사용하여 파일의 내용을 읽어보자.
* <p>
* 읽어온 파일의 내용을 I/O Stream을 사용해서 사용자에게 전달 해야 한다. File, Files 클래스를 사용하여 파일의 내용을 읽어보자.
*/
@Test
void 파일의_내용을_읽는다() {
void 파일의_내용을_읽는다() throws IOException {
final String fileName = "nextstep.txt";
final URL resource = getClass().getClassLoader().getResource(fileName);
final Path path = Path.of(Objects.requireNonNull(resource).getFile());

// todo
final Path path = null;

// todo
final List<String> actual = Collections.emptyList();
final List<String> actual = Files.readAllLines(path);

assertThat(actual).containsOnly("nextstep");
}
Expand Down
135 changes: 72 additions & 63 deletions study/src/test/java/study/IOStreamTest.java
Original file line number Diff line number Diff line change
@@ -1,45 +1,51 @@
package study;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import java.io.*;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.*;

/**
* 자바는 스트림(Stream)으로부터 I/O를 사용한다.
* 입출력(I/O)은 하나의 시스템에서 다른 시스템으로 데이터를 이동 시킬 때 사용한다.
*
* InputStream은 데이터를 읽고, OutputStream은 데이터를 쓴다.
* FilterStream은 InputStream이나 OutputStream에 연결될 수 있다.
* FilterStream은 읽거나 쓰는 데이터를 수정할 때 사용한다. (e.g. 암호화, 압축, 포맷 변환)
*
* Stream은 데이터를 바이트로 읽고 쓴다.
* 바이트가 아닌 텍스트(문자)를 읽고 쓰려면 Reader와 Writer 클래스를 연결한다.
* Reader, Writer는 다양한 문자 인코딩(e.g. UTF-8)을 처리할 수 있다.
* 자바는 스트림(Stream)으로부터 I/O를 사용한다. 입출력(I/O)은 하나의 시스템에서 다른 시스템으로 데이터를 이동 시킬 때 사용한다.
* <p>
* InputStream은 데이터를 읽고, OutputStream은 데이터를 쓴다. FilterStream은 InputStream이나 OutputStream에 연결될 수 있다. FilterStream은 읽거나 쓰는
* 데이터를 수정할 때 사용한다. (e.g. 암호화, 압축, 포맷 변환)
* <p>
* Stream은 데이터를 바이트로 읽고 쓴다. 바이트가 아닌 텍스트(문자)를 읽고 쓰려면 Reader와 Writer 클래스를 연결한다. Reader, Writer는 다양한 문자 인코딩(e.g. UTF-8)을
* 처리할 수 있다.
*/
@DisplayName("Java I/O Stream 클래스 학습 테스트")
class IOStreamTest {

/**
* OutputStream 학습하기
*
* 자바의 기본 출력 클래스는 java.io.OutputStream이다.
* OutputStream의 write(int b) 메서드는 기반 메서드이다.
* <p>
* 자바의 기본 출력 클래스는 java.io.OutputStream이다. OutputStream의 write(int b) 메서드는 기반 메서드이다.
* <code>public abstract void write(int b) throws IOException;</code>
*/
@Nested
class OutputStream_학습_테스트 {

/**
* OutputStream은 다른 매체에 바이트로 데이터를 쓸 때 사용한다.
* OutputStream의 서브 클래스(subclass)는 특정 매체에 데이터를 쓰기 위해 write(int b) 메서드를 사용한다.
* 예를 들어, FilterOutputStream은 파일로 데이터를 쓸 때,
* 또는 DataOutputStream은 자바의 primitive type data를 다른 매체로 데이터를 쓸 때 사용한다.
*
* OutputStream은 다른 매체에 바이트로 데이터를 쓸 때 사용한다. OutputStream의 서브 클래스(subclass)는 특정 매체에 데이터를 쓰기 위해 write(int b) 메서드를
* 사용한다. 예를 들어, FilterOutputStream은 파일로 데이터를 쓸 때, 또는 DataOutputStream은 자바의 primitive type data를 다른 매체로 데이터를 쓸 때
* 사용한다.
* <p>
* write 메서드는 데이터를 바이트로 출력하기 때문에 비효율적이다.
* <code>write(byte[] data)</code>와 <code>write(byte b[], int off, int len)</code> 메서드는
* 1바이트 이상을 한 번에 전송 할 수 있어 훨씬 효율적이다.
Expand All @@ -53,21 +59,18 @@ class OutputStream_학습_테스트 {
* todo
* OutputStream 객체의 write 메서드를 사용해서 테스트를 통과시킨다
*/

outputStream.write(bytes);
final String actual = outputStream.toString();

assertThat(actual).isEqualTo("nextstep");
outputStream.close();
}

/**
* 효율적인 전송을 위해 스트림에서 버퍼링을 사용 할 수 있다.
* BufferedOutputStream 필터를 연결하면 버퍼링이 가능하다.
*
* 버퍼링을 사용하면 OutputStream을 사용할 때 flush를 사용하자.
* flush() 메서드는 버퍼가 아직 가득 차지 않은 상황에서 강제로 버퍼의 내용을 전송한다.
* Stream은 동기(synchronous)로 동작하기 때문에 버퍼가 찰 때까지 기다리면
* 데드락(deadlock) 상태가 되기 때문에 flush로 해제해야 한다.
* 효율적인 전송을 위해 스트림에서 버퍼링을 사용 할 수 있다. BufferedOutputStream 필터를 연결하면 버퍼링이 가능하다.
* <p>
* 버퍼링을 사용하면 OutputStream을 사용할 때 flush를 사용하자. flush() 메서드는 버퍼가 아직 가득 차지 않은 상황에서 강제로 버퍼의 내용을 전송한다. Stream은
* 동기(synchronous)로 동작하기 때문에 버퍼가 찰 때까지 기다리면 데드락(deadlock) 상태가 되기 때문에 flush로 해제해야 한다.
*/
@Test
void BufferedOutputStream을_사용하면_버퍼링이_가능하다() throws IOException {
Expand All @@ -78,14 +81,14 @@ class OutputStream_학습_테스트 {
* flush를 사용해서 테스트를 통과시킨다.
* ByteArrayOutputStream과 어떤 차이가 있을까?
*/
outputStream.flush();

verify(outputStream, atLeastOnce()).flush();
outputStream.close();
}

/**
* 스트림 사용이 끝나면 항상 close() 메서드를 호출하여 스트림을 닫는다.
* 장시간 스트림을 닫지 않으면 파일, 포트 등 다양한 리소스에서 누수(leak)가 발생한다.
* 스트림 사용이 끝나면 항상 close() 메서드를 호출하여 스트림을 닫는다. 장시간 스트림을 닫지 않으면 파일, 포트 등 다양한 리소스에서 누수(leak)가 발생한다.
*/
@Test
void OutputStream은_사용하고_나서_close_처리를_해준다() throws IOException {
Expand All @@ -96,27 +99,28 @@ class OutputStream_학습_테스트 {
* try-with-resources를 사용한다.
* java 9 이상에서는 변수를 try-with-resources로 처리할 수 있다.
*/
try (outputStream) {

}

verify(outputStream, atLeastOnce()).close();
}
}

/**
* InputStream 학습하기
*
* 자바의 기본 입력 클래스는 java.io.InputStream이다.
* InputStream은 다른 매체로부터 바이트로 데이터를 읽을 때 사용한다.
* InputStream의 read() 메서드는 기반 메서드이다.
* <p>
* 자바의 기본 입력 클래스는 java.io.InputStream이다. InputStream은 다른 매체로부터 바이트로 데이터를 읽을 때 사용한다. InputStream의 read() 메서드는 기반
* 메서드이다.
* <code>public abstract int read() throws IOException;</code>
*
* <p>
* InputStream의 서브 클래스(subclass)는 특정 매체에 데이터를 읽기 위해 read() 메서드를 사용한다.
*/
@Nested
class InputStream_학습_테스트 {

/**
* read() 메서드는 매체로부터 단일 바이트를 읽는데, 0부터 255 사이의 값을 int 타입으로 반환한다.
* int 값을 byte 타입으로 변환하면 -128부터 127 사이의 값으로 변환된다.
* read() 메서드는 매체로부터 단일 바이트를 읽는데, 0부터 255 사이의 값을 int 타입으로 반환한다. int 값을 byte 타입으로 변환하면 -128부터 127 사이의 값으로 변환된다.
* 그리고 Stream 끝에 도달하면 -1을 반환한다.
*/
@Test
Expand All @@ -128,16 +132,16 @@ class InputStream_학습_테스트 {
* todo
* inputStream에서 바이트로 반환한 값을 문자열로 어떻게 바꿀까?
*/
final String actual = "";

final String actual = new String(inputStream.readAllBytes());

assertThat(actual).isEqualTo("🤩");
assertThat(inputStream.read()).isEqualTo(-1);
inputStream.close();
}

/**
* 스트림 사용이 끝나면 항상 close() 메서드를 호출하여 스트림을 닫는다.
* 장시간 스트림을 닫지 않으면 파일, 포트 등 다양한 리소스에서 누수(leak)가 발생한다.
* 스트림 사용이 끝나면 항상 close() 메서드를 호출하여 스트림을 닫는다. 장시간 스트림을 닫지 않으면 파일, 포트 등 다양한 리소스에서 누수(leak)가 발생한다.
*/
@Test
void InputStream은_사용하고_나서_close_처리를_해준다() throws IOException {
Expand All @@ -148,66 +152,71 @@ class InputStream_학습_테스트 {
* try-with-resources를 사용한다.
* java 9 이상에서는 변수를 try-with-resources로 처리할 수 있다.
*/
inputStream.close();

verify(inputStream, atLeastOnce()).close();
}
}

/**
* FilterStream 학습하기
*
* 필터는 필터 스트림, reader, writer로 나뉜다.
* 필터는 바이트를 다른 데이터 형식으로 변환 할 때 사용한다.
* reader, writer는 UTF-8, ISO 8859-1 같은 형식으로 인코딩된 텍스트를 처리하는 데 사용된다.
* <p>
* 필터는 필터 스트림, reader, writer로 나뉜다. 필터는 바이트를 다른 데이터 형식으로 변환 할 때 사용한다. reader, writer는 UTF-8, ISO 8859-1 같은 형식으로 인코딩된
* 텍스트를 처리하는 데 사용된다.
*/
@Nested
class FilterStream_학습_테스트 {

/**
* BufferedInputStream은 데이터 처리 속도를 높이기 위해 데이터를 버퍼에 저장한다.
* InputStream 객체를 생성하고 필터 생성자에 전달하면 필터에 연결된다.
* 버퍼 크기를 지정하지 않으면 버퍼의 기본 사이즈는 얼마일까?
* BufferedInputStream은 데이터 처리 속도를 높이기 위해 데이터를 버퍼에 저장한다. InputStream 객체를 생성하고 필터 생성자에 전달하면 필터에 연결된다. 버퍼 크기를 지정하지
* 않으면 버퍼의 기본 사이즈는 얼마일까?
*/
@Test
void 필터인_BufferedInputStream를_사용해보자() {
void 필터인_BufferedInputStream를_사용해보자() throws IOException {
final String text = "필터에 연결해보자.";
final InputStream inputStream = new ByteArrayInputStream(text.getBytes());
final InputStream bufferedInputStream = null;
final InputStream bufferedInputStream = new BufferedInputStream(inputStream, text.getBytes().length);

final byte[] actual = new byte[0];
final byte[] actual = bufferedInputStream.readAllBytes();

assertThat(bufferedInputStream).isInstanceOf(FilterInputStream.class);
assertThat(actual).isEqualTo("필터에 연결해보자.".getBytes());
inputStream.close();
bufferedInputStream.close();
}
}

/**
* 자바의 기본 문자열은 UTF-16 유니코드 인코딩을 사용한다.
* 문자열이 아닌 바이트 단위로 처리하려니 불편하다.
* 그리고 바이트를 문자(char)로 처리하려면 인코딩을 신경 써야 한다.
* reader, writer를 사용하면 입출력 스트림을 바이트가 아닌 문자 단위로 데이터를 처리하게 된다.
* 그리고 InputStreamReader를 사용하면 지정된 인코딩에 따라 유니코드 문자로 변환할 수 있다.
* 자바의 기본 문자열은 UTF-16 유니코드 인코딩을 사용한다. 문자열이 아닌 바이트 단위로 처리하려니 불편하다. 그리고 바이트를 문자(char)로 처리하려면 인코딩을 신경 써야 한다. reader,
* writer를 사용하면 입출력 스트림을 바이트가 아닌 문자 단위로 데이터를 처리하게 된다. 그리고 InputStreamReader를 사용하면 지정된 인코딩에 따라 유니코드 문자로 변환할 수 있다.
*/
@Nested
class InputStreamReader_학습_테스트 {

/**
* InputStreamReader를 사용해서 바이트를 문자(char)로 읽어온다.
* 읽어온 문자(char)를 문자열(String)로 처리하자.
* 필터인 BufferedReader를 사용하면 readLine 메서드를 사용해서 문자열(String)을 한 줄 씩 읽어올 수 있다.
* InputStreamReader를 사용해서 바이트를 문자(char)로 읽어온다. 읽어온 문자(char)를 문자열(String)로 처리하자. 필터인 BufferedReader를 사용하면
* readLine 메서드를 사용해서 문자열(String)을 한 줄 씩 읽어올 수 있다.
*/
@Test
void BufferedReader를_사용하여_문자열을_읽어온다() {
void BufferedReader를_사용하여_문자열을_읽어온다() throws IOException {
final String emoji = String.join("\r\n",
"😀😃😄😁😆😅😂🤣🥲☺️😊",
"😇🙂🙃😉😌😍🥰😘😗😙😚",
"😋😛😝😜🤪🤨🧐🤓😎🥸🤩",
"");
final InputStream inputStream = new ByteArrayInputStream(emoji.getBytes());

final BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
final StringBuilder actual = new StringBuilder();
String line;

while ((line = br.readLine()) != null) {
actual.append(line);
actual.append("\r\n");
}

assertThat(actual).hasToString(emoji);
inputStream.close();
br.close();
}
}
}
11 changes: 11 additions & 0 deletions tomcat/src/main/java/nextstep/jwp/application/RegisterService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package nextstep.jwp.application;

import nextstep.jwp.db.InMemoryUserRepository;
import nextstep.jwp.model.User;

public class RegisterService {

public void register(final String account, final String password, final String email) {
InMemoryUserRepository.save(new User(account, password, email));
}
}
16 changes: 16 additions & 0 deletions tomcat/src/main/java/nextstep/jwp/application/UserService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package nextstep.jwp.application;

import nextstep.jwp.db.InMemoryUserRepository;
import nextstep.jwp.model.User;

public class UserService {

public boolean validateLogin(final String account, final String password) {
return getUserByAccount(account).checkPassword(password);
}

public User getUserByAccount(final String account) {
return InMemoryUserRepository.findByAccount(account)
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 사용자입니다."));
}
}
Loading